From a581492978b5ae337b59b61ea456f569614da0bd Mon Sep 17 00:00:00 2001 From: Arunim Chaudhary Date: Fri, 4 Sep 2026 17:21:16 +0530 Subject: [PATCH 1/2] feat: cover every sg-sdk-go operation in sg-cli Extend the CLI from workflow/stack/artifacts to all 30 resource groups exposed by the StackGuardian Go SDK (226 SDK methods, 230 leaf commands). - Bump sg-sdk-go to the API-parity branch (commit e8047d5) and adapt the existing workflow commands to its type changes. - Add cmd/common with shared client construction, raw-response JSON output, payload loading (--patch-payload/--preview/--dry-run), and flag helpers used by every new command. - Add command groups: organization, user, role, role-binding, api-access, api-token, audit-log, benchmark-report, secret, policy, connector, connector-group, runner-group, state-backend, resource, billing, chat, workflow-group, stack-run, stack-workflow, workflow-run, stack-workflow-run, template, workflow-template, workflow-step-template, stack-template; extra subcommands attached to workflow, stack and artifacts. - Add offline unit tests: a request/response matrix for every new command and a pinned command-tree test. - Bump version to 2.2.0. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01QFnDMC1JV9J4Hpk2oxwnAM --- go/cmd/apiaccess/apiaccess.go | 36 +++ go/cmd/apiaccess/create.go | 41 +++ go/cmd/apiaccess/delete.go | 34 +++ go/cmd/apiaccess/list.go | 46 +++ go/cmd/apiaccess/read.go | 33 +++ go/cmd/apiaccess/regenerate_key.go | 46 +++ go/cmd/apiaccess/update.go | 44 +++ go/cmd/apitoken/apitoken.go | 28 ++ go/cmd/apitoken/create.go | 34 +++ go/cmd/apitoken/delete.go | 34 +++ go/cmd/artifacts/artifacts.go | 3 + go/cmd/artifacts/extra/create.go | 45 +++ go/cmd/artifacts/extra/delete.go | 36 +++ go/cmd/artifacts/extra/extra.go | 22 ++ go/cmd/artifacts/extra/get_url.go | 37 +++ go/cmd/artifacts/extra/lock.go | 36 +++ go/cmd/artifacts/extra/read.go | 35 +++ go/cmd/artifacts/extra/rollback.go | 40 +++ go/cmd/artifacts/extra/unlock.go | 36 +++ go/cmd/artifacts/extra/versions.go | 38 +++ go/cmd/artifacts/list/artifacts_list.go | 5 +- go/cmd/auditlog/auditlog.go | 26 ++ go/cmd/auditlog/list.go | 40 +++ go/cmd/benchmarkreport/benchmarkreport.go | 26 ++ go/cmd/benchmarkreport/read.go | 45 +++ go/cmd/billing/balance.go | 30 ++ go/cmd/billing/billing.go | 76 +++++ go/cmd/billing/change_plan.go | 36 +++ go/cmd/billing/dashboard_url.go | 32 ++ go/cmd/billing/details.go | 30 ++ go/cmd/billing/invoices.go | 33 +++ go/cmd/billing/payment_methods_detach.go | 35 +++ go/cmd/billing/payment_methods_list.go | 30 ++ go/cmd/billing/payment_methods_set_default.go | 35 +++ .../billing/payment_methods_setup_intent.go | 30 ++ go/cmd/billing/profile_setup.go | 43 +++ go/cmd/billing/profile_update.go | 41 +++ go/cmd/chat/artifacts_get_url.go | 35 +++ go/cmd/chat/artifacts_list.go | 35 +++ go/cmd/chat/artifacts_upload_url.go | 36 +++ go/cmd/chat/chat.go | 92 ++++++ go/cmd/chat/commit_bundle.go | 38 +++ go/cmd/chat/create.go | 41 +++ go/cmd/chat/create_pr.go | 44 +++ go/cmd/chat/delete.go | 34 +++ go/cmd/chat/list.go | 36 +++ go/cmd/chat/messages_cancel.go | 35 +++ go/cmd/chat/messages_create.go | 56 ++++ go/cmd/chat/messages_list.go | 34 +++ go/cmd/chat/messages_read.go | 34 +++ go/cmd/chat/messages_retry.go | 35 +++ go/cmd/chat/pr_status.go | 33 +++ go/cmd/chat/pr_sync_status.go | 33 +++ go/cmd/chat/read.go | 35 +++ go/cmd/chat/update.go | 44 +++ go/cmd/common/common.go | 232 +++++++++++++++ go/cmd/connector/authenticate.go | 33 +++ go/cmd/connector/connector.go | 42 +++ go/cmd/connector/create.go | 41 +++ go/cmd/connector/delete.go | 34 +++ go/cmd/connector/github_repos.go | 33 +++ go/cmd/connector/list.go | 35 +++ go/cmd/connector/list_accounts.go | 41 +++ go/cmd/connector/read.go | 33 +++ go/cmd/connector/repos.go | 39 +++ go/cmd/connector/update.go | 44 +++ go/cmd/connectorgroup/authenticate.go | 33 +++ go/cmd/connectorgroup/connectorgroup.go | 65 +++++ .../connectorgroup/connectors_authenticate.go | 34 +++ go/cmd/connectorgroup/connectors_delete.go | 35 +++ go/cmd/connectorgroup/connectors_list.go | 37 +++ go/cmd/connectorgroup/connectors_read.go | 34 +++ go/cmd/connectorgroup/connectors_update.go | 45 +++ go/cmd/connectorgroup/create.go | 41 +++ go/cmd/connectorgroup/delete.go | 34 +++ go/cmd/connectorgroup/discovery_scan.go | 36 +++ go/cmd/connectorgroup/list.go | 36 +++ go/cmd/connectorgroup/read.go | 33 +++ go/cmd/connectorgroup/update.go | 44 +++ go/cmd/organization/bulk_action.go | 44 +++ go/cmd/organization/count_workflows.go | 39 +++ go/cmd/organization/create.go | 40 +++ go/cmd/organization/delete.go | 33 +++ go/cmd/organization/list.go | 29 ++ go/cmd/organization/organization.go | 38 +++ go/cmd/organization/read.go | 32 ++ go/cmd/organization/update.go | 43 +++ go/cmd/organization/workflows.go | 56 ++++ go/cmd/policy/create.go | 41 +++ go/cmd/policy/delete.go | 33 +++ go/cmd/policy/list.go | 38 +++ go/cmd/policy/policy.go | 34 +++ go/cmd/policy/read.go | 33 +++ go/cmd/policy/update.go | 44 +++ go/cmd/resource/move.go | 54 ++++ go/cmd/resource/resource.go | 30 ++ go/cmd/resource/search.go | 59 ++++ go/cmd/resource/tags.go | 36 +++ go/cmd/role/create.go | 41 +++ go/cmd/role/delete.go | 33 +++ go/cmd/role/list.go | 32 ++ go/cmd/role/read.go | 33 +++ go/cmd/role/role.go | 34 +++ go/cmd/role/update.go | 47 +++ go/cmd/rolebinding/read.go | 32 ++ go/cmd/rolebinding/rolebinding.go | 26 ++ go/cmd/root.go | 73 ++++- go/cmd/runnergroup/create.go | 41 +++ go/cmd/runnergroup/delete.go | 34 +++ go/cmd/runnergroup/deregister_runner.go | 47 +++ go/cmd/runnergroup/list.go | 34 +++ go/cmd/runnergroup/read.go | 36 +++ go/cmd/runnergroup/register.go | 34 +++ go/cmd/runnergroup/runnergroup.go | 42 +++ go/cmd/runnergroup/storage_backend_auth.go | 33 +++ go/cmd/runnergroup/update.go | 44 +++ go/cmd/runnergroup/update_runner_state.go | 50 ++++ go/cmd/secret/create.go | 41 +++ go/cmd/secret/delete.go | 34 +++ go/cmd/secret/list.go | 30 ++ go/cmd/secret/read_bulk.go | 34 +++ go/cmd/secret/secret.go | 34 +++ go/cmd/secret/update.go | 47 +++ go/cmd/stack/apply/stack_apply.go | 3 +- go/cmd/stack/create/stack_create.go | 3 +- go/cmd/stack/delete/stack_delete.go | 3 +- go/cmd/stack/destroy/stack_destroy.go | 3 +- go/cmd/stack/extra/compare.go | 58 ++++ go/cmd/stack/extra/extra.go | 18 ++ go/cmd/stack/extra/list.go | 37 +++ go/cmd/stack/extra/read.go | 34 +++ go/cmd/stack/extra/update.go | 45 +++ go/cmd/stack/outputs/stack_outputs.go | 3 +- go/cmd/stack/stack.go | 3 + go/cmd/stackrun/create.go | 53 ++++ go/cmd/stackrun/list.go | 35 +++ go/cmd/stackrun/read.go | 35 +++ go/cmd/stackrun/stackrun.go | 34 +++ go/cmd/stacktemplate/create.go | 43 +++ go/cmd/stacktemplate/delete.go | 33 +++ go/cmd/stacktemplate/read.go | 33 +++ go/cmd/stacktemplate/revisions_create.go | 44 +++ go/cmd/stacktemplate/revisions_delete.go | 35 +++ go/cmd/stacktemplate/revisions_read.go | 33 +++ go/cmd/stacktemplate/revisions_update.go | 44 +++ go/cmd/stacktemplate/stacktemplate.go | 55 ++++ go/cmd/stacktemplate/update.go | 44 +++ go/cmd/stackworkflow/artifacts_create.go | 46 +++ go/cmd/stackworkflow/artifacts_delete.go | 37 +++ go/cmd/stackworkflow/artifacts_get_url.go | 37 +++ go/cmd/stackworkflow/artifacts_list.go | 33 +++ go/cmd/stackworkflow/artifacts_lock.go | 37 +++ go/cmd/stackworkflow/artifacts_read.go | 36 +++ go/cmd/stackworkflow/artifacts_unlock.go | 37 +++ go/cmd/stackworkflow/compare.go | 59 ++++ go/cmd/stackworkflow/create.go | 43 +++ go/cmd/stackworkflow/delete.go | 35 +++ go/cmd/stackworkflow/file_upload_url.go | 40 +++ go/cmd/stackworkflow/list.go | 41 +++ go/cmd/stackworkflow/outputs.go | 35 +++ go/cmd/stackworkflow/read.go | 35 +++ go/cmd/stackworkflow/stackworkflow.go | 79 +++++ go/cmd/stackworkflow/tfstate_upload_url.go | 37 +++ go/cmd/stackworkflow/update.go | 46 +++ go/cmd/stackworkflow/vcs_triggers.go | 46 +++ go/cmd/stackworkflowrun/approve.go | 44 +++ go/cmd/stackworkflowrun/create.go | 46 +++ go/cmd/stackworkflowrun/delete.go | 37 +++ go/cmd/stackworkflowrun/facts_create.go | 47 +++ go/cmd/stackworkflowrun/facts_read.go | 37 +++ go/cmd/stackworkflowrun/facts_update.go | 47 +++ go/cmd/stackworkflowrun/list.go | 54 ++++ go/cmd/stackworkflowrun/logs.go | 36 +++ go/cmd/stackworkflowrun/read.go | 36 +++ go/cmd/stackworkflowrun/stackworkflowrun.go | 67 +++++ go/cmd/stackworkflowrun/update.go | 47 +++ go/cmd/statebackend/create.go | 41 +++ go/cmd/statebackend/delete.go | 34 +++ go/cmd/statebackend/list.go | 34 +++ go/cmd/statebackend/list_statefiles.go | 34 +++ go/cmd/statebackend/read.go | 33 +++ go/cmd/statebackend/statebackend.go | 36 +++ go/cmd/statebackend/update.go | 44 +++ go/cmd/template/artifacts_delete.go | 44 +++ go/cmd/template/artifacts_download_url.go | 43 +++ go/cmd/template/artifacts_list.go | 43 +++ go/cmd/template/artifacts_upload_url.go | 43 +++ go/cmd/template/create.go | 41 +++ go/cmd/template/delete.go | 45 +++ go/cmd/template/group_iac.go | 42 +++ go/cmd/template/input_schema.go | 48 +++ go/cmd/template/list.go | 42 +++ go/cmd/template/list_by_owner.go | 38 +++ go/cmd/template/public_list.go | 43 +++ go/cmd/template/public_list_all.go | 41 +++ go/cmd/template/public_read.go | 41 +++ go/cmd/template/read.go | 45 +++ go/cmd/template/subscriptions_create.go | 41 +++ go/cmd/template/subscriptions_read.go | 37 +++ go/cmd/template/subscriptions_update.go | 49 ++++ go/cmd/template/template.go | 114 ++++++++ go/cmd/template/update.go | 56 ++++ go/cmd/template/vcs_triggers.go | 55 ++++ go/cmd/user/create.go | 41 +++ go/cmd/user/delete.go | 35 +++ go/cmd/user/list.go | 36 +++ go/cmd/user/read.go | 34 +++ go/cmd/user/update.go | 41 +++ go/cmd/user/user.go | 34 +++ go/cmd/workflow/apply/workflow_apply.go | 3 +- go/cmd/workflow/create/workflow_create.go | 70 ++--- go/cmd/workflow/delete/workflow_delete.go | 3 +- go/cmd/workflow/destroy/workflow_destroy.go | 3 +- go/cmd/workflow/extra/compare.go | 58 ++++ go/cmd/workflow/extra/extra.go | 20 ++ go/cmd/workflow/extra/file_upload_url.go | 39 +++ go/cmd/workflow/extra/outputs.go | 34 +++ go/cmd/workflow/extra/tfstate_upload_url.go | 36 +++ go/cmd/workflow/extra/update.go | 54 ++++ go/cmd/workflow/extra/vcs_triggers.go | 45 +++ go/cmd/workflow/list/workflow_list.go | 3 +- go/cmd/workflow/read/workflow_read.go | 3 +- go/cmd/workflow/workflow.go | 3 + go/cmd/workflowgroup/create.go | 41 +++ go/cmd/workflowgroup/create_child.go | 44 +++ go/cmd/workflowgroup/delete.go | 34 +++ go/cmd/workflowgroup/list.go | 37 +++ go/cmd/workflowgroup/list_children.go | 39 +++ go/cmd/workflowgroup/list_resources.go | 44 +++ go/cmd/workflowgroup/read.go | 33 +++ go/cmd/workflowgroup/update.go | 44 +++ go/cmd/workflowgroup/workflowgroup.go | 40 +++ go/cmd/workflowrun/approve.go | 47 +++ go/cmd/workflowrun/cancel.go | 39 +++ go/cmd/workflowrun/create.go | 48 +++ go/cmd/workflowrun/delete.go | 39 +++ go/cmd/workflowrun/facts_create.go | 49 ++++ go/cmd/workflowrun/facts_read.go | 39 +++ go/cmd/workflowrun/facts_update.go | 49 ++++ go/cmd/workflowrun/list.go | 39 +++ go/cmd/workflowrun/logs.go | 38 +++ go/cmd/workflowrun/read.go | 38 +++ go/cmd/workflowrun/read_by_ksuid.go | 36 +++ go/cmd/workflowrun/update.go | 49 ++++ go/cmd/workflowrun/update_by_ksuid.go | 47 +++ go/cmd/workflowrun/workflowrun.go | 69 +++++ go/cmd/workflowsteptemplate/create.go | 43 +++ go/cmd/workflowsteptemplate/delete.go | 33 +++ go/cmd/workflowsteptemplate/read.go | 33 +++ .../workflowsteptemplate/revisions_create.go | 44 +++ .../workflowsteptemplate/revisions_delete.go | 35 +++ go/cmd/workflowsteptemplate/revisions_read.go | 33 +++ .../workflowsteptemplate/revisions_update.go | 44 +++ go/cmd/workflowsteptemplate/update.go | 44 +++ .../workflowsteptemplate.go | 55 ++++ go/cmd/workflowtemplate/create.go | 43 +++ go/cmd/workflowtemplate/delete.go | 33 +++ go/cmd/workflowtemplate/read.go | 33 +++ go/cmd/workflowtemplate/revisions_create.go | 44 +++ go/cmd/workflowtemplate/revisions_delete.go | 35 +++ go/cmd/workflowtemplate/revisions_read.go | 33 +++ go/cmd/workflowtemplate/revisions_update.go | 44 +++ go/cmd/workflowtemplate/update.go | 44 +++ go/cmd/workflowtemplate/workflowtemplate.go | 55 ++++ go/go.mod | 2 +- go/go.sum | 4 +- go/tests/matrix_a_test.go | 169 +++++++++++ go/tests/matrix_b_test.go | 182 ++++++++++++ go/tests/matrix_test.go | 118 ++++++++ go/tests/tree_test.go | 274 ++++++++++++++++++ go/tests/workflow_test.go | 4 +- 271 files changed, 11053 insertions(+), 63 deletions(-) create mode 100644 go/cmd/apiaccess/apiaccess.go create mode 100644 go/cmd/apiaccess/create.go create mode 100644 go/cmd/apiaccess/delete.go create mode 100644 go/cmd/apiaccess/list.go create mode 100644 go/cmd/apiaccess/read.go create mode 100644 go/cmd/apiaccess/regenerate_key.go create mode 100644 go/cmd/apiaccess/update.go create mode 100644 go/cmd/apitoken/apitoken.go create mode 100644 go/cmd/apitoken/create.go create mode 100644 go/cmd/apitoken/delete.go create mode 100644 go/cmd/artifacts/extra/create.go create mode 100644 go/cmd/artifacts/extra/delete.go create mode 100644 go/cmd/artifacts/extra/extra.go create mode 100644 go/cmd/artifacts/extra/get_url.go create mode 100644 go/cmd/artifacts/extra/lock.go create mode 100644 go/cmd/artifacts/extra/read.go create mode 100644 go/cmd/artifacts/extra/rollback.go create mode 100644 go/cmd/artifacts/extra/unlock.go create mode 100644 go/cmd/artifacts/extra/versions.go create mode 100644 go/cmd/auditlog/auditlog.go create mode 100644 go/cmd/auditlog/list.go create mode 100644 go/cmd/benchmarkreport/benchmarkreport.go create mode 100644 go/cmd/benchmarkreport/read.go create mode 100644 go/cmd/billing/balance.go create mode 100644 go/cmd/billing/billing.go create mode 100644 go/cmd/billing/change_plan.go create mode 100644 go/cmd/billing/dashboard_url.go create mode 100644 go/cmd/billing/details.go create mode 100644 go/cmd/billing/invoices.go create mode 100644 go/cmd/billing/payment_methods_detach.go create mode 100644 go/cmd/billing/payment_methods_list.go create mode 100644 go/cmd/billing/payment_methods_set_default.go create mode 100644 go/cmd/billing/payment_methods_setup_intent.go create mode 100644 go/cmd/billing/profile_setup.go create mode 100644 go/cmd/billing/profile_update.go create mode 100644 go/cmd/chat/artifacts_get_url.go create mode 100644 go/cmd/chat/artifacts_list.go create mode 100644 go/cmd/chat/artifacts_upload_url.go create mode 100644 go/cmd/chat/chat.go create mode 100644 go/cmd/chat/commit_bundle.go create mode 100644 go/cmd/chat/create.go create mode 100644 go/cmd/chat/create_pr.go create mode 100644 go/cmd/chat/delete.go create mode 100644 go/cmd/chat/list.go create mode 100644 go/cmd/chat/messages_cancel.go create mode 100644 go/cmd/chat/messages_create.go create mode 100644 go/cmd/chat/messages_list.go create mode 100644 go/cmd/chat/messages_read.go create mode 100644 go/cmd/chat/messages_retry.go create mode 100644 go/cmd/chat/pr_status.go create mode 100644 go/cmd/chat/pr_sync_status.go create mode 100644 go/cmd/chat/read.go create mode 100644 go/cmd/chat/update.go create mode 100644 go/cmd/common/common.go create mode 100644 go/cmd/connector/authenticate.go create mode 100644 go/cmd/connector/connector.go create mode 100644 go/cmd/connector/create.go create mode 100644 go/cmd/connector/delete.go create mode 100644 go/cmd/connector/github_repos.go create mode 100644 go/cmd/connector/list.go create mode 100644 go/cmd/connector/list_accounts.go create mode 100644 go/cmd/connector/read.go create mode 100644 go/cmd/connector/repos.go create mode 100644 go/cmd/connector/update.go create mode 100644 go/cmd/connectorgroup/authenticate.go create mode 100644 go/cmd/connectorgroup/connectorgroup.go create mode 100644 go/cmd/connectorgroup/connectors_authenticate.go create mode 100644 go/cmd/connectorgroup/connectors_delete.go create mode 100644 go/cmd/connectorgroup/connectors_list.go create mode 100644 go/cmd/connectorgroup/connectors_read.go create mode 100644 go/cmd/connectorgroup/connectors_update.go create mode 100644 go/cmd/connectorgroup/create.go create mode 100644 go/cmd/connectorgroup/delete.go create mode 100644 go/cmd/connectorgroup/discovery_scan.go create mode 100644 go/cmd/connectorgroup/list.go create mode 100644 go/cmd/connectorgroup/read.go create mode 100644 go/cmd/connectorgroup/update.go create mode 100644 go/cmd/organization/bulk_action.go create mode 100644 go/cmd/organization/count_workflows.go create mode 100644 go/cmd/organization/create.go create mode 100644 go/cmd/organization/delete.go create mode 100644 go/cmd/organization/list.go create mode 100644 go/cmd/organization/organization.go create mode 100644 go/cmd/organization/read.go create mode 100644 go/cmd/organization/update.go create mode 100644 go/cmd/organization/workflows.go create mode 100644 go/cmd/policy/create.go create mode 100644 go/cmd/policy/delete.go create mode 100644 go/cmd/policy/list.go create mode 100644 go/cmd/policy/policy.go create mode 100644 go/cmd/policy/read.go create mode 100644 go/cmd/policy/update.go create mode 100644 go/cmd/resource/move.go create mode 100644 go/cmd/resource/resource.go create mode 100644 go/cmd/resource/search.go create mode 100644 go/cmd/resource/tags.go create mode 100644 go/cmd/role/create.go create mode 100644 go/cmd/role/delete.go create mode 100644 go/cmd/role/list.go create mode 100644 go/cmd/role/read.go create mode 100644 go/cmd/role/role.go create mode 100644 go/cmd/role/update.go create mode 100644 go/cmd/rolebinding/read.go create mode 100644 go/cmd/rolebinding/rolebinding.go create mode 100644 go/cmd/runnergroup/create.go create mode 100644 go/cmd/runnergroup/delete.go create mode 100644 go/cmd/runnergroup/deregister_runner.go create mode 100644 go/cmd/runnergroup/list.go create mode 100644 go/cmd/runnergroup/read.go create mode 100644 go/cmd/runnergroup/register.go create mode 100644 go/cmd/runnergroup/runnergroup.go create mode 100644 go/cmd/runnergroup/storage_backend_auth.go create mode 100644 go/cmd/runnergroup/update.go create mode 100644 go/cmd/runnergroup/update_runner_state.go create mode 100644 go/cmd/secret/create.go create mode 100644 go/cmd/secret/delete.go create mode 100644 go/cmd/secret/list.go create mode 100644 go/cmd/secret/read_bulk.go create mode 100644 go/cmd/secret/secret.go create mode 100644 go/cmd/secret/update.go create mode 100644 go/cmd/stack/extra/compare.go create mode 100644 go/cmd/stack/extra/extra.go create mode 100644 go/cmd/stack/extra/list.go create mode 100644 go/cmd/stack/extra/read.go create mode 100644 go/cmd/stack/extra/update.go create mode 100644 go/cmd/stackrun/create.go create mode 100644 go/cmd/stackrun/list.go create mode 100644 go/cmd/stackrun/read.go create mode 100644 go/cmd/stackrun/stackrun.go create mode 100644 go/cmd/stacktemplate/create.go create mode 100644 go/cmd/stacktemplate/delete.go create mode 100644 go/cmd/stacktemplate/read.go create mode 100644 go/cmd/stacktemplate/revisions_create.go create mode 100644 go/cmd/stacktemplate/revisions_delete.go create mode 100644 go/cmd/stacktemplate/revisions_read.go create mode 100644 go/cmd/stacktemplate/revisions_update.go create mode 100644 go/cmd/stacktemplate/stacktemplate.go create mode 100644 go/cmd/stacktemplate/update.go create mode 100644 go/cmd/stackworkflow/artifacts_create.go create mode 100644 go/cmd/stackworkflow/artifacts_delete.go create mode 100644 go/cmd/stackworkflow/artifacts_get_url.go create mode 100644 go/cmd/stackworkflow/artifacts_list.go create mode 100644 go/cmd/stackworkflow/artifacts_lock.go create mode 100644 go/cmd/stackworkflow/artifacts_read.go create mode 100644 go/cmd/stackworkflow/artifacts_unlock.go create mode 100644 go/cmd/stackworkflow/compare.go create mode 100644 go/cmd/stackworkflow/create.go create mode 100644 go/cmd/stackworkflow/delete.go create mode 100644 go/cmd/stackworkflow/file_upload_url.go create mode 100644 go/cmd/stackworkflow/list.go create mode 100644 go/cmd/stackworkflow/outputs.go create mode 100644 go/cmd/stackworkflow/read.go create mode 100644 go/cmd/stackworkflow/stackworkflow.go create mode 100644 go/cmd/stackworkflow/tfstate_upload_url.go create mode 100644 go/cmd/stackworkflow/update.go create mode 100644 go/cmd/stackworkflow/vcs_triggers.go create mode 100644 go/cmd/stackworkflowrun/approve.go create mode 100644 go/cmd/stackworkflowrun/create.go create mode 100644 go/cmd/stackworkflowrun/delete.go create mode 100644 go/cmd/stackworkflowrun/facts_create.go create mode 100644 go/cmd/stackworkflowrun/facts_read.go create mode 100644 go/cmd/stackworkflowrun/facts_update.go create mode 100644 go/cmd/stackworkflowrun/list.go create mode 100644 go/cmd/stackworkflowrun/logs.go create mode 100644 go/cmd/stackworkflowrun/read.go create mode 100644 go/cmd/stackworkflowrun/stackworkflowrun.go create mode 100644 go/cmd/stackworkflowrun/update.go create mode 100644 go/cmd/statebackend/create.go create mode 100644 go/cmd/statebackend/delete.go create mode 100644 go/cmd/statebackend/list.go create mode 100644 go/cmd/statebackend/list_statefiles.go create mode 100644 go/cmd/statebackend/read.go create mode 100644 go/cmd/statebackend/statebackend.go create mode 100644 go/cmd/statebackend/update.go create mode 100644 go/cmd/template/artifacts_delete.go create mode 100644 go/cmd/template/artifacts_download_url.go create mode 100644 go/cmd/template/artifacts_list.go create mode 100644 go/cmd/template/artifacts_upload_url.go create mode 100644 go/cmd/template/create.go create mode 100644 go/cmd/template/delete.go create mode 100644 go/cmd/template/group_iac.go create mode 100644 go/cmd/template/input_schema.go create mode 100644 go/cmd/template/list.go create mode 100644 go/cmd/template/list_by_owner.go create mode 100644 go/cmd/template/public_list.go create mode 100644 go/cmd/template/public_list_all.go create mode 100644 go/cmd/template/public_read.go create mode 100644 go/cmd/template/read.go create mode 100644 go/cmd/template/subscriptions_create.go create mode 100644 go/cmd/template/subscriptions_read.go create mode 100644 go/cmd/template/subscriptions_update.go create mode 100644 go/cmd/template/template.go create mode 100644 go/cmd/template/update.go create mode 100644 go/cmd/template/vcs_triggers.go create mode 100644 go/cmd/user/create.go create mode 100644 go/cmd/user/delete.go create mode 100644 go/cmd/user/list.go create mode 100644 go/cmd/user/read.go create mode 100644 go/cmd/user/update.go create mode 100644 go/cmd/user/user.go create mode 100644 go/cmd/workflow/extra/compare.go create mode 100644 go/cmd/workflow/extra/extra.go create mode 100644 go/cmd/workflow/extra/file_upload_url.go create mode 100644 go/cmd/workflow/extra/outputs.go create mode 100644 go/cmd/workflow/extra/tfstate_upload_url.go create mode 100644 go/cmd/workflow/extra/update.go create mode 100644 go/cmd/workflow/extra/vcs_triggers.go create mode 100644 go/cmd/workflowgroup/create.go create mode 100644 go/cmd/workflowgroup/create_child.go create mode 100644 go/cmd/workflowgroup/delete.go create mode 100644 go/cmd/workflowgroup/list.go create mode 100644 go/cmd/workflowgroup/list_children.go create mode 100644 go/cmd/workflowgroup/list_resources.go create mode 100644 go/cmd/workflowgroup/read.go create mode 100644 go/cmd/workflowgroup/update.go create mode 100644 go/cmd/workflowgroup/workflowgroup.go create mode 100644 go/cmd/workflowrun/approve.go create mode 100644 go/cmd/workflowrun/cancel.go create mode 100644 go/cmd/workflowrun/create.go create mode 100644 go/cmd/workflowrun/delete.go create mode 100644 go/cmd/workflowrun/facts_create.go create mode 100644 go/cmd/workflowrun/facts_read.go create mode 100644 go/cmd/workflowrun/facts_update.go create mode 100644 go/cmd/workflowrun/list.go create mode 100644 go/cmd/workflowrun/logs.go create mode 100644 go/cmd/workflowrun/read.go create mode 100644 go/cmd/workflowrun/read_by_ksuid.go create mode 100644 go/cmd/workflowrun/update.go create mode 100644 go/cmd/workflowrun/update_by_ksuid.go create mode 100644 go/cmd/workflowrun/workflowrun.go create mode 100644 go/cmd/workflowsteptemplate/create.go create mode 100644 go/cmd/workflowsteptemplate/delete.go create mode 100644 go/cmd/workflowsteptemplate/read.go create mode 100644 go/cmd/workflowsteptemplate/revisions_create.go create mode 100644 go/cmd/workflowsteptemplate/revisions_delete.go create mode 100644 go/cmd/workflowsteptemplate/revisions_read.go create mode 100644 go/cmd/workflowsteptemplate/revisions_update.go create mode 100644 go/cmd/workflowsteptemplate/update.go create mode 100644 go/cmd/workflowsteptemplate/workflowsteptemplate.go create mode 100644 go/cmd/workflowtemplate/create.go create mode 100644 go/cmd/workflowtemplate/delete.go create mode 100644 go/cmd/workflowtemplate/read.go create mode 100644 go/cmd/workflowtemplate/revisions_create.go create mode 100644 go/cmd/workflowtemplate/revisions_delete.go create mode 100644 go/cmd/workflowtemplate/revisions_read.go create mode 100644 go/cmd/workflowtemplate/revisions_update.go create mode 100644 go/cmd/workflowtemplate/update.go create mode 100644 go/cmd/workflowtemplate/workflowtemplate.go create mode 100644 go/tests/matrix_a_test.go create mode 100644 go/tests/matrix_b_test.go create mode 100644 go/tests/matrix_test.go create mode 100644 go/tests/tree_test.go diff --git a/go/cmd/apiaccess/apiaccess.go b/go/cmd/apiaccess/apiaccess.go new file mode 100644 index 0000000..13d0c21 --- /dev/null +++ b/go/cmd/apiaccess/apiaccess.go @@ -0,0 +1,36 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package apiaccess + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewApiAccessCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "api-access", + Short: "Manage API accesses (API keys and OIDC identities)", + Long: `Manage API accesses (API keys and OIDC identities)`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + create Create an API access + read Get an API access + update Update an API access + delete Delete an API access + regenerate-key Regenerate the key of an API access + list List API accesses`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newCreateCmd(c), + newReadCmd(c), + newUpdateCmd(c), + newDeleteCmd(c), + newRegenerateKeyCmd(c), + newListCmd(c), + ) + return cmd +} diff --git a/go/cmd/apiaccess/create.go b/go/cmd/apiaccess/create.go new file mode 100644 index 0000000..60050c1 --- /dev/null +++ b/go/cmd/apiaccess/create.go @@ -0,0 +1,41 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package apiaccess + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create an API access", + Long: `Create an API access`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req sggosdk.ApiAccess + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.AccessManagement.CreateApiAccess(ctx, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "API access created successfully.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/apiaccess/delete.go b/go/cmd/apiaccess/delete.go new file mode 100644 index 0000000..ac5031f --- /dev/null +++ b/go/cmd/apiaccess/delete.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package apiaccess + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete an API access", + Long: `Delete an API access`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + accessId := common.String(cmd, "access-id") + response, err := c.AccessManagement.DeleteApiAccess(ctx, accessId, org) + if err != nil { + return err + } + common.Done(cmd, response, "API access deleted successfully.") + return nil + }, + } + cmd.Flags().String("access-id", "", "The API access ID.") + _ = cmd.MarkFlagRequired("access-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/apiaccess/list.go b/go/cmd/apiaccess/list.go new file mode 100644 index 0000000..36b069c --- /dev/null +++ b/go/cmd/apiaccess/list.go @@ -0,0 +1,46 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package apiaccess + +import ( + "context" + "fmt" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List API accesses", + Long: `List API accesses`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var accessType *sggosdk.ListAllApiAccessesRequestAccessType + if v := common.OptString(cmd, "access-type"); v != nil { + if *v != "APIKEY" && *v != "OIDC" { + return fmt.Errorf("--access-type must be APIKEY or OIDC, got %q", *v) + } + t := sggosdk.ListAllApiAccessesRequestAccessType(*v) + accessType = &t + } + response, err := c.AccessManagement.ListAllApiAccesses(ctx, org, &sggosdk.ListAllApiAccessesRequest{Limit: common.OptInt(cmd, "limit"), LastEvaluatedKey: common.OptString(cmd, "last-evaluated-key"), ResourceName: common.OptString(cmd, "resource-name"), Roles: common.OptString(cmd, "roles"), Status: common.OptString(cmd, "status"), AccessType: accessType}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + cmd.Flags().String("access-type", "", "Filter by access type (APIKEY, OIDC).") + cmd.Flags().String("resource-name", "", "Filter by resource name.") + cmd.Flags().String("roles", "", "Filter by roles (comma-separated).") + cmd.Flags().String("status", "", "Filter by status (active, expired).") + return cmd +} diff --git a/go/cmd/apiaccess/read.go b/go/cmd/apiaccess/read.go new file mode 100644 index 0000000..6d559ea --- /dev/null +++ b/go/cmd/apiaccess/read.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package apiaccess + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get an API access", + Long: `Get an API access`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + accessId := common.String(cmd, "access-id") + response, err := c.AccessManagement.ReadApiAccess(ctx, accessId, org) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("access-id", "", "The API access ID.") + _ = cmd.MarkFlagRequired("access-id") + return cmd +} diff --git a/go/cmd/apiaccess/regenerate_key.go b/go/cmd/apiaccess/regenerate_key.go new file mode 100644 index 0000000..7d4142c --- /dev/null +++ b/go/cmd/apiaccess/regenerate_key.go @@ -0,0 +1,46 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package apiaccess + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newRegenerateKeyCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "regenerate-key", + Short: "Regenerate the key of an API access", + Long: `Regenerate the key of an API access`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + accessId := common.String(cmd, "access-id") + noExpiration := common.Bool(cmd, "no-expiration") + var body sggosdk.ApiAccessRegenerate + if v := common.OptInt(cmd, "expires-at"); v != nil { + body.ExpiresAt = sggosdk.Optional(*v) + } + if noExpiration { + body.ExpiresAt = sggosdk.Null[int]() + } + response, err := c.AccessManagement.RegenerateApiKey(ctx, accessId, org, &body) + if err != nil { + return err + } + common.Done(cmd, response, "API key regenerated.") + return nil + }, + } + cmd.Flags().String("access-id", "", "The API access ID.") + _ = cmd.MarkFlagRequired("access-id") + cmd.Flags().Int("expires-at", 0, "New expiration as a Unix timestamp in milliseconds.") + cmd.Flags().Bool("no-expiration", false, "Remove the expiration.") + common.AddOutputJSONFlag(cmd) + cmd.MarkFlagsMutuallyExclusive("expires-at", "no-expiration") + return cmd +} diff --git a/go/cmd/apiaccess/update.go b/go/cmd/apiaccess/update.go new file mode 100644 index 0000000..01c1fcb --- /dev/null +++ b/go/cmd/apiaccess/update.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package apiaccess + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update an API access", + Long: `Update an API access`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + accessId := common.String(cmd, "access-id") + var req sggosdk.PatchedApiAccessPatch + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.AccessManagement.UpdateApiAccess(ctx, accessId, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "API access updated successfully.") + return nil + }, + } + cmd.Flags().String("access-id", "", "The API access ID.") + _ = cmd.MarkFlagRequired("access-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/apitoken/apitoken.go b/go/cmd/apitoken/apitoken.go new file mode 100644 index 0000000..537f236 --- /dev/null +++ b/go/cmd/apitoken/apitoken.go @@ -0,0 +1,28 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package apitoken + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewApiTokenCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "api-token", + Short: "Manage legacy user API keys", + Long: `Manage legacy user API keys`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + create Create or retrieve the caller's API key, or look up a runner group's key + delete Revoke the API key of a principal`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newCreateCmd(c), + newDeleteCmd(c), + ) + return cmd +} diff --git a/go/cmd/apitoken/create.go b/go/cmd/apitoken/create.go new file mode 100644 index 0000000..ab9b339 --- /dev/null +++ b/go/cmd/apitoken/create.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package apitoken + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/accessmanagement" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Create or retrieve the caller's API key, or look up a runner group's key", + Long: `Create or retrieve the caller's API key, or look up a runner group's key`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.AccessManagement.CreateApiToken(ctx, org, &accessmanagement.ApiTokenRequest{Regenerate: common.OptBool(cmd, "regenerate"), RunnerGroupId: common.OptString(cmd, "runner-group-id")}) + if err != nil { + return err + } + common.Done(cmd, response, "API token request completed.") + return nil + }, + } + cmd.Flags().Bool("regenerate", false, "Replace the existing key with a new one.") + cmd.Flags().String("runner-group-id", "", "Look up the key of this runner group (/runnergroups/).") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/apitoken/delete.go b/go/cmd/apitoken/delete.go new file mode 100644 index 0000000..e2d9ba1 --- /dev/null +++ b/go/cmd/apitoken/delete.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package apitoken + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Revoke the API key of a principal", + Long: `Revoke the API key of a principal`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + principalId := common.String(cmd, "principal-id") + response, err := c.AccessManagement.DeleteApiToken(ctx, org, principalId) + if err != nil { + return err + } + common.Done(cmd, response, "API token revoked.") + return nil + }, + } + cmd.Flags().String("principal-id", "", "Principal id in the form //.") + _ = cmd.MarkFlagRequired("principal-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/artifacts/artifacts.go b/go/cmd/artifacts/artifacts.go index 47604aa..da12728 100644 --- a/go/cmd/artifacts/artifacts.go +++ b/go/cmd/artifacts/artifacts.go @@ -3,6 +3,7 @@ package artifacts import ( "fmt" + artifactsextra "github.com/StackGuardian/sg-cli/cmd/artifacts/extra" "github.com/StackGuardian/sg-cli/cmd/artifacts/list" "github.com/StackGuardian/sg-sdk-go/client" "github.com/spf13/cobra" @@ -31,5 +32,7 @@ func NewArtifactsCmd(c *client.Client) *cobra.Command { artifactsCmd.AddCommand(list.NewListCmd(c)) + artifactsextra.AddCommands(artifactsCmd, c) + return artifactsCmd } diff --git a/go/cmd/artifacts/extra/create.go b/go/cmd/artifacts/extra/create.go new file mode 100644 index 0000000..a261fc6 --- /dev/null +++ b/go/cmd/artifacts/extra/create.go @@ -0,0 +1,45 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create or replace an artifact with the JSON payload as its content", + Long: `Create or replace an artifact with the JSON payload as its content`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + artifactId := common.String(cmd, "artifact-id") + var req interface{} + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.Workflows.CreateArtifact(ctx, org, workflowId, workflowGroup, artifactId, req) + if err != nil { + return err + } + common.Done(cmd, response, "Artifact created successfully.") + return nil + }, + } + cmd.Flags().String("artifact-id", "", "The artifact ID (path).") + _ = cmd.MarkFlagRequired("artifact-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/artifacts/extra/delete.go b/go/cmd/artifacts/extra/delete.go new file mode 100644 index 0000000..4344431 --- /dev/null +++ b/go/cmd/artifacts/extra/delete.go @@ -0,0 +1,36 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete an artifact", + Long: `Delete an artifact`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + artifactId := common.String(cmd, "artifact-id") + response, err := c.Workflows.DeleteArtifact(ctx, org, workflowId, workflowGroup, artifactId) + if err != nil { + return err + } + common.Done(cmd, response, "Artifact deleted successfully.") + return nil + }, + } + cmd.Flags().String("artifact-id", "", "The artifact ID (path).") + _ = cmd.MarkFlagRequired("artifact-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/artifacts/extra/extra.go b/go/cmd/artifacts/extra/extra.go new file mode 100644 index 0000000..19e0a56 --- /dev/null +++ b/go/cmd/artifacts/extra/extra.go @@ -0,0 +1,22 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +// AddCommands attaches the generated sub-commands to an existing command group. +func AddCommands(cmd *cobra.Command, c *client.Client) { + cmd.AddCommand( + newGetUrlCmd(c), + newReadCmd(c), + newCreateCmd(c), + newDeleteCmd(c), + newVersionsCmd(c), + newRollbackCmd(c), + newLockCmd(c), + newUnlockCmd(c), + ) +} diff --git a/go/cmd/artifacts/extra/get_url.go b/go/cmd/artifacts/extra/get_url.go new file mode 100644 index 0000000..672eb17 --- /dev/null +++ b/go/cmd/artifacts/extra/get_url.go @@ -0,0 +1,37 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflows" + "github.com/spf13/cobra" +) + +func newGetUrlCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "get-url", + Short: "Get a signed download URL for an artifact", + Long: `Get a signed download URL for an artifact`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + artifactPath := common.String(cmd, "artifact-path") + response, err := c.Workflows.GetWorkflowArtifactUrl(ctx, org, workflowId, workflowGroup, &workflows.GetWorkflowArtifactRequest{ArtifactPath: artifactPath, VersionId: common.OptString(cmd, "version-id")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("artifact-path", "", "Path of the artifact.") + _ = cmd.MarkFlagRequired("artifact-path") + cmd.Flags().String("version-id", "", "Specific version of the artifact.") + return cmd +} diff --git a/go/cmd/artifacts/extra/lock.go b/go/cmd/artifacts/extra/lock.go new file mode 100644 index 0000000..73c862e --- /dev/null +++ b/go/cmd/artifacts/extra/lock.go @@ -0,0 +1,36 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newLockCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "lock", + Short: "Lock the workflow on an artifact", + Long: `Lock the workflow on an artifact`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + artifactId := common.String(cmd, "artifact-id") + response, err := c.Workflows.LockArtifact(ctx, org, workflowId, workflowGroup, artifactId) + if err != nil { + return err + } + common.Done(cmd, response, "Artifact locked.") + return nil + }, + } + cmd.Flags().String("artifact-id", "", "The artifact ID (path).") + _ = cmd.MarkFlagRequired("artifact-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/artifacts/extra/read.go b/go/cmd/artifacts/extra/read.go new file mode 100644 index 0000000..12e26d8 --- /dev/null +++ b/go/cmd/artifacts/extra/read.go @@ -0,0 +1,35 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Read an artifact's content (or a signed URL on private runners)", + Long: `Read an artifact's content (or a signed URL on private runners)`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + artifactId := common.String(cmd, "artifact-id") + response, err := c.Workflows.ReadArtifact(ctx, org, workflowId, workflowGroup, artifactId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("artifact-id", "", "The artifact ID (path).") + _ = cmd.MarkFlagRequired("artifact-id") + return cmd +} diff --git a/go/cmd/artifacts/extra/rollback.go b/go/cmd/artifacts/extra/rollback.go new file mode 100644 index 0000000..0f2e18a --- /dev/null +++ b/go/cmd/artifacts/extra/rollback.go @@ -0,0 +1,40 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflows" + "github.com/spf13/cobra" +) + +func newRollbackCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "rollback", + Short: "Roll an artifact back to a previous version", + Long: `Roll an artifact back to a previous version`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + artifactId := common.String(cmd, "artifact-id") + versionId := common.String(cmd, "version-id") + response, err := c.Workflows.RollbackArtifactVersion(ctx, org, workflowId, workflowGroup, artifactId, &workflows.RollbackArtifactVersionRequest{VersionId: versionId}) + if err != nil { + return err + } + common.Done(cmd, response, "Artifact rolled back.") + return nil + }, + } + cmd.Flags().String("artifact-id", "", "The artifact ID (path).") + _ = cmd.MarkFlagRequired("artifact-id") + cmd.Flags().String("version-id", "", "Version to roll back to.") + _ = cmd.MarkFlagRequired("version-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/artifacts/extra/unlock.go b/go/cmd/artifacts/extra/unlock.go new file mode 100644 index 0000000..8c9dd2c --- /dev/null +++ b/go/cmd/artifacts/extra/unlock.go @@ -0,0 +1,36 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newUnlockCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "unlock", + Short: "Release the workflow's lock on an artifact", + Long: `Release the workflow's lock on an artifact`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + artifactId := common.String(cmd, "artifact-id") + response, err := c.Workflows.UnlockArtifact(ctx, org, workflowId, workflowGroup, artifactId) + if err != nil { + return err + } + common.Done(cmd, response, "Artifact unlocked.") + return nil + }, + } + cmd.Flags().String("artifact-id", "", "The artifact ID (path).") + _ = cmd.MarkFlagRequired("artifact-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/artifacts/extra/versions.go b/go/cmd/artifacts/extra/versions.go new file mode 100644 index 0000000..5c337d7 --- /dev/null +++ b/go/cmd/artifacts/extra/versions.go @@ -0,0 +1,38 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflows" + "github.com/spf13/cobra" +) + +func newVersionsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "versions", + Short: "List the versions of an artifact", + Long: `List the versions of an artifact`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + artifactId := common.String(cmd, "artifact-id") + response, err := c.Workflows.ListArtifactVersions(ctx, org, workflowId, workflowGroup, artifactId, &workflows.ListArtifactVersionsRequest{Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), Limit: common.OptInt(cmd, "limit")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("artifact-id", "", "The artifact ID (path).") + _ = cmd.MarkFlagRequired("artifact-id") + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + return cmd +} diff --git a/go/cmd/artifacts/list/artifacts_list.go b/go/cmd/artifacts/list/artifacts_list.go index d8d4016..4c74a3b 100644 --- a/go/cmd/artifacts/list/artifacts_list.go +++ b/go/cmd/artifacts/list/artifacts_list.go @@ -2,6 +2,7 @@ package list import ( "context" + "github.com/StackGuardian/sg-cli/cmd/common" "os" "strings" @@ -38,10 +39,10 @@ func NewListCmd(c *client.Client) *cobra.Command { } if opts.OutputJson { - cmd.Println(response) + common.PrintJSON(cmd, response) } - cmd.Println(response) + common.PrintJSON(cmd, response) }, } listCmd.Flags().BoolVar(&opts.OutputJson, "output-json", false, "Output execution response as json to STDIN.") diff --git a/go/cmd/auditlog/auditlog.go b/go/cmd/auditlog/auditlog.go new file mode 100644 index 0000000..41e098b --- /dev/null +++ b/go/cmd/auditlog/auditlog.go @@ -0,0 +1,26 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package auditlog + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewAuditLogCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "audit-log", + Short: "Read organization audit logs", + Long: `Read organization audit logs`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + list List audit log entries`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newListCmd(c), + ) + return cmd +} diff --git a/go/cmd/auditlog/list.go b/go/cmd/auditlog/list.go new file mode 100644 index 0000000..28b2f88 --- /dev/null +++ b/go/cmd/auditlog/list.go @@ -0,0 +1,40 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package auditlog + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List audit log entries", + Long: `List audit log entries`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.AccessManagement.ReadAuditLogs(ctx, org, &sggosdk.ReadAuditLogsRequest{Effect: common.OptString(cmd, "effect"), EndTime: common.OptInt(cmd, "end-time"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), Limit: common.OptInt(cmd, "limit"), PrincipalEmail: common.OptString(cmd, "principal-email"), RequestMethod: common.OptString(cmd, "request-method"), Resource: common.OptString(cmd, "resource"), SourceIp: common.OptString(cmd, "source-ip"), StartTime: common.OptInt(cmd, "start-time")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + cmd.Flags().String("effect", "", "Filter by effect (Allow, Deny).") + cmd.Flags().Int("start-time", 0, "Start time as a Unix timestamp in milliseconds.") + cmd.Flags().Int("end-time", 0, "End time as a Unix timestamp in milliseconds.") + cmd.Flags().String("principal-email", "", "Filter by principal email.") + cmd.Flags().String("request-method", "", "Filter by HTTP method.") + cmd.Flags().String("resource", "", "Filter by resource name.") + cmd.Flags().String("source-ip", "", "Filter by source IP address.") + return cmd +} diff --git a/go/cmd/benchmarkreport/benchmarkreport.go b/go/cmd/benchmarkreport/benchmarkreport.go new file mode 100644 index 0000000..4a28e3a --- /dev/null +++ b/go/cmd/benchmarkreport/benchmarkreport.go @@ -0,0 +1,26 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package benchmarkreport + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewBenchmarkReportCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "benchmark-report", + Short: "Read compliance benchmark reports", + Long: `Read compliance benchmark reports`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + read Get the benchmark report`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newReadCmd(c), + ) + return cmd +} diff --git a/go/cmd/benchmarkreport/read.go b/go/cmd/benchmarkreport/read.go new file mode 100644 index 0000000..56515a1 --- /dev/null +++ b/go/cmd/benchmarkreport/read.go @@ -0,0 +1,45 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package benchmarkreport + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get the benchmark report", + Long: `Get the benchmark report`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.BenchmarkReports.GetBenchmarkReports(ctx, org, &sggosdk.GetBenchmarkReportsRequest{Date: common.OptString(cmd, "date"), Detailed: common.OptBool(cmd, "detailed"), FilterCsp: common.OptString(cmd, "filter-csp"), FilterAccountId: common.OptString(cmd, "filter-account-id"), FilterBenchmark: common.OptString(cmd, "filter-benchmark"), FilterControlId: common.OptString(cmd, "filter-control-id"), FilterControlTitle: common.OptString(cmd, "filter-control-title"), FilterRegion: common.OptString(cmd, "filter-region"), FilterSeverity: common.OptString(cmd, "filter-severity"), FilterStatus: common.OptString(cmd, "filter-status"), GroupBy: common.OptString(cmd, "group-by"), Limit: common.OptInt(cmd, "limit"), Page: common.OptInt(cmd, "page"), RequiredColumns: common.OptString(cmd, "required-columns")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("date", "", "Report date in DD_MM_YYYY format (defaults to today).") + cmd.Flags().Bool("detailed", false, "Return detailed results instead of grouped data.") + cmd.Flags().String("filter-csp", "", "Filter by cloud provider (AWS, AZURE, GCP).") + cmd.Flags().String("filter-account-id", "", "Filter by account id.") + cmd.Flags().String("filter-benchmark", "", "Filter by benchmark, e.g. cis_v200.") + cmd.Flags().String("filter-control-id", "", "Filter by control id.") + cmd.Flags().String("filter-control-title", "", "Filter by control title.") + cmd.Flags().String("filter-region", "", "Filter by region.") + cmd.Flags().String("filter-severity", "", "Filter by severity.") + cmd.Flags().String("filter-status", "", "Filter by status (fails, passes, info, skips, error).") + cmd.Flags().String("group-by", "", "Column(s) to group by (required when not --detailed).") + cmd.Flags().Int("limit", 0, "Maximum number of records.") + cmd.Flags().Int("page", 0, "Page number (requires --limit).") + cmd.Flags().String("required-columns", "", "Columns to include in a detailed report (comma-separated).") + return cmd +} diff --git a/go/cmd/billing/balance.go b/go/cmd/billing/balance.go new file mode 100644 index 0000000..431dce4 --- /dev/null +++ b/go/cmd/billing/balance.go @@ -0,0 +1,30 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package billing + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newBalanceCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "balance", + Short: "Show the credit balances", + Long: `Show the credit balances`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.Billing.ListBalance(ctx, org) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + return cmd +} diff --git a/go/cmd/billing/billing.go b/go/cmd/billing/billing.go new file mode 100644 index 0000000..beec92f --- /dev/null +++ b/go/cmd/billing/billing.go @@ -0,0 +1,76 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package billing + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewBillingCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "billing", + Short: "Inspect and manage the organization's billing", + Long: `Inspect and manage the organization's billing`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + balance Show the credit balances + dashboard-url Get the URL of the embeddable billing dashboard + invoices List invoices + details Show the current package and billing information + change-plan Move the organization to another billing package + profile Manage the Stripe billing profile + payment-methods Manage the cards on the billing profile`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newBalanceCmd(c), + newDashboardUrlCmd(c), + newInvoicesCmd(c), + newDetailsCmd(c), + newChangePlanCmd(c), + newProfileCmd(c), + newPaymentMethodsCmd(c), + ) + return cmd +} +func newProfileCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "profile", + Short: "Manage the Stripe billing profile", + Long: `Manage the Stripe billing profile`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + setup Create the billing profile (once per organization) + update Update the billing profile's email, name or address`) + }, + } + cmd.AddCommand( + newProfileSetupCmd(c), + newProfileUpdateCmd(c), + ) + return cmd +} +func newPaymentMethodsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "payment-methods", + Short: "Manage the cards on the billing profile", + Long: `Manage the cards on the billing profile`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + list List payment methods + setup-intent Create a Stripe SetupIntent for adding a card + set-default Make a card the default payment method + detach Remove a card`) + }, + } + cmd.AddCommand( + newPaymentMethodsListCmd(c), + newPaymentMethodsSetupIntentCmd(c), + newPaymentMethodsSetDefaultCmd(c), + newPaymentMethodsDetachCmd(c), + ) + return cmd +} diff --git a/go/cmd/billing/change_plan.go b/go/cmd/billing/change_plan.go new file mode 100644 index 0000000..e45a394 --- /dev/null +++ b/go/cmd/billing/change_plan.go @@ -0,0 +1,36 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package billing + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/billing" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newChangePlanCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "change-plan", + Short: "Move the organization to another billing package", + Long: `Move the organization to another billing package`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.Billing.ChangePlan(ctx, org, &billing.ChangePlanRequest{TargetPackageId: common.OptString(cmd, "target-package-id"), TargetPackage: common.OptString(cmd, "target-package")}) + if err != nil { + return err + } + common.Done(cmd, response, "Plan change submitted.") + return nil + }, + } + cmd.Flags().String("target-package-id", "", "Id of the target package.") + cmd.Flags().String("target-package", "", "Name of the target package, e.g. \"SG | Standard\".") + common.AddOutputJSONFlag(cmd) + cmd.MarkFlagsOneRequired("target-package-id", "target-package") + cmd.MarkFlagsMutuallyExclusive("target-package-id", "target-package") + return cmd +} diff --git a/go/cmd/billing/dashboard_url.go b/go/cmd/billing/dashboard_url.go new file mode 100644 index 0000000..5fbba49 --- /dev/null +++ b/go/cmd/billing/dashboard_url.go @@ -0,0 +1,32 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package billing + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/billing" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDashboardUrlCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "dashboard-url", + Short: "Get the URL of the embeddable billing dashboard", + Long: `Get the URL of the embeddable billing dashboard`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.Billing.GetDashboardUrl(ctx, org, &billing.DashboardRequest{Type: common.OptString(cmd, "type")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("type", "", "Dashboard type (invoices, usage).") + return cmd +} diff --git a/go/cmd/billing/details.go b/go/cmd/billing/details.go new file mode 100644 index 0000000..44e2c24 --- /dev/null +++ b/go/cmd/billing/details.go @@ -0,0 +1,30 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package billing + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDetailsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "details", + Short: "Show the current package and billing information", + Long: `Show the current package and billing information`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.Billing.GetBillingDetails(ctx, org) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + return cmd +} diff --git a/go/cmd/billing/invoices.go b/go/cmd/billing/invoices.go new file mode 100644 index 0000000..c653dad --- /dev/null +++ b/go/cmd/billing/invoices.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package billing + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/billing" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newInvoicesCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "invoices", + Short: "List invoices", + Long: `List invoices`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.Billing.ListInvoices(ctx, org, &billing.ListInvoicesRequest{Limit: common.OptInt(cmd, "limit"), NextPage: common.OptString(cmd, "next-page")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().Int("limit", 0, "Page size (1-100).") + cmd.Flags().String("next-page", "", "Cursor from the previous response.") + return cmd +} diff --git a/go/cmd/billing/payment_methods_detach.go b/go/cmd/billing/payment_methods_detach.go new file mode 100644 index 0000000..374ad3d --- /dev/null +++ b/go/cmd/billing/payment_methods_detach.go @@ -0,0 +1,35 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package billing + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/billing" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newPaymentMethodsDetachCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "detach", + Short: "Remove a card", + Long: `Remove a card`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + paymentMethodId := common.String(cmd, "payment-method-id") + response, err := c.Billing.DetachCard(ctx, org, &billing.PaymentMethodRequest{PaymentMethodId: paymentMethodId}) + if err != nil { + return err + } + common.Done(cmd, response, "Card detached.") + return nil + }, + } + cmd.Flags().String("payment-method-id", "", "Stripe payment method id.") + _ = cmd.MarkFlagRequired("payment-method-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/billing/payment_methods_list.go b/go/cmd/billing/payment_methods_list.go new file mode 100644 index 0000000..77fb25a --- /dev/null +++ b/go/cmd/billing/payment_methods_list.go @@ -0,0 +1,30 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package billing + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newPaymentMethodsListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List payment methods", + Long: `List payment methods`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.Billing.ListPaymentMethods(ctx, org) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + return cmd +} diff --git a/go/cmd/billing/payment_methods_set_default.go b/go/cmd/billing/payment_methods_set_default.go new file mode 100644 index 0000000..3e7fdde --- /dev/null +++ b/go/cmd/billing/payment_methods_set_default.go @@ -0,0 +1,35 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package billing + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/billing" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newPaymentMethodsSetDefaultCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "set-default", + Short: "Make a card the default payment method", + Long: `Make a card the default payment method`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + paymentMethodId := common.String(cmd, "payment-method-id") + response, err := c.Billing.SetDefaultPaymentMethod(ctx, org, &billing.PaymentMethodRequest{PaymentMethodId: paymentMethodId}) + if err != nil { + return err + } + common.Done(cmd, response, "Default payment method set.") + return nil + }, + } + cmd.Flags().String("payment-method-id", "", "Stripe payment method id.") + _ = cmd.MarkFlagRequired("payment-method-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/billing/payment_methods_setup_intent.go b/go/cmd/billing/payment_methods_setup_intent.go new file mode 100644 index 0000000..8cc52a6 --- /dev/null +++ b/go/cmd/billing/payment_methods_setup_intent.go @@ -0,0 +1,30 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package billing + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newPaymentMethodsSetupIntentCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "setup-intent", + Short: "Create a Stripe SetupIntent for adding a card", + Long: `Create a Stripe SetupIntent for adding a card`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.Billing.CreatePaymentSetupIntent(ctx, org) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + return cmd +} diff --git a/go/cmd/billing/profile_setup.go b/go/cmd/billing/profile_setup.go new file mode 100644 index 0000000..9bbbff3 --- /dev/null +++ b/go/cmd/billing/profile_setup.go @@ -0,0 +1,43 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package billing + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/billing" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newProfileSetupCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "setup -- payload.json", + Short: "Create the billing profile (once per organization)", + Long: `Create the billing profile (once per organization)`, + Args: cobra.MaximumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req billing.BillingProfileRequest + if len(args) > 0 { + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + } + response, err := c.Billing.SetupBillingProfile(ctx, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Billing profile created.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/billing/profile_update.go b/go/cmd/billing/profile_update.go new file mode 100644 index 0000000..c15a1ac --- /dev/null +++ b/go/cmd/billing/profile_update.go @@ -0,0 +1,41 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package billing + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/billing" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newProfileUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update the billing profile's email, name or address", + Long: `Update the billing profile's email, name or address`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req billing.BillingProfileRequest + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.Billing.UpdateBillingProfile(ctx, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Billing profile updated.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/chat/artifacts_get_url.go b/go/cmd/chat/artifacts_get_url.go new file mode 100644 index 0000000..73517d1 --- /dev/null +++ b/go/cmd/chat/artifacts_get_url.go @@ -0,0 +1,35 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package chat + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/chats" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newArtifactsGetUrlCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "get-url", + Short: "Get a presigned download URL for an artifact", + Long: `Get a presigned download URL for an artifact`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + chatId := common.String(cmd, "chat-id") + artifactPath := common.String(cmd, "artifact-path") + response, err := c.Chats.GetChatArtifact(ctx, org, chatId, &chats.GetChatArtifactRequest{ArtifactPath: artifactPath}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("artifact-path", "", "Artifact path relative to the chat's artifact store.") + _ = cmd.MarkFlagRequired("artifact-path") + return cmd +} diff --git a/go/cmd/chat/artifacts_list.go b/go/cmd/chat/artifacts_list.go new file mode 100644 index 0000000..3f0b607 --- /dev/null +++ b/go/cmd/chat/artifacts_list.go @@ -0,0 +1,35 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package chat + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/chats" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newArtifactsListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "Get a presigned URL that lists the artifacts", + Long: `Get a presigned URL that lists the artifacts`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + chatId := common.String(cmd, "chat-id") + response, err := c.Chats.ListAllChatArtifacts(ctx, org, chatId, &chats.ListAllChatArtifactsRequest{Prefix: common.OptString(cmd, "prefix"), MaxKeys: common.OptInt(cmd, "max-keys"), StartAfterKey: common.OptString(cmd, "start-after-key")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("prefix", "", "Only list artifacts under this prefix.") + cmd.Flags().Int("max-keys", 0, "Maximum number of keys.") + cmd.Flags().String("start-after-key", "", "Full S3 key to start after.") + return cmd +} diff --git a/go/cmd/chat/artifacts_upload_url.go b/go/cmd/chat/artifacts_upload_url.go new file mode 100644 index 0000000..854a135 --- /dev/null +++ b/go/cmd/chat/artifacts_upload_url.go @@ -0,0 +1,36 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package chat + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/chats" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newArtifactsUploadUrlCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "upload-url", + Short: "Get a presigned upload URL for an artifact", + Long: `Get a presigned upload URL for an artifact`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + chatId := common.String(cmd, "chat-id") + artifactPath := common.String(cmd, "artifact-path") + response, err := c.Chats.SaveChatArtifact(ctx, org, chatId, &chats.SaveChatArtifactRequest{ArtifactPath: artifactPath, ContentType: common.OptString(cmd, "content-type")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("artifact-path", "", "Artifact path relative to the chat's artifact store.") + _ = cmd.MarkFlagRequired("artifact-path") + cmd.Flags().String("content-type", "", "Content type the upload must use (default application/octet-stream).") + return cmd +} diff --git a/go/cmd/chat/chat.go b/go/cmd/chat/chat.go new file mode 100644 index 0000000..7d4d51a --- /dev/null +++ b/go/cmd/chat/chat.go @@ -0,0 +1,92 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package chat + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewChatCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "chat", + Short: "Manage AI assistant chats (infra2code and kyro) and their messages", + Long: `Manage AI assistant chats (infra2code and kyro) and their messages`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + create Create a chat + list List chats + read Get a chat + update Update a chat + delete Archive a chat + commit-bundle Commit an uploaded git bundle + create-pr Push the generated code and open a pull request + pr-status Show the status of the chat's pull request + pr-sync-status Compare the local bundle with the pull request + artifacts Work with a chat's artifacts through presigned URLs + messages Send and read the messages of a kyro chat`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newCreateCmd(c), + newListCmd(c), + newReadCmd(c), + newUpdateCmd(c), + newDeleteCmd(c), + newCommitBundleCmd(c), + newCreatePrCmd(c), + newPrStatusCmd(c), + newPrSyncStatusCmd(c), + newArtifactsCmd(c), + newMessagesCmd(c), + ) + return cmd +} +func newArtifactsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "artifacts", + Short: "Work with a chat's artifacts through presigned URLs", + Long: `Work with a chat's artifacts through presigned URLs`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + list Get a presigned URL that lists the artifacts + get-url Get a presigned download URL for an artifact + upload-url Get a presigned upload URL for an artifact`) + }, + } + cmd.PersistentFlags().String("chat-id", "", "The chat ID.") + _ = cmd.MarkPersistentFlagRequired("chat-id") + cmd.AddCommand( + newArtifactsListCmd(c), + newArtifactsGetUrlCmd(c), + newArtifactsUploadUrlCmd(c), + ) + return cmd +} +func newMessagesCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "messages", + Short: "Send and read the messages of a kyro chat", + Long: `Send and read the messages of a kyro chat`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + create Send a message (use --text or a payload) + list List the messages of a chat, oldest first + read Get a message + cancel Stop a pending or streaming assistant message + retry Retry an errored or stopped assistant message`) + }, + } + cmd.PersistentFlags().String("chat-id", "", "The chat ID.") + _ = cmd.MarkPersistentFlagRequired("chat-id") + cmd.AddCommand( + newMessagesCreateCmd(c), + newMessagesListCmd(c), + newMessagesReadCmd(c), + newMessagesCancelCmd(c), + newMessagesRetryCmd(c), + ) + return cmd +} diff --git a/go/cmd/chat/commit_bundle.go b/go/cmd/chat/commit_bundle.go new file mode 100644 index 0000000..3568a87 --- /dev/null +++ b/go/cmd/chat/commit_bundle.go @@ -0,0 +1,38 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package chat + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/chats" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCommitBundleCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "commit-bundle", + Short: "Commit an uploaded git bundle", + Long: `Commit an uploaded git bundle`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + chatId := common.String(cmd, "chat-id") + expectedVersion, _ := cmd.Flags().GetInt("expected-version") + response, err := c.Chats.CommitChatBundle(ctx, org, chatId, &chats.CommitChatBundleRequest{ExpectedVersion: expectedVersion}) + if err != nil { + return err + } + common.Done(cmd, response, "Bundle committed.") + return nil + }, + } + cmd.Flags().String("chat-id", "", "The chat ID.") + _ = cmd.MarkFlagRequired("chat-id") + cmd.Flags().Int("expected-version", 0, "The BundleVersion last seen by the caller.") + _ = cmd.MarkFlagRequired("expected-version") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/chat/create.go b/go/cmd/chat/create.go new file mode 100644 index 0000000..ef91784 --- /dev/null +++ b/go/cmd/chat/create.go @@ -0,0 +1,41 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package chat + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/chats" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create a chat", + Long: `Create a chat`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req chats.Chat + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.Chats.CreateChat(ctx, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Chat created successfully.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/chat/create_pr.go b/go/cmd/chat/create_pr.go new file mode 100644 index 0000000..b4c3f7d --- /dev/null +++ b/go/cmd/chat/create_pr.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package chat + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/chats" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCreatePrCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create-pr -- payload.json", + Short: "Push the generated code and open a pull request", + Long: `Push the generated code and open a pull request`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + chatId := common.String(cmd, "chat-id") + var req chats.CreateChatPrRequest + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.Chats.CreateChatPr(ctx, org, chatId, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Pull request request completed.") + return nil + }, + } + cmd.Flags().String("chat-id", "", "The chat ID.") + _ = cmd.MarkFlagRequired("chat-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/chat/delete.go b/go/cmd/chat/delete.go new file mode 100644 index 0000000..c7982a7 --- /dev/null +++ b/go/cmd/chat/delete.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package chat + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Archive a chat", + Long: `Archive a chat`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + chatId := common.String(cmd, "chat-id") + response, err := c.Chats.DeleteChat(ctx, org, chatId) + if err != nil { + return err + } + common.Done(cmd, response, "Chat archived successfully.") + return nil + }, + } + cmd.Flags().String("chat-id", "", "The chat ID.") + _ = cmd.MarkFlagRequired("chat-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/chat/list.go b/go/cmd/chat/list.go new file mode 100644 index 0000000..74f2834 --- /dev/null +++ b/go/cmd/chat/list.go @@ -0,0 +1,36 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package chat + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/chats" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List chats", + Long: `List chats`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.Chats.ListAllChats(ctx, org, &chats.ListAllChatsRequest{Limit: common.OptInt(cmd, "limit"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), SearchQuery: common.OptString(cmd, "search-query"), RefreshPrStatus: common.OptBool(cmd, "refresh-pr-status"), ChatType: common.OptString(cmd, "chat-type")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + cmd.Flags().String("search-query", "", "Comma-separated terms matched against name, description and tags.") + cmd.Flags().Bool("refresh-pr-status", false, "Refresh pull request statuses from the VCS provider.") + cmd.Flags().String("chat-type", "", "Filter by chat type (infra2code, kyro).") + return cmd +} diff --git a/go/cmd/chat/messages_cancel.go b/go/cmd/chat/messages_cancel.go new file mode 100644 index 0000000..fb94ba9 --- /dev/null +++ b/go/cmd/chat/messages_cancel.go @@ -0,0 +1,35 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package chat + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newMessagesCancelCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "cancel", + Short: "Stop a pending or streaming assistant message", + Long: `Stop a pending or streaming assistant message`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + chatId := common.String(cmd, "chat-id") + messageId := common.String(cmd, "message-id") + response, err := c.Chats.CancelMessage(ctx, org, chatId, messageId) + if err != nil { + return err + } + common.Done(cmd, response, "Message cancelled.") + return nil + }, + } + cmd.Flags().String("message-id", "", "The message ID.") + _ = cmd.MarkFlagRequired("message-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/chat/messages_create.go b/go/cmd/chat/messages_create.go new file mode 100644 index 0000000..b4ef1f9 --- /dev/null +++ b/go/cmd/chat/messages_create.go @@ -0,0 +1,56 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package chat + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/chats" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newMessagesCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Send a message (use --text or a payload)", + Long: `Send a message (use --text or a payload)`, + Args: cobra.MaximumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + chatId := common.String(cmd, "chat-id") + text := common.String(cmd, "text") + var req chats.Message + if len(args) > 0 { + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + } + if text != "" { + req.Content = []*chats.ContentBlock{{Type: "text", Text: &text}} + } + if v := common.OptString(cmd, "client-request-id"); v != nil { + req.ClientRequestId = v + } + if len(req.Content) == 0 { + return errors.New("provide --text or a payload with content blocks") + } + response, err := c.Chats.CreateMessage(ctx, org, chatId, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Message sent.") + return nil + }, + } + cmd.Flags().String("text", "", "Text of the message (shortcut for a single text content block).") + cmd.Flags().String("client-request-id", "", "Idempotency key.") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/chat/messages_list.go b/go/cmd/chat/messages_list.go new file mode 100644 index 0000000..e54a4de --- /dev/null +++ b/go/cmd/chat/messages_list.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package chat + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/chats" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newMessagesListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List the messages of a chat, oldest first", + Long: `List the messages of a chat, oldest first`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + chatId := common.String(cmd, "chat-id") + response, err := c.Chats.ListAllMessages(ctx, org, chatId, &chats.ListAllMessagesRequest{Limit: common.OptInt(cmd, "limit"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + return cmd +} diff --git a/go/cmd/chat/messages_read.go b/go/cmd/chat/messages_read.go new file mode 100644 index 0000000..0808d21 --- /dev/null +++ b/go/cmd/chat/messages_read.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package chat + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newMessagesReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get a message", + Long: `Get a message`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + chatId := common.String(cmd, "chat-id") + messageId := common.String(cmd, "message-id") + response, err := c.Chats.ReadMessage(ctx, org, chatId, messageId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("message-id", "", "The message ID.") + _ = cmd.MarkFlagRequired("message-id") + return cmd +} diff --git a/go/cmd/chat/messages_retry.go b/go/cmd/chat/messages_retry.go new file mode 100644 index 0000000..4240e83 --- /dev/null +++ b/go/cmd/chat/messages_retry.go @@ -0,0 +1,35 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package chat + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newMessagesRetryCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "retry", + Short: "Retry an errored or stopped assistant message", + Long: `Retry an errored or stopped assistant message`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + chatId := common.String(cmd, "chat-id") + messageId := common.String(cmd, "message-id") + response, err := c.Chats.RetryMessage(ctx, org, chatId, messageId) + if err != nil { + return err + } + common.Done(cmd, response, "Message retried.") + return nil + }, + } + cmd.Flags().String("message-id", "", "The message ID.") + _ = cmd.MarkFlagRequired("message-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/chat/pr_status.go b/go/cmd/chat/pr_status.go new file mode 100644 index 0000000..b8338de --- /dev/null +++ b/go/cmd/chat/pr_status.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package chat + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newPrStatusCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "pr-status", + Short: "Show the status of the chat's pull request", + Long: `Show the status of the chat's pull request`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + chatId := common.String(cmd, "chat-id") + response, err := c.Chats.GetChatPrStatus(ctx, org, chatId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("chat-id", "", "The chat ID.") + _ = cmd.MarkFlagRequired("chat-id") + return cmd +} diff --git a/go/cmd/chat/pr_sync_status.go b/go/cmd/chat/pr_sync_status.go new file mode 100644 index 0000000..052e247 --- /dev/null +++ b/go/cmd/chat/pr_sync_status.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package chat + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newPrSyncStatusCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "pr-sync-status", + Short: "Compare the local bundle with the pull request", + Long: `Compare the local bundle with the pull request`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + chatId := common.String(cmd, "chat-id") + response, err := c.Chats.GetChatPrSyncStatus(ctx, org, chatId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("chat-id", "", "The chat ID.") + _ = cmd.MarkFlagRequired("chat-id") + return cmd +} diff --git a/go/cmd/chat/read.go b/go/cmd/chat/read.go new file mode 100644 index 0000000..477c741 --- /dev/null +++ b/go/cmd/chat/read.go @@ -0,0 +1,35 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package chat + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/chats" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get a chat", + Long: `Get a chat`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + chatId := common.String(cmd, "chat-id") + response, err := c.Chats.ReadChat(ctx, org, chatId, &chats.ReadChatRequest{RefreshPrStatus: common.OptBool(cmd, "refresh-pr-status")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("chat-id", "", "The chat ID.") + _ = cmd.MarkFlagRequired("chat-id") + cmd.Flags().Bool("refresh-pr-status", false, "Refresh the pull request status from the VCS provider.") + return cmd +} diff --git a/go/cmd/chat/update.go b/go/cmd/chat/update.go new file mode 100644 index 0000000..89cc8ae --- /dev/null +++ b/go/cmd/chat/update.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package chat + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/chats" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a chat", + Long: `Update a chat`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + chatId := common.String(cmd, "chat-id") + var req chats.PatchedChat + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.Chats.UpdateChat(ctx, org, chatId, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Chat updated successfully.") + return nil + }, + } + cmd.Flags().String("chat-id", "", "The chat ID.") + _ = cmd.MarkFlagRequired("chat-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/common/common.go b/go/cmd/common/common.go new file mode 100644 index 0000000..27f29b9 --- /dev/null +++ b/go/cmd/common/common.go @@ -0,0 +1,232 @@ +// Package common holds the helpers shared by every sg-cli command: client +// construction, JSON output, flag access and payload handling. +package common + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "os" + "strings" + "sync" + + "github.com/StackGuardian/sg-cli/utilities" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/option" + "github.com/spf13/cobra" +) + +const ( + DefaultBaseURL = "https://api.app.stackguardian.io" + DashboardURL = "https://app.stackguardian.io/orchestrator" +) + +// capture records the most recent response body so commands can print the +// API's JSON verbatim: re-encoding the SDK's typed structs would drop any +// field the SDK does not declare. +type capture struct { + next http.RoundTripper + mu sync.Mutex + body []byte +} + +func (c *capture) RoundTrip(req *http.Request) (*http.Response, error) { + resp, err := c.next.RoundTrip(req) + if err != nil { + return nil, err + } + body, err := io.ReadAll(resp.Body) + resp.Body.Close() + if err != nil { + return nil, err + } + resp.Body = io.NopCloser(bytes.NewReader(body)) + c.mu.Lock() + c.body = body + c.mu.Unlock() + return resp, nil +} + +var lastResponse = &capture{next: http.DefaultTransport} + +// NewClient builds the SDK client from SG_API_TOKEN and SG_BASE_URL with the +// response capture installed. Both sgu_ (personal) and sgo_ (org) tokens work. +func NewClient() *client.Client { + apiKey := strings.TrimSpace(os.Getenv("SG_API_TOKEN")) + if !strings.HasPrefix(strings.ToLower(apiKey), "apikey ") { + apiKey = "apikey " + apiKey + } + baseURL := os.Getenv("SG_BASE_URL") + if baseURL == "" { + baseURL = DefaultBaseURL + } + return client.NewClient( + option.WithApiKey(apiKey), + option.WithBaseURL(strings.TrimRight(baseURL, "/")), + option.WithHTTPClient(&http.Client{Transport: lastResponse}), + ) +} + +// PrintJSON writes the API response as indented JSON: the captured raw body +// when the client was built by NewClient, otherwise the encoded value. +func PrintJSON(cmd *cobra.Command, response interface{}) { + lastResponse.mu.Lock() + body := lastResponse.body + lastResponse.mu.Unlock() + var out bytes.Buffer + if len(bytes.TrimSpace(body)) > 0 && json.Indent(&out, body, "", " ") == nil { + cmd.Println(out.String()) + return + } + encoded, err := json.MarshalIndent(response, "", " ") + if err != nil { + cmd.Println(response) + return + } + cmd.Println(string(encoded)) +} + +// Org returns the value of the --org flag, searching parent commands. +func Org(cmd *cobra.Command) string { + return String(cmd, "org") +} + +// String returns a string flag defined on cmd or inherited from a parent. +func String(cmd *cobra.Command, name string) string { + if f := cmd.Flag(name); f != nil { + return f.Value.String() + } + return "" +} + +// Bool returns a bool flag defined on cmd or inherited from a parent. +func Bool(cmd *cobra.Command, name string) bool { + if f := cmd.Flag(name); f != nil { + return f.Value.String() == "true" + } + return false +} + +// Optional flag helpers: they return nil when the flag was not set, so a +// default never overrides the API's own default. + +func OptString(cmd *cobra.Command, name string) *string { + if f := cmd.Flags().Lookup(name); f == nil || !f.Changed { + return nil + } + v, _ := cmd.Flags().GetString(name) + return &v +} + +func OptInt(cmd *cobra.Command, name string) *int { + if f := cmd.Flags().Lookup(name); f == nil || !f.Changed { + return nil + } + v, _ := cmd.Flags().GetInt(name) + return &v +} + +func OptBool(cmd *cobra.Command, name string) *bool { + if f := cmd.Flags().Lookup(name); f == nil || !f.Changed { + return nil + } + v, _ := cmd.Flags().GetBool(name) + return &v +} + +func OptStringSlice(cmd *cobra.Command, name string) []string { + if f := cmd.Flags().Lookup(name); f == nil || !f.Changed { + return nil + } + v, _ := cmd.Flags().GetStringSlice(name) + return v +} + +// AddOrgFlag registers the required --org persistent flag on a command group. +func AddOrgFlag(cmd *cobra.Command) { + cmd.PersistentFlags().String("org", "", "The organization name on Stackguardian platform.") + _ = cmd.MarkPersistentFlagRequired("org") +} + +// AddPayloadFlags registers the flags that accompany a JSON payload file. +func AddPayloadFlags(cmd *cobra.Command) { + cmd.Flags().String("patch-payload", "", "Patch original payload.json input. Add or replace values. Requires valid JSON input.") + cmd.Flags().Bool("preview", false, "Preview payload content before sending. Execution will not pause.") + cmd.Flags().Bool("dry-run", false, "Similar to --preview. But execution will stop, nothing will be sent.") +} + +// AddOutputJSONFlag registers --output-json on commands that print a message by default. +func AddOutputJSONFlag(cmd *cobra.Command) { + cmd.Flags().Bool("output-json", false, "Output execution response as json to STDOUT.") +} + +// ErrDryRun is returned by ReadPayload after printing the payload for --dry-run. +var ErrDryRun = errors.New("dry run: nothing was sent") + +// ReadPayload reads the JSON payload file given as the positional argument +// (use "-" for stdin), applies --patch-payload, honours --preview/--dry-run +// and decodes the result into dst. +func ReadPayload(cmd *cobra.Command, args []string, dst interface{}) error { + if len(args) != 1 { + return errors.New("a JSON payload file is required after --") + } + var payload []byte + var err error + if args[0] == "-" { + payload, err = io.ReadAll(cmd.InOrStdin()) + } else { + payload, err = os.ReadFile(args[0]) + } + if err != nil { + return fmt.Errorf("read payload: %w", err) + } + if patch := String(cmd, "patch-payload"); patch != "" { + payload = []byte(utilities.PatchJSON(string(payload), patch)) + } + if Bool(cmd, "preview") || Bool(cmd, "dry-run") { + var pretty bytes.Buffer + if json.Indent(&pretty, payload, "", " ") == nil { + cmd.Println(pretty.String()) + } else { + cmd.Println(string(payload)) + } + if Bool(cmd, "dry-run") { + return ErrDryRun + } + } + if err := json.Unmarshal(payload, dst); err != nil { + return fmt.Errorf("invalid JSON payload: %w", err) + } + return nil +} + +// Done prints the response when --output-json is set, then the message. +func Done(cmd *cobra.Command, response interface{}, message string) { + if Bool(cmd, "output-json") { + PrintJSON(cmd, response) + } + cmd.Println(message) +} + +// Require returns an error naming the first of the given flags that is empty. +func Require(cmd *cobra.Command, names ...string) error { + for _, n := range names { + if String(cmd, n) == "" { + return fmt.Errorf("required flag \"%s\" not set", n) + } + } + return nil +} + +// CheckEnum validates that value is one of allowed. +func CheckEnum(flag, value string, allowed ...string) error { + for _, a := range allowed { + if value == a { + return nil + } + } + return fmt.Errorf("invalid value %q for --%s: must be one of %s", value, flag, strings.Join(allowed, ", ")) +} diff --git a/go/cmd/connector/authenticate.go b/go/cmd/connector/authenticate.go new file mode 100644 index 0000000..b4cca8e --- /dev/null +++ b/go/cmd/connector/authenticate.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connector + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newAuthenticateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "authenticate", + Short: "Verify that a connector can authenticate against its provider", + Long: `Verify that a connector can authenticate against its provider`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + connectorId := common.String(cmd, "connector-id") + response, err := c.Connectors.AuthenticateConnector(ctx, connectorId, org) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("connector-id", "", "The connector ID.") + _ = cmd.MarkFlagRequired("connector-id") + return cmd +} diff --git a/go/cmd/connector/connector.go b/go/cmd/connector/connector.go new file mode 100644 index 0000000..d9ac3ab --- /dev/null +++ b/go/cmd/connector/connector.go @@ -0,0 +1,42 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connector + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewConnectorCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "connector", + Short: "Manage connectors (cloud and VCS integrations)", + Long: `Manage connectors (cloud and VCS integrations)`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + create Create a new connector + read Get details of a connector + update Update a connector + delete Delete a connector + list List connectors + authenticate Verify that a connector can authenticate against its provider + list-accounts List the cloud accounts or subscriptions reachable with a connector's credentials + github-repos List the repositories accessible to a GITHUB_COM connector + repos List the repositories reachable through a VCS connector`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newCreateCmd(c), + newReadCmd(c), + newUpdateCmd(c), + newDeleteCmd(c), + newListCmd(c), + newAuthenticateCmd(c), + newListAccountsCmd(c), + newGithubReposCmd(c), + newReposCmd(c), + ) + return cmd +} diff --git a/go/cmd/connector/create.go b/go/cmd/connector/create.go new file mode 100644 index 0000000..d00ad24 --- /dev/null +++ b/go/cmd/connector/create.go @@ -0,0 +1,41 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connector + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create a new connector", + Long: `Create a new connector`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req sggosdk.Integration + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.Connectors.CreateConnector(ctx, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Connector created successfully.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/connector/delete.go b/go/cmd/connector/delete.go new file mode 100644 index 0000000..99be3e3 --- /dev/null +++ b/go/cmd/connector/delete.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connector + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete a connector", + Long: `Delete a connector`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + connectorId := common.String(cmd, "connector-id") + response, err := c.Connectors.DeleteConnector(ctx, connectorId, org) + if err != nil { + return err + } + common.Done(cmd, response, "Connector deleted successfully.") + return nil + }, + } + cmd.Flags().String("connector-id", "", "The connector ID.") + _ = cmd.MarkFlagRequired("connector-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/connector/github_repos.go b/go/cmd/connector/github_repos.go new file mode 100644 index 0000000..dc3534c --- /dev/null +++ b/go/cmd/connector/github_repos.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connector + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newGithubReposCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "github-repos", + Short: "List the repositories accessible to a GITHUB_COM connector", + Long: `List the repositories accessible to a GITHUB_COM connector`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + connectorId := common.String(cmd, "connector-id") + response, err := c.Connectors.GetGithubComRepos(ctx, connectorId, org) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("connector-id", "", "The connector ID.") + _ = cmd.MarkFlagRequired("connector-id") + return cmd +} diff --git a/go/cmd/connector/list.go b/go/cmd/connector/list.go new file mode 100644 index 0000000..2b93d50 --- /dev/null +++ b/go/cmd/connector/list.go @@ -0,0 +1,35 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connector + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List connectors", + Long: `List connectors`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.Connectors.ListAllConnectors(ctx, org, &sggosdk.ListAllConnectorsRequest{ResourceNames: common.OptString(cmd, "resource-names"), Kind: common.OptString(cmd, "kind"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), Limit: common.OptInt(cmd, "limit")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + cmd.Flags().String("resource-names", "", "Filter by resource name.") + cmd.Flags().String("kind", "", "Filter by kind (comma-separated), e.g. AWS_RBAC,AZURE_OIDC.") + return cmd +} diff --git a/go/cmd/connector/list_accounts.go b/go/cmd/connector/list_accounts.go new file mode 100644 index 0000000..b07f9d5 --- /dev/null +++ b/go/cmd/connector/list_accounts.go @@ -0,0 +1,41 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connector + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/connectors" + "github.com/spf13/cobra" +) + +func newListAccountsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list-accounts -- payload.json", + Short: "List the cloud accounts or subscriptions reachable with a connector's credentials", + Long: `List the cloud accounts or subscriptions reachable with a connector's credentials`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req connectors.ListAccountsRequest + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.Connectors.ListAccounts(ctx, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Accounts listed.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/connector/read.go b/go/cmd/connector/read.go new file mode 100644 index 0000000..80078af --- /dev/null +++ b/go/cmd/connector/read.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connector + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get details of a connector", + Long: `Get details of a connector`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + connectorId := common.String(cmd, "connector-id") + response, err := c.Connectors.ReadConnector(ctx, connectorId, org) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("connector-id", "", "The connector ID.") + _ = cmd.MarkFlagRequired("connector-id") + return cmd +} diff --git a/go/cmd/connector/repos.go b/go/cmd/connector/repos.go new file mode 100644 index 0000000..b69036c --- /dev/null +++ b/go/cmd/connector/repos.go @@ -0,0 +1,39 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connector + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/connectors" + "github.com/spf13/cobra" +) + +func newReposCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "repos", + Short: "List the repositories reachable through a VCS connector", + Long: `List the repositories reachable through a VCS connector`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + connectorId := common.String(cmd, "connector-id") + response, err := c.Connectors.ListRepositories(ctx, connectorId, org, &connectors.ListRepositoriesRequest{Login: common.OptString(cmd, "login"), InstallationId: common.OptString(cmd, "installation-id"), Page: common.OptString(cmd, "page"), Limit: common.OptInt(cmd, "limit"), SearchQuery: common.OptString(cmd, "search-query")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("connector-id", "", "The connector ID.") + _ = cmd.MarkFlagRequired("connector-id") + cmd.Flags().String("login", "", "GitHub account or organization login (GITHUB_COM).") + cmd.Flags().String("installation-id", "", "GitHub App installation id (GITHUB_COM).") + cmd.Flags().String("page", "", "Page number or provider cursor.") + cmd.Flags().Int("limit", 0, "Page size.") + cmd.Flags().String("search-query", "", "Filter by name or namespace.") + return cmd +} diff --git a/go/cmd/connector/update.go b/go/cmd/connector/update.go new file mode 100644 index 0000000..98bc838 --- /dev/null +++ b/go/cmd/connector/update.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connector + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a connector", + Long: `Update a connector`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + connectorId := common.String(cmd, "connector-id") + var req sggosdk.PatchedIntegration + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.Connectors.UpdateConnector(ctx, connectorId, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Connector updated successfully.") + return nil + }, + } + cmd.Flags().String("connector-id", "", "The connector ID.") + _ = cmd.MarkFlagRequired("connector-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/connectorgroup/authenticate.go b/go/cmd/connectorgroup/authenticate.go new file mode 100644 index 0000000..f901902 --- /dev/null +++ b/go/cmd/connectorgroup/authenticate.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connectorgroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newAuthenticateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "authenticate", + Short: "Authenticate a connector group", + Long: `Authenticate a connector group`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + connectorGroup := common.String(cmd, "connector-group") + response, err := c.ConnectorGroups.AuthenticateConnectorGroup(ctx, connectorGroup, org) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("connector-group", "", "The connector group name.") + _ = cmd.MarkFlagRequired("connector-group") + return cmd +} diff --git a/go/cmd/connectorgroup/connectorgroup.go b/go/cmd/connectorgroup/connectorgroup.go new file mode 100644 index 0000000..dea5191 --- /dev/null +++ b/go/cmd/connectorgroup/connectorgroup.go @@ -0,0 +1,65 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connectorgroup + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewConnectorGroupCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "connector-group", + Short: "Manage connector groups (cloud integration groups)", + Long: `Manage connector groups (cloud integration groups)`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + create Create a new connector group + read Get details of a connector group + update Update a connector group + delete Delete a connector group + authenticate Authenticate a connector group + list List connector groups + discovery-scan Trigger discovery scans across the group's child connectors + connectors Manage the connectors inside a connector group`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newCreateCmd(c), + newReadCmd(c), + newUpdateCmd(c), + newDeleteCmd(c), + newAuthenticateCmd(c), + newListCmd(c), + newDiscoveryScanCmd(c), + newConnectorsCmd(c), + ) + return cmd +} +func newConnectorsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "connectors", + Short: "Manage the connectors inside a connector group", + Long: `Manage the connectors inside a connector group`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + read Get a connector in the group + update Update a connector in the group + delete Delete a connector from the group + list List the connectors in the group + authenticate Verify that a connector in the group can authenticate`) + }, + } + cmd.PersistentFlags().String("connector-group", "", "The connector group name.") + _ = cmd.MarkPersistentFlagRequired("connector-group") + cmd.AddCommand( + newConnectorsReadCmd(c), + newConnectorsUpdateCmd(c), + newConnectorsDeleteCmd(c), + newConnectorsListCmd(c), + newConnectorsAuthenticateCmd(c), + ) + return cmd +} diff --git a/go/cmd/connectorgroup/connectors_authenticate.go b/go/cmd/connectorgroup/connectors_authenticate.go new file mode 100644 index 0000000..91be9c4 --- /dev/null +++ b/go/cmd/connectorgroup/connectors_authenticate.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connectorgroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newConnectorsAuthenticateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "authenticate", + Short: "Verify that a connector in the group can authenticate", + Long: `Verify that a connector in the group can authenticate`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + connectorGroup := common.String(cmd, "connector-group") + connectorId := common.String(cmd, "connector-id") + response, err := c.ConnectorGroups.AuthenticateChildInACloudConnectorGroup(ctx, connectorId, connectorGroup, org) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("connector-id", "", "The connector ID.") + _ = cmd.MarkFlagRequired("connector-id") + return cmd +} diff --git a/go/cmd/connectorgroup/connectors_delete.go b/go/cmd/connectorgroup/connectors_delete.go new file mode 100644 index 0000000..577b85a --- /dev/null +++ b/go/cmd/connectorgroup/connectors_delete.go @@ -0,0 +1,35 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connectorgroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newConnectorsDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete a connector from the group", + Long: `Delete a connector from the group`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + connectorGroup := common.String(cmd, "connector-group") + connectorId := common.String(cmd, "connector-id") + response, err := c.ConnectorGroups.DeleteChildInACloudConnectorGroup(ctx, connectorId, connectorGroup, org) + if err != nil { + return err + } + common.Done(cmd, response, "Connector deleted successfully.") + return nil + }, + } + cmd.Flags().String("connector-id", "", "The connector ID.") + _ = cmd.MarkFlagRequired("connector-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/connectorgroup/connectors_list.go b/go/cmd/connectorgroup/connectors_list.go new file mode 100644 index 0000000..0027899 --- /dev/null +++ b/go/cmd/connectorgroup/connectors_list.go @@ -0,0 +1,37 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connectorgroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newConnectorsListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List the connectors in the group", + Long: `List the connectors in the group`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + connectorGroup := common.String(cmd, "connector-group") + response, err := c.ConnectorGroups.ListAllConnectorsInAGroup(ctx, connectorGroup, org, &sggosdk.ListAllConnectorsInAGroupRequest{ResourceNames: common.OptString(cmd, "resource-names"), Kind: common.OptString(cmd, "kind"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), Limit: common.OptInt(cmd, "limit"), Scope: common.OptString(cmd, "scope")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + cmd.Flags().String("resource-names", "", "Filter by resource name.") + cmd.Flags().String("kind", "", "Filter by kind.") + cmd.Flags().String("scope", "", "Filter by scope.") + return cmd +} diff --git a/go/cmd/connectorgroup/connectors_read.go b/go/cmd/connectorgroup/connectors_read.go new file mode 100644 index 0000000..5f7f26e --- /dev/null +++ b/go/cmd/connectorgroup/connectors_read.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connectorgroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newConnectorsReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get a connector in the group", + Long: `Get a connector in the group`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + connectorGroup := common.String(cmd, "connector-group") + connectorId := common.String(cmd, "connector-id") + response, err := c.ConnectorGroups.ReadChildInACloudConnectorGroup(ctx, connectorId, connectorGroup, org) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("connector-id", "", "The connector ID.") + _ = cmd.MarkFlagRequired("connector-id") + return cmd +} diff --git a/go/cmd/connectorgroup/connectors_update.go b/go/cmd/connectorgroup/connectors_update.go new file mode 100644 index 0000000..c48c4dd --- /dev/null +++ b/go/cmd/connectorgroup/connectors_update.go @@ -0,0 +1,45 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connectorgroup + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newConnectorsUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a connector in the group", + Long: `Update a connector in the group`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + connectorGroup := common.String(cmd, "connector-group") + connectorId := common.String(cmd, "connector-id") + var req sggosdk.PatchedIntegration + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.ConnectorGroups.UpdateChildInACloudConnectorGroup(ctx, connectorId, connectorGroup, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Connector updated successfully.") + return nil + }, + } + cmd.Flags().String("connector-id", "", "The connector ID.") + _ = cmd.MarkFlagRequired("connector-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/connectorgroup/create.go b/go/cmd/connectorgroup/create.go new file mode 100644 index 0000000..49b0327 --- /dev/null +++ b/go/cmd/connectorgroup/create.go @@ -0,0 +1,41 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connectorgroup + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create a new connector group", + Long: `Create a new connector group`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req sggosdk.IntegrationGroups + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.ConnectorGroups.CreateConnectorGroup(ctx, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Connector group created successfully.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/connectorgroup/delete.go b/go/cmd/connectorgroup/delete.go new file mode 100644 index 0000000..7ecd0da --- /dev/null +++ b/go/cmd/connectorgroup/delete.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connectorgroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete a connector group", + Long: `Delete a connector group`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + connectorGroup := common.String(cmd, "connector-group") + response, err := c.ConnectorGroups.DeleteConnectorGroup(ctx, connectorGroup, org) + if err != nil { + return err + } + common.Done(cmd, response, "Connector group deleted successfully.") + return nil + }, + } + cmd.Flags().String("connector-group", "", "The connector group name.") + _ = cmd.MarkFlagRequired("connector-group") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/connectorgroup/discovery_scan.go b/go/cmd/connectorgroup/discovery_scan.go new file mode 100644 index 0000000..a481a95 --- /dev/null +++ b/go/cmd/connectorgroup/discovery_scan.go @@ -0,0 +1,36 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connectorgroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/connectorgroups" + "github.com/spf13/cobra" +) + +func newDiscoveryScanCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "discovery-scan", + Short: "Trigger discovery scans across the group's child connectors", + Long: `Trigger discovery scans across the group's child connectors`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + connectorGroup := common.String(cmd, "connector-group") + response, err := c.ConnectorGroups.TriggerDiscoveryScan(ctx, connectorGroup, org, &connectorgroups.DiscoveryScanRequest{Benchmark: common.OptString(cmd, "benchmark")}) + if err != nil { + return err + } + common.Done(cmd, response, "Discovery scan triggered.") + return nil + }, + } + cmd.Flags().String("connector-group", "", "The connector group name.") + _ = cmd.MarkFlagRequired("connector-group") + cmd.Flags().String("benchmark", "", "Benchmarks to scan (comma-separated, default inventory).") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/connectorgroup/list.go b/go/cmd/connectorgroup/list.go new file mode 100644 index 0000000..13045e0 --- /dev/null +++ b/go/cmd/connectorgroup/list.go @@ -0,0 +1,36 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connectorgroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List connector groups", + Long: `List connector groups`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.ConnectorGroups.ListAllConnectorGroups(ctx, org, &sggosdk.ListAllConnectorGroupsRequest{ResourceNames: common.OptString(cmd, "resource-names"), Kind: common.OptString(cmd, "kind"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), Limit: common.OptInt(cmd, "limit"), Scope: common.OptString(cmd, "scope")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + cmd.Flags().String("resource-names", "", "Filter by resource name.") + cmd.Flags().String("kind", "", "Filter by kind.") + cmd.Flags().String("scope", "", "Filter by scope.") + return cmd +} diff --git a/go/cmd/connectorgroup/read.go b/go/cmd/connectorgroup/read.go new file mode 100644 index 0000000..b9c3fa1 --- /dev/null +++ b/go/cmd/connectorgroup/read.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connectorgroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get details of a connector group", + Long: `Get details of a connector group`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + connectorGroup := common.String(cmd, "connector-group") + response, err := c.ConnectorGroups.ReadConnectorGroup(ctx, connectorGroup, org) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("connector-group", "", "The connector group name.") + _ = cmd.MarkFlagRequired("connector-group") + return cmd +} diff --git a/go/cmd/connectorgroup/update.go b/go/cmd/connectorgroup/update.go new file mode 100644 index 0000000..bd095bb --- /dev/null +++ b/go/cmd/connectorgroup/update.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package connectorgroup + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a connector group", + Long: `Update a connector group`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + connectorGroup := common.String(cmd, "connector-group") + var req sggosdk.PatchedIntegrationGroups + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.ConnectorGroups.UpdateConnectorGroup(ctx, connectorGroup, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Connector group updated successfully.") + return nil + }, + } + cmd.Flags().String("connector-group", "", "The connector group name.") + _ = cmd.MarkFlagRequired("connector-group") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/organization/bulk_action.go b/go/cmd/organization/bulk_action.go new file mode 100644 index 0000000..b6f9959 --- /dev/null +++ b/go/cmd/organization/bulk_action.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package organization + +import ( + "context" + "fmt" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/organizations" + "github.com/spf13/cobra" +) + +func newBulkActionCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "bulk-action", + Short: "Activate or deactivate workflows and stacks in bulk", + Long: `Activate or deactivate workflows and stacks in bulk`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + action := common.String(cmd, "action") + resourceIds := common.OptStringSlice(cmd, "resource-ids") + if action != "activate" && action != "deactivate" { + return fmt.Errorf("--action must be activate or deactivate, got %q", action) + } + response, err := c.Organizations.BulkActionWorkflows(ctx, org, &organizations.WorkflowsBulkActionRequest{Action: action, ResourceIds: resourceIds}) + if err != nil { + return err + } + common.Done(cmd, response, "Bulk action submitted.") + return nil + }, + } + cmd.Flags().String("org", "", "The organization name on Stackguardian platform.") + _ = cmd.MarkFlagRequired("org") + cmd.Flags().String("action", "", "activate or deactivate.") + _ = cmd.MarkFlagRequired("action") + cmd.Flags().StringSlice("resource-ids", nil, "Resource paths relative to the organization, e.g. /wfgrps/g/wfs/w (comma-separated).") + _ = cmd.MarkFlagRequired("resource-ids") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/organization/count_workflows.go b/go/cmd/organization/count_workflows.go new file mode 100644 index 0000000..dd22102 --- /dev/null +++ b/go/cmd/organization/count_workflows.go @@ -0,0 +1,39 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package organization + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/organizations" + "github.com/spf13/cobra" +) + +func newCountWorkflowsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "count-workflows", + Short: "Count workflows across every workflow group of an organization", + Long: `Count workflows across every workflow group of an organization`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.Organizations.CountWorkflows(ctx, org, &organizations.ListAllOrganizationWorkflowsRequest{ + ResourceNames: common.OptString(cmd, "resource-names"), Description: common.OptString(cmd, "description"), Tags: common.OptString(cmd, "tags"), IsActive: common.OptString(cmd, "is-active"), + }) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("org", "", "The organization name on Stackguardian platform.") + _ = cmd.MarkFlagRequired("org") + cmd.Flags().String("resource-names", "", "Filter by resource names (comma-separated).") + cmd.Flags().String("description", "", "Filter by description.") + cmd.Flags().String("tags", "", "Filter by tags (comma-separated).") + cmd.Flags().String("is-active", "", "Filter by active state (0 or 1).") + return cmd +} diff --git a/go/cmd/organization/create.go b/go/cmd/organization/create.go new file mode 100644 index 0000000..596137a --- /dev/null +++ b/go/cmd/organization/create.go @@ -0,0 +1,40 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package organization + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/organizations" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create a new organization (requires a user token, not an API key)", + Long: `Create a new organization (requires a user token, not an API key)`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + var req organizations.CreateOrganizationRequest + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.Organizations.CreateOrganization(ctx, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Organization created successfully.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/organization/delete.go b/go/cmd/organization/delete.go new file mode 100644 index 0000000..590643c --- /dev/null +++ b/go/cmd/organization/delete.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package organization + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Archive an organization and all of its resources", + Long: `Archive an organization and all of its resources`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.Organizations.DeleteOrganization(ctx, org) + if err != nil { + return err + } + common.Done(cmd, response, "Organization archived successfully.") + return nil + }, + } + cmd.Flags().String("org", "", "The organization name on Stackguardian platform.") + _ = cmd.MarkFlagRequired("org") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/organization/list.go b/go/cmd/organization/list.go new file mode 100644 index 0000000..e829023 --- /dev/null +++ b/go/cmd/organization/list.go @@ -0,0 +1,29 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package organization + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List the organizations the caller belongs to (requires a user token)", + Long: `List the organizations the caller belongs to (requires a user token)`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + response, err := c.Organizations.ListAllOrganizations(ctx) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + return cmd +} diff --git a/go/cmd/organization/organization.go b/go/cmd/organization/organization.go new file mode 100644 index 0000000..02e23e5 --- /dev/null +++ b/go/cmd/organization/organization.go @@ -0,0 +1,38 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package organization + +import ( + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewOrganizationCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "organization", + Short: "Manage organizations", + Long: `Manage organizations`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + read Get details of an organization + create Create a new organization (requires a user token, not an API key) + list List the organizations the caller belongs to (requires a user token) + update Update the settings of an organization + delete Archive an organization and all of its resources + workflows List workflows across every workflow group of an organization + count-workflows Count workflows across every workflow group of an organization + bulk-action Activate or deactivate workflows and stacks in bulk`) + }, + } + cmd.AddCommand( + newReadCmd(c), + newCreateCmd(c), + newListCmd(c), + newUpdateCmd(c), + newDeleteCmd(c), + newWorkflowsCmd(c), + newCountWorkflowsCmd(c), + newBulkActionCmd(c), + ) + return cmd +} diff --git a/go/cmd/organization/read.go b/go/cmd/organization/read.go new file mode 100644 index 0000000..727f87b --- /dev/null +++ b/go/cmd/organization/read.go @@ -0,0 +1,32 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package organization + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get details of an organization", + Long: `Get details of an organization`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.Organizations.ReadOrganization(ctx, org) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("org", "", "The organization name on Stackguardian platform.") + _ = cmd.MarkFlagRequired("org") + return cmd +} diff --git a/go/cmd/organization/update.go b/go/cmd/organization/update.go new file mode 100644 index 0000000..22fe033 --- /dev/null +++ b/go/cmd/organization/update.go @@ -0,0 +1,43 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package organization + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/organizations" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update the settings of an organization", + Long: `Update the settings of an organization`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req organizations.PatchedOrganization + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.Organizations.UpdateOrganization(ctx, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Organization updated successfully.") + return nil + }, + } + cmd.Flags().String("org", "", "The organization name on Stackguardian platform.") + _ = cmd.MarkFlagRequired("org") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/organization/workflows.go b/go/cmd/organization/workflows.go new file mode 100644 index 0000000..1dded23 --- /dev/null +++ b/go/cmd/organization/workflows.go @@ -0,0 +1,56 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package organization + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/organizations" + "github.com/spf13/cobra" +) + +func newWorkflowsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "workflows", + Short: "List workflows across every workflow group of an organization", + Long: `List workflows across every workflow group of an organization`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.Organizations.ListAllWorkflows(ctx, org, &organizations.ListAllOrganizationWorkflowsRequest{ + Limit: common.OptInt(cmd, "limit"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), FetchSgOwnedWfs: common.OptBool(cmd, "fetch-sg-owned-wfs"), + LatestWfRunStatuses: common.OptString(cmd, "latest-wf-run-statuses"), LatestDriftRunStatuses: common.OptString(cmd, "latest-drift-run-statuses"), + RepoId: common.OptString(cmd, "repo-id"), UseMarketplaceTemplate: common.OptString(cmd, "use-marketplace-template"), IacTemplateId: common.OptString(cmd, "iac-template-id"), + ParentIacTemplateId: common.OptString(cmd, "parent-iac-template-id"), TerraformConfigTerraformVersion: common.OptString(cmd, "terraform-version"), + RunnerNames: common.OptString(cmd, "runner-names"), TerraformConfigDriftCheck: common.OptString(cmd, "drift-check"), ResourceNames: common.OptString(cmd, "resource-names"), + Description: common.OptString(cmd, "description"), Tags: common.OptString(cmd, "tags"), IsActive: common.OptString(cmd, "is-active"), + }) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("org", "", "The organization name on Stackguardian platform.") + _ = cmd.MarkFlagRequired("org") + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + cmd.Flags().Bool("fetch-sg-owned-wfs", true, "Include workflows owned by StackGuardian.") + cmd.Flags().String("latest-wf-run-statuses", "", "Filter by latest run status (comma-separated).") + cmd.Flags().String("latest-drift-run-statuses", "", "Filter by latest drift run status (comma-separated).") + cmd.Flags().String("repo-id", "", "Filter by VCS repository.") + cmd.Flags().String("use-marketplace-template", "", "Filter by marketplace template usage (true/false).") + cmd.Flags().String("iac-template-id", "", "Filter by IaC template id.") + cmd.Flags().String("parent-iac-template-id", "", "Filter by parent IaC template id.") + cmd.Flags().String("terraform-version", "", "Filter by Terraform version.") + cmd.Flags().String("runner-names", "", "Filter by runner names (comma-separated).") + cmd.Flags().String("drift-check", "", "Any value restricts to workflows with drift information.") + cmd.Flags().String("resource-names", "", "Filter by resource names (comma-separated).") + cmd.Flags().String("description", "", "Filter by description.") + cmd.Flags().String("tags", "", "Filter by tags (comma-separated).") + cmd.Flags().String("is-active", "", "Filter by active state (0 or 1).") + return cmd +} diff --git a/go/cmd/policy/create.go b/go/cmd/policy/create.go new file mode 100644 index 0000000..4f24e4a --- /dev/null +++ b/go/cmd/policy/create.go @@ -0,0 +1,41 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package policy + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create a new policy (payload must include PolicyType: GENERAL or FILTER.INSIGHT)", + Long: `Create a new policy (payload must include PolicyType: GENERAL or FILTER.INSIGHT)`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req sggosdk.PolymorphicPolicy + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.Policies.CreatePolicy(ctx, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Policy created successfully.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/policy/delete.go b/go/cmd/policy/delete.go new file mode 100644 index 0000000..a32c234 --- /dev/null +++ b/go/cmd/policy/delete.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package policy + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete a policy", + Long: `Delete a policy`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + policyId := common.String(cmd, "policy-id") + if err := c.Policies.DeletePolicy(ctx, org, policyId); err != nil { + return err + } + common.Done(cmd, nil, "Policy deleted successfully.") + return nil + }, + } + cmd.Flags().String("policy-id", "", "The policy ID.") + _ = cmd.MarkFlagRequired("policy-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/policy/list.go b/go/cmd/policy/list.go new file mode 100644 index 0000000..0b7bdcd --- /dev/null +++ b/go/cmd/policy/list.go @@ -0,0 +1,38 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package policy + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List policies", + Long: `List policies`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.Policies.ListAllPolicies(ctx, org, &sggosdk.ListAllPoliciesRequest{Description: common.OptString(cmd, "description"), PolicyTypes: common.OptString(cmd, "policy-types"), ResourceNames: common.OptString(cmd, "resource-names"), Tags: common.OptString(cmd, "tags"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), Limit: common.OptInt(cmd, "limit"), SearchQuery: common.OptString(cmd, "search-query")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + cmd.Flags().String("description", "", "Filter by description.") + cmd.Flags().String("policy-types", "", "Filter by policy types (default GENERAL).") + cmd.Flags().String("resource-names", "", "Filter by resource names.") + cmd.Flags().String("tags", "", "Filter by tags.") + cmd.Flags().String("search-query", "", "Search by resource name, tags or description.") + return cmd +} diff --git a/go/cmd/policy/policy.go b/go/cmd/policy/policy.go new file mode 100644 index 0000000..2aa3568 --- /dev/null +++ b/go/cmd/policy/policy.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package policy + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewPolicyCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "policy", + Short: "Manage policies", + Long: `Manage policies`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + create Create a new policy (payload must include PolicyType: GENERAL or FILTER.INSIGHT) + read Get details of a policy + update Update a policy (payload must include PolicyType) + delete Delete a policy + list List policies`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newCreateCmd(c), + newReadCmd(c), + newUpdateCmd(c), + newDeleteCmd(c), + newListCmd(c), + ) + return cmd +} diff --git a/go/cmd/policy/read.go b/go/cmd/policy/read.go new file mode 100644 index 0000000..4587e6f --- /dev/null +++ b/go/cmd/policy/read.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package policy + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get details of a policy", + Long: `Get details of a policy`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + policyId := common.String(cmd, "policy-id") + response, err := c.Policies.ReadPolicy(ctx, org, policyId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("policy-id", "", "The policy ID.") + _ = cmd.MarkFlagRequired("policy-id") + return cmd +} diff --git a/go/cmd/policy/update.go b/go/cmd/policy/update.go new file mode 100644 index 0000000..3ac7f02 --- /dev/null +++ b/go/cmd/policy/update.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package policy + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a policy (payload must include PolicyType)", + Long: `Update a policy (payload must include PolicyType)`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + policyId := common.String(cmd, "policy-id") + var req sggosdk.PatchedPolymorphicPolicy + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.Policies.UpdatePolicy(ctx, org, policyId, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Policy updated successfully.") + return nil + }, + } + cmd.Flags().String("policy-id", "", "The policy ID.") + _ = cmd.MarkFlagRequired("policy-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/resource/move.go b/go/cmd/resource/move.go new file mode 100644 index 0000000..7b0a08b --- /dev/null +++ b/go/cmd/resource/move.go @@ -0,0 +1,54 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package resource + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/resources" + "github.com/spf13/cobra" +) + +func newMoveCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "move -- payload.json", + Short: "Move workflows, stacks or workflow groups to another parent", + Long: `Move workflows, stacks or workflow groups to another parent`, + Args: cobra.MaximumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req resources.MoveResourcesRequest + if len(args) > 0 { + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + } + if v := common.OptStringSlice(cmd, "source-ids"); v != nil { + req.SourceResourceIds = v + } + if v := common.OptString(cmd, "destination"); v != nil { + req.DestinationParentId = *v + } + if len(req.SourceResourceIds) == 0 || req.DestinationParentId == "" { + return errors.New("provide --source-ids and --destination, or a payload with SourceResourceIds and DestinationParentId") + } + response, err := c.Resources.MoveResources(ctx, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Resources moved.") + return nil + }, + } + cmd.Flags().StringSlice("source-ids", nil, "Resource ids to move (comma-separated).") + cmd.Flags().String("destination", "", "Id of the destination parent.") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/resource/resource.go b/go/cmd/resource/resource.go new file mode 100644 index 0000000..fd6c6fe --- /dev/null +++ b/go/cmd/resource/resource.go @@ -0,0 +1,30 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package resource + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewResourceCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "resource", + Short: "Move and search resources across the organization", + Long: `Move and search resources across the organization`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + move Move workflows, stacks or workflow groups to another parent + search Search resources (payload and flags are merged; ResourceTypes is required by the API) + tags List the distinct tags used on resources`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newMoveCmd(c), + newSearchCmd(c), + newTagsCmd(c), + ) + return cmd +} diff --git a/go/cmd/resource/search.go b/go/cmd/resource/search.go new file mode 100644 index 0000000..c3aba80 --- /dev/null +++ b/go/cmd/resource/search.go @@ -0,0 +1,59 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package resource + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/resources" + "github.com/spf13/cobra" +) + +func newSearchCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "search -- payload.json", + Short: "Search resources (payload and flags are merged; ResourceTypes is required by the API)", + Long: `Search resources (payload and flags are merged; ResourceTypes is required by the API)`, + Args: cobra.MaximumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req resources.SearchResourcesRequest + if len(args) > 0 { + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + } + if v := common.OptString(cmd, "search-query"); v != nil { + req.SearchQuery = v + } + if v := common.OptStringSlice(cmd, "resource-types"); v != nil { + req.ResourceTypes = v + } + if v := common.OptInt(cmd, "limit"); v != nil { + req.Limit = v + } + if v := common.OptString(cmd, "last-evaluated-key"); v != nil { + req.LastEvaluatedKey = v + } + response, err := c.Resources.SearchResources(ctx, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Search completed.") + return nil + }, + } + cmd.Flags().String("search-query", "", "Free-text search query.") + cmd.Flags().StringSlice("resource-types", nil, "Resource types to search, e.g. WORKFLOW,STACK (comma-separated).") + cmd.Flags().Int("limit", 0, "Maximum number of results.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/resource/tags.go b/go/cmd/resource/tags.go new file mode 100644 index 0000000..ef4cc41 --- /dev/null +++ b/go/cmd/resource/tags.go @@ -0,0 +1,36 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package resource + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/resources" + "github.com/spf13/cobra" +) + +func newTagsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "tags", + Short: "List the distinct tags used on resources", + Long: `List the distinct tags used on resources`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.Resources.ListResourceTags(ctx, org, &resources.ListResourceTagsRequest{ContextTagKey: common.OptString(cmd, "context-tag-key"), Limit: common.OptInt(cmd, "limit"), Query: common.OptString(cmd, "query"), ResourceType: common.OptString(cmd, "resource-type"), TagKind: common.OptString(cmd, "tag-kind")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("context-tag-key", "", "Context tag key to list values for.") + cmd.Flags().Int("limit", 0, "Maximum number of tags.") + cmd.Flags().String("query", "", "Filter tags by prefix or substring.") + cmd.Flags().String("resource-type", "", "Restrict to a resource type.") + cmd.Flags().String("tag-kind", "", "Tag kind to list.") + return cmd +} diff --git a/go/cmd/role/create.go b/go/cmd/role/create.go new file mode 100644 index 0000000..f1adea9 --- /dev/null +++ b/go/cmd/role/create.go @@ -0,0 +1,41 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package role + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create a new role", + Long: `Create a new role`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req sggosdk.Role + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.AccessManagement.CreateRole(ctx, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Role created successfully.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/role/delete.go b/go/cmd/role/delete.go new file mode 100644 index 0000000..663f0bf --- /dev/null +++ b/go/cmd/role/delete.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package role + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete a role", + Long: `Delete a role`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + roleId := common.String(cmd, "role-id") + if err := c.AccessManagement.DeleteRole(ctx, org, roleId); err != nil { + return err + } + common.Done(cmd, nil, "Role deleted successfully.") + return nil + }, + } + cmd.Flags().String("role-id", "", "The role ID.") + _ = cmd.MarkFlagRequired("role-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/role/list.go b/go/cmd/role/list.go new file mode 100644 index 0000000..be5fd38 --- /dev/null +++ b/go/cmd/role/list.go @@ -0,0 +1,32 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package role + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List roles", + Long: `List roles`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.AccessManagement.ListAllRoles(ctx, org, &sggosdk.ListAllRolesRequest{IncludePredefinedRoles: common.OptBool(cmd, "include-predefined-roles")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().Bool("include-predefined-roles", false, "Include predefined system roles.") + return cmd +} diff --git a/go/cmd/role/read.go b/go/cmd/role/read.go new file mode 100644 index 0000000..b32bf7b --- /dev/null +++ b/go/cmd/role/read.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package role + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get details of a role", + Long: `Get details of a role`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + roleId := common.String(cmd, "role-id") + response, err := c.AccessManagement.ReadRole(ctx, org, roleId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("role-id", "", "The role ID.") + _ = cmd.MarkFlagRequired("role-id") + return cmd +} diff --git a/go/cmd/role/role.go b/go/cmd/role/role.go new file mode 100644 index 0000000..8ec3c34 --- /dev/null +++ b/go/cmd/role/role.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package role + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewRoleCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "role", + Short: "Manage roles", + Long: `Manage roles`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + create Create a new role + read Get details of a role + update Update a role + delete Delete a role + list List roles`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newCreateCmd(c), + newReadCmd(c), + newUpdateCmd(c), + newDeleteCmd(c), + newListCmd(c), + ) + return cmd +} diff --git a/go/cmd/role/update.go b/go/cmd/role/update.go new file mode 100644 index 0000000..fa9abee --- /dev/null +++ b/go/cmd/role/update.go @@ -0,0 +1,47 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package role + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a role", + Long: `Update a role`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + roleId := common.String(cmd, "role-id") + var req sggosdk.PatchedRole + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + if req.ResourceName == nil { + req.ResourceName = sggosdk.Optional(roleId) // the API requires it on updates + } + response, err := c.AccessManagement.UpdateRole(ctx, org, roleId, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Role updated successfully.") + return nil + }, + } + cmd.Flags().String("role-id", "", "The role ID.") + _ = cmd.MarkFlagRequired("role-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/rolebinding/read.go b/go/cmd/rolebinding/read.go new file mode 100644 index 0000000..fde3854 --- /dev/null +++ b/go/cmd/rolebinding/read.go @@ -0,0 +1,32 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package rolebinding + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get a role binding", + Long: `Get a role binding`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + roleBinding := common.String(cmd, "role-binding") + response, err := c.AccessManagement.ReadRoleBinding(ctx, org, roleBinding) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("role-binding", "default", "The role binding name.") + return cmd +} diff --git a/go/cmd/rolebinding/rolebinding.go b/go/cmd/rolebinding/rolebinding.go new file mode 100644 index 0000000..5b28bf8 --- /dev/null +++ b/go/cmd/rolebinding/rolebinding.go @@ -0,0 +1,26 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package rolebinding + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewRoleBindingCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "role-binding", + Short: "Inspect role bindings", + Long: `Inspect role bindings`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + read Get a role binding`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newReadCmd(c), + ) + return cmd +} diff --git a/go/cmd/root.go b/go/cmd/root.go index 370a890..2f40e4e 100644 --- a/go/cmd/root.go +++ b/go/cmd/root.go @@ -3,18 +3,43 @@ package cmd import ( "os" + "github.com/StackGuardian/sg-cli/cmd/apiaccess" + "github.com/StackGuardian/sg-cli/cmd/apitoken" "github.com/StackGuardian/sg-cli/cmd/artifacts" + "github.com/StackGuardian/sg-cli/cmd/auditlog" + "github.com/StackGuardian/sg-cli/cmd/benchmarkreport" + "github.com/StackGuardian/sg-cli/cmd/billing" + "github.com/StackGuardian/sg-cli/cmd/chat" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-cli/cmd/connector" + "github.com/StackGuardian/sg-cli/cmd/connectorgroup" + "github.com/StackGuardian/sg-cli/cmd/organization" + "github.com/StackGuardian/sg-cli/cmd/policy" + "github.com/StackGuardian/sg-cli/cmd/resource" + "github.com/StackGuardian/sg-cli/cmd/role" + "github.com/StackGuardian/sg-cli/cmd/rolebinding" + "github.com/StackGuardian/sg-cli/cmd/runnergroup" + "github.com/StackGuardian/sg-cli/cmd/secret" "github.com/StackGuardian/sg-cli/cmd/stack" + "github.com/StackGuardian/sg-cli/cmd/stackrun" + "github.com/StackGuardian/sg-cli/cmd/stacktemplate" + "github.com/StackGuardian/sg-cli/cmd/stackworkflow" + "github.com/StackGuardian/sg-cli/cmd/stackworkflowrun" + "github.com/StackGuardian/sg-cli/cmd/statebackend" + "github.com/StackGuardian/sg-cli/cmd/template" + "github.com/StackGuardian/sg-cli/cmd/user" workflow "github.com/StackGuardian/sg-cli/cmd/workflow" - "github.com/StackGuardian/sg-sdk-go/client" - "github.com/StackGuardian/sg-sdk-go/option" + "github.com/StackGuardian/sg-cli/cmd/workflowgroup" + "github.com/StackGuardian/sg-cli/cmd/workflowrun" + "github.com/StackGuardian/sg-cli/cmd/workflowsteptemplate" + "github.com/StackGuardian/sg-cli/cmd/workflowtemplate" "github.com/spf13/cobra" ) // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ Use: "sg-cli", - Version: "2.1.0", + Version: "2.2.0", Short: "sg-cli is CLI command for managing resources on Stackguardian platform.", Long: `sg-cli is CLI command for managing resources on Stackguardian platform. More information available at: https://docs.qa.stackguardian.io/docs/`, @@ -29,17 +54,39 @@ func Execute() { } func init() { - - API_KEY := "apikey " + os.Getenv("SG_API_TOKEN") - SG_BASE_URL := os.Getenv("SG_BASE_URL") - if SG_BASE_URL == "" { - SG_BASE_URL = "https://api.app.stackguardian.io" - } - c := client.NewClient( - option.WithApiKey(API_KEY), - option.WithBaseURL(SG_BASE_URL), - ) + c := common.NewClient() rootCmd.AddCommand(workflow.NewWorkflowCmd(c)) rootCmd.AddCommand(stack.NewStackCmd(c)) rootCmd.AddCommand(artifacts.NewArtifactsCmd(c)) + rootCmd.AddCommand(apiaccess.NewApiAccessCmd(c)) + rootCmd.AddCommand(apitoken.NewApiTokenCmd(c)) + rootCmd.AddCommand(auditlog.NewAuditLogCmd(c)) + rootCmd.AddCommand(benchmarkreport.NewBenchmarkReportCmd(c)) + rootCmd.AddCommand(billing.NewBillingCmd(c)) + rootCmd.AddCommand(chat.NewChatCmd(c)) + rootCmd.AddCommand(connector.NewConnectorCmd(c)) + rootCmd.AddCommand(connectorgroup.NewConnectorGroupCmd(c)) + rootCmd.AddCommand(organization.NewOrganizationCmd(c)) + rootCmd.AddCommand(policy.NewPolicyCmd(c)) + rootCmd.AddCommand(resource.NewResourceCmd(c)) + rootCmd.AddCommand(role.NewRoleCmd(c)) + rootCmd.AddCommand(rolebinding.NewRoleBindingCmd(c)) + rootCmd.AddCommand(runnergroup.NewRunnerGroupCmd(c)) + rootCmd.AddCommand(secret.NewSecretCmd(c)) + rootCmd.AddCommand(stackrun.NewStackRunCmd(c)) + rootCmd.AddCommand(stacktemplate.NewStackTemplateCmd(c)) + rootCmd.AddCommand(stackworkflow.NewStackWorkflowCmd(c)) + rootCmd.AddCommand(stackworkflowrun.NewStackWorkflowRunCmd(c)) + rootCmd.AddCommand(statebackend.NewStateBackendCmd(c)) + rootCmd.AddCommand(template.NewTemplateCmd(c)) + rootCmd.AddCommand(user.NewUserCmd(c)) + rootCmd.AddCommand(workflowgroup.NewWorkflowGroupCmd(c)) + rootCmd.AddCommand(workflowrun.NewWorkflowRunCmd(c)) + rootCmd.AddCommand(workflowsteptemplate.NewWorkflowStepTemplateCmd(c)) + rootCmd.AddCommand(workflowtemplate.NewWorkflowTemplateCmd(c)) +} + +// RootCommand returns the root command with every sub-command attached (used by tests). +func RootCommand() *cobra.Command { + return rootCmd } diff --git a/go/cmd/runnergroup/create.go b/go/cmd/runnergroup/create.go new file mode 100644 index 0000000..1367b9c --- /dev/null +++ b/go/cmd/runnergroup/create.go @@ -0,0 +1,41 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package runnergroup + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create a new runner group", + Long: `Create a new runner group`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req sggosdk.RunnerGroup + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.RunnerGroups.CreateNewRunnerGroup(ctx, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Runner group created successfully.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/runnergroup/delete.go b/go/cmd/runnergroup/delete.go new file mode 100644 index 0000000..b40c68c --- /dev/null +++ b/go/cmd/runnergroup/delete.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package runnergroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete a runner group", + Long: `Delete a runner group`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + runnerGroup := common.String(cmd, "runner-group") + response, err := c.RunnerGroups.DeleteRunnerGroup(ctx, org, runnerGroup) + if err != nil { + return err + } + common.Done(cmd, response, "Runner group deleted successfully.") + return nil + }, + } + cmd.Flags().String("runner-group", "", "The runner group name.") + _ = cmd.MarkFlagRequired("runner-group") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/runnergroup/deregister_runner.go b/go/cmd/runnergroup/deregister_runner.go new file mode 100644 index 0000000..eee6976 --- /dev/null +++ b/go/cmd/runnergroup/deregister_runner.go @@ -0,0 +1,47 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package runnergroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeregisterRunnerCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "deregister-runner", + Short: "Deregister a runner from a runner group", + Long: `Deregister a runner from a runner group`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + runnerGroup := common.String(cmd, "runner-group") + var body sggosdk.RunnerDeregister + if v := common.OptString(cmd, "runner-id"); v != nil { + body.RunnerId = sggosdk.Optional(*v) + } + if v := common.OptStringSlice(cmd, "container-instance-ids"); v != nil { + body.ContainerInstanceIds = sggosdk.Optional(v) + } + if v := common.OptBool(cmd, "force"); v != nil { + body.ForceDeregister = sggosdk.Optional(*v) + } + if err := c.RunnerGroups.DeregisterRunner(ctx, org, runnerGroup, &body); err != nil { + return err + } + common.Done(cmd, nil, "Runner deregistered.") + return nil + }, + } + cmd.Flags().String("runner-group", "", "The runner group name.") + _ = cmd.MarkFlagRequired("runner-group") + cmd.Flags().String("runner-id", "", "Runner id.") + cmd.Flags().StringSlice("container-instance-ids", nil, "Container instance ids (comma-separated).") + cmd.Flags().Bool("force", false, "Force deregistration.") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/runnergroup/list.go b/go/cmd/runnergroup/list.go new file mode 100644 index 0000000..850d1b6 --- /dev/null +++ b/go/cmd/runnergroup/list.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package runnergroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/runnergroups" + "github.com/spf13/cobra" +) + +func newListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List runner groups", + Long: `List runner groups`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.RunnerGroups.ListAllRunnerGroups(ctx, org, &runnergroups.ListAllRunnerGroupsRequest{Limit: common.OptInt(cmd, "limit"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), FilterResourceNames: common.OptString(cmd, "resource-names")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + cmd.Flags().String("resource-names", "", "Filter by resource names.") + return cmd +} diff --git a/go/cmd/runnergroup/read.go b/go/cmd/runnergroup/read.go new file mode 100644 index 0000000..b9136e2 --- /dev/null +++ b/go/cmd/runnergroup/read.go @@ -0,0 +1,36 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package runnergroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get details of a runner group", + Long: `Get details of a runner group`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + runnerGroup := common.String(cmd, "runner-group") + response, err := c.RunnerGroups.ReadRunnerGroup(ctx, org, runnerGroup, &sggosdk.ReadRunnerGroupRequest{GetActiveWorkflows: common.OptBool(cmd, "get-active-workflows"), GetActiveWorkflowsDetails: common.OptBool(cmd, "get-active-workflows-details")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("runner-group", "", "The runner group name.") + _ = cmd.MarkFlagRequired("runner-group") + cmd.Flags().Bool("get-active-workflows", false, "Include the active workflows.") + cmd.Flags().Bool("get-active-workflows-details", false, "Include details of the active workflows.") + return cmd +} diff --git a/go/cmd/runnergroup/register.go b/go/cmd/runnergroup/register.go new file mode 100644 index 0000000..fab4d41 --- /dev/null +++ b/go/cmd/runnergroup/register.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package runnergroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newRegisterCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "register", + Short: "Register a runner node (use the runner group's own token as the API key)", + Long: `Register a runner node (use the runner group's own token as the API key)`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + runnerGroup := common.String(cmd, "runner-group") + response, err := c.RunnerGroups.RegisterRunner(ctx, org, runnerGroup) + if err != nil { + return err + } + common.Done(cmd, response, "Runner registered.") + return nil + }, + } + cmd.Flags().String("runner-group", "", "The runner group name.") + _ = cmd.MarkFlagRequired("runner-group") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/runnergroup/runnergroup.go b/go/cmd/runnergroup/runnergroup.go new file mode 100644 index 0000000..2444eef --- /dev/null +++ b/go/cmd/runnergroup/runnergroup.go @@ -0,0 +1,42 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package runnergroup + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewRunnerGroupCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "runner-group", + Short: "Manage private runner groups", + Long: `Manage private runner groups`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + create Create a new runner group + read Get details of a runner group + update Update a runner group + delete Delete a runner group + list List runner groups + register Register a runner node (use the runner group's own token as the API key) + storage-backend-auth Generate short-lived credentials for the runner group's storage backend + deregister-runner Deregister a runner from a runner group + update-runner-state Update the state of a runner (ACTIVE or DRAINING)`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newCreateCmd(c), + newReadCmd(c), + newUpdateCmd(c), + newDeleteCmd(c), + newListCmd(c), + newRegisterCmd(c), + newStorageBackendAuthCmd(c), + newDeregisterRunnerCmd(c), + newUpdateRunnerStateCmd(c), + ) + return cmd +} diff --git a/go/cmd/runnergroup/storage_backend_auth.go b/go/cmd/runnergroup/storage_backend_auth.go new file mode 100644 index 0000000..4ab59f8 --- /dev/null +++ b/go/cmd/runnergroup/storage_backend_auth.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package runnergroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newStorageBackendAuthCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "storage-backend-auth", + Short: "Generate short-lived credentials for the runner group's storage backend", + Long: `Generate short-lived credentials for the runner group's storage backend`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + runnerGroup := common.String(cmd, "runner-group") + response, err := c.RunnerGroups.GenerateStorageBackendAuth(ctx, org, runnerGroup) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("runner-group", "", "The runner group name.") + _ = cmd.MarkFlagRequired("runner-group") + return cmd +} diff --git a/go/cmd/runnergroup/update.go b/go/cmd/runnergroup/update.go new file mode 100644 index 0000000..1e64bed --- /dev/null +++ b/go/cmd/runnergroup/update.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package runnergroup + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a runner group", + Long: `Update a runner group`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + runnerGroup := common.String(cmd, "runner-group") + var req sggosdk.PatchedRunnerGroup + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.RunnerGroups.UpdateRunnerGroup(ctx, org, runnerGroup, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Runner group updated successfully.") + return nil + }, + } + cmd.Flags().String("runner-group", "", "The runner group name.") + _ = cmd.MarkFlagRequired("runner-group") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/runnergroup/update_runner_state.go b/go/cmd/runnergroup/update_runner_state.go new file mode 100644 index 0000000..302f678 --- /dev/null +++ b/go/cmd/runnergroup/update_runner_state.go @@ -0,0 +1,50 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package runnergroup + +import ( + "context" + "fmt" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newUpdateRunnerStateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update-runner-state", + Short: "Update the state of a runner (ACTIVE or DRAINING)", + Long: `Update the state of a runner (ACTIVE or DRAINING)`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + runnerGroup := common.String(cmd, "runner-group") + status := common.String(cmd, "status") + if status != "ACTIVE" && status != "DRAINING" { + return fmt.Errorf("--status must be ACTIVE or DRAINING, got %q", status) + } + body := sggosdk.RunnerStatus{Status: sggosdk.StatusEnum(status)} + if v := common.OptString(cmd, "runner-id"); v != nil { + body.RunnerId = sggosdk.Optional(*v) + } + if v := common.OptStringSlice(cmd, "container-instance-ids"); v != nil { + body.ContainerInstanceIds = sggosdk.Optional(v) + } + if err := c.RunnerGroups.UpdateRunnerState(ctx, org, runnerGroup, &body); err != nil { + return err + } + common.Done(cmd, nil, "Runner state updated.") + return nil + }, + } + cmd.Flags().String("runner-group", "", "The runner group name.") + _ = cmd.MarkFlagRequired("runner-group") + cmd.Flags().String("status", "", "New runner status (ACTIVE, DRAINING).") + _ = cmd.MarkFlagRequired("status") + cmd.Flags().String("runner-id", "", "Runner id.") + cmd.Flags().StringSlice("container-instance-ids", nil, "Container instance ids (comma-separated).") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/secret/create.go b/go/cmd/secret/create.go new file mode 100644 index 0000000..0044e11 --- /dev/null +++ b/go/cmd/secret/create.go @@ -0,0 +1,41 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package secret + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create a new secret", + Long: `Create a new secret`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req sggosdk.Secret + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.Secrets.CreateSecret(ctx, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Secret created successfully.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/secret/delete.go b/go/cmd/secret/delete.go new file mode 100644 index 0000000..f2abd78 --- /dev/null +++ b/go/cmd/secret/delete.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package secret + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete a secret", + Long: `Delete a secret`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + secretId := common.String(cmd, "secret-id") + response, err := c.Secrets.DeleteSecret(ctx, org, secretId) + if err != nil { + return err + } + common.Done(cmd, response, "Secret deleted successfully.") + return nil + }, + } + cmd.Flags().String("secret-id", "", "The secret name.") + _ = cmd.MarkFlagRequired("secret-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/secret/list.go b/go/cmd/secret/list.go new file mode 100644 index 0000000..c7ccfcb --- /dev/null +++ b/go/cmd/secret/list.go @@ -0,0 +1,30 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package secret + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List secrets", + Long: `List secrets`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.Secrets.ListAllSecrets(ctx, org) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + return cmd +} diff --git a/go/cmd/secret/read_bulk.go b/go/cmd/secret/read_bulk.go new file mode 100644 index 0000000..3573b43 --- /dev/null +++ b/go/cmd/secret/read_bulk.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package secret + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/secrets" + "github.com/spf13/cobra" +) + +func newReadBulkCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read-bulk", + Short: "Read several secrets by name", + Long: `Read several secrets by name`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + names := common.OptStringSlice(cmd, "names") + response, err := c.Secrets.ReadSecretsInBulk(ctx, org, &secrets.ReadSecretsInBulkRequest{ResourceNames: names}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().StringSlice("names", nil, "Secret names (comma-separated).") + _ = cmd.MarkFlagRequired("names") + return cmd +} diff --git a/go/cmd/secret/secret.go b/go/cmd/secret/secret.go new file mode 100644 index 0000000..67e444f --- /dev/null +++ b/go/cmd/secret/secret.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package secret + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewSecretCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "secret", + Short: "Manage secrets", + Long: `Manage secrets`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + create Create a new secret + update Update a secret + delete Delete a secret + list List secrets + read-bulk Read several secrets by name`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newCreateCmd(c), + newUpdateCmd(c), + newDeleteCmd(c), + newListCmd(c), + newReadBulkCmd(c), + ) + return cmd +} diff --git a/go/cmd/secret/update.go b/go/cmd/secret/update.go new file mode 100644 index 0000000..7d0cc69 --- /dev/null +++ b/go/cmd/secret/update.go @@ -0,0 +1,47 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package secret + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a secret", + Long: `Update a secret`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + secretId := common.String(cmd, "secret-id") + var req sggosdk.PatchedSecret + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + if req.ResourceName == nil { + req.ResourceName = sggosdk.Optional(secretId) // the API requires it on updates + } + response, err := c.Secrets.UpdateSecret(ctx, org, secretId, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Secret updated successfully.") + return nil + }, + } + cmd.Flags().String("secret-id", "", "The secret name.") + _ = cmd.MarkFlagRequired("secret-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stack/apply/stack_apply.go b/go/cmd/stack/apply/stack_apply.go index cde4e4e..17423fa 100644 --- a/go/cmd/stack/apply/stack_apply.go +++ b/go/cmd/stack/apply/stack_apply.go @@ -2,6 +2,7 @@ package apply import ( "context" + "github.com/StackGuardian/sg-cli/cmd/common" "os" sggosdk "github.com/StackGuardian/sg-sdk-go" @@ -42,7 +43,7 @@ func NewApplyCmd(c *client.Client) *cobra.Command { os.Exit(-1) } if opts.OutputJson { - cmd.Println(response) + common.PrintJSON(cmd, response) } workflowRunPath := DASHBOARD_URL + "/orgs/" + diff --git a/go/cmd/stack/create/stack_create.go b/go/cmd/stack/create/stack_create.go index 64b015d..e6b512c 100644 --- a/go/cmd/stack/create/stack_create.go +++ b/go/cmd/stack/create/stack_create.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "errors" + "github.com/StackGuardian/sg-cli/cmd/common" "os" "strings" @@ -91,7 +92,7 @@ func NewCreateCmd(c *client.Client) *cobra.Command { os.Exit(-1) } if opts.OutputJson { - cmd.Println(response) + common.PrintJSON(cmd, response) } cmd.Println("Stack created successfully.") diff --git a/go/cmd/stack/delete/stack_delete.go b/go/cmd/stack/delete/stack_delete.go index f78e680..4317881 100644 --- a/go/cmd/stack/delete/stack_delete.go +++ b/go/cmd/stack/delete/stack_delete.go @@ -3,6 +3,7 @@ package delete import ( "context" "fmt" + "github.com/StackGuardian/sg-cli/cmd/common" "os" "strings" @@ -37,7 +38,7 @@ func NewDeleteCmd(c *client.Client) *cobra.Command { } if opts.OutputJson && response != nil { - cmd.Println(response) + common.PrintJSON(cmd, response) } cmd.Println("Stack deleted successfully.") }, diff --git a/go/cmd/stack/destroy/stack_destroy.go b/go/cmd/stack/destroy/stack_destroy.go index c81d5c5..972e9a9 100644 --- a/go/cmd/stack/destroy/stack_destroy.go +++ b/go/cmd/stack/destroy/stack_destroy.go @@ -2,6 +2,7 @@ package destroy import ( "context" + "github.com/StackGuardian/sg-cli/cmd/common" "os" sggosdk "github.com/StackGuardian/sg-sdk-go" @@ -42,7 +43,7 @@ func NewDestroyCmd(c *client.Client) *cobra.Command { os.Exit(-1) } if opts.OutputJson { - cmd.Println(response) + common.PrintJSON(cmd, response) } workflowRunPath := DASHBOARD_URL + "/orgs/" + diff --git a/go/cmd/stack/extra/compare.go b/go/cmd/stack/extra/compare.go new file mode 100644 index 0000000..9eab920 --- /dev/null +++ b/go/cmd/stack/extra/compare.go @@ -0,0 +1,58 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/stacks" + "github.com/spf13/cobra" +) + +func newCompareCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "compare -- payload.json", + Short: "Compare a stack against a stack template without applying changes", + Long: `Compare a stack against a stack template without applying changes`, + Args: cobra.MaximumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + var req stacks.CompareStackRequest + if len(args) > 0 { + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + } + if v := common.OptString(cmd, "target-template-group-id"); v != nil { + req.TargetTemplateGroupId = *v + } + if v := common.OptString(cmd, "upgrade-mode"); v != nil { + req.UpgradeMode = v + } + if req.TargetTemplateGroupId == "" { + return errors.New("provide --target-template-group-id or a payload with targetTemplateGroupId") + } + response, err := c.Stacks.CompareStack(ctx, org, stackId, workflowGroup, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Comparison completed.") + return nil + }, + } + cmd.Flags().String("stack-id", "", "The stack ID.") + _ = cmd.MarkFlagRequired("stack-id") + cmd.Flags().String("target-template-group-id", "", "Stack template to compare against.") + cmd.Flags().String("upgrade-mode", "", "Upgrade mode to simulate.") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stack/extra/extra.go b/go/cmd/stack/extra/extra.go new file mode 100644 index 0000000..b986485 --- /dev/null +++ b/go/cmd/stack/extra/extra.go @@ -0,0 +1,18 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +// AddCommands attaches the generated sub-commands to an existing command group. +func AddCommands(cmd *cobra.Command, c *client.Client) { + cmd.AddCommand( + newReadCmd(c), + newUpdateCmd(c), + newListCmd(c), + newCompareCmd(c), + ) +} diff --git a/go/cmd/stack/extra/list.go b/go/cmd/stack/extra/list.go new file mode 100644 index 0000000..5e79bf8 --- /dev/null +++ b/go/cmd/stack/extra/list.go @@ -0,0 +1,37 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List the stacks in a workflow group", + Long: `List the stacks in a workflow group`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + response, err := c.Stacks.ListAllStacks(ctx, org, workflowGroup, &sggosdk.ListAllStacksRequest{Description: common.OptString(cmd, "description"), ResourceNames: common.OptString(cmd, "resource-names"), Tags: common.OptString(cmd, "tags"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), Limit: common.OptInt(cmd, "limit")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + cmd.Flags().String("description", "", "Filter by description.") + cmd.Flags().String("resource-names", "", "Filter by resource names.") + cmd.Flags().String("tags", "", "Filter by tags.") + return cmd +} diff --git a/go/cmd/stack/extra/read.go b/go/cmd/stack/extra/read.go new file mode 100644 index 0000000..56a4337 --- /dev/null +++ b/go/cmd/stack/extra/read.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get details of a stack", + Long: `Get details of a stack`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + response, err := c.Stacks.ReadStack(ctx, org, stackId, workflowGroup) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("stack-id", "", "The stack ID.") + _ = cmd.MarkFlagRequired("stack-id") + return cmd +} diff --git a/go/cmd/stack/extra/update.go b/go/cmd/stack/extra/update.go new file mode 100644 index 0000000..a039df7 --- /dev/null +++ b/go/cmd/stack/extra/update.go @@ -0,0 +1,45 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a stack", + Long: `Update a stack`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + var req sggosdk.PatchedStack + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.Stacks.UpdateStack(ctx, org, stackId, workflowGroup, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Stack updated successfully.") + return nil + }, + } + cmd.Flags().String("stack-id", "", "The stack ID.") + _ = cmd.MarkFlagRequired("stack-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stack/outputs/stack_outputs.go b/go/cmd/stack/outputs/stack_outputs.go index caf80c6..f8d8b64 100644 --- a/go/cmd/stack/outputs/stack_outputs.go +++ b/go/cmd/stack/outputs/stack_outputs.go @@ -2,6 +2,7 @@ package outputs import ( "context" + "github.com/StackGuardian/sg-cli/cmd/common" "os" "github.com/StackGuardian/sg-sdk-go/client" @@ -25,7 +26,7 @@ func NewOutputsCmd(c *client.Client) *cobra.Command { cmd.Println(err) os.Exit(-1) } - cmd.Println(response) + common.PrintJSON(cmd, response) }, } diff --git a/go/cmd/stack/stack.go b/go/cmd/stack/stack.go index dfaa630..12c0d99 100644 --- a/go/cmd/stack/stack.go +++ b/go/cmd/stack/stack.go @@ -7,6 +7,7 @@ import ( "github.com/StackGuardian/sg-cli/cmd/stack/create" "github.com/StackGuardian/sg-cli/cmd/stack/delete" "github.com/StackGuardian/sg-cli/cmd/stack/destroy" + stackextra "github.com/StackGuardian/sg-cli/cmd/stack/extra" "github.com/StackGuardian/sg-cli/cmd/stack/outputs" "github.com/StackGuardian/sg-sdk-go/client" "github.com/spf13/cobra" @@ -40,5 +41,7 @@ func NewStackCmd(c *client.Client) *cobra.Command { stackCmd.AddCommand(delete.NewDeleteCmd(c)) stackCmd.AddCommand(apply.NewApplyCmd(c)) + stackextra.AddCommands(stackCmd, c) + return stackCmd } diff --git a/go/cmd/stackrun/create.go b/go/cmd/stackrun/create.go new file mode 100644 index 0000000..16f2c3d --- /dev/null +++ b/go/cmd/stackrun/create.go @@ -0,0 +1,53 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackrun + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Trigger a stack run (use --action-type or a payload)", + Long: `Trigger a stack run (use --action-type or a payload)`, + Args: cobra.MaximumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + actionType := common.String(cmd, "action-type") + var req sggosdk.StackAction + if len(args) > 0 { + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + } + if actionType != "" { + req.ActionType = actionType + } + if req.ActionType == "" { + return errors.New("provide --action-type or a payload with ActionType") + } + response, err := c.StackRuns.CreateStackRun(ctx, org, stackId, workflowGroup, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Stack run created successfully.") + return nil + }, + } + cmd.Flags().String("action-type", "", "Action to run, e.g. APPLY or DESTROY.") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stackrun/list.go b/go/cmd/stackrun/list.go new file mode 100644 index 0000000..742e7da --- /dev/null +++ b/go/cmd/stackrun/list.go @@ -0,0 +1,35 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackrun + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List the runs of a stack", + Long: `List the runs of a stack`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + response, err := c.StackRuns.ListAllStackRuns(ctx, org, stackId, workflowGroup, &sggosdk.ListAllStackRunsRequest{Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), Limit: common.OptInt(cmd, "limit")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + return cmd +} diff --git a/go/cmd/stackrun/read.go b/go/cmd/stackrun/read.go new file mode 100644 index 0000000..27adfa5 --- /dev/null +++ b/go/cmd/stackrun/read.go @@ -0,0 +1,35 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackrun + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get a stack run", + Long: `Get a stack run`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + runId := common.String(cmd, "run-id") + response, err := c.StackRuns.ReadStackRun(ctx, org, stackId, runId, workflowGroup) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("run-id", "", "The stack run ID.") + _ = cmd.MarkFlagRequired("run-id") + return cmd +} diff --git a/go/cmd/stackrun/stackrun.go b/go/cmd/stackrun/stackrun.go new file mode 100644 index 0000000..e99200e --- /dev/null +++ b/go/cmd/stackrun/stackrun.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackrun + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewStackRunCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "stack-run", + Short: "Trigger and inspect stack runs", + Long: `Trigger and inspect stack runs`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + create Trigger a stack run (use --action-type or a payload) + read Get a stack run + list List the runs of a stack`) + }, + } + common.AddOrgFlag(cmd) + cmd.PersistentFlags().String("workflow-group", "", "The workflow group under the organization.") + _ = cmd.MarkPersistentFlagRequired("workflow-group") + cmd.PersistentFlags().String("stack-id", "", "The stack ID.") + _ = cmd.MarkPersistentFlagRequired("stack-id") + cmd.AddCommand( + newCreateCmd(c), + newReadCmd(c), + newListCmd(c), + ) + return cmd +} diff --git a/go/cmd/stacktemplate/create.go b/go/cmd/stacktemplate/create.go new file mode 100644 index 0000000..c246ccd --- /dev/null +++ b/go/cmd/stacktemplate/create.go @@ -0,0 +1,43 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stacktemplate + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/stacktemplates" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create a stack template", + Long: `Create a stack template`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + createFirstRevision := common.Bool(cmd, "create-first-revision") + var req stacktemplates.CreateStackTemplateRequest + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.StackTemplates.CreateStackTemplate(ctx, org, createFirstRevision, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Stack template created successfully.") + return nil + }, + } + cmd.Flags().Bool("create-first-revision", true, "Also create the first revision of the template.") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stacktemplate/delete.go b/go/cmd/stacktemplate/delete.go new file mode 100644 index 0000000..0db09cb --- /dev/null +++ b/go/cmd/stacktemplate/delete.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stacktemplate + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete a stack template", + Long: `Delete a stack template`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + if err := c.StackTemplates.DeleteStackTemplate(ctx, org, templateId); err != nil { + return err + } + common.Done(cmd, nil, "Stack template deleted successfully.") + return nil + }, + } + cmd.Flags().String("template-id", "", "The template ID.") + _ = cmd.MarkFlagRequired("template-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stacktemplate/read.go b/go/cmd/stacktemplate/read.go new file mode 100644 index 0000000..8c78321 --- /dev/null +++ b/go/cmd/stacktemplate/read.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stacktemplate + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get a stack template", + Long: `Get a stack template`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + response, err := c.StackTemplates.ReadStackTemplate(ctx, org, templateId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("template-id", "", "The template ID.") + _ = cmd.MarkFlagRequired("template-id") + return cmd +} diff --git a/go/cmd/stacktemplate/revisions_create.go b/go/cmd/stacktemplate/revisions_create.go new file mode 100644 index 0000000..0dabfbd --- /dev/null +++ b/go/cmd/stacktemplate/revisions_create.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stacktemplate + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/stacktemplaterevisions" + "github.com/spf13/cobra" +) + +func newRevisionsCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create a new revision of a stack template", + Long: `Create a new revision of a stack template`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + var req stacktemplaterevisions.CreateStackTemplateRevisionRequest + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.StackTemplateRevisions.CreateStackTemplateRevision(ctx, org, templateId, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Revision created successfully.") + return nil + }, + } + cmd.Flags().String("template-id", "", "The template ID.") + _ = cmd.MarkFlagRequired("template-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stacktemplate/revisions_delete.go b/go/cmd/stacktemplate/revisions_delete.go new file mode 100644 index 0000000..0ed7ed6 --- /dev/null +++ b/go/cmd/stacktemplate/revisions_delete.go @@ -0,0 +1,35 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stacktemplate + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newRevisionsDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete a stack template revision", + Long: `Delete a stack template revision`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + revisionId := common.String(cmd, "revision-id") + keepParentTemplate := common.Bool(cmd, "keep-parent-template") + if err := c.StackTemplateRevisions.DeleteStackTemplateRevision(ctx, org, revisionId, keepParentTemplate); err != nil { + return err + } + common.Done(cmd, nil, "Revision deleted successfully.") + return nil + }, + } + cmd.Flags().String("revision-id", "", "The revision ID (NAME:REVISION).") + _ = cmd.MarkFlagRequired("revision-id") + cmd.Flags().Bool("keep-parent-template", false, "Keep the parent template when deleting its last revision.") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stacktemplate/revisions_read.go b/go/cmd/stacktemplate/revisions_read.go new file mode 100644 index 0000000..62091e5 --- /dev/null +++ b/go/cmd/stacktemplate/revisions_read.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stacktemplate + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newRevisionsReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get a stack template revision", + Long: `Get a stack template revision`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + revisionId := common.String(cmd, "revision-id") + response, err := c.StackTemplateRevisions.ReadStackTemplateRevision(ctx, org, revisionId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("revision-id", "", "The revision ID (NAME:REVISION).") + _ = cmd.MarkFlagRequired("revision-id") + return cmd +} diff --git a/go/cmd/stacktemplate/revisions_update.go b/go/cmd/stacktemplate/revisions_update.go new file mode 100644 index 0000000..32eb6fb --- /dev/null +++ b/go/cmd/stacktemplate/revisions_update.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stacktemplate + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/stacktemplaterevisions" + "github.com/spf13/cobra" +) + +func newRevisionsUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a stack template revision", + Long: `Update a stack template revision`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + revisionId := common.String(cmd, "revision-id") + var req stacktemplaterevisions.UpdateStackTemplateRevisionRequest + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.StackTemplateRevisions.UpdateStackTemplateRevision(ctx, org, revisionId, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Revision updated successfully.") + return nil + }, + } + cmd.Flags().String("revision-id", "", "The revision ID (NAME:REVISION).") + _ = cmd.MarkFlagRequired("revision-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stacktemplate/stacktemplate.go b/go/cmd/stacktemplate/stacktemplate.go new file mode 100644 index 0000000..149ff52 --- /dev/null +++ b/go/cmd/stacktemplate/stacktemplate.go @@ -0,0 +1,55 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stacktemplate + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewStackTemplateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "stack-template", + Short: "Manage stack (IaC group) templates", + Long: `Manage stack (IaC group) templates`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + read Get a stack template + create Create a stack template + update Update a stack template + delete Delete a stack template + revisions Manage revisions of stack (IaC group) templates`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newReadCmd(c), + newCreateCmd(c), + newUpdateCmd(c), + newDeleteCmd(c), + newRevisionsCmd(c), + ) + return cmd +} +func newRevisionsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "revisions", + Short: "Manage revisions of stack (IaC group) templates", + Long: `Manage revisions of stack (IaC group) templates`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + create Create a new revision of a stack template + read Get a stack template revision + update Update a stack template revision + delete Delete a stack template revision`) + }, + } + cmd.AddCommand( + newRevisionsCreateCmd(c), + newRevisionsReadCmd(c), + newRevisionsUpdateCmd(c), + newRevisionsDeleteCmd(c), + ) + return cmd +} diff --git a/go/cmd/stacktemplate/update.go b/go/cmd/stacktemplate/update.go new file mode 100644 index 0000000..ec41c6b --- /dev/null +++ b/go/cmd/stacktemplate/update.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stacktemplate + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/stacktemplates" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a stack template", + Long: `Update a stack template`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + var req stacktemplates.UpdateStackTemplateRequest + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.StackTemplates.UpdateStackTemplate(ctx, org, templateId, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Stack template updated successfully.") + return nil + }, + } + cmd.Flags().String("template-id", "", "The template ID.") + _ = cmd.MarkFlagRequired("template-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stackworkflow/artifacts_create.go b/go/cmd/stackworkflow/artifacts_create.go new file mode 100644 index 0000000..2cc25dc --- /dev/null +++ b/go/cmd/stackworkflow/artifacts_create.go @@ -0,0 +1,46 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflow + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newArtifactsCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create or replace an artifact with the JSON payload as its content", + Long: `Create or replace an artifact with the JSON payload as its content`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + artifactId := common.String(cmd, "artifact-id") + var req interface{} + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.StackWorkflows.CreateStackWorkflowArtifact(ctx, org, stackId, workflowId, workflowGroup, artifactId, req) + if err != nil { + return err + } + common.Done(cmd, response, "Artifact created successfully.") + return nil + }, + } + cmd.Flags().String("artifact-id", "", "The artifact ID (path).") + _ = cmd.MarkFlagRequired("artifact-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stackworkflow/artifacts_delete.go b/go/cmd/stackworkflow/artifacts_delete.go new file mode 100644 index 0000000..35a823a --- /dev/null +++ b/go/cmd/stackworkflow/artifacts_delete.go @@ -0,0 +1,37 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflow + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newArtifactsDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete an artifact", + Long: `Delete an artifact`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + artifactId := common.String(cmd, "artifact-id") + response, err := c.StackWorkflows.DeleteStackWorkflowArtifact(ctx, org, stackId, workflowId, workflowGroup, artifactId) + if err != nil { + return err + } + common.Done(cmd, response, "Artifact deleted successfully.") + return nil + }, + } + cmd.Flags().String("artifact-id", "", "The artifact ID (path).") + _ = cmd.MarkFlagRequired("artifact-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stackworkflow/artifacts_get_url.go b/go/cmd/stackworkflow/artifacts_get_url.go new file mode 100644 index 0000000..e98f9e5 --- /dev/null +++ b/go/cmd/stackworkflow/artifacts_get_url.go @@ -0,0 +1,37 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflow + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflows" + "github.com/spf13/cobra" +) + +func newArtifactsGetUrlCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "get-url", + Short: "Get a signed download URL for an artifact", + Long: `Get a signed download URL for an artifact`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + artifactPath := common.String(cmd, "artifact-path") + response, err := c.StackWorkflows.GetStackWorkflowArtifactUrl(ctx, org, stackId, workflowId, workflowGroup, &workflows.GetWorkflowArtifactRequest{ArtifactPath: artifactPath}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("artifact-path", "", "Path of the artifact.") + _ = cmd.MarkFlagRequired("artifact-path") + return cmd +} diff --git a/go/cmd/stackworkflow/artifacts_list.go b/go/cmd/stackworkflow/artifacts_list.go new file mode 100644 index 0000000..3965f1c --- /dev/null +++ b/go/cmd/stackworkflow/artifacts_list.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflow + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newArtifactsListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List the artifacts of a stack workflow", + Long: `List the artifacts of a stack workflow`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + response, err := c.StackWorkflows.ListAllStackWorkflowsArtifacts(ctx, org, stackId, workflowId, workflowGroup) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + return cmd +} diff --git a/go/cmd/stackworkflow/artifacts_lock.go b/go/cmd/stackworkflow/artifacts_lock.go new file mode 100644 index 0000000..9515a63 --- /dev/null +++ b/go/cmd/stackworkflow/artifacts_lock.go @@ -0,0 +1,37 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflow + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newArtifactsLockCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "lock", + Short: "Lock the stack workflow on an artifact", + Long: `Lock the stack workflow on an artifact`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + artifactId := common.String(cmd, "artifact-id") + response, err := c.StackWorkflows.LockStackWorkflowArtifact(ctx, org, stackId, workflowId, workflowGroup, artifactId) + if err != nil { + return err + } + common.Done(cmd, response, "Artifact locked.") + return nil + }, + } + cmd.Flags().String("artifact-id", "", "The artifact ID (path).") + _ = cmd.MarkFlagRequired("artifact-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stackworkflow/artifacts_read.go b/go/cmd/stackworkflow/artifacts_read.go new file mode 100644 index 0000000..14c0e4e --- /dev/null +++ b/go/cmd/stackworkflow/artifacts_read.go @@ -0,0 +1,36 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflow + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newArtifactsReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Read an artifact's content (or a signed URL on private runners)", + Long: `Read an artifact's content (or a signed URL on private runners)`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + artifactId := common.String(cmd, "artifact-id") + response, err := c.StackWorkflows.ReadStackWorkflowArtifact(ctx, org, stackId, workflowId, workflowGroup, artifactId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("artifact-id", "", "The artifact ID (path).") + _ = cmd.MarkFlagRequired("artifact-id") + return cmd +} diff --git a/go/cmd/stackworkflow/artifacts_unlock.go b/go/cmd/stackworkflow/artifacts_unlock.go new file mode 100644 index 0000000..474d93f --- /dev/null +++ b/go/cmd/stackworkflow/artifacts_unlock.go @@ -0,0 +1,37 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflow + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newArtifactsUnlockCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "unlock", + Short: "Release the stack workflow's lock on an artifact", + Long: `Release the stack workflow's lock on an artifact`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + artifactId := common.String(cmd, "artifact-id") + response, err := c.StackWorkflows.UnlockStackWorkflowArtifact(ctx, org, stackId, workflowId, workflowGroup, artifactId) + if err != nil { + return err + } + common.Done(cmd, response, "Artifact unlocked.") + return nil + }, + } + cmd.Flags().String("artifact-id", "", "The artifact ID (path).") + _ = cmd.MarkFlagRequired("artifact-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stackworkflow/compare.go b/go/cmd/stackworkflow/compare.go new file mode 100644 index 0000000..057b8c5 --- /dev/null +++ b/go/cmd/stackworkflow/compare.go @@ -0,0 +1,59 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflow + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflows" + "github.com/spf13/cobra" +) + +func newCompareCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "compare -- payload.json", + Short: "Compare a stack workflow against a template without applying changes", + Long: `Compare a stack workflow against a template without applying changes`, + Args: cobra.MaximumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + var req workflows.CompareWorkflowRequest + if len(args) > 0 { + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + } + if v := common.OptString(cmd, "target-template-id"); v != nil { + req.TargetTemplateId = *v + } + if v := common.OptString(cmd, "upgrade-mode"); v != nil { + req.UpgradeMode = v + } + if req.TargetTemplateId == "" { + return errors.New("provide --target-template-id or a payload with targetTemplateId") + } + response, err := c.StackWorkflows.CompareStackWorkflow(ctx, org, stackId, workflowId, workflowGroup, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Comparison completed.") + return nil + }, + } + cmd.Flags().String("workflow-id", "", "The workflow ID.") + _ = cmd.MarkFlagRequired("workflow-id") + cmd.Flags().String("target-template-id", "", "Template to compare against.") + cmd.Flags().String("upgrade-mode", "", "Upgrade mode to simulate.") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stackworkflow/create.go b/go/cmd/stackworkflow/create.go new file mode 100644 index 0000000..314dafe --- /dev/null +++ b/go/cmd/stackworkflow/create.go @@ -0,0 +1,43 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflow + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflows" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create a workflow inside a stack", + Long: `Create a workflow inside a stack`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + var req workflows.Workflow + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.StackWorkflows.CreateStackWorkflow(ctx, org, stackId, workflowGroup, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Stack workflow created successfully.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stackworkflow/delete.go b/go/cmd/stackworkflow/delete.go new file mode 100644 index 0000000..efacebf --- /dev/null +++ b/go/cmd/stackworkflow/delete.go @@ -0,0 +1,35 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflow + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete a stack workflow", + Long: `Delete a stack workflow`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + if err := c.StackWorkflows.DeleteStackWorkflow(ctx, org, stackId, workflowId, workflowGroup); err != nil { + return err + } + common.Done(cmd, nil, "Stack workflow deleted successfully.") + return nil + }, + } + cmd.Flags().String("workflow-id", "", "The workflow ID.") + _ = cmd.MarkFlagRequired("workflow-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stackworkflow/file_upload_url.go b/go/cmd/stackworkflow/file_upload_url.go new file mode 100644 index 0000000..7561093 --- /dev/null +++ b/go/cmd/stackworkflow/file_upload_url.go @@ -0,0 +1,40 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflow + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflows" + "github.com/spf13/cobra" +) + +func newFileUploadUrlCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "file-upload-url", + Short: "Get a signed URL to upload a file to a stack workflow", + Long: `Get a signed URL to upload a file to a stack workflow`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + filename := common.String(cmd, "filename") + response, err := c.StackWorkflows.GetFileUploadUrlForStackWorkflow(ctx, org, stackId, workflowId, workflowGroup, &workflows.GetFileUploadUrlRequest{Filename: filename, Folder: common.OptString(cmd, "folder")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("workflow-id", "", "The workflow ID.") + _ = cmd.MarkFlagRequired("workflow-id") + cmd.Flags().String("filename", "", "Name of the file to upload.") + _ = cmd.MarkFlagRequired("filename") + cmd.Flags().String("folder", "", "Folder to upload the file into.") + return cmd +} diff --git a/go/cmd/stackworkflow/list.go b/go/cmd/stackworkflow/list.go new file mode 100644 index 0000000..82e2220 --- /dev/null +++ b/go/cmd/stackworkflow/list.go @@ -0,0 +1,41 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflow + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List the workflows of a stack", + Long: `List the workflows of a stack`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + response, err := c.StackWorkflows.ListAllStackWorkflows(ctx, org, stackId, workflowGroup, &sggosdk.ListAllStackWorkflowsRequest{Description: common.OptString(cmd, "description"), IacTemplateId: common.OptString(cmd, "iac-template-id"), LatestWfRunStatuses: common.OptInt(cmd, "latest-wf-run-statuses"), ResourceNames: common.OptString(cmd, "resource-names"), RunnerNames: common.OptString(cmd, "runner-names"), Tags: common.OptString(cmd, "tags"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), Limit: common.OptInt(cmd, "limit")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + cmd.Flags().String("description", "", "Filter by description.") + cmd.Flags().String("iac-template-id", "", "Filter by IaC template id.") + cmd.Flags().Int("latest-wf-run-statuses", 0, "Filter by latest workflow run status.") + cmd.Flags().String("resource-names", "", "Filter by resource names.") + cmd.Flags().String("runner-names", "", "Filter by runner names.") + cmd.Flags().String("tags", "", "Filter by tags.") + return cmd +} diff --git a/go/cmd/stackworkflow/outputs.go b/go/cmd/stackworkflow/outputs.go new file mode 100644 index 0000000..94e7bc1 --- /dev/null +++ b/go/cmd/stackworkflow/outputs.go @@ -0,0 +1,35 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflow + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newOutputsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "outputs", + Short: "Get the outputs of a stack workflow", + Long: `Get the outputs of a stack workflow`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + response, err := c.StackWorkflows.StackWorkflowOutputs(ctx, org, stackId, workflowId, workflowGroup) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("workflow-id", "", "The workflow ID.") + _ = cmd.MarkFlagRequired("workflow-id") + return cmd +} diff --git a/go/cmd/stackworkflow/read.go b/go/cmd/stackworkflow/read.go new file mode 100644 index 0000000..485d1d6 --- /dev/null +++ b/go/cmd/stackworkflow/read.go @@ -0,0 +1,35 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflow + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get a stack workflow", + Long: `Get a stack workflow`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + response, err := c.StackWorkflows.ReadStackWorkflow(ctx, org, stackId, workflowId, workflowGroup) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("workflow-id", "", "The workflow ID.") + _ = cmd.MarkFlagRequired("workflow-id") + return cmd +} diff --git a/go/cmd/stackworkflow/stackworkflow.go b/go/cmd/stackworkflow/stackworkflow.go new file mode 100644 index 0000000..859afff --- /dev/null +++ b/go/cmd/stackworkflow/stackworkflow.go @@ -0,0 +1,79 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflow + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewStackWorkflowCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "stack-workflow", + Short: "Manage the workflows that belong to a stack", + Long: `Manage the workflows that belong to a stack`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + create Create a workflow inside a stack + read Get a stack workflow + update Update a stack workflow + delete Delete a stack workflow + list List the workflows of a stack + outputs Get the outputs of a stack workflow + tfstate-upload-url Get a signed URL to upload a Terraform state file + file-upload-url Get a signed URL to upload a file to a stack workflow + compare Compare a stack workflow against a template without applying changes + vcs-triggers Create VCS webhook triggers for a stack workflow + artifacts Manage the artifacts of a stack workflow`) + }, + } + common.AddOrgFlag(cmd) + cmd.PersistentFlags().String("workflow-group", "", "The workflow group under the organization.") + _ = cmd.MarkPersistentFlagRequired("workflow-group") + cmd.PersistentFlags().String("stack-id", "", "The stack ID.") + _ = cmd.MarkPersistentFlagRequired("stack-id") + cmd.AddCommand( + newCreateCmd(c), + newReadCmd(c), + newUpdateCmd(c), + newDeleteCmd(c), + newListCmd(c), + newOutputsCmd(c), + newTfstateUploadUrlCmd(c), + newFileUploadUrlCmd(c), + newCompareCmd(c), + newVcsTriggersCmd(c), + newArtifactsCmd(c), + ) + return cmd +} +func newArtifactsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "artifacts", + Short: "Manage the artifacts of a stack workflow", + Long: `Manage the artifacts of a stack workflow`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + list List the artifacts of a stack workflow + get-url Get a signed download URL for an artifact + read Read an artifact's content (or a signed URL on private runners) + create Create or replace an artifact with the JSON payload as its content + delete Delete an artifact + lock Lock the stack workflow on an artifact + unlock Release the stack workflow's lock on an artifact`) + }, + } + cmd.PersistentFlags().String("workflow-id", "", "The workflow ID.") + _ = cmd.MarkPersistentFlagRequired("workflow-id") + cmd.AddCommand( + newArtifactsListCmd(c), + newArtifactsGetUrlCmd(c), + newArtifactsReadCmd(c), + newArtifactsCreateCmd(c), + newArtifactsDeleteCmd(c), + newArtifactsLockCmd(c), + newArtifactsUnlockCmd(c), + ) + return cmd +} diff --git a/go/cmd/stackworkflow/tfstate_upload_url.go b/go/cmd/stackworkflow/tfstate_upload_url.go new file mode 100644 index 0000000..b8df44c --- /dev/null +++ b/go/cmd/stackworkflow/tfstate_upload_url.go @@ -0,0 +1,37 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflow + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newTfstateUploadUrlCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "tfstate-upload-url", + Short: "Get a signed URL to upload a Terraform state file", + Long: `Get a signed URL to upload a Terraform state file`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + response, err := c.StackWorkflows.GetSignedUrlToUploadTfstateFileForStackWorkflow(ctx, org, stackId, workflowId, workflowGroup, &sggosdk.GetSignedUrlToUploadTfstateFileForStackWorkflowRequest{Filename: common.OptString(cmd, "filename")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("workflow-id", "", "The workflow ID.") + _ = cmd.MarkFlagRequired("workflow-id") + cmd.Flags().String("filename", "", "Name of the file to upload (default tfstate.json).") + return cmd +} diff --git a/go/cmd/stackworkflow/update.go b/go/cmd/stackworkflow/update.go new file mode 100644 index 0000000..4c295c3 --- /dev/null +++ b/go/cmd/stackworkflow/update.go @@ -0,0 +1,46 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflow + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a stack workflow", + Long: `Update a stack workflow`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + var req sggosdk.PatchedWorkflow + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.StackWorkflows.UpdateStackWorkflow(ctx, org, stackId, workflowId, workflowGroup, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Stack workflow updated successfully.") + return nil + }, + } + cmd.Flags().String("workflow-id", "", "The workflow ID.") + _ = cmd.MarkFlagRequired("workflow-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stackworkflow/vcs_triggers.go b/go/cmd/stackworkflow/vcs_triggers.go new file mode 100644 index 0000000..27d53a4 --- /dev/null +++ b/go/cmd/stackworkflow/vcs_triggers.go @@ -0,0 +1,46 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflow + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflows" + "github.com/spf13/cobra" +) + +func newVcsTriggersCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "vcs-triggers -- payload.json", + Short: "Create VCS webhook triggers for a stack workflow", + Long: `Create VCS webhook triggers for a stack workflow`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + var req workflows.CreateVcsTriggersRequest + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.StackWorkflows.CreateVcsTriggersForStackWorkflow(ctx, org, stackId, workflowId, workflowGroup, &req) + if err != nil { + return err + } + common.Done(cmd, response, "VCS triggers created successfully.") + return nil + }, + } + cmd.Flags().String("workflow-id", "", "The workflow ID.") + _ = cmd.MarkFlagRequired("workflow-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stackworkflowrun/approve.go b/go/cmd/stackworkflowrun/approve.go new file mode 100644 index 0000000..705ca2d --- /dev/null +++ b/go/cmd/stackworkflowrun/approve.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflowrun + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newApproveCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "approve", + Short: "Approve (or, with --reject, reject) a stack workflow run waiting for approval", + Long: `Approve (or, with --reject, reject) a stack workflow run waiting for approval`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + runId := common.String(cmd, "run-id") + reject := common.Bool(cmd, "reject") + approve := !reject + body := sggosdk.WorkflowRunApproval{Approve: &approve, Message: common.OptString(cmd, "message"), ApprovalStep: common.OptString(cmd, "approval-step"), ReasonForApprovalRequired: common.OptString(cmd, "reason")} + if err := c.StackWorkflowRuns.ApproveStackWorkflowRun(ctx, org, stackId, workflowId, workflowGroup, runId, &body); err != nil { + return err + } + common.Done(cmd, nil, "Approval decision submitted.") + return nil + }, + } + cmd.PersistentFlags().String("run-id", "", "The workflow run ID.") + _ = cmd.MarkPersistentFlagRequired("run-id") + cmd.Flags().Bool("reject", false, "Reject instead of approve.") + cmd.Flags().String("message", "", "Message to attach to the decision.") + cmd.Flags().String("approval-step", "", "Name of the approval step.") + cmd.Flags().String("reason", "", "Reason the approval was required.") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stackworkflowrun/create.go b/go/cmd/stackworkflowrun/create.go new file mode 100644 index 0000000..07a89db --- /dev/null +++ b/go/cmd/stackworkflowrun/create.go @@ -0,0 +1,46 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflowrun + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Trigger a run of a stack workflow (payload optional)", + Long: `Trigger a run of a stack workflow (payload optional)`, + Args: cobra.MaximumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + var req sggosdk.WorkflowRun + if len(args) > 0 { + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + } + response, err := c.StackWorkflowRuns.CreateStackWorkflowRun(ctx, org, stackId, workflowId, workflowGroup, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Stack workflow run created successfully.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stackworkflowrun/delete.go b/go/cmd/stackworkflowrun/delete.go new file mode 100644 index 0000000..7aa4092 --- /dev/null +++ b/go/cmd/stackworkflowrun/delete.go @@ -0,0 +1,37 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflowrun + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Cancel a stack workflow run through the DELETE endpoint", + Long: `Cancel a stack workflow run through the DELETE endpoint`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + runId := common.String(cmd, "run-id") + response, err := c.StackWorkflowRuns.DeleteStackWorkflowRun(ctx, org, stackId, workflowId, workflowGroup, runId) + if err != nil { + return err + } + common.Done(cmd, response, "Stack workflow run cancelled.") + return nil + }, + } + cmd.PersistentFlags().String("run-id", "", "The workflow run ID.") + _ = cmd.MarkPersistentFlagRequired("run-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stackworkflowrun/facts_create.go b/go/cmd/stackworkflowrun/facts_create.go new file mode 100644 index 0000000..724750d --- /dev/null +++ b/go/cmd/stackworkflowrun/facts_create.go @@ -0,0 +1,47 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflowrun + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newFactsCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create or replace the facts of a stack workflow run", + Long: `Create or replace the facts of a stack workflow run`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + runId := common.String(cmd, "run-id") + factsId := common.String(cmd, "facts-id") + var req map[string]interface{} + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.StackWorkflowRunFacts.CreateStackWorkflowRunFacts(ctx, org, stackId, workflowId, workflowGroup, runId, factsId, req) + if err != nil { + return err + } + common.Done(cmd, response, "Stack workflow run facts created.") + return nil + }, + } + cmd.Flags().String("facts-id", "", "The workflow run facts ID.") + _ = cmd.MarkFlagRequired("facts-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stackworkflowrun/facts_read.go b/go/cmd/stackworkflowrun/facts_read.go new file mode 100644 index 0000000..f276c72 --- /dev/null +++ b/go/cmd/stackworkflowrun/facts_read.go @@ -0,0 +1,37 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflowrun + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newFactsReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get the facts of a stack workflow run", + Long: `Get the facts of a stack workflow run`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + runId := common.String(cmd, "run-id") + factsId := common.String(cmd, "facts-id") + response, err := c.StackWorkflowRunFacts.GetStackWorkflowRunFacts(ctx, org, stackId, workflowId, workflowGroup, runId, factsId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("facts-id", "", "The workflow run facts ID.") + _ = cmd.MarkFlagRequired("facts-id") + return cmd +} diff --git a/go/cmd/stackworkflowrun/facts_update.go b/go/cmd/stackworkflowrun/facts_update.go new file mode 100644 index 0000000..81cc7d9 --- /dev/null +++ b/go/cmd/stackworkflowrun/facts_update.go @@ -0,0 +1,47 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflowrun + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newFactsUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update the facts of a stack workflow run", + Long: `Update the facts of a stack workflow run`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + runId := common.String(cmd, "run-id") + factsId := common.String(cmd, "facts-id") + var req map[string]interface{} + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.StackWorkflowRunFacts.UpdateStackWorkflowRunFacts(ctx, org, stackId, workflowId, workflowGroup, runId, factsId, req) + if err != nil { + return err + } + common.Done(cmd, response, "Stack workflow run facts updated.") + return nil + }, + } + cmd.Flags().String("facts-id", "", "The workflow run facts ID.") + _ = cmd.MarkFlagRequired("facts-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/stackworkflowrun/list.go b/go/cmd/stackworkflowrun/list.go new file mode 100644 index 0000000..797bd1c --- /dev/null +++ b/go/cmd/stackworkflowrun/list.go @@ -0,0 +1,54 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflowrun + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/stackworkflowruns" + "github.com/spf13/cobra" +) + +func newListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List the runs of a stack workflow", + Long: `List the runs of a stack workflow`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + response, err := c.StackWorkflowRuns.ListAllStackWorkflowRuns(ctx, org, stackId, workflowId, workflowGroup, &stackworkflowruns.ListAllStackWorkflowRunsRequest{ + Limit: common.OptInt(cmd, "limit"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), CreatedAfter: common.OptString(cmd, "created-after"), ParentKSUID: common.OptString(cmd, "parent-ksuid"), + ResourceNames: common.OptString(cmd, "resource-names"), TemplateId: common.OptString(cmd, "template-id"), UseMarketplaceTemplate: common.OptString(cmd, "use-marketplace-template"), Author: common.OptString(cmd, "author"), + Approver: common.OptString(cmd, "approver"), LatestStatus: common.OptString(cmd, "latest-status"), RepoId: common.OptString(cmd, "repo-id"), Ref: common.OptString(cmd, "ref"), TerraformAction: common.OptString(cmd, "terraform-action"), + RunnerType: common.OptString(cmd, "runner-type"), ContextTags: common.OptString(cmd, "context-tags"), + }) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + cmd.Flags().String("created-after", "", "Only runs created after this Unix timestamp in milliseconds.") + cmd.Flags().String("parent-ksuid", "", "KSUID of the parent workflow.") + cmd.Flags().String("resource-names", "", "Filter by resource names (comma-separated).") + cmd.Flags().String("template-id", "", "Filter by IaC template id.") + cmd.Flags().String("use-marketplace-template", "", "Filter by marketplace template usage (true/false).") + cmd.Flags().String("author", "", "Filter by authors (comma-separated).") + cmd.Flags().String("approver", "", "Filter by approvers (comma-separated).") + cmd.Flags().String("latest-status", "", "Filter by latest status (comma-separated).") + cmd.Flags().String("repo-id", "", "Filter by VCS repository.") + cmd.Flags().String("ref", "", "Filter by VCS ref.") + cmd.Flags().String("terraform-action", "", "Filter by Terraform action (comma-separated).") + cmd.Flags().String("runner-type", "", "Filter by runner type.") + cmd.Flags().String("context-tags", "", "Filter by context tags as key or key:value (comma-separated).") + return cmd +} diff --git a/go/cmd/stackworkflowrun/logs.go b/go/cmd/stackworkflowrun/logs.go new file mode 100644 index 0000000..6aae008 --- /dev/null +++ b/go/cmd/stackworkflowrun/logs.go @@ -0,0 +1,36 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflowrun + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newLogsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "logs", + Short: "Get the logs of a stack workflow run", + Long: `Get the logs of a stack workflow run`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + runId := common.String(cmd, "run-id") + response, err := c.StackWorkflowRuns.ReadStackWorkflowRunLogs(ctx, org, stackId, workflowId, workflowGroup, runId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.PersistentFlags().String("run-id", "", "The workflow run ID.") + _ = cmd.MarkPersistentFlagRequired("run-id") + return cmd +} diff --git a/go/cmd/stackworkflowrun/read.go b/go/cmd/stackworkflowrun/read.go new file mode 100644 index 0000000..e54b827 --- /dev/null +++ b/go/cmd/stackworkflowrun/read.go @@ -0,0 +1,36 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflowrun + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get a stack workflow run", + Long: `Get a stack workflow run`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + runId := common.String(cmd, "run-id") + response, err := c.StackWorkflowRuns.ReadStackWorkflowRun(ctx, org, stackId, workflowId, workflowGroup, runId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.PersistentFlags().String("run-id", "", "The workflow run ID.") + _ = cmd.MarkPersistentFlagRequired("run-id") + return cmd +} diff --git a/go/cmd/stackworkflowrun/stackworkflowrun.go b/go/cmd/stackworkflowrun/stackworkflowrun.go new file mode 100644 index 0000000..9118dda --- /dev/null +++ b/go/cmd/stackworkflowrun/stackworkflowrun.go @@ -0,0 +1,67 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflowrun + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewStackWorkflowRunCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "stack-workflow-run", + Short: "Trigger, inspect and approve runs of a stack workflow", + Long: `Trigger, inspect and approve runs of a stack workflow`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + create Trigger a run of a stack workflow (payload optional) + read Get a stack workflow run + update Update a stack workflow run + delete Cancel a stack workflow run through the DELETE endpoint + logs Get the logs of a stack workflow run + approve Approve (or, with --reject, reject) a stack workflow run waiting for approval + list List the runs of a stack workflow + facts Read and write the facts of a stack workflow run`) + }, + } + common.AddOrgFlag(cmd) + cmd.PersistentFlags().String("workflow-group", "", "The workflow group under the organization.") + _ = cmd.MarkPersistentFlagRequired("workflow-group") + cmd.PersistentFlags().String("stack-id", "", "The stack ID.") + _ = cmd.MarkPersistentFlagRequired("stack-id") + cmd.PersistentFlags().String("workflow-id", "", "The workflow ID.") + _ = cmd.MarkPersistentFlagRequired("workflow-id") + cmd.AddCommand( + newCreateCmd(c), + newReadCmd(c), + newUpdateCmd(c), + newDeleteCmd(c), + newLogsCmd(c), + newApproveCmd(c), + newListCmd(c), + newFactsCmd(c), + ) + return cmd +} +func newFactsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "facts", + Short: "Read and write the facts of a stack workflow run", + Long: `Read and write the facts of a stack workflow run`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + read Get the facts of a stack workflow run + create Create or replace the facts of a stack workflow run + update Update the facts of a stack workflow run`) + }, + } + cmd.PersistentFlags().String("run-id", "", "The workflow run ID.") + _ = cmd.MarkPersistentFlagRequired("run-id") + cmd.AddCommand( + newFactsReadCmd(c), + newFactsCreateCmd(c), + newFactsUpdateCmd(c), + ) + return cmd +} diff --git a/go/cmd/stackworkflowrun/update.go b/go/cmd/stackworkflowrun/update.go new file mode 100644 index 0000000..f0b3231 --- /dev/null +++ b/go/cmd/stackworkflowrun/update.go @@ -0,0 +1,47 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package stackworkflowrun + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a stack workflow run", + Long: `Update a stack workflow run`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + stackId := common.String(cmd, "stack-id") + workflowId := common.String(cmd, "workflow-id") + runId := common.String(cmd, "run-id") + var req sggosdk.PatchedWorkflowRun + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.StackWorkflowRuns.UpdateStackWorkflowRun(ctx, org, stackId, workflowId, workflowGroup, runId, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Stack workflow run updated successfully.") + return nil + }, + } + cmd.PersistentFlags().String("run-id", "", "The workflow run ID.") + _ = cmd.MarkPersistentFlagRequired("run-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/statebackend/create.go b/go/cmd/statebackend/create.go new file mode 100644 index 0000000..55a50dd --- /dev/null +++ b/go/cmd/statebackend/create.go @@ -0,0 +1,41 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package statebackend + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/statebackends" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create a new state backend", + Long: `Create a new state backend`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req statebackends.StateBackend + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.StateBackends.CreateStateBackend(ctx, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "State backend created successfully.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/statebackend/delete.go b/go/cmd/statebackend/delete.go new file mode 100644 index 0000000..3dee392 --- /dev/null +++ b/go/cmd/statebackend/delete.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package statebackend + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete a state backend", + Long: `Delete a state backend`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + stateBackend := common.String(cmd, "state-backend") + response, err := c.StateBackends.DeleteStateBackend(ctx, org, stateBackend) + if err != nil { + return err + } + common.Done(cmd, response, "State backend deleted successfully.") + return nil + }, + } + cmd.Flags().String("state-backend", "", "The state backend name.") + _ = cmd.MarkFlagRequired("state-backend") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/statebackend/list.go b/go/cmd/statebackend/list.go new file mode 100644 index 0000000..4bc8aa8 --- /dev/null +++ b/go/cmd/statebackend/list.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package statebackend + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/statebackends" + "github.com/spf13/cobra" +) + +func newListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List state backends", + Long: `List state backends`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.StateBackends.ListAllStateBackends(ctx, org, &statebackends.ListAllStateBackendsRequest{Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), Limit: common.OptInt(cmd, "limit"), SearchQuery: common.OptString(cmd, "search-query")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + cmd.Flags().String("search-query", "", "Search by resource name, tags or description.") + return cmd +} diff --git a/go/cmd/statebackend/list_statefiles.go b/go/cmd/statebackend/list_statefiles.go new file mode 100644 index 0000000..0fb135a --- /dev/null +++ b/go/cmd/statebackend/list_statefiles.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package statebackend + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/statebackends" + "github.com/spf13/cobra" +) + +func newListStatefilesCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list-statefiles", + Short: "List the state files in a storage backend", + Long: `List the state files in a storage backend`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + config := common.String(cmd, "config") + response, err := c.StateBackends.ListStatefiles(ctx, org, &statebackends.ListStatefilesRequest{Config: config}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("config", "", "Base64-encoded JSON StateBackendConfig.") + _ = cmd.MarkFlagRequired("config") + return cmd +} diff --git a/go/cmd/statebackend/read.go b/go/cmd/statebackend/read.go new file mode 100644 index 0000000..b3d25a3 --- /dev/null +++ b/go/cmd/statebackend/read.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package statebackend + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get details of a state backend", + Long: `Get details of a state backend`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + stateBackend := common.String(cmd, "state-backend") + response, err := c.StateBackends.ReadStateBackend(ctx, org, stateBackend) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("state-backend", "", "The state backend name.") + _ = cmd.MarkFlagRequired("state-backend") + return cmd +} diff --git a/go/cmd/statebackend/statebackend.go b/go/cmd/statebackend/statebackend.go new file mode 100644 index 0000000..1f724f6 --- /dev/null +++ b/go/cmd/statebackend/statebackend.go @@ -0,0 +1,36 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package statebackend + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewStateBackendCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "state-backend", + Short: "Manage state backends (S3 or Azure Blob storage for state files)", + Long: `Manage state backends (S3 or Azure Blob storage for state files)`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + create Create a new state backend + read Get details of a state backend + update Update a state backend + delete Delete a state backend + list List state backends + list-statefiles List the state files in a storage backend`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newCreateCmd(c), + newReadCmd(c), + newUpdateCmd(c), + newDeleteCmd(c), + newListCmd(c), + newListStatefilesCmd(c), + ) + return cmd +} diff --git a/go/cmd/statebackend/update.go b/go/cmd/statebackend/update.go new file mode 100644 index 0000000..3296d8a --- /dev/null +++ b/go/cmd/statebackend/update.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package statebackend + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/statebackends" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a state backend", + Long: `Update a state backend`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + stateBackend := common.String(cmd, "state-backend") + var req statebackends.PatchedStateBackend + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.StateBackends.UpdateStateBackend(ctx, org, stateBackend, &req) + if err != nil { + return err + } + common.Done(cmd, response, "State backend updated successfully.") + return nil + }, + } + cmd.Flags().String("state-backend", "", "The state backend name.") + _ = cmd.MarkFlagRequired("state-backend") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/template/artifacts_delete.go b/go/cmd/template/artifacts_delete.go new file mode 100644 index 0000000..9ecfc41 --- /dev/null +++ b/go/cmd/template/artifacts_delete.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/templates" + "github.com/spf13/cobra" +) + +func newArtifactsDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete an artifact", + Long: `Delete an artifact`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + templateType := common.String(cmd, "template-type") + ownerOrg := common.String(cmd, "owner-org") + artifactId := common.String(cmd, "artifact-id") + if err := common.CheckEnum("template-type", templateType, "IAC", "IAC_GROUP", "IAC_POLICY", "WORKFLOW_STEP"); err != nil { + return err + } + if ownerOrg == "" { + ownerOrg = org + } + response, err := c.Templates.DeleteTemplateArtifact(ctx, ownerOrg, templateType, templateId, artifactId, &templates.TemplateArtifactRequest{SgOrgid: org}) + if err != nil { + return err + } + common.Done(cmd, response, "Artifact deleted successfully.") + return nil + }, + } + cmd.Flags().String("artifact-id", "", "The artifact ID.") + _ = cmd.MarkFlagRequired("artifact-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/template/artifacts_download_url.go b/go/cmd/template/artifacts_download_url.go new file mode 100644 index 0000000..30dac6a --- /dev/null +++ b/go/cmd/template/artifacts_download_url.go @@ -0,0 +1,43 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/templates" + "github.com/spf13/cobra" +) + +func newArtifactsDownloadUrlCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "download-url", + Short: "Get a presigned download URL for an artifact", + Long: `Get a presigned download URL for an artifact`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + templateType := common.String(cmd, "template-type") + ownerOrg := common.String(cmd, "owner-org") + artifactId := common.String(cmd, "artifact-id") + if err := common.CheckEnum("template-type", templateType, "IAC", "IAC_GROUP", "IAC_POLICY", "WORKFLOW_STEP"); err != nil { + return err + } + if ownerOrg == "" { + ownerOrg = org + } + response, err := c.Templates.GetTemplateArtifactDownloadUrl(ctx, ownerOrg, templateType, templateId, artifactId, &templates.TemplateArtifactRequest{SgOrgid: org}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("artifact-id", "", "The artifact ID.") + _ = cmd.MarkFlagRequired("artifact-id") + return cmd +} diff --git a/go/cmd/template/artifacts_list.go b/go/cmd/template/artifacts_list.go new file mode 100644 index 0000000..73e307c --- /dev/null +++ b/go/cmd/template/artifacts_list.go @@ -0,0 +1,43 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/templates" + "github.com/spf13/cobra" +) + +func newArtifactsListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List the artifacts of a template", + Long: `List the artifacts of a template`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + templateType := common.String(cmd, "template-type") + ownerOrg := common.String(cmd, "owner-org") + if err := common.CheckEnum("template-type", templateType, "IAC", "IAC_GROUP", "IAC_POLICY", "WORKFLOW_STEP"); err != nil { + return err + } + if ownerOrg == "" { + ownerOrg = org + } + response, err := c.Templates.ListAllTemplateArtifacts(ctx, ownerOrg, templateType, templateId, &templates.ListAllTemplateArtifactsRequest{SgOrgid: org, ArtifactPrefix: common.OptString(cmd, "prefix"), MaxKeys: common.OptInt(cmd, "max-keys"), StartAfterKey: common.OptString(cmd, "start-after-key")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("prefix", "", "Only list artifacts under this prefix.") + cmd.Flags().Int("max-keys", 0, "Maximum number of keys.") + cmd.Flags().String("start-after-key", "", "Pagination: start after this key.") + return cmd +} diff --git a/go/cmd/template/artifacts_upload_url.go b/go/cmd/template/artifacts_upload_url.go new file mode 100644 index 0000000..91b8430 --- /dev/null +++ b/go/cmd/template/artifacts_upload_url.go @@ -0,0 +1,43 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/templates" + "github.com/spf13/cobra" +) + +func newArtifactsUploadUrlCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "upload-url", + Short: "Get a presigned upload URL for an artifact", + Long: `Get a presigned upload URL for an artifact`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + templateType := common.String(cmd, "template-type") + ownerOrg := common.String(cmd, "owner-org") + artifactId := common.String(cmd, "artifact-id") + if err := common.CheckEnum("template-type", templateType, "IAC", "IAC_GROUP", "IAC_POLICY", "WORKFLOW_STEP"); err != nil { + return err + } + if ownerOrg == "" { + ownerOrg = org + } + response, err := c.Templates.GetTemplateArtifactUploadUrl(ctx, ownerOrg, templateType, templateId, artifactId, &templates.TemplateArtifactRequest{SgOrgid: org}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("artifact-id", "", "The artifact ID.") + _ = cmd.MarkFlagRequired("artifact-id") + return cmd +} diff --git a/go/cmd/template/create.go b/go/cmd/template/create.go new file mode 100644 index 0000000..dbdee92 --- /dev/null +++ b/go/cmd/template/create.go @@ -0,0 +1,41 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create a template or a new revision of it (payload must include TemplateType: IAC, IAC_GROUP or IAC_POLICY)", + Long: `Create a template or a new revision of it (payload must include TemplateType: IAC, IAC_GROUP or IAC_POLICY)`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req sggosdk.CreateTemplateRequest + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.Templates.CreateTemplateRevision(ctx, &sggosdk.CreateTemplateRevisionRequest{SgOrgid: org, Body: &req}) + if err != nil { + return err + } + common.Done(cmd, response, "Template created successfully.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/template/delete.go b/go/cmd/template/delete.go new file mode 100644 index 0000000..d2a5b34 --- /dev/null +++ b/go/cmd/template/delete.go @@ -0,0 +1,45 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete a template or one of its revisions", + Long: `Delete a template or one of its revisions`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + templateType := common.String(cmd, "template-type") + ownerOrg := common.String(cmd, "owner-org") + if err := common.CheckEnum("template-type", templateType, "IAC", "IAC_GROUP", "IAC_POLICY", "WORKFLOW_STEP"); err != nil { + return err + } + if ownerOrg == "" { + ownerOrg = org + } + if err := c.Templates.DeleteTemplateRevision(ctx, ownerOrg, templateId, templateType, &sggosdk.DeleteTemplateRevisionRequest{SgOrgid: org}); err != nil { + return err + } + common.Done(cmd, nil, "Template deleted successfully.") + return nil + }, + } + cmd.Flags().String("template-id", "", "Template name, optionally with revision as NAME:REVISION.") + _ = cmd.MarkFlagRequired("template-id") + cmd.Flags().String("template-type", "", "Template type (IAC, IAC_GROUP, IAC_POLICY, WORKFLOW_STEP).") + _ = cmd.MarkFlagRequired("template-type") + cmd.Flags().String("owner-org", "", "Organization that owns the template (defaults to --org).") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/template/group_iac.go b/go/cmd/template/group_iac.go new file mode 100644 index 0000000..e12b177 --- /dev/null +++ b/go/cmd/template/group_iac.go @@ -0,0 +1,42 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newGroupIacCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "group-iac", + Short: "Get an IaC template that belongs to an IaC group template", + Long: `Get an IaC template that belongs to an IaC group template`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + iacTemplateId := common.String(cmd, "iac-template-id") + ownerOrg := common.String(cmd, "owner-org") + if ownerOrg == "" { + ownerOrg = org + } + response, err := c.Templates.ReadIacGroupsIacTemplate(ctx, ownerOrg, iacTemplateId, templateId, &sggosdk.ReadIacGroupsIacTemplateRequest{SgOrgid: org}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("template-id", "", "The IaC group template.") + _ = cmd.MarkFlagRequired("template-id") + cmd.Flags().String("iac-template-id", "", "The IaC template inside the group.") + _ = cmd.MarkFlagRequired("iac-template-id") + cmd.Flags().String("owner-org", "", "Organization that owns the template (defaults to --org).") + return cmd +} diff --git a/go/cmd/template/input_schema.go b/go/cmd/template/input_schema.go new file mode 100644 index 0000000..442bed7 --- /dev/null +++ b/go/cmd/template/input_schema.go @@ -0,0 +1,48 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/templates" + "github.com/spf13/cobra" +) + +func newInputSchemaCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "input-schema", + Short: "Decode one of a template's input schemas (requires a user token)", + Long: `Decode one of a template's input schemas (requires a user token)`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + templateType := common.String(cmd, "template-type") + ownerOrg := common.String(cmd, "owner-org") + schemaType := common.String(cmd, "schema-type") + if err := common.CheckEnum("template-type", templateType, "IAC", "IAC_GROUP", "IAC_POLICY", "WORKFLOW_STEP"); err != nil { + return err + } + if ownerOrg == "" { + ownerOrg = org + } + response, err := c.Templates.GetTemplateInputSchema(ctx, ownerOrg, templateType, templateId, &templates.GetTemplateInputSchemaRequest{SchemaType: schemaType}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("template-id", "", "Template name, optionally with revision as NAME:REVISION.") + _ = cmd.MarkFlagRequired("template-id") + cmd.Flags().String("template-type", "", "Template type (IAC, IAC_GROUP, IAC_POLICY, WORKFLOW_STEP).") + _ = cmd.MarkFlagRequired("template-type") + cmd.Flags().String("owner-org", "", "Organization that owns the template (defaults to --org).") + cmd.Flags().String("schema-type", "", "Schema to decode (FORM_JSONSCHEMA, RAW_JSON, NO_CODE_JSON, TIRITH_JSON).") + _ = cmd.MarkFlagRequired("schema-type") + return cmd +} diff --git a/go/cmd/template/list.go b/go/cmd/template/list.go new file mode 100644 index 0000000..40df712 --- /dev/null +++ b/go/cmd/template/list.go @@ -0,0 +1,42 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List templates of a type", + Long: `List templates of a type`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateType := common.String(cmd, "template-type") + if err := common.CheckEnum("template-type", templateType, "IAC", "IAC_GROUP", "IAC_POLICY", "WORKFLOW_STEP"); err != nil { + return err + } + response, err := c.Templates.ListAllTemplates(ctx, sggosdk.ListAllTemplatesRequestTemplateType(templateType), &sggosdk.ListAllTemplatesRequest{SgOrgid: org, IsPublic: common.OptString(cmd, "is-public"), OwnerOrgs: common.OptString(cmd, "owner-orgs"), SearchQuery: common.OptString(cmd, "search-query"), TemplateId: common.OptString(cmd, "template-id"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("template-type", "", "Template type (IAC, IAC_GROUP, IAC_POLICY, WORKFLOW_STEP).") + _ = cmd.MarkFlagRequired("template-type") + cmd.Flags().String("is-public", "", "0 for private, 1 for public templates.") + cmd.Flags().String("owner-orgs", "", "Organizations that own the templates (comma-separated).") + cmd.Flags().String("search-query", "", "Search by name, tags or description.") + cmd.Flags().String("template-id", "", "Parent template id to list its revisions.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + return cmd +} diff --git a/go/cmd/template/list_by_owner.go b/go/cmd/template/list_by_owner.go new file mode 100644 index 0000000..06634b0 --- /dev/null +++ b/go/cmd/template/list_by_owner.go @@ -0,0 +1,38 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newListByOwnerCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list-by-owner", + Short: "List templates owned by an organization", + Long: `List templates owned by an organization`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + ownerOrg := common.String(cmd, "owner-org") + response, err := c.Templates.ListAllTemplatesBasedOnOwnerOrg(ctx, ownerOrg, &sggosdk.ListAllTemplatesBasedOnOwnerOrgRequest{SgOrgid: org, IsPublic: common.OptString(cmd, "is-public"), SearchQuery: common.OptString(cmd, "search-query"), IsSharedTemplate: common.OptBool(cmd, "shared"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("owner-org", "", "Organization that owns the templates.") + _ = cmd.MarkFlagRequired("owner-org") + cmd.Flags().String("is-public", "", "0 for private, 1 for public templates.") + cmd.Flags().String("search-query", "", "Search by name, tags or description.") + cmd.Flags().Bool("shared", false, "List shared templates.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + return cmd +} diff --git a/go/cmd/template/public_list.go b/go/cmd/template/public_list.go new file mode 100644 index 0000000..5e34893 --- /dev/null +++ b/go/cmd/template/public_list.go @@ -0,0 +1,43 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/templates" + "github.com/spf13/cobra" +) + +func newPublicListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List public templates of a type", + Long: `List public templates of a type`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + templateType := common.String(cmd, "template-type") + if err := common.CheckEnum("template-type", templateType, "IAC", "IAC_GROUP", "IAC_POLICY", "WORKFLOW_STEP"); err != nil { + return err + } + response, err := c.Templates.ListAllPublicTemplates(ctx, templateType, &templates.ListAllPublicTemplatesRequest{Limit: common.OptInt(cmd, "limit"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), TemplateId: common.OptString(cmd, "template-id"), OwnerOrgs: common.OptString(cmd, "owner-orgs"), SearchQuery: common.OptString(cmd, "search-query"), ContextTags: common.OptString(cmd, "context-tags"), SourceConfigKinds: common.OptString(cmd, "source-config-kinds")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.PersistentFlags().String("template-type", "", "Template type (IAC, IAC_GROUP, IAC_POLICY, WORKFLOW_STEP).") + _ = cmd.MarkPersistentFlagRequired("template-type") + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + cmd.Flags().String("template-id", "", "Parent template id (with owner org) to list its revisions.") + cmd.Flags().String("owner-orgs", "", "Owner organizations (comma-separated).") + cmd.Flags().String("search-query", "", "Search by name, description or tags.") + cmd.Flags().String("context-tags", "", "Filter by context tags as key or key:value (comma-separated).") + cmd.Flags().String("source-config-kinds", "", "Filter by source config kind (comma-separated).") + return cmd +} diff --git a/go/cmd/template/public_list_all.go b/go/cmd/template/public_list_all.go new file mode 100644 index 0000000..d6a950b --- /dev/null +++ b/go/cmd/template/public_list_all.go @@ -0,0 +1,41 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/templates" + "github.com/spf13/cobra" +) + +func newPublicListAllCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list-all", + Short: "List public templates across all types", + Long: `List public templates across all types`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + response, err := c.Templates.ListAllPublicTemplatesV2(ctx, &templates.ListAllPublicTemplatesV2Request{Limit: common.OptInt(cmd, "limit"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), IsActive: common.OptString(cmd, "is-active"), TemplateName: common.OptString(cmd, "template-name"), GitHubComRepoID: common.OptString(cmd, "github-repo-id"), SearchQuery: common.OptString(cmd, "search-query"), Tags: common.OptString(cmd, "tags"), TemplateTypes: common.OptString(cmd, "template-types"), SourceConfigKinds: common.OptString(cmd, "source-config-kinds"), ContextTags: common.OptString(cmd, "context-tags"), OwnerOrgs: common.OptString(cmd, "owner-orgs")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + cmd.Flags().String("is-active", "", "Filter by active state (0 or 1).") + cmd.Flags().String("template-name", "", "Filter by template name.") + cmd.Flags().String("github-repo-id", "", "Filter by GitHub repository id.") + cmd.Flags().String("search-query", "", "Search by name, description, tags or id.") + cmd.Flags().String("tags", "", "Filter by tags (comma-separated).") + cmd.Flags().String("template-types", "", "Filter by template types (comma-separated).") + cmd.Flags().String("source-config-kinds", "", "Filter by source config kind (comma-separated).") + cmd.Flags().String("context-tags", "", "Filter by context tags as key or key:value (comma-separated).") + cmd.Flags().String("owner-orgs", "", "Owner organizations (comma-separated).") + return cmd +} diff --git a/go/cmd/template/public_read.go b/go/cmd/template/public_read.go new file mode 100644 index 0000000..c4ab7cf --- /dev/null +++ b/go/cmd/template/public_read.go @@ -0,0 +1,41 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newPublicReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get a public template", + Long: `Get a public template`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + templateId := common.String(cmd, "template-id") + templateType := common.String(cmd, "template-type") + ownerOrg := common.String(cmd, "owner-org") + if err := common.CheckEnum("template-type", templateType, "IAC", "IAC_GROUP", "IAC_POLICY", "WORKFLOW_STEP"); err != nil { + return err + } + response, err := c.Templates.ReadPublicTemplate(ctx, ownerOrg, templateType, templateId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.PersistentFlags().String("template-id", "", "Template name, optionally with revision as NAME:REVISION.") + _ = cmd.MarkPersistentFlagRequired("template-id") + cmd.PersistentFlags().String("template-type", "", "Template type (IAC, IAC_GROUP, IAC_POLICY, WORKFLOW_STEP).") + _ = cmd.MarkPersistentFlagRequired("template-type") + cmd.Flags().String("owner-org", "", "Organization that owns the template.") + _ = cmd.MarkFlagRequired("owner-org") + return cmd +} diff --git a/go/cmd/template/read.go b/go/cmd/template/read.go new file mode 100644 index 0000000..844a20f --- /dev/null +++ b/go/cmd/template/read.go @@ -0,0 +1,45 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get a template or one of its revisions", + Long: `Get a template or one of its revisions`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + templateType := common.String(cmd, "template-type") + ownerOrg := common.String(cmd, "owner-org") + if err := common.CheckEnum("template-type", templateType, "IAC", "IAC_GROUP", "IAC_POLICY", "WORKFLOW_STEP"); err != nil { + return err + } + if ownerOrg == "" { + ownerOrg = org + } + response, err := c.Templates.ReadTemplateRevision(ctx, ownerOrg, templateId, sggosdk.ReadTemplateRevisionRequestTemplateType(templateType), &sggosdk.ReadTemplateRevisionRequest{SgOrgid: org}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("template-id", "", "Template name, optionally with revision as NAME:REVISION.") + _ = cmd.MarkFlagRequired("template-id") + cmd.Flags().String("template-type", "", "Template type (IAC, IAC_GROUP, IAC_POLICY, WORKFLOW_STEP).") + _ = cmd.MarkFlagRequired("template-type") + cmd.Flags().String("owner-org", "", "Organization that owns the template (defaults to --org).") + return cmd +} diff --git a/go/cmd/template/subscriptions_create.go b/go/cmd/template/subscriptions_create.go new file mode 100644 index 0000000..37ab8b6 --- /dev/null +++ b/go/cmd/template/subscriptions_create.go @@ -0,0 +1,41 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/templates" + "github.com/spf13/cobra" +) + +func newSubscriptionsCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create a subscription set (all four subscription maps are required)", + Long: `Create a subscription set (all four subscription maps are required)`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req templates.CreateSubscriptionRequest + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.Templates.CreateSubscription(ctx, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Subscription created successfully.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/template/subscriptions_read.go b/go/cmd/template/subscriptions_read.go new file mode 100644 index 0000000..f3671aa --- /dev/null +++ b/go/cmd/template/subscriptions_read.go @@ -0,0 +1,37 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newSubscriptionsReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get the subscriptions of a type", + Long: `Get the subscriptions of a type`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + subscriptionType := common.String(cmd, "subscription-type") + if err := common.CheckEnum("subscription-type", subscriptionType, "IACGroupSubscriptions", "IACSubscriptions", "PolicySubscriptions", "WfStepSubscriptions"); err != nil { + return err + } + response, err := c.Templates.ReadSubscription(ctx, org, &sggosdk.ReadSubscriptionRequest{SubscriptionType: sggosdk.ReadSubscriptionRequestSubscriptionType(subscriptionType)}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("subscription-type", "", "Subscription type (IACGroupSubscriptions, IACSubscriptions, PolicySubscriptions, WfStepSubscriptions).") + _ = cmd.MarkFlagRequired("subscription-type") + return cmd +} diff --git a/go/cmd/template/subscriptions_update.go b/go/cmd/template/subscriptions_update.go new file mode 100644 index 0000000..41ccc6a --- /dev/null +++ b/go/cmd/template/subscriptions_update.go @@ -0,0 +1,49 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/templates" + "github.com/spf13/cobra" +) + +func newSubscriptionsUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Subscribe to or unsubscribe from templates", + Long: `Subscribe to or unsubscribe from templates`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + subscription := common.String(cmd, "subscription") + action := common.String(cmd, "action") + var req templates.UpdateSubscriptionRequest + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + if err := common.CheckEnum("action", action, "subscribe", "unsubscribe"); err != nil { + return err + } + response, err := c.Templates.UpdateSubscription(ctx, org, subscription, action, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Subscription updated successfully.") + return nil + }, + } + cmd.Flags().String("subscription", "default", "The subscription name.") + cmd.Flags().String("action", "", "subscribe or unsubscribe.") + _ = cmd.MarkFlagRequired("action") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/template/template.go b/go/cmd/template/template.go new file mode 100644 index 0000000..da5bbf6 --- /dev/null +++ b/go/cmd/template/template.go @@ -0,0 +1,114 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewTemplateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "template", + Short: "Manage templates and template revisions across all template types", + Long: `Manage templates and template revisions across all template types. + +A template revision is addressed as NAME or NAME:REVISION (for example my-template:5). Without a revision the base template is used.`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + list List templates of a type + list-by-owner List templates owned by an organization + create Create a template or a new revision of it (payload must include TemplateType: IAC, IAC_GROUP or IAC_POLICY) + read Get a template or one of its revisions + update Update a template or one of its revisions + delete Delete a template or one of its revisions + group-iac Get an IaC template that belongs to an IaC group template + input-schema Decode one of a template's input schemas (requires a user token) + vcs-triggers Create VCS webhook triggers for a template + subscriptions Manage the organization's template subscriptions + artifacts Work with template artifacts through presigned URLs + public Browse public marketplace templates (requires a user token)`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newListCmd(c), + newListByOwnerCmd(c), + newCreateCmd(c), + newReadCmd(c), + newUpdateCmd(c), + newDeleteCmd(c), + newGroupIacCmd(c), + newInputSchemaCmd(c), + newVcsTriggersCmd(c), + newSubscriptionsCmd(c), + newArtifactsCmd(c), + newPublicCmd(c), + ) + return cmd +} +func newSubscriptionsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "subscriptions", + Short: "Manage the organization's template subscriptions", + Long: `Manage the organization's template subscriptions`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + read Get the subscriptions of a type + create Create a subscription set (all four subscription maps are required) + update Subscribe to or unsubscribe from templates`) + }, + } + cmd.AddCommand( + newSubscriptionsReadCmd(c), + newSubscriptionsCreateCmd(c), + newSubscriptionsUpdateCmd(c), + ) + return cmd +} +func newArtifactsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "artifacts", + Short: "Work with template artifacts through presigned URLs", + Long: `Work with template artifacts through presigned URLs`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + list List the artifacts of a template + download-url Get a presigned download URL for an artifact + upload-url Get a presigned upload URL for an artifact + delete Delete an artifact`) + }, + } + cmd.PersistentFlags().String("template-id", "", "Template name, optionally with revision as NAME:REVISION.") + _ = cmd.MarkPersistentFlagRequired("template-id") + cmd.PersistentFlags().String("template-type", "", "Template type (IAC, IAC_GROUP, IAC_POLICY, WORKFLOW_STEP).") + _ = cmd.MarkPersistentFlagRequired("template-type") + cmd.PersistentFlags().String("owner-org", "", "Organization that owns the template (defaults to --org).") + cmd.AddCommand( + newArtifactsListCmd(c), + newArtifactsDownloadUrlCmd(c), + newArtifactsUploadUrlCmd(c), + newArtifactsDeleteCmd(c), + ) + return cmd +} +func newPublicCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "public", + Short: "Browse public marketplace templates (requires a user token)", + Long: `Browse public marketplace templates (requires a user token)`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + list List public templates of a type + list-all List public templates across all types + read Get a public template`) + }, + } + cmd.AddCommand( + newPublicListCmd(c), + newPublicListAllCmd(c), + newPublicReadCmd(c), + ) + return cmd +} diff --git a/go/cmd/template/update.go b/go/cmd/template/update.go new file mode 100644 index 0000000..a759e91 --- /dev/null +++ b/go/cmd/template/update.go @@ -0,0 +1,56 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a template or one of its revisions", + Long: `Update a template or one of its revisions`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + templateType := common.String(cmd, "template-type") + ownerOrg := common.String(cmd, "owner-org") + var req sggosdk.PatchedTemplateUpdate + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + if err := common.CheckEnum("template-type", templateType, "IAC", "IAC_GROUP", "IAC_POLICY", "WORKFLOW_STEP"); err != nil { + return err + } + if ownerOrg == "" { + ownerOrg = org + } + req.SgOrgid = org + response, err := c.Templates.UpdateTemplateRevision(ctx, ownerOrg, templateId, templateType, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Template updated successfully.") + return nil + }, + } + cmd.Flags().String("template-id", "", "Template name, optionally with revision as NAME:REVISION.") + _ = cmd.MarkFlagRequired("template-id") + cmd.Flags().String("template-type", "", "Template type (IAC, IAC_GROUP, IAC_POLICY, WORKFLOW_STEP).") + _ = cmd.MarkFlagRequired("template-type") + cmd.Flags().String("owner-org", "", "Organization that owns the template (defaults to --org).") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/template/vcs_triggers.go b/go/cmd/template/vcs_triggers.go new file mode 100644 index 0000000..a173166 --- /dev/null +++ b/go/cmd/template/vcs_triggers.go @@ -0,0 +1,55 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package template + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflows" + "github.com/spf13/cobra" +) + +func newVcsTriggersCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "vcs-triggers -- payload.json", + Short: "Create VCS webhook triggers for a template", + Long: `Create VCS webhook triggers for a template`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + templateType := common.String(cmd, "template-type") + ownerOrg := common.String(cmd, "owner-org") + var req workflows.CreateVcsTriggersRequest + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + if err := common.CheckEnum("template-type", templateType, "IAC", "IAC_GROUP", "IAC_POLICY", "WORKFLOW_STEP"); err != nil { + return err + } + if ownerOrg == "" { + ownerOrg = org + } + response, err := c.Templates.CreateTemplateVcsTriggers(ctx, ownerOrg, templateType, templateId, &req) + if err != nil { + return err + } + common.Done(cmd, response, "VCS triggers created successfully.") + return nil + }, + } + cmd.Flags().String("template-id", "", "Template name, optionally with revision as NAME:REVISION.") + _ = cmd.MarkFlagRequired("template-id") + cmd.Flags().String("template-type", "", "Template type (IAC, IAC_GROUP, IAC_POLICY, WORKFLOW_STEP).") + _ = cmd.MarkFlagRequired("template-type") + cmd.Flags().String("owner-org", "", "Organization that owns the template (defaults to --org).") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/user/create.go b/go/cmd/user/create.go new file mode 100644 index 0000000..aa2a9cd --- /dev/null +++ b/go/cmd/user/create.go @@ -0,0 +1,41 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package user + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Invite a user or SSO group to the organization", + Long: `Invite a user or SSO group to the organization`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req sggosdk.AddUserToOrganization + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.AccessManagement.CreateUser(ctx, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "User invited successfully.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/user/delete.go b/go/cmd/user/delete.go new file mode 100644 index 0000000..6477b04 --- /dev/null +++ b/go/cmd/user/delete.go @@ -0,0 +1,35 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package user + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Remove a user or SSO group from the organization", + Long: `Remove a user or SSO group from the organization`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.AccessManagement.DeleteUser(ctx, org, &sggosdk.GetorRemoveUserFromOrganization{UserId: common.OptString(cmd, "user-id"), Alias: common.OptString(cmd, "alias")}) + if err != nil { + return err + } + common.Done(cmd, response, "User removed successfully.") + return nil + }, + } + cmd.Flags().String("user-id", "", "User id (email) or SSO group id.") + cmd.Flags().String("alias", "", "Alias of an SSO group.") + common.AddOutputJSONFlag(cmd) + cmd.MarkFlagsOneRequired("user-id", "alias") + return cmd +} diff --git a/go/cmd/user/list.go b/go/cmd/user/list.go new file mode 100644 index 0000000..4d9ad43 --- /dev/null +++ b/go/cmd/user/list.go @@ -0,0 +1,36 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package user + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List users and SSO groups", + Long: `List users and SSO groups`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.AccessManagement.ListAllUsers(ctx, org, &sggosdk.ListAllUsersRequest{Alias: common.OptString(cmd, "alias"), EntityType: common.OptString(cmd, "entity-type"), LoginMethod: common.OptString(cmd, "login-method"), Roles: common.OptString(cmd, "roles"), UserId: common.OptString(cmd, "user-id")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("alias", "", "Filter by alias.") + cmd.Flags().String("entity-type", "", "Filter by entity type (EMAIL, GROUP).") + cmd.Flags().String("login-method", "", "Filter by login method.") + cmd.Flags().String("roles", "", "Filter by roles (comma-separated).") + cmd.Flags().String("user-id", "", "Filter by user id.") + return cmd +} diff --git a/go/cmd/user/read.go b/go/cmd/user/read.go new file mode 100644 index 0000000..ee8fa01 --- /dev/null +++ b/go/cmd/user/read.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package user + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get a user or SSO group", + Long: `Get a user or SSO group`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.AccessManagement.ReadUser(ctx, org, &sggosdk.GetorRemoveUserFromOrganization{UserId: common.OptString(cmd, "user-id"), Alias: common.OptString(cmd, "alias")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("user-id", "", "User id (email) or SSO group id.") + cmd.Flags().String("alias", "", "Alias of an SSO group.") + cmd.MarkFlagsOneRequired("user-id", "alias") + return cmd +} diff --git a/go/cmd/user/update.go b/go/cmd/user/update.go new file mode 100644 index 0000000..06bbef5 --- /dev/null +++ b/go/cmd/user/update.go @@ -0,0 +1,41 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package user + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a user or SSO group", + Long: `Update a user or SSO group`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req sggosdk.AddUserToOrganization + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.AccessManagement.UpdateUser(ctx, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "User updated successfully.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/user/user.go b/go/cmd/user/user.go new file mode 100644 index 0000000..ef395f5 --- /dev/null +++ b/go/cmd/user/user.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package user + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewUserCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "user", + Short: "Manage users and SSO groups", + Long: `Manage users and SSO groups`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + read Get a user or SSO group + create Invite a user or SSO group to the organization + delete Remove a user or SSO group from the organization + update Update a user or SSO group + list List users and SSO groups`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newReadCmd(c), + newCreateCmd(c), + newDeleteCmd(c), + newUpdateCmd(c), + newListCmd(c), + ) + return cmd +} diff --git a/go/cmd/workflow/apply/workflow_apply.go b/go/cmd/workflow/apply/workflow_apply.go index f134116..e3a3891 100644 --- a/go/cmd/workflow/apply/workflow_apply.go +++ b/go/cmd/workflow/apply/workflow_apply.go @@ -2,6 +2,7 @@ package apply import ( "context" + "github.com/StackGuardian/sg-cli/cmd/common" "os" sggosdk "github.com/StackGuardian/sg-sdk-go" @@ -44,7 +45,7 @@ func NewApplyCmd(c *client.Client) *cobra.Command { os.Exit(-1) } if opts.OutputJson { - cmd.Println(response) + common.PrintJSON(cmd, response) } cmd.Println("Workflow apply run successfully.") workflowRunPath := DASHBOARD_URL + diff --git a/go/cmd/workflow/create/workflow_create.go b/go/cmd/workflow/create/workflow_create.go index c22ed19..4c15f7f 100644 --- a/go/cmd/workflow/create/workflow_create.go +++ b/go/cmd/workflow/create/workflow_create.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "errors" + "github.com/StackGuardian/sg-cli/cmd/common" "io" "net/http" "os" @@ -13,12 +14,13 @@ import ( "github.com/StackGuardian/sg-cli/utilities" sggosdk "github.com/StackGuardian/sg-sdk-go" "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflows" "github.com/spf13/cobra" ) // Extend the Workflow struct from the sdk to add the new field for bulk type BulkWorkflow struct { - sggosdk.Workflow + workflows.Workflow CLIConfiguration } @@ -102,7 +104,7 @@ func NewCreateCmd(c *client.Client) *cobra.Command { // Iterate over the slice of BulkWorkflow objects for idx, bulkWorkflow := range createBulkWorkflowRequest { - var individualWorkflow *sggosdk.Workflow + var individualWorkflow *workflows.Workflow // delete the CLIConfiguration field from the tempMap delete(tempMap[idx], "CLIConfiguration") // Convert map to []byte and then unmarshal to workflow object @@ -116,7 +118,7 @@ func NewCreateCmd(c *client.Client) *cobra.Command { cmd.PrintErrln(err) continue } - cmd.Println(">> Processing workflow: " + individualWorkflow.ResourceName.Value) + cmd.Println(">> Processing workflow: " + *individualWorkflow.ResourceName) err = performPreExecutionFlagChecks(cmd, individualWorkflow, opts) if err != nil { cmd.PrintErrln(err) @@ -136,14 +138,14 @@ func NewCreateCmd(c *client.Client) *cobra.Command { ) if err != nil { if !strings.Contains(err.Error(), "Workflow name not unique") { - cmd.PrintErrln(">> [ERROR] Processing workflow failed for resource name: " + individualWorkflow.ResourceName.Value + "\n") + cmd.PrintErrln(">> [ERROR] Processing workflow failed for resource name: " + *individualWorkflow.ResourceName + "\n") cmd.PrintErrln(err) continue } else { cmd.Println("Workflow already exists, updating instead...") // convert to update workflow request - var updateIndividualWorkflow *sggosdk.PatchedWorkflow - err = json.Unmarshal(jsonBody, &individualWorkflow) + var updateIndividualWorkflow *workflows.PatchedWorkflow + err = json.Unmarshal(jsonBody, &updateIndividualWorkflow) if err != nil { cmd.PrintErrln(err) continue @@ -151,45 +153,47 @@ func NewCreateCmd(c *client.Client) *cobra.Command { response, err := c.Workflows.UpdateWorkflow( context.Background(), opts.Org, - individualWorkflow.ResourceName.Value, + *individualWorkflow.ResourceName, opts.WfgGrp, + nil, updateIndividualWorkflow, ) if err != nil { - cmd.PrintErrln(">> [ERROR] Updating workflow failed for resource name: " + *updateIndividualWorkflow.ResourceName + "\n") + cmd.PrintErrln(">> [ERROR] Updating workflow failed for resource name: " + *individualWorkflow.ResourceName + "\n") cmd.PrintErrln(err) continue } if opts.OutputJson { - cmd.Println(response) + common.PrintJSON(cmd, response) } cmd.Println("Workflow updated successfully.") if bulkWorkflow.CLIConfiguration.CLIConfiguration.TfStateFilePath == "" { - cmd.Println("TfStateFilePath is not provided for workflow: " + bulkWorkflow.ResourceName.Value) - cmd.Println(">> Skipping update of state file..\n") + cmd.Println("TfStateFilePath is not provided for workflow: " + *bulkWorkflow.ResourceName) + cmd.Println(">> Skipping update of state file..") + cmd.Println() } else { cmd.Println(">> Attempting to upload state file..") err = uploadTfState(cmd, &bulkWorkflow, opts) if err != nil { - cmd.PrintErrln("Failed to upload state file for workflow: " + individualWorkflow.ResourceName.Value + "\n") + cmd.PrintErrln("Failed to upload state file for workflow: " + *individualWorkflow.ResourceName + "\n") continue } } } } else { if opts.OutputJson { - cmd.Println(response) + common.PrintJSON(cmd, response) } cmd.Println("Workflow created successfully.") if bulkWorkflow.CLIConfiguration.CLIConfiguration.TfStateFilePath == "" { - cmd.PrintErrln("[ERROR] TfStateFilePath is not provided for workflow: " + bulkWorkflow.ResourceName.Value) + cmd.PrintErrln("[ERROR] TfStateFilePath is not provided for workflow: " + *bulkWorkflow.ResourceName) cmd.PrintErrln(">> Skipping update of state file..") } else { cmd.Println(">> Attempting to upload state file..") err = uploadTfState(cmd, &bulkWorkflow, opts) if err != nil { - cmd.PrintErrln("Failed to upload state file for workflow: " + individualWorkflow.ResourceName.Value + "\n") + cmd.PrintErrln("Failed to upload state file for workflow: " + *individualWorkflow.ResourceName + "\n") } } // Run on create @@ -203,7 +207,7 @@ func NewCreateCmd(c *client.Client) *cobra.Command { response, err := c.WorkflowRuns.CreateWorkflowRun( context.Background(), opts.Org, - bulkWorkflow.ResourceName.Value, + *bulkWorkflow.ResourceName, opts.WfgGrp, createWorkflowRunRequest, ) @@ -213,7 +217,7 @@ func NewCreateCmd(c *client.Client) *cobra.Command { continue } if opts.OutputJson { - cmd.Println(response) + common.PrintJSON(cmd, response) } cmd.Println("Workflow run created successfully.") workflowRunPath := DASHBOARD_URL + @@ -222,7 +226,7 @@ func NewCreateCmd(c *client.Client) *cobra.Command { "/wfgrps/" + opts.WfgGrp + "/wfs/" + - bulkWorkflow.ResourceName.Value + + *bulkWorkflow.ResourceName + "?tab=runs" cmd.Println("To view the workflow run, please visit the following URL:") cmd.Println(workflowRunPath) @@ -232,7 +236,7 @@ func NewCreateCmd(c *client.Client) *cobra.Command { } } } else { - var createWorkflowRequest *sggosdk.Workflow + var createWorkflowRequest *workflows.Workflow var createWorkflowRunRequest *sggosdk.WorkflowRun if opts.PatchPayload != "" && !opts.Bulk { patchedJson := utilities.PatchJSON(string(payload), opts.PatchPayload) @@ -286,7 +290,7 @@ func NewCreateCmd(c *client.Client) *cobra.Command { response, err := c.WorkflowRuns.CreateWorkflowRun( context.Background(), opts.Org, - createWorkflowRequest.ResourceName.Value, + *createWorkflowRequest.ResourceName, opts.WfgGrp, createWorkflowRunRequest, ) @@ -296,7 +300,7 @@ func NewCreateCmd(c *client.Client) *cobra.Command { os.Exit(-1) } if opts.OutputJson { - cmd.Println(response) + common.PrintJSON(cmd, response) } cmd.Println("Workflow run created successfully.") workflowRunPath := DASHBOARD_URL + @@ -305,7 +309,7 @@ func NewCreateCmd(c *client.Client) *cobra.Command { "/wfgrps/" + opts.WfgGrp + "/wfs/" + - createWorkflowRequest.ResourceName.Value + + *createWorkflowRequest.ResourceName + "?tab=runs" cmd.Println("To view the workflow run, please visit the following URL:") cmd.Println(workflowRunPath) @@ -322,7 +326,7 @@ func NewCreateCmd(c *client.Client) *cobra.Command { os.Exit(-1) } if opts.OutputJson { - cmd.Println(response) + common.PrintJSON(cmd, response) } cmd.Println("Workflow created successfully.") } @@ -349,9 +353,9 @@ func NewCreateCmd(c *client.Client) *cobra.Command { } // performPreExecutionFlagChecks performs pre-execution flag checks and returns the payload -func performPreExecutionFlagChecks(cmd *cobra.Command, payload *sggosdk.Workflow, opts *RunOptions) error { +func performPreExecutionFlagChecks(cmd *cobra.Command, payload *workflows.Workflow, opts *RunOptions) error { - if payload.ResourceName == nil || payload.ResourceName.Value == "" { + if payload.ResourceName == nil || *payload.ResourceName == "" { return errors.New(">> [ERROR] Workflow ResourceName is required in object payload, skipping") } @@ -385,11 +389,11 @@ func uploadTfState(cmd *cobra.Command, payload *BulkWorkflow, opts *RunOptions) "/wfgrps/" + opts.WfgGrp + "/wfs/" + - payload.ResourceName.Value + + *payload.ResourceName + "/tfstate_upload_url" req, err := http.NewRequest("GET", url, nil) if err != nil { - cmd.PrintErrln(">> [ERROR] Failed to get tfstate upload url for workflow: " + payload.ResourceName.Value + "\n") + cmd.PrintErrln(">> [ERROR] Failed to get tfstate upload url for workflow: " + *payload.ResourceName + "\n") cmd.PrintErrln(err) return err } @@ -398,25 +402,25 @@ func uploadTfState(cmd *cobra.Command, payload *BulkWorkflow, opts *RunOptions) client := &http.Client{} resp, err := client.Do(req) if err != nil { - cmd.PrintErrln(">> [ERROR] Failed to get tfstate upload url for workflow: " + payload.ResourceName.Value + "\n") + cmd.PrintErrln(">> [ERROR] Failed to get tfstate upload url for workflow: " + *payload.ResourceName + "\n") cmd.PrintErrln(err) return err } defer resp.Body.Close() if resp.StatusCode != 200 { - cmd.PrintErrln(">> [ERROR] Failed to get tfstate upload url for workflow: " + payload.ResourceName.Value + "\n") + cmd.PrintErrln(">> [ERROR] Failed to get tfstate upload url for workflow: " + *payload.ResourceName + "\n") cmd.PrintErrln("Expected status code 200, got " + resp.Status) return err } body, err := io.ReadAll(resp.Body) if err != nil { - cmd.PrintErrln(">> [ERROR] Failed to get tfstate upload url for workflow: " + payload.ResourceName.Value + "\n") + cmd.PrintErrln(">> [ERROR] Failed to get tfstate upload url for workflow: " + *payload.ResourceName + "\n") cmd.PrintErrln(err) return err } var response tfStateUploadUrlResponse if err := json.Unmarshal(body, &response); err != nil { - cmd.PrintErrln(">> [ERROR] Failed to get tfstate upload url for workflow: " + payload.ResourceName.Value + "\n") + cmd.PrintErrln(">> [ERROR] Failed to get tfstate upload url for workflow: " + *payload.ResourceName + "\n") cmd.PrintErrln(err) return err } @@ -427,7 +431,7 @@ func uploadTfState(cmd *cobra.Command, payload *BulkWorkflow, opts *RunOptions) // Create a temporary directory to store the state file tmpDir, err := os.MkdirTemp("", opts.Org+"-"+opts.WfgGrp) if err != nil { - cmd.PrintErrln(">> [ERROR] Failed to create temp directory for state file upload: " + payload.ResourceName.Value + "\n") + cmd.PrintErrln(">> [ERROR] Failed to create temp directory for state file upload: " + *payload.ResourceName + "\n") cmd.PrintErrln(err) return err } @@ -459,7 +463,7 @@ func uploadTfState(cmd *cobra.Command, payload *BulkWorkflow, opts *RunOptions) if strings.Contains(string(output), "HTTP/1.1 200 OK") { cmd.Println(">> State file uploaded successfully.") } else { - cmd.PrintErrln(">> [ERROR] Failed to upload state file for workflow: " + payload.ResourceName.Value + "\n") + cmd.PrintErrln(">> [ERROR] Failed to upload state file for workflow: " + *payload.ResourceName + "\n") cmd.PrintErrln(string(output)) } diff --git a/go/cmd/workflow/delete/workflow_delete.go b/go/cmd/workflow/delete/workflow_delete.go index 41c2da5..d2b2164 100644 --- a/go/cmd/workflow/delete/workflow_delete.go +++ b/go/cmd/workflow/delete/workflow_delete.go @@ -2,6 +2,7 @@ package delete import ( "context" + "github.com/StackGuardian/sg-cli/cmd/common" "os" "github.com/StackGuardian/sg-sdk-go/client" @@ -38,7 +39,7 @@ func NewDeleteCmd(c *client.Client) *cobra.Command { os.Exit(-1) } if opts.OutputJson { - cmd.Println(response) + common.PrintJSON(cmd, response) } cmd.Println("Workflow deleted successfully.") }, diff --git a/go/cmd/workflow/destroy/workflow_destroy.go b/go/cmd/workflow/destroy/workflow_destroy.go index c128cb9..897f735 100644 --- a/go/cmd/workflow/destroy/workflow_destroy.go +++ b/go/cmd/workflow/destroy/workflow_destroy.go @@ -2,6 +2,7 @@ package destroy import ( "context" + "github.com/StackGuardian/sg-cli/cmd/common" "os" sggosdk "github.com/StackGuardian/sg-sdk-go" @@ -45,7 +46,7 @@ func NewDestroyCmd(c *client.Client) *cobra.Command { os.Exit(-1) } if opts.OutputJson { - cmd.Println(response) + common.PrintJSON(cmd, response) } cmd.Println("Workflow destroy run successfully.") workflowRunPath := DASHBOARD_URL + diff --git a/go/cmd/workflow/extra/compare.go b/go/cmd/workflow/extra/compare.go new file mode 100644 index 0000000..fbffa51 --- /dev/null +++ b/go/cmd/workflow/extra/compare.go @@ -0,0 +1,58 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflows" + "github.com/spf13/cobra" +) + +func newCompareCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "compare -- payload.json", + Short: "Compare a workflow against a template without applying changes", + Long: `Compare a workflow against a template without applying changes`, + Args: cobra.MaximumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + var req workflows.CompareWorkflowRequest + if len(args) > 0 { + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + } + if v := common.OptString(cmd, "target-template-id"); v != nil { + req.TargetTemplateId = *v + } + if v := common.OptString(cmd, "upgrade-mode"); v != nil { + req.UpgradeMode = v + } + if req.TargetTemplateId == "" { + return errors.New("provide --target-template-id or a payload with targetTemplateId") + } + response, err := c.Workflows.CompareWorkflow(ctx, org, workflowId, workflowGroup, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Comparison completed.") + return nil + }, + } + cmd.Flags().String("workflow-id", "", "The workflow ID.") + _ = cmd.MarkFlagRequired("workflow-id") + cmd.Flags().String("target-template-id", "", "Template to compare against.") + cmd.Flags().String("upgrade-mode", "", "Upgrade mode to simulate.") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflow/extra/extra.go b/go/cmd/workflow/extra/extra.go new file mode 100644 index 0000000..7de9848 --- /dev/null +++ b/go/cmd/workflow/extra/extra.go @@ -0,0 +1,20 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +// AddCommands attaches the generated sub-commands to an existing command group. +func AddCommands(cmd *cobra.Command, c *client.Client) { + cmd.AddCommand( + newUpdateCmd(c), + newOutputsCmd(c), + newCompareCmd(c), + newFileUploadUrlCmd(c), + newTfstateUploadUrlCmd(c), + newVcsTriggersCmd(c), + ) +} diff --git a/go/cmd/workflow/extra/file_upload_url.go b/go/cmd/workflow/extra/file_upload_url.go new file mode 100644 index 0000000..d3158cd --- /dev/null +++ b/go/cmd/workflow/extra/file_upload_url.go @@ -0,0 +1,39 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflows" + "github.com/spf13/cobra" +) + +func newFileUploadUrlCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "file-upload-url", + Short: "Get a signed URL to upload a file to a workflow", + Long: `Get a signed URL to upload a file to a workflow`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + filename := common.String(cmd, "filename") + response, err := c.Workflows.GetFileUploadUrl(ctx, org, workflowId, workflowGroup, &workflows.GetFileUploadUrlRequest{Filename: filename, Folder: common.OptString(cmd, "folder")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("workflow-id", "", "The workflow ID.") + _ = cmd.MarkFlagRequired("workflow-id") + cmd.Flags().String("filename", "", "Name of the file to upload.") + _ = cmd.MarkFlagRequired("filename") + cmd.Flags().String("folder", "", "Folder to upload the file into.") + return cmd +} diff --git a/go/cmd/workflow/extra/outputs.go b/go/cmd/workflow/extra/outputs.go new file mode 100644 index 0000000..a3a16f9 --- /dev/null +++ b/go/cmd/workflow/extra/outputs.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newOutputsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "outputs", + Short: "Get the outputs of a workflow", + Long: `Get the outputs of a workflow`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + response, err := c.Workflows.Outputs(ctx, org, workflowId, workflowGroup) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("workflow-id", "", "The workflow ID.") + _ = cmd.MarkFlagRequired("workflow-id") + return cmd +} diff --git a/go/cmd/workflow/extra/tfstate_upload_url.go b/go/cmd/workflow/extra/tfstate_upload_url.go new file mode 100644 index 0000000..dcf0898 --- /dev/null +++ b/go/cmd/workflow/extra/tfstate_upload_url.go @@ -0,0 +1,36 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newTfstateUploadUrlCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "tfstate-upload-url", + Short: "Get a signed URL to upload a Terraform state file", + Long: `Get a signed URL to upload a Terraform state file`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + response, err := c.Workflows.GetSignedUrlToUploadTfstateFile(ctx, org, workflowId, workflowGroup, &sggosdk.GetSignedUrlToUploadTfstateFileRequest{Filename: common.OptString(cmd, "filename")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("workflow-id", "", "The workflow ID.") + _ = cmd.MarkFlagRequired("workflow-id") + cmd.Flags().String("filename", "", "Name of the file to upload (default tfstate.json).") + return cmd +} diff --git a/go/cmd/workflow/extra/update.go b/go/cmd/workflow/extra/update.go new file mode 100644 index 0000000..011a875 --- /dev/null +++ b/go/cmd/workflow/extra/update.go @@ -0,0 +1,54 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflows" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update an existing workflow", + Long: `Update an existing workflow`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + var req workflows.PatchedWorkflow + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + var mode *workflows.UpgradeModeEnum + if v := common.OptString(cmd, "upgrade-mode"); v != nil { + if err := common.CheckEnum("upgrade-mode", *v, "PRESERVE_SETTINGS", "RESET_TO_TEMPLATE", "MANUAL"); err != nil { + return err + } + m := workflows.UpgradeModeEnum(*v) + mode = &m + } + response, err := c.Workflows.UpdateWorkflow(ctx, org, workflowId, workflowGroup, mode, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Workflow updated successfully.") + return nil + }, + } + cmd.Flags().String("workflow-id", "", "The workflow ID.") + _ = cmd.MarkFlagRequired("workflow-id") + cmd.Flags().String("upgrade-mode", "", "Template upgrade mode (PRESERVE_SETTINGS, RESET_TO_TEMPLATE, MANUAL).") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflow/extra/vcs_triggers.go b/go/cmd/workflow/extra/vcs_triggers.go new file mode 100644 index 0000000..871fadb --- /dev/null +++ b/go/cmd/workflow/extra/vcs_triggers.go @@ -0,0 +1,45 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package extra + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflows" + "github.com/spf13/cobra" +) + +func newVcsTriggersCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "vcs-triggers -- payload.json", + Short: "Create VCS webhook triggers for a workflow", + Long: `Create VCS webhook triggers for a workflow`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + var req workflows.CreateVcsTriggersRequest + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.Workflows.CreateVcsTriggers(ctx, org, workflowGroup, workflowId, &req) + if err != nil { + return err + } + common.Done(cmd, response, "VCS triggers created successfully.") + return nil + }, + } + cmd.Flags().String("workflow-id", "", "The workflow ID.") + _ = cmd.MarkFlagRequired("workflow-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflow/list/workflow_list.go b/go/cmd/workflow/list/workflow_list.go index 1d3e0ae..0861a0b 100644 --- a/go/cmd/workflow/list/workflow_list.go +++ b/go/cmd/workflow/list/workflow_list.go @@ -2,6 +2,7 @@ package list import ( "context" + "github.com/StackGuardian/sg-cli/cmd/common" "os" sggosdk "github.com/StackGuardian/sg-sdk-go" @@ -33,7 +34,7 @@ func NewListCmd(c *client.Client) *cobra.Command { } if opts.OutputJson { - cmd.Println(response) + common.PrintJSON(cmd, response) } for _, workflow := range response.Msg { diff --git a/go/cmd/workflow/read/workflow_read.go b/go/cmd/workflow/read/workflow_read.go index de69a79..c138243 100644 --- a/go/cmd/workflow/read/workflow_read.go +++ b/go/cmd/workflow/read/workflow_read.go @@ -2,6 +2,7 @@ package read import ( "context" + "github.com/StackGuardian/sg-cli/cmd/common" "os" "github.com/StackGuardian/sg-sdk-go/client" @@ -25,7 +26,7 @@ func NewReadCmd(c *client.Client) *cobra.Command { cmd.Println(err) os.Exit(-1) } - cmd.Println(response) + common.PrintJSON(cmd, response) }, } diff --git a/go/cmd/workflow/workflow.go b/go/cmd/workflow/workflow.go index 0ad39b3..c14272e 100644 --- a/go/cmd/workflow/workflow.go +++ b/go/cmd/workflow/workflow.go @@ -7,6 +7,7 @@ import ( "github.com/StackGuardian/sg-cli/cmd/workflow/create" "github.com/StackGuardian/sg-cli/cmd/workflow/delete" "github.com/StackGuardian/sg-cli/cmd/workflow/destroy" + workflowextra "github.com/StackGuardian/sg-cli/cmd/workflow/extra" "github.com/StackGuardian/sg-cli/cmd/workflow/list" "github.com/StackGuardian/sg-cli/cmd/workflow/read" "github.com/StackGuardian/sg-sdk-go/client" @@ -43,5 +44,7 @@ func NewWorkflowCmd(c *client.Client) *cobra.Command { workflowCmd.AddCommand(list.NewListCmd(c)) workflowCmd.AddCommand(destroy.NewDestroyCmd(c)) + workflowextra.AddCommands(workflowCmd, c) + return workflowCmd } diff --git a/go/cmd/workflowgroup/create.go b/go/cmd/workflowgroup/create.go new file mode 100644 index 0000000..59c42d9 --- /dev/null +++ b/go/cmd/workflowgroup/create.go @@ -0,0 +1,41 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowgroup + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create a new workflow group", + Long: `Create a new workflow group`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + var req sggosdk.WorkflowGroup + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.WorkflowGroups.CreateWorkflowGroup(ctx, org, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Workflow group created successfully.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowgroup/create_child.go b/go/cmd/workflowgroup/create_child.go new file mode 100644 index 0000000..8dffb37 --- /dev/null +++ b/go/cmd/workflowgroup/create_child.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowgroup + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCreateChildCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create-child -- payload.json", + Short: "Create a child workflow group inside a parent group", + Long: `Create a child workflow group inside a parent group`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + parent := common.String(cmd, "parent") + var req sggosdk.WorkflowGroup + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.WorkflowGroups.CreateChildWorkflowGroup(ctx, org, parent, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Child workflow group created successfully.") + return nil + }, + } + cmd.Flags().String("parent", "", "The parent workflow group.") + _ = cmd.MarkFlagRequired("parent") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowgroup/delete.go b/go/cmd/workflowgroup/delete.go new file mode 100644 index 0000000..3715047 --- /dev/null +++ b/go/cmd/workflowgroup/delete.go @@ -0,0 +1,34 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowgroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete a workflow group", + Long: `Delete a workflow group`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + response, err := c.WorkflowGroups.DeleteWorkflowGroup(ctx, org, workflowGroup) + if err != nil { + return err + } + common.Done(cmd, response, "Workflow group deleted successfully.") + return nil + }, + } + cmd.Flags().String("workflow-group", "", "The workflow group under the organization.") + _ = cmd.MarkFlagRequired("workflow-group") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowgroup/list.go b/go/cmd/workflowgroup/list.go new file mode 100644 index 0000000..b353f35 --- /dev/null +++ b/go/cmd/workflowgroup/list.go @@ -0,0 +1,37 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowgroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List workflow groups", + Long: `List workflow groups`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + response, err := c.WorkflowGroups.ListAllWorkflowGroups(ctx, org, &sggosdk.ListAllWorkflowGroupsRequest{Description: common.OptString(cmd, "description"), ResourceNames: common.OptString(cmd, "resource-names"), Tags: common.OptString(cmd, "tags"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), Limit: common.OptInt(cmd, "limit"), SearchQuery: common.OptString(cmd, "search-query")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + cmd.Flags().String("description", "", "Filter by description.") + cmd.Flags().String("resource-names", "", "Filter by resource names.") + cmd.Flags().String("tags", "", "Filter by tags.") + cmd.Flags().String("search-query", "", "Search by resource name, tags or description.") + return cmd +} diff --git a/go/cmd/workflowgroup/list_children.go b/go/cmd/workflowgroup/list_children.go new file mode 100644 index 0000000..f8855bb --- /dev/null +++ b/go/cmd/workflowgroup/list_children.go @@ -0,0 +1,39 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowgroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newListChildrenCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list-children", + Short: "List the child workflow groups of a parent group", + Long: `List the child workflow groups of a parent group`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + parent := common.String(cmd, "parent") + response, err := c.WorkflowGroups.ListAllChildWorkflowGroups(ctx, org, parent, &sggosdk.ListAllChildWorkflowGroupsRequest{Description: common.OptString(cmd, "description"), ResourceNames: common.OptString(cmd, "resource-names"), Tags: common.OptString(cmd, "tags"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), Limit: common.OptInt(cmd, "limit")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("parent", "", "The parent workflow group.") + _ = cmd.MarkFlagRequired("parent") + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + cmd.Flags().String("description", "", "Filter by description.") + cmd.Flags().String("resource-names", "", "Filter by resource names.") + cmd.Flags().String("tags", "", "Filter by tags.") + return cmd +} diff --git a/go/cmd/workflowgroup/list_resources.go b/go/cmd/workflowgroup/list_resources.go new file mode 100644 index 0000000..561aed3 --- /dev/null +++ b/go/cmd/workflowgroup/list_resources.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowgroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflowgroups" + "github.com/spf13/cobra" +) + +func newListResourcesCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list-resources", + Short: "List the workflows, stacks and child groups inside a workflow group", + Long: `List the workflows, stacks and child groups inside a workflow group`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + response, err := c.WorkflowGroups.ListAllResourcesInWorkflowGroup(ctx, org, workflowGroup, &workflowgroups.ListAllResourcesRequest{Limit: common.OptInt(cmd, "limit"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), ResourceNames: common.OptString(cmd, "resource-names"), Description: common.OptString(cmd, "description"), Tags: common.OptString(cmd, "tags"), SearchQuery: common.OptString(cmd, "search-query"), LatestStatuses: common.OptString(cmd, "latest-statuses"), ResourceTypes: common.OptString(cmd, "resource-types"), ContextTags: common.OptString(cmd, "context-tags"), IsActive: common.OptString(cmd, "is-active")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("workflow-group", "", "The workflow group under the organization.") + _ = cmd.MarkFlagRequired("workflow-group") + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + cmd.Flags().String("resource-names", "", "Filter by resource names (comma-separated).") + cmd.Flags().String("description", "", "Filter by description.") + cmd.Flags().String("tags", "", "Filter by tags (comma-separated).") + cmd.Flags().String("search-query", "", "Search by resource name, description or tags.") + cmd.Flags().String("latest-statuses", "", "Filter by latest status (comma-separated).") + cmd.Flags().String("resource-types", "", "Filter by resource type: WORKFLOW, STACK, WORKFLOW_GROUP (comma-separated).") + cmd.Flags().String("context-tags", "", "Filter by context tags as key or key:value (comma-separated).") + cmd.Flags().String("is-active", "", "Filter by active state (0 or 1).") + return cmd +} diff --git a/go/cmd/workflowgroup/read.go b/go/cmd/workflowgroup/read.go new file mode 100644 index 0000000..262bcfe --- /dev/null +++ b/go/cmd/workflowgroup/read.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowgroup + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get details of a workflow group", + Long: `Get details of a workflow group`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + response, err := c.WorkflowGroups.ReadWorkflowGroup(ctx, org, workflowGroup) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("workflow-group", "", "The workflow group under the organization.") + _ = cmd.MarkFlagRequired("workflow-group") + return cmd +} diff --git a/go/cmd/workflowgroup/update.go b/go/cmd/workflowgroup/update.go new file mode 100644 index 0000000..9bedfa0 --- /dev/null +++ b/go/cmd/workflowgroup/update.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowgroup + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a workflow group", + Long: `Update a workflow group`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + var req sggosdk.PatchedWorkflowGroup + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.WorkflowGroups.UpdateWorkflowGroup(ctx, org, workflowGroup, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Workflow group updated successfully.") + return nil + }, + } + cmd.Flags().String("workflow-group", "", "The workflow group under the organization.") + _ = cmd.MarkFlagRequired("workflow-group") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowgroup/workflowgroup.go b/go/cmd/workflowgroup/workflowgroup.go new file mode 100644 index 0000000..1aa0a2f --- /dev/null +++ b/go/cmd/workflowgroup/workflowgroup.go @@ -0,0 +1,40 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowgroup + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewWorkflowGroupCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "workflow-group", + Short: "Manage workflow groups (nested groups are addressed as parent/child)", + Long: `Manage workflow groups (nested groups are addressed as parent/child)`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + create Create a new workflow group + read Get details of a workflow group + update Update a workflow group + delete Delete a workflow group + create-child Create a child workflow group inside a parent group + list-children List the child workflow groups of a parent group + list List workflow groups + list-resources List the workflows, stacks and child groups inside a workflow group`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newCreateCmd(c), + newReadCmd(c), + newUpdateCmd(c), + newDeleteCmd(c), + newCreateChildCmd(c), + newListChildrenCmd(c), + newListCmd(c), + newListResourcesCmd(c), + ) + return cmd +} diff --git a/go/cmd/workflowrun/approve.go b/go/cmd/workflowrun/approve.go new file mode 100644 index 0000000..2b6a2f9 --- /dev/null +++ b/go/cmd/workflowrun/approve.go @@ -0,0 +1,47 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowrun + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newApproveCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "approve", + Short: "Approve (or, with --reject, reject) a workflow run waiting for approval", + Long: `Approve (or, with --reject, reject) a workflow run waiting for approval`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + runId := common.String(cmd, "run-id") + reject := common.Bool(cmd, "reject") + if err := common.Require(cmd, "workflow-group", "workflow-id"); err != nil { + return err + } + approve := !reject + body := sggosdk.WorkflowRunApproval{Approve: &approve, Message: common.OptString(cmd, "message"), ApprovalStep: common.OptString(cmd, "approval-step"), ReasonForApprovalRequired: common.OptString(cmd, "reason")} + response, err := c.WorkflowRuns.ApproveWorkflowRun(ctx, org, workflowId, workflowGroup, runId, &body) + if err != nil { + return err + } + common.Done(cmd, response, "Approval decision submitted.") + return nil + }, + } + cmd.Flags().String("run-id", "", "The workflow run ID.") + _ = cmd.MarkFlagRequired("run-id") + cmd.Flags().Bool("reject", false, "Reject instead of approve.") + cmd.Flags().String("message", "", "Message to attach to the decision.") + cmd.Flags().String("approval-step", "", "Name of the approval step.") + cmd.Flags().String("reason", "", "Reason the approval was required.") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowrun/cancel.go b/go/cmd/workflowrun/cancel.go new file mode 100644 index 0000000..496100b --- /dev/null +++ b/go/cmd/workflowrun/cancel.go @@ -0,0 +1,39 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowrun + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCancelCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "cancel", + Short: "Cancel a workflow run", + Long: `Cancel a workflow run`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + runId := common.String(cmd, "run-id") + if err := common.Require(cmd, "workflow-group", "workflow-id"); err != nil { + return err + } + response, err := c.WorkflowRuns.CancelWorkflowRun(ctx, org, workflowId, workflowGroup, runId) + if err != nil { + return err + } + common.Done(cmd, response, "Workflow run cancelled.") + return nil + }, + } + cmd.Flags().String("run-id", "", "The workflow run ID.") + _ = cmd.MarkFlagRequired("run-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowrun/create.go b/go/cmd/workflowrun/create.go new file mode 100644 index 0000000..b938ec1 --- /dev/null +++ b/go/cmd/workflowrun/create.go @@ -0,0 +1,48 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowrun + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Trigger a workflow run (payload optional)", + Long: `Trigger a workflow run (payload optional)`, + Args: cobra.MaximumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + var req sggosdk.WorkflowRun + if len(args) > 0 { + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + } + if err := common.Require(cmd, "workflow-group", "workflow-id"); err != nil { + return err + } + response, err := c.WorkflowRuns.CreateWorkflowRun(ctx, org, workflowId, workflowGroup, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Workflow run created successfully.") + return nil + }, + } + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowrun/delete.go b/go/cmd/workflowrun/delete.go new file mode 100644 index 0000000..275ba89 --- /dev/null +++ b/go/cmd/workflowrun/delete.go @@ -0,0 +1,39 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowrun + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Cancel a workflow run through the DELETE endpoint", + Long: `Cancel a workflow run through the DELETE endpoint`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + runId := common.String(cmd, "run-id") + if err := common.Require(cmd, "workflow-group", "workflow-id"); err != nil { + return err + } + response, err := c.WorkflowRuns.DeleteWorkflowRun(ctx, org, workflowId, workflowGroup, runId) + if err != nil { + return err + } + common.Done(cmd, response, "Workflow run cancelled.") + return nil + }, + } + cmd.Flags().String("run-id", "", "The workflow run ID.") + _ = cmd.MarkFlagRequired("run-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowrun/facts_create.go b/go/cmd/workflowrun/facts_create.go new file mode 100644 index 0000000..579ba07 --- /dev/null +++ b/go/cmd/workflowrun/facts_create.go @@ -0,0 +1,49 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowrun + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newFactsCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create or replace the facts of a workflow run", + Long: `Create or replace the facts of a workflow run`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + runId := common.String(cmd, "run-id") + factsId := common.String(cmd, "facts-id") + var req map[string]interface{} + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + if err := common.Require(cmd, "workflow-group", "workflow-id"); err != nil { + return err + } + response, err := c.WorkflowRunFacts.CreateWorkflowRunFacts(ctx, org, workflowId, workflowGroup, runId, factsId, req) + if err != nil { + return err + } + common.Done(cmd, response, "Workflow run facts created.") + return nil + }, + } + cmd.Flags().String("facts-id", "", "The workflow run facts ID.") + _ = cmd.MarkFlagRequired("facts-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowrun/facts_read.go b/go/cmd/workflowrun/facts_read.go new file mode 100644 index 0000000..81b1b5a --- /dev/null +++ b/go/cmd/workflowrun/facts_read.go @@ -0,0 +1,39 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowrun + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newFactsReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get the facts of a workflow run", + Long: `Get the facts of a workflow run`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + runId := common.String(cmd, "run-id") + factsId := common.String(cmd, "facts-id") + if err := common.Require(cmd, "workflow-group", "workflow-id"); err != nil { + return err + } + response, err := c.WorkflowRunFacts.ReadWorkflowRunFacts(ctx, org, workflowId, workflowGroup, runId, factsId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("facts-id", "", "The workflow run facts ID.") + _ = cmd.MarkFlagRequired("facts-id") + return cmd +} diff --git a/go/cmd/workflowrun/facts_update.go b/go/cmd/workflowrun/facts_update.go new file mode 100644 index 0000000..3838ac9 --- /dev/null +++ b/go/cmd/workflowrun/facts_update.go @@ -0,0 +1,49 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowrun + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newFactsUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update the facts of a workflow run", + Long: `Update the facts of a workflow run`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + runId := common.String(cmd, "run-id") + factsId := common.String(cmd, "facts-id") + var req map[string]interface{} + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + if err := common.Require(cmd, "workflow-group", "workflow-id"); err != nil { + return err + } + response, err := c.WorkflowRunFacts.UpdateWorkflowRunFacts(ctx, org, workflowId, workflowGroup, runId, factsId, req) + if err != nil { + return err + } + common.Done(cmd, response, "Workflow run facts updated.") + return nil + }, + } + cmd.Flags().String("facts-id", "", "The workflow run facts ID.") + _ = cmd.MarkFlagRequired("facts-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowrun/list.go b/go/cmd/workflowrun/list.go new file mode 100644 index 0000000..3b9839a --- /dev/null +++ b/go/cmd/workflowrun/list.go @@ -0,0 +1,39 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowrun + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newListCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List the runs of a workflow", + Long: `List the runs of a workflow`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + if err := common.Require(cmd, "workflow-group", "workflow-id"); err != nil { + return err + } + response, err := c.WorkflowRuns.ListAllWorkflowRuns(ctx, org, workflowId, workflowGroup, &sggosdk.ListAllWorkflowRunsRequest{ContextTags: common.OptString(cmd, "context-tags"), Lastevaluatedkey: common.OptString(cmd, "last-evaluated-key"), Limit: common.OptInt(cmd, "limit")}) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().Int("limit", 0, "Limit the number of results returned.") + cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") + cmd.Flags().String("context-tags", "", "Filter by context tags.") + return cmd +} diff --git a/go/cmd/workflowrun/logs.go b/go/cmd/workflowrun/logs.go new file mode 100644 index 0000000..2f2ec25 --- /dev/null +++ b/go/cmd/workflowrun/logs.go @@ -0,0 +1,38 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowrun + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newLogsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "logs", + Short: "Get the logs of a workflow run", + Long: `Get the logs of a workflow run`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + runId := common.String(cmd, "run-id") + if err := common.Require(cmd, "workflow-group", "workflow-id"); err != nil { + return err + } + response, err := c.WorkflowRuns.ReadWorkflowRunLogs(ctx, org, workflowId, workflowGroup, runId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("run-id", "", "The workflow run ID.") + _ = cmd.MarkFlagRequired("run-id") + return cmd +} diff --git a/go/cmd/workflowrun/read.go b/go/cmd/workflowrun/read.go new file mode 100644 index 0000000..aeb30f0 --- /dev/null +++ b/go/cmd/workflowrun/read.go @@ -0,0 +1,38 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowrun + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get a workflow run", + Long: `Get a workflow run`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + runId := common.String(cmd, "run-id") + if err := common.Require(cmd, "workflow-group", "workflow-id"); err != nil { + return err + } + response, err := c.WorkflowRuns.ReadWorkflowRun(ctx, org, workflowId, workflowGroup, runId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("run-id", "", "The workflow run ID.") + _ = cmd.MarkFlagRequired("run-id") + return cmd +} diff --git a/go/cmd/workflowrun/read_by_ksuid.go b/go/cmd/workflowrun/read_by_ksuid.go new file mode 100644 index 0000000..a1d84e3 --- /dev/null +++ b/go/cmd/workflowrun/read_by_ksuid.go @@ -0,0 +1,36 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowrun + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadByKsuidCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read-by-ksuid", + Short: "Get a workflow run by KSUIDs (runner and machine tokens only)", + Long: `Get a workflow run by KSUIDs (runner and machine tokens only)`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + parentKsuid := common.String(cmd, "parent-ksuid") + resourceKsuid := common.String(cmd, "resource-ksuid") + response, err := c.WorkflowRuns.ReadWorkflowRunByKsuid(ctx, org, parentKsuid, resourceKsuid) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("parent-ksuid", "", "KSUID of the parent workflow.") + _ = cmd.MarkFlagRequired("parent-ksuid") + cmd.Flags().String("resource-ksuid", "", "KSUID of the workflow run.") + _ = cmd.MarkFlagRequired("resource-ksuid") + return cmd +} diff --git a/go/cmd/workflowrun/update.go b/go/cmd/workflowrun/update.go new file mode 100644 index 0000000..57656fa --- /dev/null +++ b/go/cmd/workflowrun/update.go @@ -0,0 +1,49 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowrun + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a workflow run", + Long: `Update a workflow run`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + workflowGroup := common.String(cmd, "workflow-group") + workflowId := common.String(cmd, "workflow-id") + runId := common.String(cmd, "run-id") + var req sggosdk.PatchedWorkflowRun + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + if err := common.Require(cmd, "workflow-group", "workflow-id"); err != nil { + return err + } + response, err := c.WorkflowRuns.UpdateWorkflowRun(ctx, org, workflowId, workflowGroup, runId, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Workflow run updated successfully.") + return nil + }, + } + cmd.Flags().String("run-id", "", "The workflow run ID.") + _ = cmd.MarkFlagRequired("run-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowrun/update_by_ksuid.go b/go/cmd/workflowrun/update_by_ksuid.go new file mode 100644 index 0000000..0cc235d --- /dev/null +++ b/go/cmd/workflowrun/update_by_ksuid.go @@ -0,0 +1,47 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowrun + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + sggosdk "github.com/StackGuardian/sg-sdk-go" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newUpdateByKsuidCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update-by-ksuid -- payload.json", + Short: "Update a workflow run by KSUIDs (runner and machine tokens only)", + Long: `Update a workflow run by KSUIDs (runner and machine tokens only)`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + parentKsuid := common.String(cmd, "parent-ksuid") + resourceKsuid := common.String(cmd, "resource-ksuid") + var req sggosdk.PatchedWorkflowRun + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.WorkflowRuns.UpdateWorkflowRunByKsuid(ctx, org, parentKsuid, resourceKsuid, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Workflow run updated successfully.") + return nil + }, + } + cmd.Flags().String("parent-ksuid", "", "KSUID of the parent workflow.") + _ = cmd.MarkFlagRequired("parent-ksuid") + cmd.Flags().String("resource-ksuid", "", "KSUID of the workflow run.") + _ = cmd.MarkFlagRequired("resource-ksuid") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowrun/workflowrun.go b/go/cmd/workflowrun/workflowrun.go new file mode 100644 index 0000000..1db1b12 --- /dev/null +++ b/go/cmd/workflowrun/workflowrun.go @@ -0,0 +1,69 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowrun + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewWorkflowRunCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "workflow-run", + Short: "Trigger, inspect, cancel and approve workflow runs", + Long: `Trigger, inspect, cancel and approve workflow runs`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + create Trigger a workflow run (payload optional) + read Get a workflow run + update Update a workflow run + cancel Cancel a workflow run + delete Cancel a workflow run through the DELETE endpoint + logs Get the logs of a workflow run + approve Approve (or, with --reject, reject) a workflow run waiting for approval + list List the runs of a workflow + read-by-ksuid Get a workflow run by KSUIDs (runner and machine tokens only) + update-by-ksuid Update a workflow run by KSUIDs (runner and machine tokens only) + facts Read and write the facts of a workflow run`) + }, + } + common.AddOrgFlag(cmd) + cmd.PersistentFlags().String("workflow-group", "", "The workflow group under the organization.") + cmd.PersistentFlags().String("workflow-id", "", "The workflow ID.") + cmd.AddCommand( + newCreateCmd(c), + newReadCmd(c), + newUpdateCmd(c), + newCancelCmd(c), + newDeleteCmd(c), + newLogsCmd(c), + newApproveCmd(c), + newListCmd(c), + newReadByKsuidCmd(c), + newUpdateByKsuidCmd(c), + newFactsCmd(c), + ) + return cmd +} +func newFactsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "facts", + Short: "Read and write the facts of a workflow run", + Long: `Read and write the facts of a workflow run`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + read Get the facts of a workflow run + create Create or replace the facts of a workflow run + update Update the facts of a workflow run`) + }, + } + cmd.PersistentFlags().String("run-id", "", "The workflow run ID.") + _ = cmd.MarkPersistentFlagRequired("run-id") + cmd.AddCommand( + newFactsReadCmd(c), + newFactsCreateCmd(c), + newFactsUpdateCmd(c), + ) + return cmd +} diff --git a/go/cmd/workflowsteptemplate/create.go b/go/cmd/workflowsteptemplate/create.go new file mode 100644 index 0000000..9fe12b7 --- /dev/null +++ b/go/cmd/workflowsteptemplate/create.go @@ -0,0 +1,43 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowsteptemplate + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflowsteptemplate" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create a workflow step template", + Long: `Create a workflow step template`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + createFirstRevision := common.Bool(cmd, "create-first-revision") + var req workflowsteptemplate.CreateWorkflowStepTemplate + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.WorkflowStepTemplate.CreateWorkflowStepTemplate(ctx, org, createFirstRevision, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Workflow step template created successfully.") + return nil + }, + } + cmd.Flags().Bool("create-first-revision", true, "Also create the first revision of the template.") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowsteptemplate/delete.go b/go/cmd/workflowsteptemplate/delete.go new file mode 100644 index 0000000..4dee215 --- /dev/null +++ b/go/cmd/workflowsteptemplate/delete.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowsteptemplate + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete a workflow step template", + Long: `Delete a workflow step template`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + if err := c.WorkflowStepTemplate.DeleteWorkflowStepTemplate(ctx, org, templateId); err != nil { + return err + } + common.Done(cmd, nil, "Workflow step template deleted successfully.") + return nil + }, + } + cmd.Flags().String("template-id", "", "The template ID.") + _ = cmd.MarkFlagRequired("template-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowsteptemplate/read.go b/go/cmd/workflowsteptemplate/read.go new file mode 100644 index 0000000..6e199b3 --- /dev/null +++ b/go/cmd/workflowsteptemplate/read.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowsteptemplate + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get a workflow step template", + Long: `Get a workflow step template`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + response, err := c.WorkflowStepTemplate.ReadWorkflowStepTemplate(ctx, org, templateId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("template-id", "", "The template ID.") + _ = cmd.MarkFlagRequired("template-id") + return cmd +} diff --git a/go/cmd/workflowsteptemplate/revisions_create.go b/go/cmd/workflowsteptemplate/revisions_create.go new file mode 100644 index 0000000..56a27d2 --- /dev/null +++ b/go/cmd/workflowsteptemplate/revisions_create.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowsteptemplate + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflowsteptemplaterevision" + "github.com/spf13/cobra" +) + +func newRevisionsCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create a new revision of a workflow step template", + Long: `Create a new revision of a workflow step template`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + var req workflowsteptemplaterevision.CreateWorkflowStepTemplateRevisionModel + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.WorkflowStepTemplateRevision.CreateWorkflowStepTemplateRevision(ctx, org, templateId, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Revision created successfully.") + return nil + }, + } + cmd.Flags().String("template-id", "", "The template ID.") + _ = cmd.MarkFlagRequired("template-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowsteptemplate/revisions_delete.go b/go/cmd/workflowsteptemplate/revisions_delete.go new file mode 100644 index 0000000..14715e6 --- /dev/null +++ b/go/cmd/workflowsteptemplate/revisions_delete.go @@ -0,0 +1,35 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowsteptemplate + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newRevisionsDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete a workflow step template revision", + Long: `Delete a workflow step template revision`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + revisionId := common.String(cmd, "revision-id") + keepParentTemplate := common.Bool(cmd, "keep-parent-template") + if err := c.WorkflowStepTemplateRevision.DeleteWorkflowStepTemplateRevision(ctx, org, revisionId, keepParentTemplate); err != nil { + return err + } + common.Done(cmd, nil, "Revision deleted successfully.") + return nil + }, + } + cmd.Flags().String("revision-id", "", "The revision ID (NAME:REVISION).") + _ = cmd.MarkFlagRequired("revision-id") + cmd.Flags().Bool("keep-parent-template", false, "Keep the parent template when deleting its last revision.") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowsteptemplate/revisions_read.go b/go/cmd/workflowsteptemplate/revisions_read.go new file mode 100644 index 0000000..bace6db --- /dev/null +++ b/go/cmd/workflowsteptemplate/revisions_read.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowsteptemplate + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newRevisionsReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get a workflow step template revision", + Long: `Get a workflow step template revision`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + revisionId := common.String(cmd, "revision-id") + response, err := c.WorkflowStepTemplateRevision.ReadWorkflowStepTemplateRevision(ctx, org, revisionId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("revision-id", "", "The revision ID (NAME:REVISION).") + _ = cmd.MarkFlagRequired("revision-id") + return cmd +} diff --git a/go/cmd/workflowsteptemplate/revisions_update.go b/go/cmd/workflowsteptemplate/revisions_update.go new file mode 100644 index 0000000..fc96bcd --- /dev/null +++ b/go/cmd/workflowsteptemplate/revisions_update.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowsteptemplate + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflowsteptemplaterevision" + "github.com/spf13/cobra" +) + +func newRevisionsUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a workflow step template revision", + Long: `Update a workflow step template revision`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + revisionId := common.String(cmd, "revision-id") + var req workflowsteptemplaterevision.UpdateWorkflowStepTemplateRevisionModel + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.WorkflowStepTemplateRevision.UpdateWorkflowStepTemplateRevision(ctx, org, revisionId, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Revision updated successfully.") + return nil + }, + } + cmd.Flags().String("revision-id", "", "The revision ID (NAME:REVISION).") + _ = cmd.MarkFlagRequired("revision-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowsteptemplate/update.go b/go/cmd/workflowsteptemplate/update.go new file mode 100644 index 0000000..f81fd92 --- /dev/null +++ b/go/cmd/workflowsteptemplate/update.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowsteptemplate + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflowsteptemplate" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a workflow step template", + Long: `Update a workflow step template`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + var req workflowsteptemplate.UpdateWorkflowStepTemplateRequestModel + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.WorkflowStepTemplate.UpdateWorkflowStepTemplate(ctx, org, templateId, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Workflow step template updated successfully.") + return nil + }, + } + cmd.Flags().String("template-id", "", "The template ID.") + _ = cmd.MarkFlagRequired("template-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowsteptemplate/workflowsteptemplate.go b/go/cmd/workflowsteptemplate/workflowsteptemplate.go new file mode 100644 index 0000000..bf2bfa5 --- /dev/null +++ b/go/cmd/workflowsteptemplate/workflowsteptemplate.go @@ -0,0 +1,55 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowsteptemplate + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewWorkflowStepTemplateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "workflow-step-template", + Short: "Manage workflow step templates", + Long: `Manage workflow step templates`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + read Get a workflow step template + create Create a workflow step template + update Update a workflow step template + delete Delete a workflow step template + revisions Manage revisions of workflow step templates`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newReadCmd(c), + newCreateCmd(c), + newUpdateCmd(c), + newDeleteCmd(c), + newRevisionsCmd(c), + ) + return cmd +} +func newRevisionsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "revisions", + Short: "Manage revisions of workflow step templates", + Long: `Manage revisions of workflow step templates`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + create Create a new revision of a workflow step template + read Get a workflow step template revision + update Update a workflow step template revision + delete Delete a workflow step template revision`) + }, + } + cmd.AddCommand( + newRevisionsCreateCmd(c), + newRevisionsReadCmd(c), + newRevisionsUpdateCmd(c), + newRevisionsDeleteCmd(c), + ) + return cmd +} diff --git a/go/cmd/workflowtemplate/create.go b/go/cmd/workflowtemplate/create.go new file mode 100644 index 0000000..0521f69 --- /dev/null +++ b/go/cmd/workflowtemplate/create.go @@ -0,0 +1,43 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowtemplate + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflowtemplates" + "github.com/spf13/cobra" +) + +func newCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create a workflow template", + Long: `Create a workflow template`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + createFirstRevision := common.Bool(cmd, "create-first-revision") + var req workflowtemplates.CreateWorkflowTemplateRequest + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.WorkflowTemplates.CreateWorkflowTemplate(ctx, org, createFirstRevision, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Workflow template created successfully.") + return nil + }, + } + cmd.Flags().Bool("create-first-revision", true, "Also create the first revision of the template.") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowtemplate/delete.go b/go/cmd/workflowtemplate/delete.go new file mode 100644 index 0000000..89878a0 --- /dev/null +++ b/go/cmd/workflowtemplate/delete.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowtemplate + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete a workflow template", + Long: `Delete a workflow template`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + if err := c.WorkflowTemplates.DeleteWorkflowTemplate(ctx, org, templateId); err != nil { + return err + } + common.Done(cmd, nil, "Workflow template deleted successfully.") + return nil + }, + } + cmd.Flags().String("template-id", "", "The template ID.") + _ = cmd.MarkFlagRequired("template-id") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowtemplate/read.go b/go/cmd/workflowtemplate/read.go new file mode 100644 index 0000000..61edcf9 --- /dev/null +++ b/go/cmd/workflowtemplate/read.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowtemplate + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get a workflow template", + Long: `Get a workflow template`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + response, err := c.WorkflowTemplates.ReadWorkflowTemplate(ctx, org, templateId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("template-id", "", "The template ID.") + _ = cmd.MarkFlagRequired("template-id") + return cmd +} diff --git a/go/cmd/workflowtemplate/revisions_create.go b/go/cmd/workflowtemplate/revisions_create.go new file mode 100644 index 0000000..c88c783 --- /dev/null +++ b/go/cmd/workflowtemplate/revisions_create.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowtemplate + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflowtemplaterevisions" + "github.com/spf13/cobra" +) + +func newRevisionsCreateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "create -- payload.json", + Short: "Create a new revision of a workflow template", + Long: `Create a new revision of a workflow template`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + var req workflowtemplaterevisions.CreateWorkflowTemplateRevisionsRequest + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.WorkflowTemplatesRevisions.CreateWorkflowTemplateRevision(ctx, org, templateId, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Revision created successfully.") + return nil + }, + } + cmd.Flags().String("template-id", "", "The template ID.") + _ = cmd.MarkFlagRequired("template-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowtemplate/revisions_delete.go b/go/cmd/workflowtemplate/revisions_delete.go new file mode 100644 index 0000000..f6b59cc --- /dev/null +++ b/go/cmd/workflowtemplate/revisions_delete.go @@ -0,0 +1,35 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowtemplate + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newRevisionsDeleteCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete a workflow template revision", + Long: `Delete a workflow template revision`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + revisionId := common.String(cmd, "revision-id") + keepParentTemplate := common.Bool(cmd, "keep-parent-template") + if err := c.WorkflowTemplatesRevisions.DeleteWorkflowTemplateRevision(ctx, org, revisionId, keepParentTemplate); err != nil { + return err + } + common.Done(cmd, nil, "Revision deleted successfully.") + return nil + }, + } + cmd.Flags().String("revision-id", "", "The revision ID (NAME:REVISION).") + _ = cmd.MarkFlagRequired("revision-id") + cmd.Flags().Bool("keep-parent-template", false, "Keep the parent template when deleting its last revision.") + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowtemplate/revisions_read.go b/go/cmd/workflowtemplate/revisions_read.go new file mode 100644 index 0000000..a72162f --- /dev/null +++ b/go/cmd/workflowtemplate/revisions_read.go @@ -0,0 +1,33 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowtemplate + +import ( + "context" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func newRevisionsReadCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "read", + Short: "Get a workflow template revision", + Long: `Get a workflow template revision`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + revisionId := common.String(cmd, "revision-id") + response, err := c.WorkflowTemplatesRevisions.ReadWorkflowTemplateRevision(ctx, org, revisionId) + if err != nil { + return err + } + common.PrintJSON(cmd, response) + return nil + }, + } + cmd.Flags().String("revision-id", "", "The revision ID (NAME:REVISION).") + _ = cmd.MarkFlagRequired("revision-id") + return cmd +} diff --git a/go/cmd/workflowtemplate/revisions_update.go b/go/cmd/workflowtemplate/revisions_update.go new file mode 100644 index 0000000..e90ef5b --- /dev/null +++ b/go/cmd/workflowtemplate/revisions_update.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowtemplate + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflowtemplaterevisions" + "github.com/spf13/cobra" +) + +func newRevisionsUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a workflow template revision", + Long: `Update a workflow template revision`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + revisionId := common.String(cmd, "revision-id") + var req workflowtemplaterevisions.UpdateWorkflowTemplateRevisionRequest + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.WorkflowTemplatesRevisions.UpdateWorkflowTemplateRevision(ctx, org, revisionId, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Revision updated successfully.") + return nil + }, + } + cmd.Flags().String("revision-id", "", "The revision ID (NAME:REVISION).") + _ = cmd.MarkFlagRequired("revision-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowtemplate/update.go b/go/cmd/workflowtemplate/update.go new file mode 100644 index 0000000..41777c2 --- /dev/null +++ b/go/cmd/workflowtemplate/update.go @@ -0,0 +1,44 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowtemplate + +import ( + "context" + "errors" + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/workflowtemplates" + "github.com/spf13/cobra" +) + +func newUpdateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "update -- payload.json", + Short: "Update a workflow template", + Long: `Update a workflow template`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := context.Background() + org := common.Org(cmd) + templateId := common.String(cmd, "template-id") + var req workflowtemplates.UpdateWorkflowTemplateRequest + if err := common.ReadPayload(cmd, args, &req); err != nil { + if errors.Is(err, common.ErrDryRun) { + return nil + } + return err + } + response, err := c.WorkflowTemplates.UpdateWorkflowTemplate(ctx, org, templateId, &req) + if err != nil { + return err + } + common.Done(cmd, response, "Workflow template updated successfully.") + return nil + }, + } + cmd.Flags().String("template-id", "", "The template ID.") + _ = cmd.MarkFlagRequired("template-id") + common.AddPayloadFlags(cmd) + common.AddOutputJSONFlag(cmd) + return cmd +} diff --git a/go/cmd/workflowtemplate/workflowtemplate.go b/go/cmd/workflowtemplate/workflowtemplate.go new file mode 100644 index 0000000..e19eecf --- /dev/null +++ b/go/cmd/workflowtemplate/workflowtemplate.go @@ -0,0 +1,55 @@ +// Code generated for sg-cli; edit the generator spec or this file directly. + +package workflowtemplate + +import ( + "github.com/StackGuardian/sg-cli/cmd/common" + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/spf13/cobra" +) + +func NewWorkflowTemplateCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "workflow-template", + Short: "Manage workflow (IaC) templates", + Long: `Manage workflow (IaC) templates`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + read Get a workflow template + create Create a workflow template + update Update a workflow template + delete Delete a workflow template + revisions Manage revisions of workflow (IaC) templates`) + }, + } + common.AddOrgFlag(cmd) + cmd.AddCommand( + newReadCmd(c), + newCreateCmd(c), + newUpdateCmd(c), + newDeleteCmd(c), + newRevisionsCmd(c), + ) + return cmd +} +func newRevisionsCmd(c *client.Client) *cobra.Command { + cmd := &cobra.Command{ + Use: "revisions", + Short: "Manage revisions of workflow (IaC) templates", + Long: `Manage revisions of workflow (IaC) templates`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(`Sub-commands: + create Create a new revision of a workflow template + read Get a workflow template revision + update Update a workflow template revision + delete Delete a workflow template revision`) + }, + } + cmd.AddCommand( + newRevisionsCreateCmd(c), + newRevisionsReadCmd(c), + newRevisionsUpdateCmd(c), + newRevisionsDeleteCmd(c), + ) + return cmd +} diff --git a/go/go.mod b/go/go.mod index 77fa3c0..81b5c16 100644 --- a/go/go.mod +++ b/go/go.mod @@ -3,7 +3,7 @@ module github.com/StackGuardian/sg-cli go 1.22.4 require ( - github.com/StackGuardian/sg-sdk-go v1.1.0 + github.com/StackGuardian/sg-sdk-go v1.5.7-0.20260903035653-e8047d5e8969 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 ) diff --git a/go/go.sum b/go/go.sum index 7b5d0f2..5a256ca 100644 --- a/go/go.sum +++ b/go/go.sum @@ -1,5 +1,5 @@ -github.com/StackGuardian/sg-sdk-go v1.1.0 h1:rE56fGomuuT7KLudgYSWdyPLgj4b72965V1mojtQbAU= -github.com/StackGuardian/sg-sdk-go v1.1.0/go.mod h1:iCrgHE0WbxEaaLx6ATsRe81Qjp82kahCwLGJ2t66mZ0= +github.com/StackGuardian/sg-sdk-go v1.5.7-0.20260903035653-e8047d5e8969 h1:fqke1zmp4HJU8pkCyXlj/9LDse/XbraRnj2y3p5uzqE= +github.com/StackGuardian/sg-sdk-go v1.5.7-0.20260903035653-e8047d5e8969/go.mod h1:iCrgHE0WbxEaaLx6ATsRe81Qjp82kahCwLGJ2t66mZ0= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/go/tests/matrix_a_test.go b/go/tests/matrix_a_test.go new file mode 100644 index 0000000..a70f5de --- /dev/null +++ b/go/tests/matrix_a_test.go @@ -0,0 +1,169 @@ +package tests + +import ( + "net/url" + "testing" + + "github.com/StackGuardian/sg-cli/cmd/apiaccess" + "github.com/StackGuardian/sg-cli/cmd/apitoken" + "github.com/StackGuardian/sg-cli/cmd/auditlog" + "github.com/StackGuardian/sg-cli/cmd/benchmarkreport" + "github.com/StackGuardian/sg-cli/cmd/billing" + "github.com/StackGuardian/sg-cli/cmd/chat" + "github.com/StackGuardian/sg-cli/cmd/connector" + "github.com/StackGuardian/sg-cli/cmd/connectorgroup" + "github.com/StackGuardian/sg-cli/cmd/organization" + "github.com/StackGuardian/sg-cli/cmd/policy" + "github.com/StackGuardian/sg-cli/cmd/resource" + "github.com/StackGuardian/sg-cli/cmd/role" + "github.com/StackGuardian/sg-cli/cmd/rolebinding" + "github.com/StackGuardian/sg-cli/cmd/runnergroup" + "github.com/StackGuardian/sg-cli/cmd/secret" + "github.com/StackGuardian/sg-cli/cmd/statebackend" + "github.com/StackGuardian/sg-cli/cmd/user" +) + +const org = "/api/v1/orgs/demo-org/" + +func TestOrganizationCommands(t *testing.T) { + runMatrix(t, []matrixCase{ + {name: "read", ctor: organization.NewOrganizationCmd, args: []string{"read", "--org", "demo-org"}, method: "GET", path: org}, + {name: "create", ctor: organization.NewOrganizationCmd, args: []string{"create", "@payload"}, payloadJSON: `{"ResourceName":"neworg"}`, method: "POST", path: "/api/v1/orgs/", body: `{"ResourceName":"neworg"}`, wantOut: "Organization created successfully."}, + {name: "list", ctor: organization.NewOrganizationCmd, args: []string{"list"}, method: "GET", path: "/api/v1/orgs/listall/", resp: `{"msg":["a"]}`}, + {name: "update", ctor: organization.NewOrganizationCmd, args: []string{"update", "--org", "demo-org", "@payload"}, payloadJSON: `{"ExtraSgCreditsLimit":5}`, method: "PATCH", path: org, body: `{"ExtraSgCreditsLimit":5}`, wantOut: "Organization updated successfully."}, + {name: "delete", ctor: organization.NewOrganizationCmd, args: []string{"delete", "--org", "demo-org"}, method: "DELETE", path: org, wantOut: "Organization archived successfully."}, + {name: "workflows", ctor: organization.NewOrganizationCmd, args: []string{"workflows", "--org", "demo-org", "--limit", "5", "--fetch-sg-owned-wfs=false", "--resource-names", "n"}, method: "GET", path: org + "wfs/listall/", query: url.Values{"limit": {"5"}, "fetchSgOwnedWfs": {"false"}, "resourceNames": {"n"}}, resp: `{"msg":[]}`}, + {name: "count", ctor: organization.NewOrganizationCmd, args: []string{"count-workflows", "--org", "demo-org", "--tags", "t"}, method: "GET", path: org + "wfs/listall/", query: url.Values{"onlyCount": {"1"}, "tags": {"t"}}, resp: `{"msg":3}`}, + {name: "bulk action", ctor: organization.NewOrganizationCmd, args: []string{"bulk-action", "--org", "demo-org", "--action", "activate", "--resource-ids", "/wfgrps/g/wfs/w,/wfgrps/g/stacks/s"}, method: "POST", path: org + "wfs/bulk-action/", body: `{"action":"activate","resourceIds":["/wfgrps/g/wfs/w","/wfgrps/g/stacks/s"]}`, wantOut: "Bulk action submitted."}, + }) +} + +func TestAccessCommands(t *testing.T) { + runMatrix(t, []matrixCase{ + {name: "user read", ctor: user.NewUserCmd, args: []string{"read", "--org", "demo-org", "--user-id", "u@x"}, method: "POST", path: org + "get_user/", body: `{"userId":"u@x"}`}, + {name: "user create", ctor: user.NewUserCmd, args: []string{"create", "--org", "demo-org", "@payload"}, payloadJSON: `{"userId":"u@x","role":"ADMIN"}`, method: "POST", path: org + "invite_user/", body: `{"userId":"u@x","role":"ADMIN"}`, wantOut: "User invited successfully."}, + {name: "user delete", ctor: user.NewUserCmd, args: []string{"delete", "--org", "demo-org", "--alias", "grp"}, method: "POST", path: org + "remove_user/", body: `{"alias":"grp"}`, wantOut: "User removed successfully."}, + {name: "user update", ctor: user.NewUserCmd, args: []string{"update", "--org", "demo-org", "@payload"}, payloadJSON: `{"userId":"u@x","role":"USER"}`, method: "POST", path: org + "update_user/", body: `{"userId":"u@x","role":"USER"}`, wantOut: "User updated successfully."}, + {name: "user list", ctor: user.NewUserCmd, args: []string{"list", "--org", "demo-org", "--entity-type", "EMAIL", "--roles", "ADMIN"}, method: "GET", path: org + "users/listall/", query: url.Values{"entityType": {"EMAIL"}, "roles": {"ADMIN"}}}, + {name: "role create", ctor: role.NewRoleCmd, args: []string{"create", "--org", "demo-org", "@payload"}, payloadJSON: `{"ResourceName":"r1"}`, method: "POST", path: org + "roles/", body: `{"ResourceName":"r1"}`, wantOut: "Role created successfully."}, + {name: "role read", ctor: role.NewRoleCmd, args: []string{"read", "--org", "demo-org", "--role-id", "r1"}, method: "GET", path: org + "roles/r1/"}, + {name: "role update", ctor: role.NewRoleCmd, args: []string{"update", "--org", "demo-org", "--role-id", "r1", "@payload"}, payloadJSON: `{"Description":"d"}`, method: "PATCH", path: org + "roles/r1/", body: `{"ResourceName":"r1","Description":"d"}`, wantOut: "Role updated successfully."}, + {name: "role delete", ctor: role.NewRoleCmd, args: []string{"delete", "--org", "demo-org", "--role-id", "r1"}, method: "DELETE", path: org + "roles/r1/", wantOut: "Role deleted successfully."}, + {name: "role list", ctor: role.NewRoleCmd, args: []string{"list", "--org", "demo-org", "--include-predefined-roles"}, method: "GET", path: org + "roles/listall/", query: url.Values{"includePredefinedRoles": {"true"}}, resp: `{"msg":[]}`}, + {name: "role binding", ctor: rolebinding.NewRoleBindingCmd, args: []string{"read", "--org", "demo-org"}, method: "GET", path: org + "rolebindings/default/"}, + {name: "api access create", ctor: apiaccess.NewApiAccessCmd, args: []string{"create", "--org", "demo-org", "@payload"}, payloadJSON: `{"ResourceName":"k1"}`, method: "POST", path: org + "apiaccesses/", body: `{"ResourceName":"k1"}`, wantOut: "API access created successfully."}, + {name: "api access read", ctor: apiaccess.NewApiAccessCmd, args: []string{"read", "--org", "demo-org", "--access-id", "id1"}, method: "GET", path: org + "apiaccesses/id1/"}, + {name: "api access update", ctor: apiaccess.NewApiAccessCmd, args: []string{"update", "--org", "demo-org", "--access-id", "id1", "@payload"}, payloadJSON: `{"Description":"d"}`, method: "PATCH", path: org + "apiaccesses/id1/", body: `{"Description":"d"}`, wantOut: "API access updated successfully."}, + {name: "api access delete", ctor: apiaccess.NewApiAccessCmd, args: []string{"delete", "--org", "demo-org", "--access-id", "id1"}, method: "DELETE", path: org + "apiaccesses/id1/", wantOut: "API access deleted successfully."}, + {name: "api access regenerate", ctor: apiaccess.NewApiAccessCmd, args: []string{"regenerate-key", "--org", "demo-org", "--access-id", "id1", "--no-expiration"}, method: "POST", path: org + "apiaccesses/id1/regenerate/", body: `{"ExpiresAt":null}`, wantOut: "API key regenerated."}, + {name: "api access list", ctor: apiaccess.NewApiAccessCmd, args: []string{"list", "--org", "demo-org", "--access-type", "APIKEY", "--limit", "10", "--status", "active"}, method: "GET", path: org + "apiaccesses/listall/", query: url.Values{"accessType": {"APIKEY"}, "limit": {"10"}, "status": {"active"}}}, + {name: "api token create", ctor: apitoken.NewApiTokenCmd, args: []string{"create", "--org", "demo-org", "--regenerate"}, method: "POST", path: org + "api_token/", body: `{"regenerate":true}`, wantOut: "API token request completed."}, + {name: "api token delete", ctor: apitoken.NewApiTokenCmd, args: []string{"delete", "--org", "demo-org", "--principal-id", "pool/idp/u@x"}, method: "DELETE", path: org + "api_token/", body: `"pool/idp/u@x"`, wantOut: "API token revoked."}, + {name: "audit logs", ctor: auditlog.NewAuditLogCmd, args: []string{"list", "--org", "demo-org", "--effect", "Allow", "--start-time", "1", "--limit", "5"}, method: "GET", path: org + "audit_logs/", query: url.Values{"effect": {"Allow"}, "startTime": {"1"}, "limit": {"5"}}}, + {name: "benchmark", ctor: benchmarkreport.NewBenchmarkReportCmd, args: []string{"read", "--org", "demo-org", "--detailed", "--filter-csp", "AWS", "--limit", "2"}, method: "GET", path: org + "reports/benchmark/", query: url.Values{"detailed": {"true"}, "filter:CSP": {"AWS"}, "limit": {"2"}}, resp: `[]`}, + }) +} + +func TestSecretPolicyCommands(t *testing.T) { + runMatrix(t, []matrixCase{ + {name: "secret create", ctor: secret.NewSecretCmd, args: []string{"create", "--org", "demo-org", "@payload"}, payloadJSON: `{"ResourceName":"s","ResourceValue":"v"}`, method: "POST", path: org + "secrets/", body: `{"ResourceName":"s","ResourceValue":"v"}`, wantOut: "Secret created successfully."}, + {name: "secret update", ctor: secret.NewSecretCmd, args: []string{"update", "--org", "demo-org", "--secret-id", "s", "@payload"}, payloadJSON: `{"ResourceValue":"v2"}`, method: "PATCH", path: org + "secrets/s/", body: `{"ResourceName":"s","ResourceValue":"v2"}`, wantOut: "Secret updated successfully."}, + {name: "secret delete", ctor: secret.NewSecretCmd, args: []string{"delete", "--org", "demo-org", "--secret-id", "s"}, method: "DELETE", path: org + "secrets/s/", wantOut: "Secret deleted successfully."}, + {name: "secret list", ctor: secret.NewSecretCmd, args: []string{"list", "--org", "demo-org"}, method: "GET", path: org + "secrets/listall/"}, + {name: "secret read bulk", ctor: secret.NewSecretCmd, args: []string{"read-bulk", "--org", "demo-org", "--names", "a,b"}, method: "POST", path: org + "secrets/listall/", body: `{"ResourceNames":["a","b"]}`, resp: `{"msg":[]}`}, + {name: "policy create", ctor: policy.NewPolicyCmd, args: []string{"create", "--org", "demo-org", "@payload"}, payloadJSON: `{"PolicyType":"GENERAL","ResourceName":"p"}`, method: "POST", path: org + "policies/", body: `{"PolicyType":"GENERAL","ResourceName":"p"}`, wantOut: "Policy created successfully."}, + {name: "policy read", ctor: policy.NewPolicyCmd, args: []string{"read", "--org", "demo-org", "--policy-id", "p"}, method: "GET", path: org + "policies/p/"}, + {name: "policy update", ctor: policy.NewPolicyCmd, args: []string{"update", "--org", "demo-org", "--policy-id", "p", "@payload"}, payloadJSON: `{"PolicyType":"GENERAL","Description":"d"}`, method: "PATCH", path: org + "policies/p/", body: `{"PolicyType":"GENERAL","Description":"d"}`, wantOut: "Policy updated successfully."}, + {name: "policy delete", ctor: policy.NewPolicyCmd, args: []string{"delete", "--org", "demo-org", "--policy-id", "p"}, method: "DELETE", path: org + "policies/p/", wantOut: "Policy deleted successfully."}, + {name: "policy list", ctor: policy.NewPolicyCmd, args: []string{"list", "--org", "demo-org", "--search-query", "q", "--limit", "5"}, method: "GET", path: org + "policies/listall/", query: url.Values{"searchQuery": {"q"}, "limit": {"5"}}, resp: `{"msg":[]}`}, + }) +} + +func TestConnectorCommands(t *testing.T) { + base := org + "integrations/" + gbase := org + "integrationgroups/" + runMatrix(t, []matrixCase{ + {name: "create", ctor: connector.NewConnectorCmd, args: []string{"create", "--org", "demo-org", "@payload"}, payloadJSON: `{"ResourceName":"c"}`, method: "POST", path: base, body: `{"ResourceName":"c"}`, wantOut: "Connector created successfully."}, + {name: "read", ctor: connector.NewConnectorCmd, args: []string{"read", "--org", "demo-org", "--connector-id", "c"}, method: "GET", path: base + "c/"}, + {name: "update", ctor: connector.NewConnectorCmd, args: []string{"update", "--org", "demo-org", "--connector-id", "c", "@payload"}, payloadJSON: `{"Description":"d"}`, method: "PATCH", path: base + "c/", body: `{"Description":"d"}`, wantOut: "Connector updated successfully."}, + {name: "delete", ctor: connector.NewConnectorCmd, args: []string{"delete", "--org", "demo-org", "--connector-id", "c"}, method: "DELETE", path: base + "c/", wantOut: "Connector deleted successfully."}, + {name: "list", ctor: connector.NewConnectorCmd, args: []string{"list", "--org", "demo-org", "--kind", "AWS_RBAC", "--limit", "5"}, method: "GET", path: base + "listall/", query: url.Values{"kind": {"AWS_RBAC"}, "limit": {"5"}}}, + {name: "authenticate", ctor: connector.NewConnectorCmd, args: []string{"authenticate", "--org", "demo-org", "--connector-id", "c"}, method: "GET", path: base + "c/authenticate/"}, + {name: "list accounts", ctor: connector.NewConnectorCmd, args: []string{"list-accounts", "--org", "demo-org", "@payload"}, payloadJSON: `{"ResourceId":"g"}`, method: "POST", path: base + "list_accounts/", body: `{"ResourceId":"g"}`, resp: `{"msg":[]}`, wantOut: "Accounts listed."}, + {name: "github repos", ctor: connector.NewConnectorCmd, args: []string{"github-repos", "--org", "demo-org", "--connector-id", "c"}, method: "GET", path: base + "c/get_githubcom_repos/", resp: `{"msg":["o/r"]}`}, + {name: "repos", ctor: connector.NewConnectorCmd, args: []string{"repos", "--org", "demo-org", "--connector-id", "c", "--login", "l", "--page", "2", "--limit", "5"}, method: "GET", path: base + "c/repos/", query: url.Values{"login": {"l"}, "page": {"2"}, "limit": {"5"}}}, + {name: "group create", ctor: connectorgroup.NewConnectorGroupCmd, args: []string{"create", "--org", "demo-org", "@payload"}, payloadJSON: `{"ResourceName":"g"}`, method: "POST", path: gbase, body: `{"ResourceName":"g"}`, wantOut: "Connector group created successfully."}, + {name: "group read", ctor: connectorgroup.NewConnectorGroupCmd, args: []string{"read", "--org", "demo-org", "--connector-group", "g"}, method: "GET", path: gbase + "g/"}, + {name: "group update", ctor: connectorgroup.NewConnectorGroupCmd, args: []string{"update", "--org", "demo-org", "--connector-group", "g", "@payload"}, payloadJSON: `{"Description":"d"}`, method: "PATCH", path: gbase + "g/", body: `{"Description":"d"}`, wantOut: "Connector group updated successfully."}, + {name: "group delete", ctor: connectorgroup.NewConnectorGroupCmd, args: []string{"delete", "--org", "demo-org", "--connector-group", "g"}, method: "DELETE", path: gbase + "g/", wantOut: "Connector group deleted successfully."}, + {name: "group authenticate", ctor: connectorgroup.NewConnectorGroupCmd, args: []string{"authenticate", "--org", "demo-org", "--connector-group", "g"}, method: "GET", path: gbase + "g/authenticate/"}, + {name: "group list", ctor: connectorgroup.NewConnectorGroupCmd, args: []string{"list", "--org", "demo-org", "--scope", "s"}, method: "GET", path: gbase + "listall/", query: url.Values{"scope": {"s"}}}, + {name: "group discovery scan", ctor: connectorgroup.NewConnectorGroupCmd, args: []string{"discovery-scan", "--org", "demo-org", "--connector-group", "g", "--benchmark", "inventory"}, method: "POST", path: gbase + "g/discovery_scan/", query: url.Values{"benchmark": {"inventory"}}, wantOut: "Discovery scan triggered."}, + {name: "child read", ctor: connectorgroup.NewConnectorGroupCmd, args: []string{"connectors", "read", "--org", "demo-org", "--connector-group", "g", "--connector-id", "c"}, method: "GET", path: gbase + "g/integrations/c/"}, + {name: "child update", ctor: connectorgroup.NewConnectorGroupCmd, args: []string{"connectors", "update", "--org", "demo-org", "--connector-group", "g", "--connector-id", "c", "@payload"}, payloadJSON: `{"Description":"d"}`, method: "PATCH", path: gbase + "g/integrations/c/", body: `{"Description":"d"}`, wantOut: "Connector updated successfully."}, + {name: "child delete", ctor: connectorgroup.NewConnectorGroupCmd, args: []string{"connectors", "delete", "--org", "demo-org", "--connector-group", "g", "--connector-id", "c"}, method: "DELETE", path: gbase + "g/integrations/c/", wantOut: "Connector deleted successfully."}, + {name: "child list", ctor: connectorgroup.NewConnectorGroupCmd, args: []string{"connectors", "list", "--org", "demo-org", "--connector-group", "g", "--kind", "k"}, method: "GET", path: gbase + "g/integrations/listall/", query: url.Values{"kind": {"k"}}}, + {name: "child authenticate", ctor: connectorgroup.NewConnectorGroupCmd, args: []string{"connectors", "authenticate", "--org", "demo-org", "--connector-group", "g", "--connector-id", "c"}, method: "GET", path: gbase + "g/integrations/c/authenticate/"}, + }) +} + +func TestRunnerStateBackendResourceCommands(t *testing.T) { + rbase := org + "runnergroups/" + sbase := org + "statebackends/" + runMatrix(t, []matrixCase{ + {name: "runner create", ctor: runnergroup.NewRunnerGroupCmd, args: []string{"create", "--org", "demo-org", "@payload"}, payloadJSON: `{"ResourceName":"rg"}`, method: "POST", path: rbase, body: `{"ResourceName":"rg"}`, wantOut: "Runner group created successfully."}, + {name: "runner read", ctor: runnergroup.NewRunnerGroupCmd, args: []string{"read", "--org", "demo-org", "--runner-group", "rg", "--get-active-workflows"}, method: "GET", path: rbase + "rg/", query: url.Values{"getActiveWorkflows": {"true"}}}, + {name: "runner update", ctor: runnergroup.NewRunnerGroupCmd, args: []string{"update", "--org", "demo-org", "--runner-group", "rg", "@payload"}, payloadJSON: `{"Description":"d"}`, method: "PATCH", path: rbase + "rg/", body: `{"Description":"d"}`, wantOut: "Runner group updated successfully."}, + {name: "runner delete", ctor: runnergroup.NewRunnerGroupCmd, args: []string{"delete", "--org", "demo-org", "--runner-group", "rg"}, method: "DELETE", path: rbase + "rg/", wantOut: "Runner group deleted successfully."}, + {name: "runner list", ctor: runnergroup.NewRunnerGroupCmd, args: []string{"list", "--org", "demo-org", "--limit", "5"}, method: "GET", path: rbase + "listall/", query: url.Values{"limit": {"5"}}, resp: `{"msg":[]}`}, + {name: "runner register", ctor: runnergroup.NewRunnerGroupCmd, args: []string{"register", "--org", "demo-org", "--runner-group", "rg"}, method: "POST", path: rbase + "rg/register/", wantOut: "Runner registered."}, + {name: "runner storage auth", ctor: runnergroup.NewRunnerGroupCmd, args: []string{"storage-backend-auth", "--org", "demo-org", "--runner-group", "rg"}, method: "POST", path: rbase + "rg/storage-backend-auth/"}, + {name: "runner deregister", ctor: runnergroup.NewRunnerGroupCmd, args: []string{"deregister-runner", "--org", "demo-org", "--runner-group", "rg", "--runner-id", "r1", "--container-instance-ids", "a,b", "--force"}, method: "POST", path: rbase + "rg/deregister/", body: `{"RunnerId":"r1","ContainerInstanceIds":["a","b"],"ForceDeregister":true}`, wantOut: "Runner deregistered."}, + {name: "runner state", ctor: runnergroup.NewRunnerGroupCmd, args: []string{"update-runner-state", "--org", "demo-org", "--runner-group", "rg", "--status", "DRAINING", "--runner-id", "r1"}, method: "POST", path: rbase + "rg/runner_status/", body: `{"RunnerId":"r1","Status":"DRAINING"}`, wantOut: "Runner state updated."}, + {name: "state backend create", ctor: statebackend.NewStateBackendCmd, args: []string{"create", "--org", "demo-org", "@payload"}, payloadJSON: `{"ResourceName":"sb","Statefiles":[],"StateBackendConfig":{"type":"aws_s3","s3BucketName":"b","auth":{"integrationId":"/integrations/aws"}}}`, method: "POST", path: sbase, body: `{"ResourceName":"sb","Statefiles":[],"StateBackendConfig":{"type":"aws_s3","s3BucketName":"b","auth":{"integrationId":"/integrations/aws"}}}`, wantOut: "State backend created successfully."}, + {name: "state backend read", ctor: statebackend.NewStateBackendCmd, args: []string{"read", "--org", "demo-org", "--state-backend", "sb"}, method: "GET", path: sbase + "sb/"}, + {name: "state backend update", ctor: statebackend.NewStateBackendCmd, args: []string{"update", "--org", "demo-org", "--state-backend", "sb", "@payload"}, payloadJSON: `{"Description":"d"}`, method: "PATCH", path: sbase + "sb/", body: `{"Description":"d"}`, wantOut: "State backend updated successfully."}, + {name: "state backend delete", ctor: statebackend.NewStateBackendCmd, args: []string{"delete", "--org", "demo-org", "--state-backend", "sb"}, method: "DELETE", path: sbase + "sb/", wantOut: "State backend deleted successfully."}, + {name: "state backend list", ctor: statebackend.NewStateBackendCmd, args: []string{"list", "--org", "demo-org", "--search-query", "q"}, method: "GET", path: sbase + "listall/", query: url.Values{"searchQuery": {"q"}}}, + {name: "state backend statefiles", ctor: statebackend.NewStateBackendCmd, args: []string{"list-statefiles", "--org", "demo-org", "--config", "abc"}, method: "GET", path: sbase + "list_statefiles/", query: url.Values{"config": {"abc"}}}, + {name: "resource move", ctor: resource.NewResourceCmd, args: []string{"move", "--org", "demo-org", "--source-ids", "/a,/b", "--destination", "/wfgrps/g"}, method: "POST", path: org + "resources/move/", body: `{"SourceResourceIds":["/a","/b"],"DestinationParentId":"/wfgrps/g"}`, wantOut: "Resources moved."}, + {name: "resource search", ctor: resource.NewResourceCmd, args: []string{"search", "--org", "demo-org", "--search-query", "q", "--resource-types", "WORKFLOW,STACK", "--limit", "5"}, method: "POST", path: org + "search/", body: `{"SearchQuery":"q","ResourceTypes":["WORKFLOW","STACK"],"Limit":5}`, wantOut: "Search completed."}, + {name: "resource tags", ctor: resource.NewResourceCmd, args: []string{"tags", "--org", "demo-org", "--context-tag-key", "env", "--limit", "5"}, method: "GET", path: org + "search/tags/", query: url.Values{"ContextTagKey": {"env"}, "Limit": {"5"}}}, + }) +} + +func TestBillingChatCommands(t *testing.T) { + bbase := org + "billing/" + cbase := org + "chats/" + runMatrix(t, []matrixCase{ + {name: "balance", ctor: billing.NewBillingCmd, args: []string{"balance", "--org", "demo-org"}, method: "GET", path: bbase + "list-balance/"}, + {name: "dashboard", ctor: billing.NewBillingCmd, args: []string{"dashboard-url", "--org", "demo-org", "--type", "usage"}, method: "GET", path: bbase + "dashboard/", query: url.Values{"type": {"usage"}}}, + {name: "invoices", ctor: billing.NewBillingCmd, args: []string{"invoices", "--org", "demo-org", "--limit", "5", "--next-page", "c"}, method: "GET", path: bbase + "invoices/", query: url.Values{"limit": {"5"}, "next_page": {"c"}}}, + {name: "details", ctor: billing.NewBillingCmd, args: []string{"details", "--org", "demo-org"}, method: "GET", path: bbase + "details/"}, + {name: "change plan", ctor: billing.NewBillingCmd, args: []string{"change-plan", "--org", "demo-org", "--target-package", "SG | Standard"}, method: "POST", path: bbase + "change-plan/", body: `{"TargetPackage":"SG | Standard"}`, wantOut: "Plan change submitted."}, + {name: "profile setup", ctor: billing.NewBillingCmd, args: []string{"profile", "setup", "--org", "demo-org", "@payload"}, payloadJSON: `{"Email":"e@x"}`, method: "POST", path: bbase + "profile/", body: `{"Email":"e@x"}`, wantOut: "Billing profile created."}, + {name: "profile update", ctor: billing.NewBillingCmd, args: []string{"profile", "update", "--org", "demo-org", "@payload"}, payloadJSON: `{"Name":"n"}`, method: "PATCH", path: bbase + "profile/", body: `{"Name":"n"}`, wantOut: "Billing profile updated."}, + {name: "payment list", ctor: billing.NewBillingCmd, args: []string{"payment-methods", "list", "--org", "demo-org"}, method: "GET", path: bbase + "payment-methods/"}, + {name: "payment intent", ctor: billing.NewBillingCmd, args: []string{"payment-methods", "setup-intent", "--org", "demo-org"}, method: "POST", path: bbase + "payment-methods/"}, + {name: "payment default", ctor: billing.NewBillingCmd, args: []string{"payment-methods", "set-default", "--org", "demo-org", "--payment-method-id", "pm_1"}, method: "POST", path: bbase + "set-default-payment-method/", body: `{"PaymentMethodId":"pm_1"}`, wantOut: "Default payment method set."}, + {name: "payment detach", ctor: billing.NewBillingCmd, args: []string{"payment-methods", "detach", "--org", "demo-org", "--payment-method-id", "pm_1"}, method: "POST", path: bbase + "detach-card/", body: `{"PaymentMethodId":"pm_1"}`, wantOut: "Card detached."}, + {name: "chat create", ctor: chat.NewChatCmd, args: []string{"create", "--org", "demo-org", "@payload"}, payloadJSON: `{"ChatType":"kyro","Config":{}}`, method: "POST", path: cbase, body: `{"ChatType":"kyro","Config":{}}`, wantOut: "Chat created successfully."}, + {name: "chat list", ctor: chat.NewChatCmd, args: []string{"list", "--org", "demo-org", "--chat-type", "kyro", "--refresh-pr-status"}, method: "GET", path: cbase + "listall/", query: url.Values{"chatType": {"kyro"}, "refreshPrStatus": {"true"}}, resp: `{"msg":[]}`}, + {name: "chat read", ctor: chat.NewChatCmd, args: []string{"read", "--org", "demo-org", "--chat-id", "c1"}, method: "GET", path: cbase + "c1/"}, + {name: "chat update", ctor: chat.NewChatCmd, args: []string{"update", "--org", "demo-org", "--chat-id", "c1", "@payload"}, payloadJSON: `{"Status":"archived"}`, method: "PATCH", path: cbase + "c1/", body: `{"Status":"archived"}`, wantOut: "Chat updated successfully."}, + {name: "chat delete", ctor: chat.NewChatCmd, args: []string{"delete", "--org", "demo-org", "--chat-id", "c1"}, method: "DELETE", path: cbase + "c1/", wantOut: "Chat archived successfully."}, + {name: "chat commit", ctor: chat.NewChatCmd, args: []string{"commit-bundle", "--org", "demo-org", "--chat-id", "c1", "--expected-version", "3"}, method: "POST", path: cbase + "c1/commit_bundle/", body: `{"expected_version":3}`, wantOut: "Bundle committed."}, + {name: "chat create pr", ctor: chat.NewChatCmd, args: []string{"create-pr", "--org", "demo-org", "--chat-id", "c1", "@payload"}, payloadJSON: `{"vcsConnector":"v","repoUrl":"https://x"}`, method: "POST", path: cbase + "c1/create_pr/", body: `{"vcsConnector":"v","repoUrl":"https://x"}`, wantOut: "Pull request request completed."}, + {name: "chat pr status", ctor: chat.NewChatCmd, args: []string{"pr-status", "--org", "demo-org", "--chat-id", "c1"}, method: "GET", path: cbase + "c1/pr_status/"}, + {name: "chat pr sync", ctor: chat.NewChatCmd, args: []string{"pr-sync-status", "--org", "demo-org", "--chat-id", "c1"}, method: "GET", path: cbase + "c1/pr_sync_status/"}, + {name: "chat artifacts list", ctor: chat.NewChatCmd, args: []string{"artifacts", "list", "--org", "demo-org", "--chat-id", "c1", "--prefix", "p"}, method: "GET", path: cbase + "c1/listall_artifacts/", query: url.Values{"prefix": {"p"}}}, + {name: "chat artifact url", ctor: chat.NewChatCmd, args: []string{"artifacts", "get-url", "--org", "demo-org", "--chat-id", "c1", "--artifact-path", "a"}, method: "GET", path: cbase + "c1/get_artifact/", query: url.Values{"artifactPath": {"a"}}}, + {name: "chat artifact upload", ctor: chat.NewChatCmd, args: []string{"artifacts", "upload-url", "--org", "demo-org", "--chat-id", "c1", "--artifact-path", "a", "--content-type", "text/plain"}, method: "POST", path: cbase + "c1/save_artifact/", query: url.Values{"artifactPath": {"a"}, "contentType": {"text/plain"}}}, + {name: "message create", ctor: chat.NewChatCmd, args: []string{"messages", "create", "--org", "demo-org", "--chat-id", "c1", "--text", "hi", "--client-request-id", "r1"}, method: "POST", path: cbase + "c1/messages/", body: `{"content":[{"type":"text","text":"hi"}],"clientRequestId":"r1"}`, wantOut: "Message sent."}, + {name: "message create payload", ctor: chat.NewChatCmd, args: []string{"messages", "create", "--org", "demo-org", "--chat-id", "c1", "@payload"}, payloadJSON: `{"content":[{"type":"tool_result","toolUseId":"t","isError":true}]}`, method: "POST", path: cbase + "c1/messages/", body: `{"content":[{"type":"tool_result","toolUseId":"t","isError":true}]}`, wantOut: "Message sent."}, + {name: "messages list", ctor: chat.NewChatCmd, args: []string{"messages", "list", "--org", "demo-org", "--chat-id", "c1", "--limit", "5"}, method: "GET", path: cbase + "c1/messages/listall/", query: url.Values{"limit": {"5"}}, resp: `{"msg":[]}`}, + {name: "message read", ctor: chat.NewChatCmd, args: []string{"messages", "read", "--org", "demo-org", "--chat-id", "c1", "--message-id", "m1"}, method: "GET", path: cbase + "c1/messages/m1/"}, + {name: "message cancel", ctor: chat.NewChatCmd, args: []string{"messages", "cancel", "--org", "demo-org", "--chat-id", "c1", "--message-id", "m1"}, method: "POST", path: cbase + "c1/messages/m1/cancel/", wantOut: "Message cancelled."}, + {name: "message retry", ctor: chat.NewChatCmd, args: []string{"messages", "retry", "--org", "demo-org", "--chat-id", "c1", "--message-id", "m1"}, method: "POST", path: cbase + "c1/messages/m1/retry/", wantOut: "Message retried."}, + }) +} diff --git a/go/tests/matrix_b_test.go b/go/tests/matrix_b_test.go new file mode 100644 index 0000000..bdbc06c --- /dev/null +++ b/go/tests/matrix_b_test.go @@ -0,0 +1,182 @@ +package tests + +import ( + "net/url" + "testing" + + artifactscmd "github.com/StackGuardian/sg-cli/cmd/artifacts" + stackcmd "github.com/StackGuardian/sg-cli/cmd/stack" + "github.com/StackGuardian/sg-cli/cmd/stackrun" + "github.com/StackGuardian/sg-cli/cmd/stacktemplate" + "github.com/StackGuardian/sg-cli/cmd/stackworkflow" + "github.com/StackGuardian/sg-cli/cmd/stackworkflowrun" + "github.com/StackGuardian/sg-cli/cmd/template" + workflowcmd "github.com/StackGuardian/sg-cli/cmd/workflow" + "github.com/StackGuardian/sg-cli/cmd/workflowgroup" + "github.com/StackGuardian/sg-cli/cmd/workflowrun" + "github.com/StackGuardian/sg-cli/cmd/workflowsteptemplate" + "github.com/StackGuardian/sg-cli/cmd/workflowtemplate" +) + +func TestWorkflowGroupCommands(t *testing.T) { + base := org + "wfgrps/" + runMatrix(t, []matrixCase{ + {name: "create", ctor: workflowgroup.NewWorkflowGroupCmd, args: []string{"create", "--org", "demo-org", "@payload"}, payloadJSON: `{"ResourceName":"g"}`, method: "POST", path: base, body: `{"ResourceName":"g"}`, wantOut: "Workflow group created successfully."}, + {name: "read nested", ctor: workflowgroup.NewWorkflowGroupCmd, args: []string{"read", "--org", "demo-org", "--workflow-group", "parent/child"}, method: "GET", path: base + "parent/child/"}, + {name: "update", ctor: workflowgroup.NewWorkflowGroupCmd, args: []string{"update", "--org", "demo-org", "--workflow-group", "g", "@payload"}, payloadJSON: `{"Description":"d"}`, method: "PATCH", path: base + "g/", body: `{"Description":"d"}`, wantOut: "Workflow group updated successfully."}, + {name: "delete", ctor: workflowgroup.NewWorkflowGroupCmd, args: []string{"delete", "--org", "demo-org", "--workflow-group", "g"}, method: "DELETE", path: base + "g/", wantOut: "Workflow group deleted successfully."}, + {name: "create child", ctor: workflowgroup.NewWorkflowGroupCmd, args: []string{"create-child", "--org", "demo-org", "--parent", "g", "@payload"}, payloadJSON: `{"ResourceName":"c"}`, method: "POST", path: base + "g/wfgrps/", body: `{"ResourceName":"c"}`, wantOut: "Child workflow group created successfully."}, + {name: "list children", ctor: workflowgroup.NewWorkflowGroupCmd, args: []string{"list-children", "--org", "demo-org", "--parent", "g", "--limit", "5"}, method: "GET", path: base + "g/wfgrps/listall/", query: url.Values{"limit": {"5"}}}, + {name: "list", ctor: workflowgroup.NewWorkflowGroupCmd, args: []string{"list", "--org", "demo-org", "--search-query", "q"}, method: "GET", path: base + "listall/", query: url.Values{"searchQuery": {"q"}}}, + {name: "list resources", ctor: workflowgroup.NewWorkflowGroupCmd, args: []string{"list-resources", "--org", "demo-org", "--workflow-group", "g", "--resource-types", "WORKFLOW,STACK", "--limit", "5"}, method: "GET", path: base + "g/listall/", query: url.Values{"resourceTypes": {"WORKFLOW,STACK"}, "limit": {"5"}}, resp: `{"msg":[]}`}, + }) +} + +func TestWorkflowExtraCommands(t *testing.T) { + base := org + "wfgrps/g/wfs/w/" + scope := []string{"--org", "demo-org", "--workflow-group", "g"} + with := func(args ...string) []string { return append(args, scope...) } + runMatrix(t, []matrixCase{ + {name: "update", ctor: workflowcmd.NewWorkflowCmd, args: with("update", "--workflow-id", "w", "--upgrade-mode", "MANUAL", "@payload"), payloadJSON: `{"Description":"d"}`, method: "PATCH", path: base, query: url.Values{"upgradeMode": {"MANUAL"}}, body: `{"Description":"d"}`, wantOut: "Workflow updated successfully."}, + {name: "outputs", ctor: workflowcmd.NewWorkflowCmd, args: with("outputs", "--workflow-id", "w"), method: "GET", path: base + "outputs/"}, + {name: "compare", ctor: workflowcmd.NewWorkflowCmd, args: with("compare", "--workflow-id", "w", "--target-template-id", "/o/t"), method: "POST", path: base + "compare/", body: `{"targetTemplateId":"/o/t"}`, wantOut: "Comparison completed."}, + {name: "file upload url", ctor: workflowcmd.NewWorkflowCmd, args: with("file-upload-url", "--workflow-id", "w", "--filename", "f", "--folder", "d"), method: "GET", path: base + "file_upload_url/", query: url.Values{"filename": {"f"}, "folder": {"d"}}}, + {name: "tfstate upload url", ctor: workflowcmd.NewWorkflowCmd, args: with("tfstate-upload-url", "--workflow-id", "w", "--filename", "s.json"), method: "GET", path: base + "tfstate_upload_url/", query: url.Values{"filename": {"s.json"}}}, + {name: "vcs triggers", ctor: workflowcmd.NewWorkflowCmd, args: with("vcs-triggers", "--workflow-id", "w", "@payload"), payloadJSON: `{}`, method: "POST", path: base + "webhooks/vcs_triggers/", body: `{"VCSConfig":null,"VCSTriggers":null}`, wantOut: "VCS triggers created successfully."}, + {name: "artifact url", ctor: artifactscmd.NewArtifactsCmd, args: with("get-url", "--workflow-id", "w", "--artifact-path", "p", "--version-id", "v"), method: "GET", path: base + "get_artifact/", query: url.Values{"artifactPath": {"p"}, "versionId": {"v"}}}, + {name: "artifact read", ctor: artifactscmd.NewArtifactsCmd, args: with("read", "--workflow-id", "w", "--artifact-id", "a/b.json"), method: "GET", path: base + "artifacts/a/b.json/", resp: `{"v":4}`}, + {name: "artifact create", ctor: artifactscmd.NewArtifactsCmd, args: with("create", "--workflow-id", "w", "--artifact-id", "tf", "@payload"), payloadJSON: `{"version":4}`, method: "POST", path: base + "artifacts/tf/", body: `{"version":4}`, wantOut: "Artifact created successfully."}, + {name: "artifact delete", ctor: artifactscmd.NewArtifactsCmd, args: with("delete", "--workflow-id", "w", "--artifact-id", "tf"), method: "DELETE", path: base + "artifacts/tf/", wantOut: "Artifact deleted successfully."}, + {name: "artifact versions", ctor: artifactscmd.NewArtifactsCmd, args: with("versions", "--workflow-id", "w", "--artifact-id", "tf", "--limit", "5"), method: "GET", path: base + "artifacts/tf/versions/", query: url.Values{"limit": {"5"}}}, + {name: "artifact rollback", ctor: artifactscmd.NewArtifactsCmd, args: with("rollback", "--workflow-id", "w", "--artifact-id", "tf", "--version-id", "v"), method: "POST", path: base + "artifacts/tf/rollback/", body: `{"VersionId":"v"}`, wantOut: "Artifact rolled back."}, + {name: "artifact lock", ctor: artifactscmd.NewArtifactsCmd, args: with("lock", "--workflow-id", "w", "--artifact-id", "tf"), method: "POST", path: base + "artifacts/tf/lock/", resp: `{"ID":"x"}`, wantOut: "Artifact locked."}, + {name: "artifact unlock", ctor: artifactscmd.NewArtifactsCmd, args: with("unlock", "--workflow-id", "w", "--artifact-id", "tf"), method: "DELETE", path: base + "artifacts/tf/lock/", resp: `{"ID":"x"}`, wantOut: "Artifact unlocked."}, + }) +} + +func TestStackCommands(t *testing.T) { + base := org + "wfgrps/g/stacks/" + scope := []string{"--org", "demo-org", "--workflow-group", "g"} + with := func(args ...string) []string { return append(args, scope...) } + runMatrix(t, []matrixCase{ + {name: "read", ctor: stackcmd.NewStackCmd, args: with("read", "--stack-id", "s"), method: "GET", path: base + "s/"}, + {name: "update", ctor: stackcmd.NewStackCmd, args: with("update", "--stack-id", "s", "@payload"), payloadJSON: `{"Description":"d"}`, method: "PATCH", path: base + "s/", body: `{"Description":"d"}`, wantOut: "Stack updated successfully."}, + {name: "list", ctor: stackcmd.NewStackCmd, args: with("list", "--tags", "t"), method: "GET", path: base + "listall/", query: url.Values{"Tags": {"t"}}}, + {name: "compare", ctor: stackcmd.NewStackCmd, args: with("compare", "--stack-id", "s", "--target-template-group-id", "/o/t", "--upgrade-mode", "MANUAL"), method: "POST", path: base + "s/compare/", body: `{"targetTemplateGroupId":"/o/t","upgradeMode":"MANUAL"}`, wantOut: "Comparison completed."}, + {name: "run create", ctor: stackrun.NewStackRunCmd, args: with("create", "--stack-id", "s", "--action-type", "APPLY"), method: "POST", path: base + "s/stackruns/", body: `{"ActionType":"APPLY"}`, wantOut: "Stack run created successfully."}, + {name: "run read", ctor: stackrun.NewStackRunCmd, args: with("read", "--stack-id", "s", "--run-id", "r1"), method: "GET", path: base + "s/stackruns/r1/"}, + {name: "run list", ctor: stackrun.NewStackRunCmd, args: with("list", "--stack-id", "s", "--limit", "5"), method: "GET", path: base + "s/stackruns/listall/", query: url.Values{"limit": {"5"}}}, + }) +} + +func TestStackWorkflowCommands(t *testing.T) { + base := org + "wfgrps/g/stacks/s/wfs/" + scope := []string{"--org", "demo-org", "--workflow-group", "g", "--stack-id", "s"} + with := func(args ...string) []string { return append(args, scope...) } + runMatrix(t, []matrixCase{ + {name: "create", ctor: stackworkflow.NewStackWorkflowCmd, args: with("create", "@payload"), payloadJSON: `{"ResourceName":"w"}`, method: "POST", path: base, body: `{"ResourceName":"w"}`, wantOut: "Stack workflow created successfully."}, + {name: "read", ctor: stackworkflow.NewStackWorkflowCmd, args: with("read", "--workflow-id", "w"), method: "GET", path: base + "w/"}, + {name: "update", ctor: stackworkflow.NewStackWorkflowCmd, args: with("update", "--workflow-id", "w", "@payload"), payloadJSON: `{"Description":"d"}`, method: "PATCH", path: base + "w/", body: `{"Description":"d"}`, wantOut: "Stack workflow updated successfully."}, + {name: "delete", ctor: stackworkflow.NewStackWorkflowCmd, args: with("delete", "--workflow-id", "w"), method: "DELETE", path: base + "w/", wantOut: "Stack workflow deleted successfully."}, + {name: "list", ctor: stackworkflow.NewStackWorkflowCmd, args: with("list", "--latest-wf-run-statuses", "3", "--limit", "5"), method: "GET", path: base + "listall/", query: url.Values{"LatestWfRunStatuses": {"3"}, "limit": {"5"}}}, + {name: "outputs", ctor: stackworkflow.NewStackWorkflowCmd, args: with("outputs", "--workflow-id", "w"), method: "GET", path: base + "w/outputs/"}, + {name: "tfstate url", ctor: stackworkflow.NewStackWorkflowCmd, args: with("tfstate-upload-url", "--workflow-id", "w", "--filename", "s.json"), method: "GET", path: base + "w/tfstate_upload_url/", query: url.Values{"filename": {"s.json"}}}, + {name: "file upload url", ctor: stackworkflow.NewStackWorkflowCmd, args: with("file-upload-url", "--workflow-id", "w", "--filename", "f"), method: "GET", path: base + "w/file_upload_url/", query: url.Values{"filename": {"f"}}}, + {name: "compare", ctor: stackworkflow.NewStackWorkflowCmd, args: with("compare", "--workflow-id", "w", "--target-template-id", "/o/t"), method: "POST", path: base + "w/compare/", body: `{"targetTemplateId":"/o/t"}`, wantOut: "Comparison completed."}, + {name: "vcs triggers", ctor: stackworkflow.NewStackWorkflowCmd, args: with("vcs-triggers", "--workflow-id", "w", "@payload"), payloadJSON: `{}`, method: "POST", path: base + "w/webhooks/vcs_triggers/", body: `{"VCSConfig":null,"VCSTriggers":null}`, wantOut: "VCS triggers created successfully."}, + {name: "artifacts list", ctor: stackworkflow.NewStackWorkflowCmd, args: with("artifacts", "list", "--workflow-id", "w"), method: "GET", path: base + "w/listall_artifacts/"}, + {name: "artifact url", ctor: stackworkflow.NewStackWorkflowCmd, args: with("artifacts", "get-url", "--workflow-id", "w", "--artifact-path", "p"), method: "GET", path: base + "w/get_artifact/", query: url.Values{"artifactPath": {"p"}}}, + {name: "artifact read", ctor: stackworkflow.NewStackWorkflowCmd, args: with("artifacts", "read", "--workflow-id", "w", "--artifact-id", "tf"), method: "GET", path: base + "w/artifacts/tf/", resp: `{"v":1}`}, + {name: "artifact create", ctor: stackworkflow.NewStackWorkflowCmd, args: with("artifacts", "create", "--workflow-id", "w", "--artifact-id", "tf", "@payload"), payloadJSON: `[1,2]`, method: "POST", path: base + "w/artifacts/tf/", body: `[1,2]`, wantOut: "Artifact created successfully."}, + {name: "artifact delete", ctor: stackworkflow.NewStackWorkflowCmd, args: with("artifacts", "delete", "--workflow-id", "w", "--artifact-id", "tf"), method: "DELETE", path: base + "w/artifacts/tf/", wantOut: "Artifact deleted successfully."}, + {name: "artifact lock", ctor: stackworkflow.NewStackWorkflowCmd, args: with("artifacts", "lock", "--workflow-id", "w", "--artifact-id", "tf"), method: "POST", path: base + "w/artifacts/tf/lock/", resp: `{"ID":"x"}`, wantOut: "Artifact locked."}, + {name: "artifact unlock", ctor: stackworkflow.NewStackWorkflowCmd, args: with("artifacts", "unlock", "--workflow-id", "w", "--artifact-id", "tf"), method: "DELETE", path: base + "w/artifacts/tf/lock/", resp: `{"ID":"x"}`, wantOut: "Artifact unlocked."}, + }) +} + +func TestRunCommands(t *testing.T) { + base := org + "wfgrps/g/wfs/w/wfruns/" + sbase := org + "wfgrps/g/stacks/s/wfs/w/wfruns/" + scope := []string{"--org", "demo-org", "--workflow-group", "g", "--workflow-id", "w"} + with := func(args ...string) []string { return append(args, scope...) } + sscope := []string{"--org", "demo-org", "--workflow-group", "g", "--stack-id", "s", "--workflow-id", "w"} + swith := func(args ...string) []string { return append(args, sscope...) } + runMatrix(t, []matrixCase{ + {name: "create empty", ctor: workflowrun.NewWorkflowRunCmd, args: with("create"), method: "POST", path: base, body: `{}`, wantOut: "Workflow run created successfully."}, + {name: "create payload", ctor: workflowrun.NewWorkflowRunCmd, args: with("create", "@payload"), payloadJSON: `{"WfType":"TERRAFORM"}`, method: "POST", path: base, body: `{"WfType":"TERRAFORM"}`, wantOut: "Workflow run created successfully."}, + {name: "read", ctor: workflowrun.NewWorkflowRunCmd, args: with("read", "--run-id", "r1"), method: "GET", path: base + "r1/"}, + {name: "update", ctor: workflowrun.NewWorkflowRunCmd, args: with("update", "--run-id", "r1", "@payload"), payloadJSON: `{"WfType":"CUSTOM"}`, method: "PATCH", path: base + "r1/", body: `{"WfType":"CUSTOM"}`, wantOut: "Workflow run updated successfully."}, + {name: "cancel", ctor: workflowrun.NewWorkflowRunCmd, args: with("cancel", "--run-id", "r1"), method: "PATCH", path: base + "r1/cancel/", wantOut: "Workflow run cancelled."}, + {name: "delete", ctor: workflowrun.NewWorkflowRunCmd, args: with("delete", "--run-id", "r1"), method: "DELETE", path: base + "r1/", wantOut: "Workflow run cancelled."}, + {name: "logs", ctor: workflowrun.NewWorkflowRunCmd, args: with("logs", "--run-id", "r1"), method: "GET", path: base + "r1/logs/"}, + {name: "approve", ctor: workflowrun.NewWorkflowRunCmd, args: with("approve", "--run-id", "r1", "--message", "ok"), method: "POST", path: base + "r1/resume/", body: `{"Approve":true,"Message":"ok"}`, wantOut: "Approval decision submitted."}, + {name: "reject", ctor: workflowrun.NewWorkflowRunCmd, args: with("approve", "--run-id", "r1", "--reject", "--approval-step", "plan"), method: "POST", path: base + "r1/resume/", body: `{"Approve":false,"ApprovalStep":"plan"}`, wantOut: "Approval decision submitted."}, + {name: "list", ctor: workflowrun.NewWorkflowRunCmd, args: with("list", "--context-tags", "c", "--limit", "5"), method: "GET", path: base + "listall/", query: url.Values{"contextTags": {"c"}, "limit": {"5"}}}, + {name: "read by ksuid", ctor: workflowrun.NewWorkflowRunCmd, args: []string{"read-by-ksuid", "--org", "demo-org", "--parent-ksuid", "pk", "--resource-ksuid", "rk"}, method: "GET", path: org + "wfs/pk/wfruns/rk/"}, + {name: "update by ksuid", ctor: workflowrun.NewWorkflowRunCmd, args: []string{"update-by-ksuid", "--org", "demo-org", "--parent-ksuid", "pk", "--resource-ksuid", "rk", "@payload"}, payloadJSON: `{"WfType":"CUSTOM"}`, method: "PATCH", path: org + "wfs/pk/wfruns/rk/", body: `{"WfType":"CUSTOM"}`, wantOut: "Workflow run updated successfully."}, + {name: "facts read", ctor: workflowrun.NewWorkflowRunCmd, args: with("facts", "read", "--run-id", "r1", "--facts-id", "f1"), method: "GET", path: base + "r1/wfrunfacts/f1/", resp: `{"facts":1}`}, + {name: "facts create", ctor: workflowrun.NewWorkflowRunCmd, args: with("facts", "create", "--run-id", "r1", "--facts-id", "f1", "@payload"), payloadJSON: `{"TfDrift":{"a":1}}`, method: "POST", path: base + "r1/wfrunfacts/f1/", body: `{"TfDrift":{"a":1}}`, resp: `{"msg":"ok"}`, wantOut: "Workflow run facts created."}, + {name: "facts update", ctor: workflowrun.NewWorkflowRunCmd, args: with("facts", "update", "--run-id", "r1", "--facts-id", "f1", "@payload"), payloadJSON: `{"Tags":["a"]}`, method: "PATCH", path: base + "r1/wfrunfacts/f1/", body: `{"Tags":["a"]}`, resp: `{"msg":"ok"}`, wantOut: "Workflow run facts updated."}, + {name: "stack create empty", ctor: stackworkflowrun.NewStackWorkflowRunCmd, args: swith("create"), method: "POST", path: sbase, body: `{}`, wantOut: "Stack workflow run created successfully."}, + {name: "stack read", ctor: stackworkflowrun.NewStackWorkflowRunCmd, args: swith("read", "--run-id", "r1"), method: "GET", path: sbase + "r1/"}, + {name: "stack update", ctor: stackworkflowrun.NewStackWorkflowRunCmd, args: swith("update", "--run-id", "r1", "@payload"), payloadJSON: `{"WfType":"CUSTOM"}`, method: "PATCH", path: sbase + "r1/", body: `{"WfType":"CUSTOM"}`, wantOut: "Stack workflow run updated successfully."}, + {name: "stack delete", ctor: stackworkflowrun.NewStackWorkflowRunCmd, args: swith("delete", "--run-id", "r1"), method: "DELETE", path: sbase + "r1/", wantOut: "Stack workflow run cancelled."}, + {name: "stack logs", ctor: stackworkflowrun.NewStackWorkflowRunCmd, args: swith("logs", "--run-id", "r1"), method: "GET", path: sbase + "r1/logs/"}, + {name: "stack approve", ctor: stackworkflowrun.NewStackWorkflowRunCmd, args: swith("approve", "--run-id", "r1", "--reject"), method: "POST", path: sbase + "r1/resume/", body: `{"Approve":false}`, wantOut: "Approval decision submitted."}, + {name: "stack list", ctor: stackworkflowrun.NewStackWorkflowRunCmd, args: swith("list", "--latest-status", "RUNNING", "--limit", "5"), method: "GET", path: sbase + "listall/", query: url.Values{"latestStatus": {"RUNNING"}, "limit": {"5"}}, resp: `{"msg":[]}`}, + {name: "stack facts read", ctor: stackworkflowrun.NewStackWorkflowRunCmd, args: swith("facts", "read", "--run-id", "r1", "--facts-id", "f1"), method: "GET", path: sbase + "r1/wfrunfacts/f1/", resp: `{"facts":1}`}, + {name: "stack facts create", ctor: stackworkflowrun.NewStackWorkflowRunCmd, args: swith("facts", "create", "--run-id", "r1", "--facts-id", "f1", "@payload"), payloadJSON: `{"TfDrift":{}}`, method: "POST", path: sbase + "r1/wfrunfacts/f1/", body: `{"TfDrift":{}}`, resp: `{"msg":"ok"}`, wantOut: "Stack workflow run facts created."}, + {name: "stack facts update", ctor: stackworkflowrun.NewStackWorkflowRunCmd, args: swith("facts", "update", "--run-id", "r1", "--facts-id", "f1", "@payload"), payloadJSON: `{"IsActive":"0"}`, method: "PATCH", path: sbase + "r1/wfrunfacts/f1/", body: `{"IsActive":"0"}`, resp: `{"msg":"ok"}`, wantOut: "Stack workflow run facts updated."}, + }) +} + +func TestTemplateCommands(t *testing.T) { + tt := "/api/v1/templatetypes/" + runMatrix(t, []matrixCase{ + {name: "list", ctor: template.NewTemplateCmd, args: []string{"list", "--org", "demo-org", "--template-type", "IAC", "--owner-orgs", "o1", "--search-query", "q"}, method: "GET", path: tt + "IAC/templates/listall/", query: url.Values{"OwnerOrgs": {"o1"}, "SearchQuery": {"q"}}}, + {name: "list by owner", ctor: template.NewTemplateCmd, args: []string{"list-by-owner", "--org", "demo-org", "--owner-org", "owner-org", "--shared"}, method: "GET", path: "/api/v1/orgs/owner-org/templates/listall/", query: url.Values{"isSharedTemplate": {"true"}}}, + {name: "create", ctor: template.NewTemplateCmd, args: []string{"create", "--org", "demo-org", "@payload"}, payloadJSON: `{"TemplateType":"IAC","TemplateName":"t1"}`, method: "POST", path: "/api/v1/templates/", body: `{"TemplateType":"IAC","TemplateName":"t1","OwnerOrg":"","SourceConfigKind":""}`, resp: `{"TemplateType":"IAC","TemplateName":"t1"}`, wantOut: "Template created successfully."}, + {name: "read", ctor: template.NewTemplateCmd, args: []string{"read", "--org", "demo-org", "--template-id", "t1:5", "--template-type", "IAC"}, method: "GET", path: tt + "IAC/demo-org/t1:5/"}, + {name: "read other owner", ctor: template.NewTemplateCmd, args: []string{"read", "--org", "demo-org", "--template-id", "t1", "--template-type", "IAC_GROUP", "--owner-org", "stackguardian"}, method: "GET", path: tt + "IAC_GROUP/stackguardian/t1/"}, + {name: "update", ctor: template.NewTemplateCmd, args: []string{"update", "--org", "demo-org", "--template-id", "t1:2", "--template-type", "WORKFLOW_STEP", "@payload"}, payloadJSON: `{"TemplateName":"t2"}`, method: "PATCH", path: tt + "WORKFLOW_STEP/demo-org/t1:2/", body: `{"TemplateName":"t2"}`, wantOut: "Template updated successfully."}, + {name: "delete", ctor: template.NewTemplateCmd, args: []string{"delete", "--org", "demo-org", "--template-id", "t1", "--template-type", "IAC_POLICY"}, method: "DELETE", path: tt + "IAC_POLICY/demo-org/t1/", wantOut: "Template deleted successfully."}, + {name: "group iac", ctor: template.NewTemplateCmd, args: []string{"group-iac", "--org", "demo-org", "--template-id", "grp", "--iac-template-id", "sub:1", "--owner-org", "stackguardian"}, method: "GET", path: tt + "IAC_GROUP/stackguardian/grp/IAC/sub:1/"}, + {name: "input schema", ctor: template.NewTemplateCmd, args: []string{"input-schema", "--org", "demo-org", "--template-id", "t1:2", "--template-type", "IAC", "--schema-type", "FORM_JSONSCHEMA"}, method: "GET", path: tt + "IAC/demo-org/t1:2/get_input_schema/", query: url.Values{"SchemaType": {"FORM_JSONSCHEMA"}}}, + {name: "vcs triggers", ctor: template.NewTemplateCmd, args: []string{"vcs-triggers", "--org", "demo-org", "--template-id", "t1", "--template-type", "IAC", "@payload"}, payloadJSON: `{}`, method: "POST", path: tt + "IAC/demo-org/t1/webhooks/vcs_triggers/", body: `{"VCSConfig":null,"VCSTriggers":null}`, wantOut: "VCS triggers created successfully."}, + {name: "subscriptions read", ctor: template.NewTemplateCmd, args: []string{"subscriptions", "read", "--org", "demo-org", "--subscription-type", "IACSubscriptions"}, method: "GET", path: org + "subscriptions/default/", query: url.Values{"subscriptionType": {"IACSubscriptions"}}}, + {name: "subscriptions create", ctor: template.NewTemplateCmd, args: []string{"subscriptions", "create", "--org", "demo-org", "@payload"}, payloadJSON: `{"IACSubscriptions":{},"WfStepSubscriptions":{},"PolicySubscriptions":{},"IACGroupSubscriptions":{}}`, method: "POST", path: org + "subscriptions/", body: `{"IACSubscriptions":{},"WfStepSubscriptions":{},"PolicySubscriptions":{},"IACGroupSubscriptions":{}}`, wantOut: "Subscription created successfully."}, + {name: "subscriptions update", ctor: template.NewTemplateCmd, args: []string{"subscriptions", "update", "--org", "demo-org", "--action", "subscribe", "@payload"}, payloadJSON: `{"IACSubscriptions":{"/o/t":{}}}`, method: "PATCH", path: org + "subscriptions/default/subscribe/", body: `{"IACSubscriptions":{"/o/t":{}}}`, wantOut: "Subscription updated successfully."}, + {name: "artifacts list", ctor: template.NewTemplateCmd, args: []string{"artifacts", "list", "--org", "demo-org", "--template-id", "t:1", "--template-type", "IAC", "--prefix", "p"}, method: "GET", path: tt + "IAC/demo-org/t:1/listall_artifacts/", query: url.Values{"artifactPrefix": {"p"}}}, + {name: "artifact download", ctor: template.NewTemplateCmd, args: []string{"artifacts", "download-url", "--org", "demo-org", "--template-id", "t", "--template-type", "IAC", "--artifact-id", "a", "--owner-org", "stackguardian"}, method: "GET", path: tt + "IAC/stackguardian/t/artifacts/a/download/presigned-url/"}, + {name: "artifact upload", ctor: template.NewTemplateCmd, args: []string{"artifacts", "upload-url", "--org", "demo-org", "--template-id", "t", "--template-type", "IAC_GROUP", "--artifact-id", "a"}, method: "GET", path: tt + "IAC_GROUP/demo-org/t/artifacts/a/upload/presigned-url/"}, + {name: "artifact delete", ctor: template.NewTemplateCmd, args: []string{"artifacts", "delete", "--org", "demo-org", "--template-id", "t", "--template-type", "IAC", "--artifact-id", "a"}, method: "DELETE", path: tt + "IAC/demo-org/t/artifacts/a/", wantOut: "Artifact deleted successfully."}, + {name: "public list", ctor: template.NewTemplateCmd, args: []string{"public", "list", "--org", "demo-org", "--template-type", "IAC", "--owner-orgs", "stackguardian"}, method: "GET", path: "/api/v1/public/templatetypes/IAC/templates/listall/", query: url.Values{"OwnerOrgs": {"stackguardian"}}}, + {name: "public list all", ctor: template.NewTemplateCmd, args: []string{"public", "list-all", "--org", "demo-org", "--template-types", "IAC,IAC_GROUP"}, method: "GET", path: "/api/v1/public/templates/listall/", query: url.Values{"templateTypes": {"IAC,IAC_GROUP"}}}, + {name: "public read", ctor: template.NewTemplateCmd, args: []string{"public", "read", "--org", "demo-org", "--template-id", "t:1", "--template-type", "IAC", "--owner-org", "stackguardian"}, method: "GET", path: "/api/v1/public/templatetypes/IAC/stackguardian/t:1/"}, + // typed template packages + {name: "wf tpl read", ctor: workflowtemplate.NewWorkflowTemplateCmd, args: []string{"read", "--org", "demo-org", "--template-id", "t1"}, method: "GET", path: tt + "IAC/demo-org/t1/"}, + {name: "wf tpl create", ctor: workflowtemplate.NewWorkflowTemplateCmd, args: []string{"create", "--org", "demo-org", "--create-first-revision=false", "@payload"}, payloadJSON: `{"TemplateName":"t1"}`, method: "POST", path: "/api/v1/templates/", query: url.Values{"createFirstRevision": {"false"}}, body: `{"TemplateType":"IAC","TemplateName":"t1"}`, wantOut: "Workflow template created successfully."}, + {name: "wf tpl update", ctor: workflowtemplate.NewWorkflowTemplateCmd, args: []string{"update", "--org", "demo-org", "--template-id", "t1", "@payload"}, payloadJSON: `{"TemplateName":"t2"}`, method: "PATCH", path: tt + "IAC/demo-org/t1/", body: `{"TemplateName":"t2"}`, wantOut: "Workflow template updated successfully."}, + {name: "wf tpl delete", ctor: workflowtemplate.NewWorkflowTemplateCmd, args: []string{"delete", "--org", "demo-org", "--template-id", "t1"}, method: "DELETE", path: tt + "IAC/demo-org/t1/", wantOut: "Workflow template deleted successfully."}, + {name: "wf rev create", ctor: workflowtemplate.NewWorkflowTemplateCmd, args: []string{"revisions", "create", "--org", "demo-org", "--template-id", "t1", "@payload"}, payloadJSON: `{"LongDescription":"d"}`, method: "POST", path: tt + "IAC/demo-org/t1/revisions/", body: `{"TemplateType":"IAC","LongDescription":"d"}`, wantOut: "Revision created successfully."}, + {name: "wf rev read", ctor: workflowtemplate.NewWorkflowTemplateCmd, args: []string{"revisions", "read", "--org", "demo-org", "--revision-id", "t1:1"}, method: "GET", path: tt + "IAC/demo-org/t1:1/"}, + {name: "wf rev update", ctor: workflowtemplate.NewWorkflowTemplateCmd, args: []string{"revisions", "update", "--org", "demo-org", "--revision-id", "t1:1", "@payload"}, payloadJSON: `{"Alias":"a"}`, method: "PATCH", path: tt + "IAC/demo-org/t1:1/", body: `{"Alias":"a"}`, wantOut: "Revision updated successfully."}, + {name: "wf rev delete", ctor: workflowtemplate.NewWorkflowTemplateCmd, args: []string{"revisions", "delete", "--org", "demo-org", "--revision-id", "t1:1", "--keep-parent-template"}, method: "DELETE", path: tt + "IAC/demo-org/t1:1/", query: url.Values{"keepParentTemplate": {"true"}}, wantOut: "Revision deleted successfully."}, + {name: "step tpl read", ctor: workflowsteptemplate.NewWorkflowStepTemplateCmd, args: []string{"read", "--org", "demo-org", "--template-id", "t1"}, method: "GET", path: tt + "WORKFLOW_STEP/demo-org/t1/"}, + {name: "step tpl create", ctor: workflowsteptemplate.NewWorkflowStepTemplateCmd, args: []string{"create", "--org", "demo-org", "@payload"}, payloadJSON: `{"TemplateName":"t1"}`, method: "POST", path: "/api/v1/templates/", body: `{"TemplateType":"WORKFLOW_STEP","TemplateName":"t1"}`, wantOut: "Workflow step template created successfully."}, + {name: "step tpl update", ctor: workflowsteptemplate.NewWorkflowStepTemplateCmd, args: []string{"update", "--org", "demo-org", "--template-id", "t1", "@payload"}, payloadJSON: `{"ShortDescription":"d"}`, method: "PATCH", path: tt + "WORKFLOW_STEP/demo-org/t1/", body: `{"ShortDescription":"d"}`, wantOut: "Workflow step template updated successfully."}, + {name: "step tpl delete", ctor: workflowsteptemplate.NewWorkflowStepTemplateCmd, args: []string{"delete", "--org", "demo-org", "--template-id", "t1"}, method: "DELETE", path: tt + "WORKFLOW_STEP/demo-org/t1/", wantOut: "Workflow step template deleted successfully."}, + {name: "step rev create", ctor: workflowsteptemplate.NewWorkflowStepTemplateCmd, args: []string{"revisions", "create", "--org", "demo-org", "--template-id", "t1", "@payload"}, payloadJSON: `{"LongDescription":"d"}`, method: "POST", path: tt + "WORKFLOW_STEP/demo-org/t1/revisions/", body: `{"TemplateType":"WORKFLOW_STEP","LongDescription":"d"}`, wantOut: "Revision created successfully."}, + {name: "step rev read", ctor: workflowsteptemplate.NewWorkflowStepTemplateCmd, args: []string{"revisions", "read", "--org", "demo-org", "--revision-id", "t1:1"}, method: "GET", path: tt + "WORKFLOW_STEP/demo-org/t1:1/"}, + {name: "step rev update", ctor: workflowsteptemplate.NewWorkflowStepTemplateCmd, args: []string{"revisions", "update", "--org", "demo-org", "--revision-id", "t1:1", "@payload"}, payloadJSON: `{"LongDescription":"d"}`, method: "PATCH", path: tt + "WORKFLOW_STEP/demo-org/t1:1/", body: `{"LongDescription":"d"}`, wantOut: "Revision updated successfully."}, + {name: "step rev delete", ctor: workflowsteptemplate.NewWorkflowStepTemplateCmd, args: []string{"revisions", "delete", "--org", "demo-org", "--revision-id", "t1:1"}, method: "DELETE", path: tt + "WORKFLOW_STEP/demo-org/t1:1/", wantOut: "Revision deleted successfully."}, + {name: "stack tpl read", ctor: stacktemplate.NewStackTemplateCmd, args: []string{"read", "--org", "demo-org", "--template-id", "t1"}, method: "GET", path: tt + "IAC_GROUP/demo-org/t1/"}, + {name: "stack tpl create", ctor: stacktemplate.NewStackTemplateCmd, args: []string{"create", "--org", "demo-org", "@payload"}, payloadJSON: `{"OwnerOrg":"demo-org"}`, method: "POST", path: "/api/v1/templates/", body: `{"TemplateType":"IAC_GROUP","OwnerOrg":"demo-org"}`, wantOut: "Stack template created successfully."}, + {name: "stack tpl update", ctor: stacktemplate.NewStackTemplateCmd, args: []string{"update", "--org", "demo-org", "--template-id", "t1", "@payload"}, payloadJSON: `{"Tags":["a"]}`, method: "PATCH", path: tt + "IAC_GROUP/demo-org/t1/", body: `{"Tags":["a"]}`, wantOut: "Stack template updated successfully."}, + {name: "stack tpl delete", ctor: stacktemplate.NewStackTemplateCmd, args: []string{"delete", "--org", "demo-org", "--template-id", "t1"}, method: "DELETE", path: tt + "IAC_GROUP/demo-org/t1/", wantOut: "Stack template deleted successfully."}, + {name: "stack rev create", ctor: stacktemplate.NewStackTemplateCmd, args: []string{"revisions", "create", "--org", "demo-org", "--template-id", "t1", "@payload"}, payloadJSON: `{"Tags":["a"]}`, method: "POST", path: tt + "IAC_GROUP/demo-org/t1/revisions/", body: `{"TemplateType":"IAC_GROUP","Tags":["a"]}`, wantOut: "Revision created successfully."}, + {name: "stack rev read", ctor: stacktemplate.NewStackTemplateCmd, args: []string{"revisions", "read", "--org", "demo-org", "--revision-id", "t1:1"}, method: "GET", path: tt + "IAC_GROUP/demo-org/t1:1/"}, + {name: "stack rev update", ctor: stacktemplate.NewStackTemplateCmd, args: []string{"revisions", "update", "--org", "demo-org", "--revision-id", "t1:1", "@payload"}, payloadJSON: `{"LongDescription":"d"}`, method: "PATCH", path: tt + "IAC_GROUP/demo-org/t1:1/", body: `{"LongDescription":"d"}`, wantOut: "Revision updated successfully."}, + {name: "stack rev delete", ctor: stacktemplate.NewStackTemplateCmd, args: []string{"revisions", "delete", "--org", "demo-org", "--revision-id", "t1:1", "--keep-parent-template"}, method: "DELETE", path: tt + "IAC_GROUP/demo-org/t1:1/", query: url.Values{"keepParentTemplate": {"true"}}, wantOut: "Revision deleted successfully."}, + }) +} diff --git a/go/tests/matrix_test.go b/go/tests/matrix_test.go new file mode 100644 index 0000000..787329f --- /dev/null +++ b/go/tests/matrix_test.go @@ -0,0 +1,118 @@ +package tests + +import ( + "bytes" + "encoding/json" + "io" + "net/http" + "net/url" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/StackGuardian/sg-sdk-go/client" + "github.com/StackGuardian/sg-sdk-go/option" + "github.com/spf13/cobra" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// recorder is an http.RoundTripper that captures the last request and answers +// with a canned JSON body, so a command's wire format can be asserted exactly. +type recorder struct { + status int + resp string + + method string + path string + query url.Values + body string + auth string + calls int +} + +func (r *recorder) RoundTrip(req *http.Request) (*http.Response, error) { + var body []byte + if req.Body != nil { + body, _ = io.ReadAll(req.Body) + } + r.method, r.path, r.query, r.body, r.auth = req.Method, req.URL.Path, req.URL.Query(), string(body), req.Header.Get("Authorization") + r.calls++ + status := r.status + if status == 0 { + status = http.StatusOK + } + resp := r.resp + if resp == "" { + resp = "{}" + } + return &http.Response{ + StatusCode: status, + Status: http.StatusText(status), + Header: http.Header{"Content-Type": {"application/json"}}, + Body: io.NopCloser(strings.NewReader(resp)), + }, nil +} + +// matrixCase describes one CLI invocation and the request it must produce. +// "@payload" in args is replaced by a temp file holding payloadJSON. +type matrixCase struct { + name string + ctor func(*client.Client) *cobra.Command + args []string + payloadJSON string + method string + path string + query url.Values // nil asserts no query string + body string // "" asserts no body + resp string + wantOut string // substring expected on stdout +} + +func runMatrix(t *testing.T, cases []matrixCase) { + t.Helper() + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + rec := &recorder{resp: tc.resp} + c := client.NewClient(option.WithApiKey("apikey test-token"), option.WithHTTPClient(&http.Client{Transport: rec})) + cmd := tc.ctor(c) + args := make([]string, 0, len(tc.args)) + for _, a := range tc.args { + if a == "@payload" { + p := filepath.Join(t.TempDir(), "payload.json") + require.NoError(t, os.WriteFile(p, []byte(tc.payloadJSON), 0o600)) + a = p + } + args = append(args, a) + } + cmd.SetArgs(args) + var out, errOut bytes.Buffer + cmd.SetOut(&out) + cmd.SetErr(&errOut) + require.NoError(t, cmd.Execute(), "stderr: %s", errOut.String()) + require.Equal(t, 1, rec.calls, "expected exactly one request") + assert.Equal(t, tc.method, rec.method, "method") + assert.Equal(t, tc.path, rec.path, "path") + if tc.query == nil { + assert.Empty(t, rec.query, "query") + } else { + assert.Equal(t, tc.query, rec.query, "query") + } + if tc.body == "" { + assert.Empty(t, rec.body, "body") + } else { + assert.JSONEq(t, tc.body, rec.body, "body") + } + assert.Equal(t, "apikey test-token", rec.auth) + if tc.wantOut != "" { + assert.Contains(t, out.String(), tc.wantOut) + } else { + // read commands print the response as JSON + var parsed interface{} + assert.NoError(t, json.Unmarshal([]byte(strings.TrimSpace(out.String())), &parsed), "stdout should be JSON: %s", out.String()) + } + }) + } +} diff --git a/go/tests/tree_test.go b/go/tests/tree_test.go new file mode 100644 index 0000000..60712fa --- /dev/null +++ b/go/tests/tree_test.go @@ -0,0 +1,274 @@ +package tests + +import ( + "sort" + "strings" + "testing" + + "github.com/StackGuardian/sg-cli/cmd" + "github.com/spf13/cobra" + "github.com/stretchr/testify/assert" +) + +// expectedLeaves pins the complete command surface (one leaf per SDK method plus +// the apply/destroy conveniences). Update it deliberately when commands change. +const expectedLeaves = ` +api-access create +api-access delete +api-access list +api-access read +api-access regenerate-key +api-access update +api-token create +api-token delete +artifacts create +artifacts delete +artifacts get-url +artifacts list +artifacts lock +artifacts read +artifacts rollback +artifacts unlock +artifacts versions +audit-log list +benchmark-report read +billing balance +billing change-plan +billing dashboard-url +billing details +billing invoices +billing payment-methods detach +billing payment-methods list +billing payment-methods set-default +billing payment-methods setup-intent +billing profile setup +billing profile update +chat artifacts get-url +chat artifacts list +chat artifacts upload-url +chat commit-bundle +chat create +chat create-pr +chat delete +chat list +chat messages cancel +chat messages create +chat messages list +chat messages read +chat messages retry +chat pr-status +chat pr-sync-status +chat read +chat update +connector authenticate +connector create +connector delete +connector github-repos +connector list +connector list-accounts +connector read +connector repos +connector update +connector-group authenticate +connector-group connectors authenticate +connector-group connectors delete +connector-group connectors list +connector-group connectors read +connector-group connectors update +connector-group create +connector-group delete +connector-group discovery-scan +connector-group list +connector-group read +connector-group update +organization bulk-action +organization count-workflows +organization create +organization delete +organization list +organization read +organization update +organization workflows +policy create +policy delete +policy list +policy read +policy update +resource move +resource search +resource tags +role create +role delete +role list +role read +role update +role-binding read +runner-group create +runner-group delete +runner-group deregister-runner +runner-group list +runner-group read +runner-group register +runner-group storage-backend-auth +runner-group update +runner-group update-runner-state +secret create +secret delete +secret list +secret read-bulk +secret update +stack apply +stack compare +stack create +stack delete +stack destroy +stack list +stack outputs +stack read +stack update +stack-run create +stack-run list +stack-run read +stack-template create +stack-template delete +stack-template read +stack-template revisions create +stack-template revisions delete +stack-template revisions read +stack-template revisions update +stack-template update +stack-workflow artifacts create +stack-workflow artifacts delete +stack-workflow artifacts get-url +stack-workflow artifacts list +stack-workflow artifacts lock +stack-workflow artifacts read +stack-workflow artifacts unlock +stack-workflow compare +stack-workflow create +stack-workflow delete +stack-workflow file-upload-url +stack-workflow list +stack-workflow outputs +stack-workflow read +stack-workflow tfstate-upload-url +stack-workflow update +stack-workflow vcs-triggers +stack-workflow-run approve +stack-workflow-run create +stack-workflow-run delete +stack-workflow-run facts create +stack-workflow-run facts read +stack-workflow-run facts update +stack-workflow-run list +stack-workflow-run logs +stack-workflow-run read +stack-workflow-run update +state-backend create +state-backend delete +state-backend list +state-backend list-statefiles +state-backend read +state-backend update +template artifacts delete +template artifacts download-url +template artifacts list +template artifacts upload-url +template create +template delete +template group-iac +template input-schema +template list +template list-by-owner +template public list +template public list-all +template public read +template read +template subscriptions create +template subscriptions read +template subscriptions update +template update +template vcs-triggers +user create +user delete +user list +user read +user update +workflow apply +workflow compare +workflow create +workflow delete +workflow destroy +workflow file-upload-url +workflow list +workflow outputs +workflow read +workflow tfstate-upload-url +workflow update +workflow vcs-triggers +workflow-group create +workflow-group create-child +workflow-group delete +workflow-group list +workflow-group list-children +workflow-group list-resources +workflow-group read +workflow-group update +workflow-run approve +workflow-run cancel +workflow-run create +workflow-run delete +workflow-run facts create +workflow-run facts read +workflow-run facts update +workflow-run list +workflow-run logs +workflow-run read +workflow-run read-by-ksuid +workflow-run update +workflow-run update-by-ksuid +workflow-step-template create +workflow-step-template delete +workflow-step-template read +workflow-step-template revisions create +workflow-step-template revisions delete +workflow-step-template revisions read +workflow-step-template revisions update +workflow-step-template update +workflow-template create +workflow-template delete +workflow-template read +workflow-template revisions create +workflow-template revisions delete +workflow-template revisions read +workflow-template revisions update +workflow-template update +` + +func leafCommands(root *cobra.Command) []string { + var leaves []string + var walk func(c *cobra.Command, prefix string) + walk = func(c *cobra.Command, prefix string) { + if c.Name() == "help" || c.Name() == "completion" { + return + } + if !c.HasSubCommands() { + leaves = append(leaves, prefix+c.Name()) + return + } + for _, sub := range c.Commands() { + walk(sub, prefix+c.Name()+" ") + } + } + for _, sub := range root.Commands() { + walk(sub, "") + } + sort.Strings(leaves) + return leaves +} + +func TestCommandTree(t *testing.T) { + want := strings.Split(strings.TrimSpace(expectedLeaves), "\n") + assert.Equal(t, want, leafCommands(cmd.RootCommand())) + assert.Len(t, want, 230) +} diff --git a/go/tests/workflow_test.go b/go/tests/workflow_test.go index e7ac627..1e0d343 100644 --- a/go/tests/workflow_test.go +++ b/go/tests/workflow_test.go @@ -98,8 +98,8 @@ func TestReadWorkflow(t *testing.T) { tc.expectedStruct.Msg.Authors, actualResponse.Msg.Authors) } - if actualResponse.Msg.Description != tc.expectedStruct.Msg.Description { - t.Fatalf("expected \"%s\" got \"%s\"", + if !reflect.DeepEqual(actualResponse.Msg.Description, tc.expectedStruct.Msg.Description) { + t.Fatalf("expected \"%v\" got \"%v\"", tc.expectedStruct.Msg.Description, actualResponse.Msg.Description) } From f6c91db1ff0bd5b4e2cd884eb79f0d3c72b09168 Mon Sep 17 00:00:00 2001 From: Arunim Chaudhary Date: Fri, 4 Sep 2026 17:45:02 +0530 Subject: [PATCH 2/2] feat: stdout output, live-validated fixes and README for the Go CLI - Route command output to stdout so read commands and --output-json can be piped; cobra's default was stderr. - Print the response for query-style commands (resource search, workflow and stack compare, connector list-accounts) instead of a message. - Bump sg-sdk-go to 674afe6, which resends the request body on retries and sends connector groups as JSON; both were found while validating the CLI against a live organization. - Document the Go CLI in go/README.md and link it from the top-level README, including the payload rules learned from the live run. - Fix a pre-existing go vet warning in workflow create. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01QFnDMC1JV9J4Hpk2oxwnAM --- README.md | 15 +++ go/README.md | 171 ++++++++++++++++++++++++++++++ go/cmd/connector/list_accounts.go | 3 +- go/cmd/resource/search.go | 3 +- go/cmd/root.go | 3 + go/cmd/stack/extra/compare.go | 3 +- go/cmd/stackworkflow/compare.go | 3 +- go/cmd/workflow/extra/compare.go | 3 +- go/go.mod | 2 +- go/go.sum | 4 +- go/tests/matrix_a_test.go | 4 +- go/tests/matrix_b_test.go | 6 +- 12 files changed, 202 insertions(+), 18 deletions(-) create mode 100644 go/README.md diff --git a/README.md b/README.md index 83b5e7f..fab15c9 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ - [Examples](#examples) - [Git VCS scan and bulk import](#git-vcs-scan-and-bulk-import) - [Interactive mode](#interactive-mode) +- [Go CLI](#go-cli) --- @@ -496,3 +497,17 @@ On launch you will be prompted for your **org** and **workflow group**, which ar Navigation: arrow keys to move, Enter to select, Ctrl+C or `q` to go back / exit. image + +--- + +## Go CLI + +The `go/` directory contains a Go implementation of `sg-cli` built on +[`sg-sdk-go`](https://github.com/StackGuardian/sg-sdk-go). It covers every +API operation exposed by the SDK (organizations, users, roles, API accesses, +secrets, policies, connectors, connector groups, runner groups, state backends, +workflow groups, workflows and runs, stacks and stack runs, templates and +revisions, chats, billing, audit logs and more) with the same `--org`, +`--patch-payload`, `--preview` and `--dry-run` conventions as the shell +script. See [go/README.md](go/README.md) for the build steps, the command +groups and examples. diff --git a/go/README.md b/go/README.md new file mode 100644 index 0000000..6aca993 --- /dev/null +++ b/go/README.md @@ -0,0 +1,171 @@ +# sg-cli (Go) + +A command-line client for the StackGuardian platform built on +[`sg-sdk-go`](https://github.com/StackGuardian/sg-sdk-go). Every SDK operation +(226 API endpoints) is reachable from one of the 30 command groups below. + +## Contents + +- [Build](#build) +- [Configuration](#configuration) +- [Conventions](#conventions) +- [Command groups](#command-groups) +- [Examples](#examples) +- [Payload notes](#payload-notes) +- [Tests](#tests) + +## Build + +Requires Go 1.22.4 or newer. + +```bash +cd go +go build -o sg-cli . +./sg-cli --help +``` + +## Configuration + +| Variable | Required | Default | Description | +|---|---|---|---| +| `SG_API_TOKEN` | Yes | — | API token. Both `sgu_` (personal) and `sgo_` (organization) tokens work; the `apikey ` prefix is added automatically. | +| `SG_BASE_URL` | No | `https://api.app.stackguardian.io` | API base URL. | + +## Conventions + +- **Organization.** Every group takes `--org ` as a persistent flag. + Groups that work inside a workflow group also take `--workflow-group`, and + workflow-scoped groups take `--workflow-id`. Nested workflow groups are + addressed as `parent/child`. +- **Identifiers are flags.** Resources are named with flags such as + `--stack-id`, `--secret-id`, `--connector-id`, `--template-id`, `--run-id` + or `--chat-id`. Template revisions use `--revision-id NAME:REVISION`. +- **Payloads.** Commands that send a body take a JSON file as the single + positional argument after `--`. Pass `-` to read the payload from stdin. + - `--patch-payload ''` merges keys into the file before sending. + - `--preview` prints the final payload and continues. + - `--dry-run` prints the final payload and stops without sending. +- **Output.** Read and list commands print the API response as indented JSON + on stdout, so they can be piped into `jq`. Write commands print a short + confirmation; add `--output-json` to print the response as well. List + endpoints that the API answers with `204 No Content` print `null`. +- **Errors.** API errors are printed as `Error: : ` and the + command exits with status 1. + +## Command groups + +| Group | Commands | +|---|---| +| `organization` | read, update, create, delete, list, workflows, count-workflows, bulk-action | +| `user` | list, read, create, update, delete | +| `role` | list, read, create, update, delete | +| `role-binding` | read | +| `api-access` | list, read, create, update, delete, regenerate-key | +| `api-token` | create, delete | +| `audit-log` | list | +| `benchmark-report` | read | +| `billing` | details, balance, invoices, dashboard-url, change-plan, `profile setup/update`, `payment-methods list/setup-intent/set-default/detach` | +| `secret` | list, read-bulk, create, update, delete | +| `policy` | list, read, create, update, delete | +| `connector` | list, read, create, update, delete, authenticate, repos, github-repos, list-accounts | +| `connector-group` | list, read, create, update, delete, authenticate, discovery-scan, `connectors list/read/update/delete/authenticate` | +| `runner-group` | list, read, create, update, delete, register, deregister-runner, update-runner-state, storage-backend-auth | +| `state-backend` | list, read, create, update, delete, list-statefiles | +| `resource` | search, move, tags | +| `chat` | list, read, create, update, delete, commit-bundle, create-pr, pr-status, pr-sync-status, `artifacts list/get-url/upload-url`, `messages list/read/create/cancel/retry` | +| `workflow-group` | list, read, create, update, delete, create-child, list-children, list-resources | +| `workflow` | list, read, create, update, delete, apply, destroy, outputs, compare, vcs-triggers, file-upload-url, tfstate-upload-url | +| `workflow-run` | list, read, create, update, delete, cancel, approve, logs, read-by-ksuid, update-by-ksuid, `facts read/create/update` | +| `artifacts` | list, read, create, delete, get-url, versions, rollback, lock, unlock | +| `stack` | list, read, create, update, delete, apply, destroy, outputs, compare | +| `stack-run` | list, read, create | +| `stack-workflow` | list, read, create, update, delete, outputs, compare, vcs-triggers, file-upload-url, tfstate-upload-url, `artifacts list/read/create/delete/get-url/lock/unlock` | +| `stack-workflow-run` | list, read, create, update, delete, approve, logs, `facts read/create/update` | +| `template` | list, list-by-owner, read, create, update, delete, group-iac, input-schema, vcs-triggers, `artifacts list/upload-url/download-url/delete`, `subscriptions read/create/update`, `public list/list-all/read` | +| `workflow-template` | read, create, update, delete, `revisions read/create/update/delete` | +| `workflow-step-template` | read, create, update, delete, `revisions read/create/update/delete` | +| `stack-template` | read, create, update, delete, `revisions read/create/update/delete` | + +`sg-cli --help` and `sg-cli --help` list the flags of +each command. Commands that need a Cognito user token rather than an API key +(organization create/list, public templates, template input schemas) say so in +their help text. + +## Examples + +```bash +export SG_API_TOKEN=sgu_xxx + +# Read commands print JSON +./sg-cli organization read --org demo-org +./sg-cli workflow-group list --org demo-org | jq '.msg[].ResourceName' +./sg-cli workflow read --org demo-org --workflow-group demo-grp --workflow-id my-wf +./sg-cli workflow-run logs --org demo-org --workflow-group demo-grp --workflow-id my-wf --run-id abc123 +./sg-cli secret read-bulk --org demo-org --names db_password,api_key +./sg-cli template list --org demo-org --template-type IAC +./sg-cli audit-log list --org demo-org --limit 20 + +# Write commands take a payload after -- +./sg-cli secret create --org demo-org -- secret.json +./sg-cli role update --org demo-org --role-id viewer --patch-payload '{"Description":"read only"}' -- role.json +./sg-cli workflow-group create-child --org demo-org --parent platform -- child.json +./sg-cli workflow-group read --org demo-org --workflow-group platform/child + +# Preview the merged payload without sending it +./sg-cli connector create --org demo-org --dry-run --patch-payload '{"ResourceName":"aws-prod"}' -- connector.json + +# Print the API response of a write command +./sg-cli workflow-template create --org demo-org --output-json -- template.json + +# Templates are addressed by NAME, revisions by NAME:REVISION +./sg-cli workflow-template revisions read --org demo-org --revision-id my-template:2 +./sg-cli template artifacts list --org demo-org --template-type IAC --template-id my-template:2 + +# Trigger and approve runs +./sg-cli workflow-run create --org demo-org --workflow-group demo-grp --workflow-id my-wf +./sg-cli workflow-run approve --org demo-org --workflow-group demo-grp --workflow-id my-wf --run-id abc123 +``` + +The `workflow` and `stack` groups keep the original behaviour: `create` +supports `--run`, `--wait`, `--bulk` and state-file upload, as documented in +the [repository README](../README.md). + +## Payload notes + +These rules come from running each command against a live organization; the +API rejects the request otherwise. + +- `policy update` needs `PolicyType` in the payload (`GENERAL` or + `FILTER.INSIGHT`) even for partial updates. +- `secret update` needs `ResourceName`; the CLI fills it from `--secret-id`. +- Template creates (`workflow-template`, `stack-template`, + `workflow-step-template`, `template create`) need `TemplateName`, + `OwnerOrg` in the form `/orgs/` and `SourceConfigKind` (`TERRAFORM`, + `OPENTOFU`, ... for IaC templates; `MIXED` for stack templates; + `DOCKER_IMAGE` for step templates). `revisions create` needs the same + `OwnerOrg` and `SourceConfigKind`. +- A template with revisions cannot be deleted directly; delete its revisions + first. Deleting the last revision removes the parent. +- `state-backend create` needs `Statefiles` (an empty list is fine) and + `StateBackendConfig.type` (`aws_s3` or `azure_blob_storage`) with + `auth.integrationId` pointing at a connector. +- `connector-group create` needs `Settings.awsDefaultRegion` for AWS kinds. +- `api-access create` needs `Roles`. +- `resource search` needs `ResourceTypes` (`--resource-types WORKFLOW,STACK`). +- Runner groups must be enabled for the organization; otherwise the API + answers `409`. + +## Tests + +Offline unit tests mock the HTTP transport and check the request each command +sends (method, path, query and body) and what it prints: + +```bash +cd go +go test ./tests/ -run 'TestCommandTree|TestMatrix|TestCreateWorkflow|TestReadWorkflow|TestListWorkflow|TestDeleteWorkflow|TestApplyWorkflow|TestDestroyWorkflow|TestUpdateWorkflow|TestCreateStack|TestDeleteStack|TestApplyStack|TestDestroyStack|TestStackOutputs|TestListArtifacts' +``` + +`tests/tree_test.go` pins the full command tree, so adding or renaming a +command requires updating `expectedLeaves`. The remaining tests in `tests/` +are end-to-end tests that run a built `../sg-cli` binary against a live +organization and need `SG_API_TOKEN`. diff --git a/go/cmd/connector/list_accounts.go b/go/cmd/connector/list_accounts.go index b07f9d5..e7dadb9 100644 --- a/go/cmd/connector/list_accounts.go +++ b/go/cmd/connector/list_accounts.go @@ -31,11 +31,10 @@ func newListAccountsCmd(c *client.Client) *cobra.Command { if err != nil { return err } - common.Done(cmd, response, "Accounts listed.") + common.PrintJSON(cmd, response) return nil }, } common.AddPayloadFlags(cmd) - common.AddOutputJSONFlag(cmd) return cmd } diff --git a/go/cmd/resource/search.go b/go/cmd/resource/search.go index c3aba80..138e114 100644 --- a/go/cmd/resource/search.go +++ b/go/cmd/resource/search.go @@ -45,7 +45,7 @@ func newSearchCmd(c *client.Client) *cobra.Command { if err != nil { return err } - common.Done(cmd, response, "Search completed.") + common.PrintJSON(cmd, response) return nil }, } @@ -54,6 +54,5 @@ func newSearchCmd(c *client.Client) *cobra.Command { cmd.Flags().Int("limit", 0, "Maximum number of results.") cmd.Flags().String("last-evaluated-key", "", "Pagination token from a previous response.") common.AddPayloadFlags(cmd) - common.AddOutputJSONFlag(cmd) return cmd } diff --git a/go/cmd/root.go b/go/cmd/root.go index 2f40e4e..8ca8980 100644 --- a/go/cmd/root.go +++ b/go/cmd/root.go @@ -54,6 +54,9 @@ func Execute() { } func init() { + // cmd.Println writes to stderr unless an output is set; responses and + // --output-json belong on stdout so they can be piped. + rootCmd.SetOut(os.Stdout) c := common.NewClient() rootCmd.AddCommand(workflow.NewWorkflowCmd(c)) rootCmd.AddCommand(stack.NewStackCmd(c)) diff --git a/go/cmd/stack/extra/compare.go b/go/cmd/stack/extra/compare.go index 9eab920..975c352 100644 --- a/go/cmd/stack/extra/compare.go +++ b/go/cmd/stack/extra/compare.go @@ -44,7 +44,7 @@ func newCompareCmd(c *client.Client) *cobra.Command { if err != nil { return err } - common.Done(cmd, response, "Comparison completed.") + common.PrintJSON(cmd, response) return nil }, } @@ -53,6 +53,5 @@ func newCompareCmd(c *client.Client) *cobra.Command { cmd.Flags().String("target-template-group-id", "", "Stack template to compare against.") cmd.Flags().String("upgrade-mode", "", "Upgrade mode to simulate.") common.AddPayloadFlags(cmd) - common.AddOutputJSONFlag(cmd) return cmd } diff --git a/go/cmd/stackworkflow/compare.go b/go/cmd/stackworkflow/compare.go index 057b8c5..246252b 100644 --- a/go/cmd/stackworkflow/compare.go +++ b/go/cmd/stackworkflow/compare.go @@ -45,7 +45,7 @@ func newCompareCmd(c *client.Client) *cobra.Command { if err != nil { return err } - common.Done(cmd, response, "Comparison completed.") + common.PrintJSON(cmd, response) return nil }, } @@ -54,6 +54,5 @@ func newCompareCmd(c *client.Client) *cobra.Command { cmd.Flags().String("target-template-id", "", "Template to compare against.") cmd.Flags().String("upgrade-mode", "", "Upgrade mode to simulate.") common.AddPayloadFlags(cmd) - common.AddOutputJSONFlag(cmd) return cmd } diff --git a/go/cmd/workflow/extra/compare.go b/go/cmd/workflow/extra/compare.go index fbffa51..1bf52aa 100644 --- a/go/cmd/workflow/extra/compare.go +++ b/go/cmd/workflow/extra/compare.go @@ -44,7 +44,7 @@ func newCompareCmd(c *client.Client) *cobra.Command { if err != nil { return err } - common.Done(cmd, response, "Comparison completed.") + common.PrintJSON(cmd, response) return nil }, } @@ -53,6 +53,5 @@ func newCompareCmd(c *client.Client) *cobra.Command { cmd.Flags().String("target-template-id", "", "Template to compare against.") cmd.Flags().String("upgrade-mode", "", "Upgrade mode to simulate.") common.AddPayloadFlags(cmd) - common.AddOutputJSONFlag(cmd) return cmd } diff --git a/go/go.mod b/go/go.mod index 81b5c16..ce3cf37 100644 --- a/go/go.mod +++ b/go/go.mod @@ -3,7 +3,7 @@ module github.com/StackGuardian/sg-cli go 1.22.4 require ( - github.com/StackGuardian/sg-sdk-go v1.5.7-0.20260903035653-e8047d5e8969 + github.com/StackGuardian/sg-sdk-go v1.5.7-0.20260904121004-674afe6f5c4c github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 ) diff --git a/go/go.sum b/go/go.sum index 5a256ca..461f109 100644 --- a/go/go.sum +++ b/go/go.sum @@ -1,5 +1,5 @@ -github.com/StackGuardian/sg-sdk-go v1.5.7-0.20260903035653-e8047d5e8969 h1:fqke1zmp4HJU8pkCyXlj/9LDse/XbraRnj2y3p5uzqE= -github.com/StackGuardian/sg-sdk-go v1.5.7-0.20260903035653-e8047d5e8969/go.mod h1:iCrgHE0WbxEaaLx6ATsRe81Qjp82kahCwLGJ2t66mZ0= +github.com/StackGuardian/sg-sdk-go v1.5.7-0.20260904121004-674afe6f5c4c h1:m92lop+JvQ7kmeog/g99dlSyKSkcbubzlEITDdLZrUU= +github.com/StackGuardian/sg-sdk-go v1.5.7-0.20260904121004-674afe6f5c4c/go.mod h1:iCrgHE0WbxEaaLx6ATsRe81Qjp82kahCwLGJ2t66mZ0= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/go/tests/matrix_a_test.go b/go/tests/matrix_a_test.go index a70f5de..cd628d1 100644 --- a/go/tests/matrix_a_test.go +++ b/go/tests/matrix_a_test.go @@ -89,7 +89,7 @@ func TestConnectorCommands(t *testing.T) { {name: "delete", ctor: connector.NewConnectorCmd, args: []string{"delete", "--org", "demo-org", "--connector-id", "c"}, method: "DELETE", path: base + "c/", wantOut: "Connector deleted successfully."}, {name: "list", ctor: connector.NewConnectorCmd, args: []string{"list", "--org", "demo-org", "--kind", "AWS_RBAC", "--limit", "5"}, method: "GET", path: base + "listall/", query: url.Values{"kind": {"AWS_RBAC"}, "limit": {"5"}}}, {name: "authenticate", ctor: connector.NewConnectorCmd, args: []string{"authenticate", "--org", "demo-org", "--connector-id", "c"}, method: "GET", path: base + "c/authenticate/"}, - {name: "list accounts", ctor: connector.NewConnectorCmd, args: []string{"list-accounts", "--org", "demo-org", "@payload"}, payloadJSON: `{"ResourceId":"g"}`, method: "POST", path: base + "list_accounts/", body: `{"ResourceId":"g"}`, resp: `{"msg":[]}`, wantOut: "Accounts listed."}, + {name: "list accounts", ctor: connector.NewConnectorCmd, args: []string{"list-accounts", "--org", "demo-org", "@payload"}, payloadJSON: `{"ResourceId":"g"}`, method: "POST", path: base + "list_accounts/", body: `{"ResourceId":"g"}`, resp: `{"msg":[]}`, wantOut: `"msg": []`}, {name: "github repos", ctor: connector.NewConnectorCmd, args: []string{"github-repos", "--org", "demo-org", "--connector-id", "c"}, method: "GET", path: base + "c/get_githubcom_repos/", resp: `{"msg":["o/r"]}`}, {name: "repos", ctor: connector.NewConnectorCmd, args: []string{"repos", "--org", "demo-org", "--connector-id", "c", "--login", "l", "--page", "2", "--limit", "5"}, method: "GET", path: base + "c/repos/", query: url.Values{"login": {"l"}, "page": {"2"}, "limit": {"5"}}}, {name: "group create", ctor: connectorgroup.NewConnectorGroupCmd, args: []string{"create", "--org", "demo-org", "@payload"}, payloadJSON: `{"ResourceName":"g"}`, method: "POST", path: gbase, body: `{"ResourceName":"g"}`, wantOut: "Connector group created successfully."}, @@ -127,7 +127,7 @@ func TestRunnerStateBackendResourceCommands(t *testing.T) { {name: "state backend list", ctor: statebackend.NewStateBackendCmd, args: []string{"list", "--org", "demo-org", "--search-query", "q"}, method: "GET", path: sbase + "listall/", query: url.Values{"searchQuery": {"q"}}}, {name: "state backend statefiles", ctor: statebackend.NewStateBackendCmd, args: []string{"list-statefiles", "--org", "demo-org", "--config", "abc"}, method: "GET", path: sbase + "list_statefiles/", query: url.Values{"config": {"abc"}}}, {name: "resource move", ctor: resource.NewResourceCmd, args: []string{"move", "--org", "demo-org", "--source-ids", "/a,/b", "--destination", "/wfgrps/g"}, method: "POST", path: org + "resources/move/", body: `{"SourceResourceIds":["/a","/b"],"DestinationParentId":"/wfgrps/g"}`, wantOut: "Resources moved."}, - {name: "resource search", ctor: resource.NewResourceCmd, args: []string{"search", "--org", "demo-org", "--search-query", "q", "--resource-types", "WORKFLOW,STACK", "--limit", "5"}, method: "POST", path: org + "search/", body: `{"SearchQuery":"q","ResourceTypes":["WORKFLOW","STACK"],"Limit":5}`, wantOut: "Search completed."}, + {name: "resource search", ctor: resource.NewResourceCmd, args: []string{"search", "--org", "demo-org", "--search-query", "q", "--resource-types", "WORKFLOW,STACK", "--limit", "5"}, method: "POST", path: org + "search/", body: `{"SearchQuery":"q","ResourceTypes":["WORKFLOW","STACK"],"Limit":5}`, wantOut: `"msg"`}, {name: "resource tags", ctor: resource.NewResourceCmd, args: []string{"tags", "--org", "demo-org", "--context-tag-key", "env", "--limit", "5"}, method: "GET", path: org + "search/tags/", query: url.Values{"ContextTagKey": {"env"}, "Limit": {"5"}}}, }) } diff --git a/go/tests/matrix_b_test.go b/go/tests/matrix_b_test.go index bdbc06c..6db1c4b 100644 --- a/go/tests/matrix_b_test.go +++ b/go/tests/matrix_b_test.go @@ -39,7 +39,7 @@ func TestWorkflowExtraCommands(t *testing.T) { runMatrix(t, []matrixCase{ {name: "update", ctor: workflowcmd.NewWorkflowCmd, args: with("update", "--workflow-id", "w", "--upgrade-mode", "MANUAL", "@payload"), payloadJSON: `{"Description":"d"}`, method: "PATCH", path: base, query: url.Values{"upgradeMode": {"MANUAL"}}, body: `{"Description":"d"}`, wantOut: "Workflow updated successfully."}, {name: "outputs", ctor: workflowcmd.NewWorkflowCmd, args: with("outputs", "--workflow-id", "w"), method: "GET", path: base + "outputs/"}, - {name: "compare", ctor: workflowcmd.NewWorkflowCmd, args: with("compare", "--workflow-id", "w", "--target-template-id", "/o/t"), method: "POST", path: base + "compare/", body: `{"targetTemplateId":"/o/t"}`, wantOut: "Comparison completed."}, + {name: "compare", ctor: workflowcmd.NewWorkflowCmd, args: with("compare", "--workflow-id", "w", "--target-template-id", "/o/t"), method: "POST", path: base + "compare/", body: `{"targetTemplateId":"/o/t"}`, wantOut: `"msg"`}, {name: "file upload url", ctor: workflowcmd.NewWorkflowCmd, args: with("file-upload-url", "--workflow-id", "w", "--filename", "f", "--folder", "d"), method: "GET", path: base + "file_upload_url/", query: url.Values{"filename": {"f"}, "folder": {"d"}}}, {name: "tfstate upload url", ctor: workflowcmd.NewWorkflowCmd, args: with("tfstate-upload-url", "--workflow-id", "w", "--filename", "s.json"), method: "GET", path: base + "tfstate_upload_url/", query: url.Values{"filename": {"s.json"}}}, {name: "vcs triggers", ctor: workflowcmd.NewWorkflowCmd, args: with("vcs-triggers", "--workflow-id", "w", "@payload"), payloadJSON: `{}`, method: "POST", path: base + "webhooks/vcs_triggers/", body: `{"VCSConfig":null,"VCSTriggers":null}`, wantOut: "VCS triggers created successfully."}, @@ -62,7 +62,7 @@ func TestStackCommands(t *testing.T) { {name: "read", ctor: stackcmd.NewStackCmd, args: with("read", "--stack-id", "s"), method: "GET", path: base + "s/"}, {name: "update", ctor: stackcmd.NewStackCmd, args: with("update", "--stack-id", "s", "@payload"), payloadJSON: `{"Description":"d"}`, method: "PATCH", path: base + "s/", body: `{"Description":"d"}`, wantOut: "Stack updated successfully."}, {name: "list", ctor: stackcmd.NewStackCmd, args: with("list", "--tags", "t"), method: "GET", path: base + "listall/", query: url.Values{"Tags": {"t"}}}, - {name: "compare", ctor: stackcmd.NewStackCmd, args: with("compare", "--stack-id", "s", "--target-template-group-id", "/o/t", "--upgrade-mode", "MANUAL"), method: "POST", path: base + "s/compare/", body: `{"targetTemplateGroupId":"/o/t","upgradeMode":"MANUAL"}`, wantOut: "Comparison completed."}, + {name: "compare", ctor: stackcmd.NewStackCmd, args: with("compare", "--stack-id", "s", "--target-template-group-id", "/o/t", "--upgrade-mode", "MANUAL"), method: "POST", path: base + "s/compare/", body: `{"targetTemplateGroupId":"/o/t","upgradeMode":"MANUAL"}`, wantOut: `"msg"`}, {name: "run create", ctor: stackrun.NewStackRunCmd, args: with("create", "--stack-id", "s", "--action-type", "APPLY"), method: "POST", path: base + "s/stackruns/", body: `{"ActionType":"APPLY"}`, wantOut: "Stack run created successfully."}, {name: "run read", ctor: stackrun.NewStackRunCmd, args: with("read", "--stack-id", "s", "--run-id", "r1"), method: "GET", path: base + "s/stackruns/r1/"}, {name: "run list", ctor: stackrun.NewStackRunCmd, args: with("list", "--stack-id", "s", "--limit", "5"), method: "GET", path: base + "s/stackruns/listall/", query: url.Values{"limit": {"5"}}}, @@ -82,7 +82,7 @@ func TestStackWorkflowCommands(t *testing.T) { {name: "outputs", ctor: stackworkflow.NewStackWorkflowCmd, args: with("outputs", "--workflow-id", "w"), method: "GET", path: base + "w/outputs/"}, {name: "tfstate url", ctor: stackworkflow.NewStackWorkflowCmd, args: with("tfstate-upload-url", "--workflow-id", "w", "--filename", "s.json"), method: "GET", path: base + "w/tfstate_upload_url/", query: url.Values{"filename": {"s.json"}}}, {name: "file upload url", ctor: stackworkflow.NewStackWorkflowCmd, args: with("file-upload-url", "--workflow-id", "w", "--filename", "f"), method: "GET", path: base + "w/file_upload_url/", query: url.Values{"filename": {"f"}}}, - {name: "compare", ctor: stackworkflow.NewStackWorkflowCmd, args: with("compare", "--workflow-id", "w", "--target-template-id", "/o/t"), method: "POST", path: base + "w/compare/", body: `{"targetTemplateId":"/o/t"}`, wantOut: "Comparison completed."}, + {name: "compare", ctor: stackworkflow.NewStackWorkflowCmd, args: with("compare", "--workflow-id", "w", "--target-template-id", "/o/t"), method: "POST", path: base + "w/compare/", body: `{"targetTemplateId":"/o/t"}`, wantOut: `"msg"`}, {name: "vcs triggers", ctor: stackworkflow.NewStackWorkflowCmd, args: with("vcs-triggers", "--workflow-id", "w", "@payload"), payloadJSON: `{}`, method: "POST", path: base + "w/webhooks/vcs_triggers/", body: `{"VCSConfig":null,"VCSTriggers":null}`, wantOut: "VCS triggers created successfully."}, {name: "artifacts list", ctor: stackworkflow.NewStackWorkflowCmd, args: with("artifacts", "list", "--workflow-id", "w"), method: "GET", path: base + "w/listall_artifacts/"}, {name: "artifact url", ctor: stackworkflow.NewStackWorkflowCmd, args: with("artifacts", "get-url", "--workflow-id", "w", "--artifact-path", "p"), method: "GET", path: base + "w/get_artifact/", query: url.Values{"artifactPath": {"p"}}},