-
Notifications
You must be signed in to change notification settings - Fork 6
WKS-2860 - Support clear-text worker properties in the CLI #63
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
3 commits
Select commit
Hold shift + click to select a range
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,106 @@ | ||
| // Package commands provides JFrog platform services worker management commands. | ||
| package commands | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "os" | ||
|
|
||
| "github.com/jfrog/jfrog-cli-platform-services/commands/common" | ||
|
|
||
| plugins_common "github.com/jfrog/jfrog-cli-core/v2/plugins/common" | ||
| "github.com/jfrog/jfrog-cli-core/v2/plugins/components" | ||
| "github.com/jfrog/jfrog-cli-core/v2/utils/ioutils" | ||
| "github.com/jfrog/jfrog-client-go/utils/log" | ||
|
|
||
| "github.com/jfrog/jfrog-cli-platform-services/model" | ||
| ) | ||
|
|
||
| type addPropertyCommand struct { | ||
| ctx *components.Context | ||
| } | ||
|
|
||
| func GetAddPropertyCommand() components.Command { | ||
| return components.Command{ | ||
| Name: "add-property", | ||
| Description: "Add a clear-text property to a worker", | ||
| AIDescription: `Add or update a clear-text property in the local manifest.json. Pass the value as a second argument, or omit it to prompt or use JFROG_WORKER_CLI_DEV_ADD_PROPERTY_VALUE. This command only writes locally; run 'jf worker deploy' to send the property to the server. | ||
|
|
||
| Properties are not secrets: values remain unencrypted and readable on disk. Omitting manifest.properties preserves remote properties, while an explicit empty object clears them on the next deploy.`, | ||
| Aliases: []string{"ap"}, | ||
| Flags: []components.Flag{ | ||
| components.NewBoolFlag(model.FlagEdit, "Whether to update an existing property.", components.WithBoolDefaultValue(false)), | ||
| }, | ||
| Arguments: []components.Argument{ | ||
| { | ||
| Name: "property-name", | ||
| Description: "The property name.", | ||
| }, | ||
| { | ||
| Name: "property-value", | ||
| Description: "The property value. If omitted, prompted or taken from JFROG_WORKER_CLI_DEV_ADD_PROPERTY_VALUE.", | ||
| Optional: true, | ||
| }, | ||
| }, | ||
| Action: func(c *components.Context) error { | ||
| return (&addPropertyCommand{ctx: c}).run() | ||
| }, | ||
| } | ||
| } | ||
|
|
||
| func (c *addPropertyCommand) run() error { | ||
| manifest, err := common.ReadManifest() | ||
| if err != nil { | ||
| return err | ||
| } | ||
| if err = common.ValidateManifest(manifest, nil); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| propertyName, err := c.getPropertyName() | ||
| if err != nil { | ||
| return err | ||
| } | ||
| if err = c.checkUpdate(manifest, propertyName); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| propertyValue := c.readPropertyValue() | ||
| if manifest.Properties == nil { | ||
| manifest.Properties = map[string]string{} | ||
| } | ||
| manifest.Properties[propertyName] = propertyValue | ||
|
|
||
| if err = common.SaveManifest(manifest); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| log.Info(fmt.Sprintf("Property '%s' saved", propertyName)) | ||
| return nil | ||
| } | ||
|
|
||
| func (c *addPropertyCommand) getPropertyName() (string, error) { | ||
| if len(c.ctx.Arguments) < 1 || len(c.ctx.Arguments) > 2 { | ||
| return "", plugins_common.WrongNumberOfArgumentsHandler(c.ctx) | ||
| } | ||
| return c.ctx.Arguments[0], nil | ||
| } | ||
|
|
||
| func (c *addPropertyCommand) checkUpdate(manifest *model.Manifest, propertyName string) error { | ||
| if _, exists := manifest.Properties[propertyName]; exists && !c.ctx.GetBoolFlagValue(model.FlagEdit) { | ||
| return fmt.Errorf("%s already exists, use --%s to overwrite", propertyName, model.FlagEdit) | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| func (c *addPropertyCommand) readPropertyValue() string { | ||
| if len(c.ctx.Arguments) > 1 { | ||
| return c.ctx.Arguments[1] | ||
| } | ||
| if propertyValue, exists := os.LookupEnv(model.EnvKeyAddPropertyValue); exists { | ||
| return propertyValue | ||
| } | ||
|
|
||
| var propertyValue string | ||
| ioutils.ScanFromConsole("Value", &propertyValue, "") | ||
| return propertyValue | ||
| } |
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,122 @@ | ||
| //go:build test | ||
| // +build test | ||
|
|
||
| package commands | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "os" | ||
| "testing" | ||
|
|
||
| "github.com/jfrog/jfrog-cli-platform-services/commands/common" | ||
| "github.com/jfrog/jfrog-cli-platform-services/model" | ||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
||
| func TestAddPropertyCmd(t *testing.T) { | ||
| tests := []struct { | ||
| name string | ||
| commandArgs []string | ||
| propertyName string | ||
| propertyValue string | ||
| wantErr string | ||
| want map[string]string | ||
| patchManifest func(mf *model.Manifest) | ||
| }{ | ||
| { | ||
| name: "add", | ||
| propertyName: "prop-1", | ||
| propertyValue: "value-1", | ||
| patchManifest: func(mf *model.Manifest) { | ||
| mf.Properties = map[string]string{"prop-2": "value-2"} | ||
| }, | ||
| want: map[string]string{"prop-1": "value-1", "prop-2": "value-2"}, | ||
| }, | ||
| { | ||
| name: "add from argument", | ||
| commandArgs: []string{"prop-1", "value-1"}, | ||
| patchManifest: func(mf *model.Manifest) { | ||
| mf.Properties = map[string]string{"prop-2": "value-2"} | ||
| }, | ||
| want: map[string]string{"prop-1": "value-1", "prop-2": "value-2"}, | ||
| }, | ||
| { | ||
| name: "argument overrides env", | ||
| commandArgs: []string{"prop-1", "from-arg"}, | ||
| propertyValue: "from-env", | ||
| want: map[string]string{"prop-1": "from-arg"}, | ||
| }, | ||
| { | ||
| name: "reject extra arguments", | ||
| commandArgs: []string{"prop-1", "value-1", "extra"}, | ||
| wantErr: "Wrong number of arguments (3).", | ||
| }, | ||
| { | ||
| name: "add with nil properties", | ||
| propertyName: "prop-1", | ||
| propertyValue: "value-1", | ||
| patchManifest: func(mf *model.Manifest) { | ||
| mf.Properties = nil | ||
| }, | ||
| want: map[string]string{"prop-1": "value-1"}, | ||
| }, | ||
| { | ||
| name: "edit property", | ||
| propertyName: "prop-1", | ||
| propertyValue: "new-value", | ||
| commandArgs: []string{fmt.Sprintf("--%s", model.FlagEdit)}, | ||
| patchManifest: func(mf *model.Manifest) { | ||
| mf.Properties = map[string]string{"prop-1": "old-value"} | ||
| }, | ||
| want: map[string]string{"prop-1": "new-value"}, | ||
| }, | ||
| { | ||
| name: "reject duplicate without edit", | ||
| propertyName: "prop-1", | ||
| propertyValue: "new-value", | ||
| patchManifest: func(mf *model.Manifest) { | ||
| mf.Properties = map[string]string{"prop-1": "old-value"} | ||
| }, | ||
| wantErr: "prop-1 already exists, use --edit to overwrite", | ||
| }, | ||
| { | ||
| name: "reject missing name", | ||
| wantErr: "Wrong number of arguments (0).", | ||
| }, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| common.NewMockWorkerServer(t, common.NewServerStub(t).WithDefaultActionsMetadataEndpoint()) | ||
|
|
||
| workerDir, workerName := common.PrepareWorkerDirForTest(t) | ||
| runCmd := common.CreateCliRunner(t, GetInitCommand(), GetAddPropertyCommand()) | ||
| require.NoError(t, runCmd("worker", "init", "GENERIC_EVENT", workerName)) | ||
|
|
||
| if tt.patchManifest != nil { | ||
| common.PatchManifest(t, tt.patchManifest) | ||
| } | ||
| if tt.propertyValue != "" { | ||
| require.NoError(t, os.Setenv(model.EnvKeyAddPropertyValue, tt.propertyValue)) | ||
| t.Cleanup(func() { _ = os.Unsetenv(model.EnvKeyAddPropertyValue) }) | ||
| } | ||
|
|
||
| cmd := append([]string{"worker", "add-property"}, tt.commandArgs...) | ||
| if tt.propertyName != "" { | ||
| cmd = append(cmd, tt.propertyName) | ||
| } | ||
|
|
||
| err := runCmd(cmd...) | ||
| if tt.wantErr != "" { | ||
| assert.EqualError(t, err, tt.wantErr) | ||
| return | ||
| } | ||
|
|
||
| require.NoError(t, err) | ||
| manifest, err := common.ReadManifest(workerDir) | ||
| require.NoError(t, err) | ||
| assert.Equal(t, tt.want, manifest.Properties) | ||
| }) | ||
| } | ||
| } |
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
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
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
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.
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.
why do we need a new command and not set them directly on the manifest ? like for filter
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.
Similar behaviour as secret, maybe useful for automation or if you dont want to trifle with the manifest syntax.
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.
ok