Repository navigation
feat: hidden kosli list rego-policies and kosli get rego-policy, read published Rego policies #1260
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
Show all changes
4 commits
Select commit
Hold shift + click to select a range
181ed04
feat(list): hidden kosli list rego-policies, list the rego policies o…
jumboduck 471e932
refactor(regopolicies): export the endpoint URLs, so every rego polic…
jumboduck 042e192
feat(get): hidden kosli get rego-policy, show a rego policy or one of…
jumboduck 2036f0b
fix(get): rename get rego-policy --version to --policy-version, and a…
jumboduck 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,215 @@ | ||
| package main | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| "fmt" | ||
| "io" | ||
| "net/http" | ||
|
|
||
| "github.com/kosli-dev/cli/internal/output" | ||
| "github.com/kosli-dev/cli/internal/regopolicies" | ||
| "github.com/kosli-dev/cli/internal/requests" | ||
| "github.com/spf13/cobra" | ||
| ) | ||
|
|
||
| const getRegoPolicyShortDesc = `Get a rego policy, or one version of it.` | ||
|
|
||
| const getRegoPolicyLongDesc = getRegoPolicyShortDesc + ` | ||
| Without ^--policy-version^, the policy is shown with its newest version and its current | ||
| version. The current version is the highest-numbered valid version, which is the | ||
| one an evaluation runs, so it can be older than the newest version. | ||
|
|
||
| With ^--policy-version^, that version is shown with its status, its digest, who | ||
| published it and when, and the reason when it is rejected or failed. The command | ||
| exits 0 whatever the status of the version.` | ||
|
|
||
| const getRegoPolicyExample = ` | ||
| # get a rego policy and its current version: | ||
| kosli get rego-policy pr-approved \ | ||
| --api-token yourAPIToken \ | ||
| --org yourOrgName | ||
|
|
||
| # get version 3 of a rego policy: | ||
| kosli get rego-policy pr-approved \ | ||
| --policy-version 3 \ | ||
| --api-token yourAPIToken \ | ||
| --org yourOrgName | ||
|
|
||
| # get version 3 of a rego policy as JSON: | ||
| kosli get rego-policy pr-approved \ | ||
| --policy-version 3 \ | ||
| --output json \ | ||
| --api-token yourAPIToken \ | ||
| --org yourOrgName | ||
| ` | ||
|
|
||
| type getRegoPolicyOptions struct { | ||
| output string | ||
| version int | ||
| } | ||
|
|
||
| func newGetRegoPolicyCmd(out io.Writer) *cobra.Command { | ||
| o := new(getRegoPolicyOptions) | ||
| cmd := &cobra.Command{ | ||
| Use: "rego-policy IDENTIFIER", | ||
| Short: getRegoPolicyShortDesc, | ||
| Long: getRegoPolicyLongDesc, | ||
| Example: getRegoPolicyExample, | ||
| Args: cobra.ExactArgs(1), | ||
| // Hidden while the server gates the endpoint behind is-server-side-evaluation-enabled. | ||
| Hidden: true, | ||
| Annotations: map[string]string{betaCLIAnnotation: ""}, | ||
| PreRunE: func(cmd *cobra.Command, args []string) error { | ||
| err := RequireGlobalFlags(global, []string{"Org", "ApiToken"}) | ||
| if err != nil { | ||
| return ErrorBeforePrintingUsage(cmd, err.Error()) | ||
| } | ||
| if cmd.Flags().Changed("policy-version") && o.version < 1 { | ||
| return ErrorBeforePrintingUsage(cmd, "--policy-version must be a positive integer") | ||
| } | ||
| return nil | ||
| }, | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| return o.run(out, args[0]) | ||
| }, | ||
| } | ||
|
|
||
| cmd.Flags().IntVar(&o.version, "policy-version", 0, regoPolicyVersionFlag) | ||
| cmd.Flags().StringVarP(&o.output, "output", "o", "table", outputFlag) | ||
|
|
||
| return cmd | ||
| } | ||
|
|
||
| func (o *getRegoPolicyOptions) run(out io.Writer, identifier string) error { | ||
| var endpoint string | ||
| var err error | ||
| var printTable output.FormatOutputFunc | ||
| if o.version > 0 { | ||
| endpoint, err = regopolicies.VersionURL(global.Host, global.Org, identifier, o.version) | ||
| printTable = printRegoPolicyVersionAsTable | ||
| } else { | ||
| endpoint, err = regopolicies.PolicyURL(global.Host, global.Org, identifier) | ||
| printTable = printRegoPolicyAsTable | ||
| } | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| response, err := kosliClient.Do(&requests.RequestParams{ | ||
| Method: http.MethodGet, | ||
| URL: endpoint, | ||
| Token: global.ApiToken, | ||
| }) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| return output.FormattedPrint(response.Body, o.output, out, 0, | ||
| map[string]output.FormatOutputFunc{ | ||
| "table": printTable, | ||
| "json": output.PrintJson, | ||
| }) | ||
| } | ||
|
|
||
| func printRegoPolicyAsTable(raw string, out io.Writer, page int) error { | ||
| var policy map[string]any | ||
| if err := json.Unmarshal([]byte(raw), &policy); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| rows := []string{ | ||
| fmt.Sprintf("Identifier:\t%s", policy["identifier"]), | ||
| fmt.Sprintf("Name:\t%s", policy["name"]), | ||
| } | ||
| if description, ok := policy["description"]; ok && description != nil { | ||
| rows = append(rows, fmt.Sprintf("Description:\t%s", description)) | ||
| } | ||
| rows = append(rows, fmt.Sprintf("Created by:\t%s", policy["created_by"])) | ||
| for _, field := range []struct{ label, key string }{ | ||
| {"Created at", "created_at"}, | ||
| {"Last updated", "updated_at"}, | ||
| } { | ||
| at, err := formattedTimestamp(policy[field.key], true) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| rows = append(rows, fmt.Sprintf("%s:\t%s", field.label, at)) | ||
| } | ||
| if newest, ok := policy["newest_version"].(map[string]any); ok { | ||
| rows = append(rows, fmt.Sprintf("Newest version:\t%.0f (%s)", newest["version"], newest["status"])) | ||
| } | ||
|
|
||
| current, ok := policy["current_version"].(map[string]any) | ||
| if !ok { | ||
| rows = append(rows, "Current version:\tnone, as no version is valid yet") | ||
| tabFormattedPrint(out, []string{}, rows) | ||
| return nil | ||
| } | ||
| rows = append(rows, | ||
| fmt.Sprintf("Current version:\t%.0f", current["version"]), | ||
| fmt.Sprintf(" Digest:\t%s", current["digest"]), | ||
| fmt.Sprintf(" Input schema:\t%s", current["input_schema"]), | ||
| ) | ||
| if schema, ok := current["params_schema"]; ok && schema != nil { | ||
| compact, err := json.Marshal(schema) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| rows = append(rows, fmt.Sprintf(" Params schema:\t%s", compact)) | ||
| } | ||
|
|
||
| tabFormattedPrint(out, []string{}, rows) | ||
| return nil | ||
| } | ||
|
|
||
| func printRegoPolicyVersionAsTable(raw string, out io.Writer, page int) error { | ||
| var version regopolicies.Version | ||
| if err := json.Unmarshal([]byte(raw), &version); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| rows := []string{ | ||
| fmt.Sprintf("Identifier:\t%s", version.Identifier), | ||
| fmt.Sprintf("Version:\t%d", version.Version), | ||
| fmt.Sprintf("Status:\t%s", version.Status), | ||
| } | ||
| if version.Error != nil { | ||
| rows = append(rows, fmt.Sprintf("Error:\t%s: %s", version.Error.Kind, version.Error.Message)) | ||
| } | ||
| rows = append(rows, | ||
| fmt.Sprintf("Digest:\t%s", version.Digest), | ||
| fmt.Sprintf("Input schema:\t%s", version.InputSchema), | ||
| ) | ||
| if version.Comment != "" { | ||
| rows = append(rows, fmt.Sprintf("Comment:\t%s", version.Comment)) | ||
| } | ||
| rows = append(rows, fmt.Sprintf("Published by:\t%s", version.CreatedBy)) | ||
| publishedAt, err := formattedTimestamp(version.CreatedAt, true) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| rows = append(rows, fmt.Sprintf("Published at:\t%s", publishedAt)) | ||
| if version.ValidatedAt != nil { | ||
| validatedAt, err := formattedTimestamp(*version.ValidatedAt, true) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| rows = append(rows, fmt.Sprintf("Validated at:\t%s", validatedAt)) | ||
| } | ||
| if version.OPAVersion != "" { | ||
| rows = append(rows, fmt.Sprintf("OPA version:\t%s", version.OPAVersion)) | ||
| } | ||
| if version.Entrypoint != "" { | ||
| rows = append(rows, fmt.Sprintf("Entrypoint:\t%s", version.Entrypoint)) | ||
| } | ||
| if version.ParamsSchema != nil { | ||
| compact, err := json.Marshal(version.ParamsSchema) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| rows = append(rows, fmt.Sprintf("Params schema:\t%s", compact)) | ||
| } | ||
|
|
||
| tabFormattedPrint(out, []string{}, rows) | ||
| return nil | ||
| } | ||
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.