-
Notifications
You must be signed in to change notification settings - Fork 1
feat: policy create cmd #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,203 @@ | ||
| package policy | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| "fmt" | ||
| "time" | ||
|
|
||
| "github.com/MakeNowJust/heredoc/v2" | ||
| "github.com/ctrlplanedev/cli/internal/api" | ||
| "github.com/ctrlplanedev/cli/internal/cliutil" | ||
| "github.com/spf13/cobra" | ||
| "github.com/spf13/viper" | ||
| ) | ||
|
|
||
| func NewCreatePolicyCmd() *cobra.Command { | ||
| var name string | ||
| var workspaceID string | ||
| var description string | ||
| var priority float32 | ||
| var enabled bool | ||
| var deploymentTargetSelector string | ||
| var environmentTargetSelector string | ||
| var resourceTargetSelector string | ||
| var denyWindows string | ||
| var versionAnyApprovals string | ||
| var versionUserApprovals string | ||
| var versionRoleApprovals string | ||
| var deploymentVersionSelector string | ||
|
|
||
| cmd := &cobra.Command{ | ||
| Use: "policy [flags]", | ||
| Short: "Create a new policy", | ||
| Long: `Create a new policy with specified parameters`, | ||
| Example: heredoc.Doc(` | ||
| # Create a new policy | ||
| $ ctrlc create policy --name my-policy --workspace-id 00000000-0000-0000-0000-000000000000 | ||
|
|
||
| # Create a new policy with deployment selector | ||
| $ ctrlc create policy --name my-policy --workspace-id 00000000-0000-0000-0000-000000000000 --deployment-selector '{"type": "production"}' | ||
|
|
||
| # Create a new policy with environment selector | ||
| $ ctrlc create policy --name my-policy --workspace-id 00000000-0000-0000-0000-000000000000 --environment-selector '{"name": "prod"}' | ||
|
|
||
| # Create a new policy with deny windows | ||
| $ ctrlc create policy --name my-policy --workspace-id 00000000-0000-0000-0000-000000000000 --deny-windows '[{"timeZone": "UTC", "rrule": {"freq": "WEEKLY", "byday": ["SA", "SU"]}}]' | ||
|
|
||
| # Create a new policy with version approvals | ||
| $ ctrlc create policy --name my-policy --workspace-id 00000000-0000-0000-0000-000000000000 --version-any-approvals '{"requiredApprovalsCount": 2}' --version-user-approvals '[{"userId": "user1"}, {"userId": "user2"}]' --version-role-approvals '[{"roleId": "role1", "requiredApprovalsCount": 1}]' | ||
| `), | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| apiURL := viper.GetString("url") | ||
| apiKey := viper.GetString("api-key") | ||
| client, err := api.NewAPIKeyClientWithResponses(apiURL, apiKey) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to create API client: %w", err) | ||
| } | ||
|
|
||
| // Parse selectors from JSON strings | ||
| var deploymentSelector *map[string]interface{} | ||
| if deploymentTargetSelector != "" { | ||
| var parsedSelector map[string]interface{} | ||
| if err := json.Unmarshal([]byte(deploymentTargetSelector), &parsedSelector); err != nil { | ||
| return fmt.Errorf("invalid deployment target selector JSON: %w", err) | ||
| } | ||
| deploymentSelector = &parsedSelector | ||
| } | ||
|
|
||
| var environmentSelector *map[string]interface{} | ||
| if environmentTargetSelector != "" { | ||
| var parsedSelector map[string]interface{} | ||
| if err := json.Unmarshal([]byte(environmentTargetSelector), &parsedSelector); err != nil { | ||
| return fmt.Errorf("invalid environment target selector JSON: %w", err) | ||
| } | ||
| environmentSelector = &parsedSelector | ||
| } | ||
|
|
||
| var resourceSelector *map[string]interface{} | ||
| if resourceTargetSelector != "" { | ||
| var parsedSelector map[string]interface{} | ||
| if err := json.Unmarshal([]byte(resourceTargetSelector), &parsedSelector); err != nil { | ||
| return fmt.Errorf("invalid resource target selector JSON: %w", err) | ||
| } | ||
| resourceSelector = &parsedSelector | ||
| } | ||
|
|
||
| // Parse deny windows | ||
| var parsedDenyWindows []struct { | ||
| Dtend *time.Time `json:"dtend,omitempty"` | ||
| Rrule *map[string]interface{} `json:"rrule,omitempty"` | ||
| TimeZone string `json:"timeZone"` | ||
| } | ||
| if denyWindows != "" { | ||
| if err := json.Unmarshal([]byte(denyWindows), &parsedDenyWindows); err != nil { | ||
| return fmt.Errorf("invalid deny windows JSON: %w", err) | ||
| } | ||
| } | ||
|
|
||
| // Parse version any approvals | ||
| var parsedVersionAnyApprovals *[]struct { | ||
| RequiredApprovalsCount *float32 `json:"requiredApprovalsCount,omitempty"` | ||
| } | ||
| if versionAnyApprovals != "" { | ||
| var approvals []struct { | ||
| RequiredApprovalsCount *float32 `json:"requiredApprovalsCount,omitempty"` | ||
| } | ||
| if err := json.Unmarshal([]byte(versionAnyApprovals), &approvals); err != nil { | ||
| return fmt.Errorf("invalid version any approvals JSON: %w", err) | ||
| } | ||
| parsedVersionAnyApprovals = &approvals | ||
| } | ||
|
|
||
| // Parse version user approvals | ||
| var parsedVersionUserApprovals []api.VersionUserApproval | ||
| if versionUserApprovals != "" { | ||
| if err := json.Unmarshal([]byte(versionUserApprovals), &parsedVersionUserApprovals); err != nil { | ||
| return fmt.Errorf("invalid version user approvals JSON: %w", err) | ||
| } | ||
| } else { | ||
| parsedVersionUserApprovals = []api.VersionUserApproval{} | ||
| } | ||
|
|
||
| // Parse version role approvals | ||
| var parsedVersionRoleApprovals []struct { | ||
| RequiredApprovalsCount *float32 `json:"requiredApprovalsCount,omitempty"` | ||
| RoleId *string `json:"roleId,omitempty"` | ||
| } | ||
| if versionRoleApprovals != "" { | ||
| if err := json.Unmarshal([]byte(versionRoleApprovals), &parsedVersionRoleApprovals); err != nil { | ||
| return fmt.Errorf("invalid version role approvals JSON: %w", err) | ||
| } | ||
| } else { | ||
| parsedVersionRoleApprovals = []struct { | ||
| RequiredApprovalsCount *float32 `json:"requiredApprovalsCount,omitempty"` | ||
| RoleId *string `json:"roleId,omitempty"` | ||
| }{} | ||
| } | ||
|
|
||
| // Parse deployment version selector | ||
| var parsedDeploymentVersionSelector *api.DeploymentVersionSelector | ||
| if deploymentVersionSelector != "" { | ||
| var selector map[string]interface{} | ||
|
|
||
| if err := json.Unmarshal([]byte(deploymentVersionSelector), &selector); err != nil { | ||
| return fmt.Errorf("invalid deployment version selector JSON: %w", err) | ||
| } | ||
|
|
||
| parsedDeploymentVersionSelector = &api.DeploymentVersionSelector{ | ||
| DeploymentVersionSelector: selector, | ||
| Name: name, | ||
| } | ||
| } | ||
|
|
||
| // Create policy request | ||
| body := api.CreatePolicyJSONRequestBody{ | ||
| Name: name, | ||
| WorkspaceId: workspaceID, | ||
| Description: &description, | ||
| Priority: &priority, | ||
| Enabled: &enabled, | ||
| Targets: []api.PolicyTarget{ | ||
| { | ||
| DeploymentSelector: deploymentSelector, | ||
| EnvironmentSelector: environmentSelector, | ||
| ResourceSelector: resourceSelector, | ||
| }, | ||
| }, | ||
| DenyWindows: parsedDenyWindows, | ||
| DeploymentVersionSelector: parsedDeploymentVersionSelector, | ||
| VersionAnyApprovals: parsedVersionAnyApprovals, | ||
| VersionUserApprovals: parsedVersionUserApprovals, | ||
| VersionRoleApprovals: parsedVersionRoleApprovals, | ||
| } | ||
|
|
||
| resp, err := client.CreatePolicy(cmd.Context(), body) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to create policy: %w", err) | ||
| } | ||
|
|
||
| return cliutil.HandleResponseOutput(cmd, resp) | ||
| }, | ||
| } | ||
|
|
||
| // Add flags | ||
| cmd.Flags().StringVarP(&name, "name", "n", "", "Name of the policy (required)") | ||
| cmd.Flags().StringVarP(&workspaceID, "workspace-id", "w", "", "Workspace ID (required)") | ||
| cmd.Flags().StringVarP(&description, "description", "d", "", "Description of the policy") | ||
| cmd.Flags().Float32VarP(&priority, "priority", "p", 0, "Priority of the policy (default: 0)") | ||
| cmd.Flags().BoolVarP(&enabled, "enabled", "e", true, "Whether the policy is enabled (default: true)") | ||
| cmd.Flags().StringVar(&deploymentTargetSelector, "deployment-selector", "", "JSON string for deployment target selector") | ||
| cmd.Flags().StringVar(&environmentTargetSelector, "environment-selector", "", "JSON string for environment target selector") | ||
| cmd.Flags().StringVar(&resourceTargetSelector, "resource-selector", "", "JSON string for resource target selector") | ||
| cmd.Flags().StringVar(&denyWindows, "deny-windows", "", "JSON string for deny windows") | ||
| cmd.Flags().StringVar(&versionAnyApprovals, "version-any-approvals", "", "JSON string for version any approvals") | ||
| cmd.Flags().StringVar(&versionUserApprovals, "version-user-approvals", "", "JSON string for version user approvals") | ||
| cmd.Flags().StringVar(&versionRoleApprovals, "version-role-approvals", "", "JSON string for version role approvals") | ||
| cmd.Flags().StringVar(&deploymentVersionSelector, "deployment-version-selector", "", "JSON string for deployment version selector") | ||
|
|
||
| // Mark required flags | ||
| cmd.MarkFlagRequired("name") | ||
| cmd.MarkFlagRequired("workspace-id") | ||
|
|
||
| return cmd | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Consider supporting multiple targets.
The API model appears to support multiple targets (using a slice), but the implementation only creates a single target. If multiple targets should be supported, consider adding flags or accepting a JSON array for all targets.
🏁 Script executed:
Length of output: 1149
Action: Enhance support for multiple policy targets
The current implementation in
cmd/ctrlc/root/api/create/policy/policy.gocreates a single target:However, as confirmed in
internal/api/client.gen.go, the API model supports multiple targets via a slice. If the design intent is to allow multiple policy targets, please consider extending the CLI to either add additional flags or allow a JSON array input so that users can specify more than one target.