Skip to content

feat(costs): add Cloud Cost Management commands and restructure cost group#374

Draft
platinummonkey wants to merge 5 commits intomainfrom
feat/costs-ccm
Draft

feat(costs): add Cloud Cost Management commands and restructure cost group#374
platinummonkey wants to merge 5 commits intomainfrom
feat/costs-ccm

Conversation

@platinummonkey
Copy link
Copy Markdown
Collaborator

@platinummonkey platinummonkey commented Apr 16, 2026

Summary

Renames pup costpup costs datadog and introduces a new pup costs ccm subgroup with full Cloud Cost Management API coverage.

Changes

  • src/commands/cost_ccm.rs (new, ~700 lines) — CCM commands via direct HTTP:
    • custom-costs: list, get, upload (multipart PUT with random UUID boundary), delete
    • tag-descriptions: list, get, generate, upsert (PUT), delete
    • tag-metadata: list, tag-sources, metrics, orchestrators, currency
    • tags: list; tag-keys: list, get
    • budgets: list, get, upsert (PUT), delete, validate
    • commitments: utilization, coverage, savings, hotspots (scalar + timeseries), list
  • src/util.rs — add pub fn percent_encode() (RFC 3986 §2.3 unreserved chars); removes duplicate local encoders from cost_ccm.rs and idp.rs
  • src/commands/idp.rs — replace local url_encode() with util::percent_encode(); add #[cfg(test)] module
  • src/main.rs — rename CostCosts (#[command(name="costs")]), wrap existing commands in CostActions::Datadog, add full CostActions::Ccm enum tree
  • docs/COMMANDS.md, docs/EXAMPLES.md, README.md — document new costs datadog / costs ccm command surface
  • skills/dd-pup/SKILL.md, scripts/test_harness.py — update all stale pup costpup costs datadog references

Testing

  • cargo test: 802 tests passing (11 new in cost_ccm, 7 new in util, 2 new in idp)
  • cargo clippy -- -D warnings: clean
  • cargo fmt --check: clean
  • New negative tests: invalid time inputs to parse_commitment_query, budgets_get with only --start or only --end, custom_costs_upload with missing file

🤖 Generated with Claude Code

platinummonkey and others added 5 commits April 15, 2026 20:53
…command group

Renames `pup cost` → `pup costs datadog` and adds a new `pup costs ccm`
subgroup backed by the internal cost-visibility-api and cost-planning-api.

Changes:
- src/commands/cost_ccm.rs (new): CCM commands via direct HTTP calls
  - custom-costs: list, get, upload (multipart PUT), delete
  - tag-descriptions: list, get, generate, upsert, delete
  - tag-metadata: list, sources, metrics, orchestrators, currency
  - tags: list; tag-keys: list, get
  - budgets: list, get, upsert (PUT), delete, validate
  - commitments: utilization, coverage, savings, hotspots (scalar + timeseries), list
- src/util.rs: add pub fn percent_encode() (RFC 3986 unreserved chars)
- src/commands/idp.rs: replace local url_encode() with util::percent_encode()
- src/main.rs: rename Cost → Costs (#[command(name="costs")]), add Datadog
  subgroup wrapping existing commands, add full CostCcmActions enum tree
- docs/, README.md, skills/, scripts/: update all references from
  `pup cost` to `pup costs datadog` and document new CCM subcommands

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… consistency

- Add #[derive(Debug)] to HttpResponse (required for unwrap_err in tests)
- Add query param doc comment to raw_request
- Fix custom_costs_upload to pass version via &q instead of ?version= in path
- Add negative-path unit tests for tag_desc_upsert and tag_desc_delete
- Add positive-path mockito tests for raw_request query branch,
  tag_desc_upsert/delete (with and without cloud), and
  custom_costs_upload with version

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
runbooks/engine.rs and main.rs were modified locally but never staged in
the previous commits. engine.rs was missing the new &[] query argument for
raw_request (causing CI compile failure); main.rs was missing the cost alias.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…st 1.95)

Rust 1.95 clippy now enforces collapsible_match on match arms that contain
a single if block. Apply the match-guard pattern in runbooks.rs and the
extra-arm pattern in tunnel.rs to satisfy the lint.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…guard

The previous approach moved write_all into a match guard condition to satisfy
clippy::collapsible_match. Binding the result to a local variable first avoids
the lint (arm body is no longer a single if block) and keeps write_all explicit
in the arm body rather than as a guard side-effect.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@platinummonkey platinummonkey marked this pull request as draft April 16, 2026 13:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant