Skip to content

Commit 2a2d746

Browse files
committed
Update application command
1 parent 730d870 commit 2a2d746

File tree

10 files changed

+292
-18
lines changed

10 files changed

+292
-18
lines changed

application/cli/cli.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ func GetJfrogApplicationCli() components.App {
4040
version.GetCreateAppVersionCommand(appContext),
4141
version.GetPromoteAppVersionCommand(appContext),
4242
application.GetCreateAppCommand(appContext),
43+
application.GetUpdateAppCommand(appContext),
4344
},
4445
)
4546
return appEntity

application/commands/application/create_app_cmd.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import (
2222
type createAppCommand struct {
2323
serverDetails *coreConfig.ServerDetails
2424
applicationService applications.ApplicationService
25-
requestBody *model.CreateAppRequest
25+
requestBody *model.AppDescriptor
2626
}
2727

2828
func (cac *createAppCommand) Run() error {
@@ -42,7 +42,7 @@ func (cac *createAppCommand) CommandName() string {
4242
return commands.CreateApp
4343
}
4444

45-
func (cac *createAppCommand) buildRequestPayload(ctx *components.Context) (*model.CreateAppRequest, error) {
45+
func (cac *createAppCommand) buildRequestPayload(ctx *components.Context) (*model.AppDescriptor, error) {
4646
appKey := ctx.Arguments[0]
4747
displayName := ctx.GetStringFlagValue(commands.DisplayNameFlag)
4848
if displayName == "" {
@@ -79,7 +79,7 @@ func (cac *createAppCommand) buildRequestPayload(ctx *components.Context) (*mode
7979
return nil, err
8080
}
8181

82-
return &model.CreateAppRequest{
82+
return &model.AppDescriptor{
8383
ApplicationName: displayName,
8484
ApplicationKey: appKey,
8585
Description: description,

application/commands/application/create_app_cmd_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func TestCreateAppCommand_Run(t *testing.T) {
1919
defer ctrl.Finish()
2020

2121
serverDetails := &config.ServerDetails{Url: "https://example.com"}
22-
requestPayload := &model.CreateAppRequest{
22+
requestPayload := &model.AppDescriptor{
2323
ApplicationKey: "app-key",
2424
ApplicationName: "app-name",
2525
ProjectKey: "proj-key",
@@ -43,7 +43,7 @@ func TestCreateAppCommand_Error(t *testing.T) {
4343
defer ctrl.Finish()
4444

4545
serverDetails := &config.ServerDetails{Url: "https://example.com"}
46-
requestPayload := &model.CreateAppRequest{
46+
requestPayload := &model.AppDescriptor{
4747
ApplicationKey: "app-key",
4848
ApplicationName: "app-name",
4949
ProjectKey: "proj-key",
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package application
2+
3+
import (
4+
pluginsCommon "github.com/jfrog/jfrog-cli-core/v2/plugins/common"
5+
"slices"
6+
7+
"github.com/jfrog/jfrog-cli-application/application/app"
8+
"github.com/jfrog/jfrog-cli-application/application/commands"
9+
"github.com/jfrog/jfrog-cli-application/application/commands/utils"
10+
"github.com/jfrog/jfrog-cli-application/application/common"
11+
"github.com/jfrog/jfrog-cli-application/application/model"
12+
"github.com/jfrog/jfrog-cli-application/application/service"
13+
"github.com/jfrog/jfrog-cli-application/application/service/applications"
14+
commonCLiCommands "github.com/jfrog/jfrog-cli-core/v2/common/commands"
15+
"github.com/jfrog/jfrog-cli-core/v2/plugins/components"
16+
coreConfig "github.com/jfrog/jfrog-cli-core/v2/utils/config"
17+
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
18+
"github.com/jfrog/jfrog-client-go/utils/errorutils"
19+
)
20+
21+
const UpdateApp = "update-app"
22+
23+
type updateAppCommand struct {
24+
serverDetails *coreConfig.ServerDetails
25+
applicationService applications.ApplicationService
26+
requestBody *model.AppDescriptor
27+
}
28+
29+
func (uac *updateAppCommand) Run() error {
30+
ctx, err := service.NewContext(*uac.serverDetails)
31+
if err != nil {
32+
return err
33+
}
34+
35+
return uac.applicationService.UpdateApplication(ctx, uac.requestBody)
36+
}
37+
38+
func (uac *updateAppCommand) ServerDetails() (*coreConfig.ServerDetails, error) {
39+
return uac.serverDetails, nil
40+
}
41+
42+
func (uac *updateAppCommand) CommandName() string {
43+
return UpdateApp
44+
}
45+
46+
func (uac *updateAppCommand) buildRequestPayload(ctx *components.Context) (*model.AppDescriptor, error) {
47+
applicationKey := ctx.Arguments[0]
48+
displayName := ctx.GetStringFlagValue(commands.DisplayNameFlag)
49+
50+
businessCriticality := ctx.GetStringFlagValue(commands.BusinessCriticalityFlag)
51+
if businessCriticality != "" && !slices.Contains(model.BusinessCriticalityValues, businessCriticality) {
52+
return nil, errorutils.CheckErrorf("invalid value for --%s: '%s'. Allowed values: %s", commands.BusinessCriticalityFlag, businessCriticality, coreutils.ListToText(model.BusinessCriticalityValues))
53+
}
54+
55+
maturityLevel := ctx.GetStringFlagValue(commands.MaturityLevelFlag)
56+
if maturityLevel != "" && !slices.Contains(model.MaturityLevelValues, maturityLevel) {
57+
return nil, errorutils.CheckErrorf("invalid value for --%s: '%s'. Allowed values: %s", commands.MaturityLevelFlag, maturityLevel, coreutils.ListToText(model.MaturityLevelValues))
58+
}
59+
60+
description := ctx.GetStringFlagValue(commands.DescriptionFlag)
61+
userOwners := utils.ParseSliceFlag(ctx.GetStringFlagValue(commands.UserOwnersFlag))
62+
groupOwners := utils.ParseSliceFlag(ctx.GetStringFlagValue(commands.GroupOwnersFlag))
63+
labelsMap, err := utils.ParseMapFlag(ctx.GetStringFlagValue(commands.LabelsFlag))
64+
if err != nil {
65+
return nil, err
66+
}
67+
68+
return &model.AppDescriptor{
69+
ApplicationKey: applicationKey,
70+
ApplicationName: displayName,
71+
Description: description,
72+
MaturityLevel: maturityLevel,
73+
BusinessCriticality: businessCriticality,
74+
Labels: labelsMap,
75+
UserOwners: userOwners,
76+
GroupOwners: groupOwners,
77+
}, nil
78+
}
79+
80+
func (uac *updateAppCommand) prepareAndRunCommand(ctx *components.Context) error {
81+
if len(ctx.Arguments) != 1 {
82+
return pluginsCommon.WrongNumberOfArgumentsHandler(ctx)
83+
}
84+
85+
var err error
86+
uac.requestBody, err = uac.buildRequestPayload(ctx)
87+
if err != nil {
88+
return err
89+
}
90+
91+
uac.serverDetails, err = utils.ServerDetailsByFlags(ctx)
92+
if err != nil {
93+
return err
94+
}
95+
96+
return commonCLiCommands.Exec(uac)
97+
}
98+
99+
func GetUpdateAppCommand(appContext app.Context) components.Command {
100+
cmd := &updateAppCommand{
101+
applicationService: appContext.GetApplicationService(),
102+
}
103+
return components.Command{
104+
Name: "update",
105+
Description: "Update an existing application",
106+
Category: common.CategoryApplication,
107+
Arguments: []components.Argument{
108+
{
109+
Name: "application-key",
110+
Description: "The key of the application to update",
111+
Optional: false,
112+
},
113+
},
114+
Flags: commands.GetCommandFlags(commands.UpdateApp),
115+
Action: cmd.prepareAndRunCommand,
116+
}
117+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package application
2+
3+
import (
4+
"errors"
5+
"flag"
6+
"github.com/urfave/cli"
7+
"testing"
8+
9+
"github.com/jfrog/jfrog-cli-application/application/model"
10+
mockapps "github.com/jfrog/jfrog-cli-application/application/service/applications/mocks"
11+
"github.com/jfrog/jfrog-cli-core/v2/plugins/components"
12+
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
13+
"github.com/stretchr/testify/assert"
14+
"go.uber.org/mock/gomock"
15+
)
16+
17+
func TestUpdateAppCommand_Run(t *testing.T) {
18+
ctrl := gomock.NewController(t)
19+
defer ctrl.Finish()
20+
21+
serverDetails := &config.ServerDetails{Url: "https://example.com"}
22+
appKey := "app-key"
23+
requestPayload := &model.AppDescriptor{
24+
ApplicationKey: appKey,
25+
ApplicationName: "app-name",
26+
Description: "Updated description",
27+
MaturityLevel: "production",
28+
BusinessCriticality: "high",
29+
Labels: map[string]string{
30+
"environment": "production",
31+
"region": "us-east",
32+
},
33+
UserOwners: []string{"JohnD", "Dave Rice"},
34+
GroupOwners: []string{"DevOps"},
35+
}
36+
37+
mockAppService := mockapps.NewMockApplicationService(ctrl)
38+
mockAppService.EXPECT().UpdateApplication(gomock.Any(), requestPayload).Return(nil).Times(1)
39+
40+
cmd := &updateAppCommand{
41+
applicationService: mockAppService,
42+
serverDetails: serverDetails,
43+
requestBody: requestPayload,
44+
}
45+
46+
err := cmd.Run()
47+
assert.NoError(t, err)
48+
}
49+
50+
func TestUpdateAppCommand_Run_Error(t *testing.T) {
51+
ctrl := gomock.NewController(t)
52+
defer ctrl.Finish()
53+
54+
serverDetails := &config.ServerDetails{Url: "https://example.com"}
55+
appKey := "app-key"
56+
requestPayload := &model.AppDescriptor{
57+
ApplicationKey: appKey,
58+
ApplicationName: "app-name",
59+
Description: "Updated description",
60+
MaturityLevel: "production",
61+
BusinessCriticality: "high",
62+
Labels: map[string]string{
63+
"environment": "production",
64+
"region": "us-east",
65+
},
66+
UserOwners: []string{"JohnD", "Dave Rice"},
67+
GroupOwners: []string{"DevOps"},
68+
}
69+
70+
mockAppService := mockapps.NewMockApplicationService(ctrl)
71+
mockAppService.EXPECT().UpdateApplication(gomock.Any(), requestPayload).Return(errors.New("failed to update application. Status code: 500")).Times(1)
72+
73+
cmd := &updateAppCommand{
74+
applicationService: mockAppService,
75+
serverDetails: serverDetails,
76+
requestBody: requestPayload,
77+
}
78+
79+
err := cmd.Run()
80+
assert.Error(t, err)
81+
assert.Equal(t, "failed to update application. Status code: 500", err.Error())
82+
}
83+
84+
func TestUpdateAppCommand_WrongNumberOfArguments(t *testing.T) {
85+
ctrl := gomock.NewController(t)
86+
defer ctrl.Finish()
87+
app := cli.NewApp()
88+
set := flag.NewFlagSet("test", 0)
89+
ctx := cli.NewContext(app, set, nil)
90+
91+
mockAppService := mockapps.NewMockApplicationService(ctrl)
92+
cmd := &updateAppCommand{
93+
applicationService: mockAppService,
94+
}
95+
96+
// Test with no arguments
97+
context, err := components.ConvertContext(ctx)
98+
assert.NoError(t, err)
99+
100+
err = cmd.prepareAndRunCommand(context)
101+
assert.Error(t, err)
102+
assert.Contains(t, err.Error(), "Wrong number of arguments")
103+
}

application/commands/flags.go

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ const (
1212
CreateAppVersion = "create-app-version"
1313
PromoteAppVersion = "promote-app-version"
1414
CreateApp = "create-app"
15+
UpdateApp = "update-app"
1516
)
1617

1718
const (
18-
ServerId = "server-id"
19+
serverId = "server-id"
1920
url = "url"
2021
user = "user"
2122
accessToken = "access-token"
@@ -42,7 +43,7 @@ const (
4243
// Flag keys mapped to their corresponding components.Flag definition.
4344
var flagsMap = map[string]components.Flag{
4445
// Common commands flags
45-
ServerId: components.NewStringFlag(ServerId, "Server ID configured using the config command.", func(f *components.StringFlag) { f.Mandatory = false }),
46+
serverId: components.NewStringFlag(serverId, "Server ID configured using the config command.", func(f *components.StringFlag) { f.Mandatory = false }),
4647
url: components.NewStringFlag(url, "JFrog Platform URL.", func(f *components.StringFlag) { f.Mandatory = false }),
4748
user: components.NewStringFlag(user, "JFrog username.", func(f *components.StringFlag) { f.Mandatory = false }),
4849
accessToken: components.NewStringFlag(accessToken, "JFrog access token.", func(f *components.StringFlag) { f.Mandatory = false }),
@@ -71,7 +72,7 @@ var commandFlags = map[string][]string{
7172
url,
7273
user,
7374
accessToken,
74-
ServerId,
75+
serverId,
7576
ApplicationKeyFlag,
7677
PackageTypeFlag,
7778
PackageNameFlag,
@@ -84,7 +85,7 @@ var commandFlags = map[string][]string{
8485
url,
8586
user,
8687
accessToken,
87-
ServerId,
88+
serverId,
8889
ApplicationKeyFlag,
8990
StageVarsFlag,
9091
},
@@ -93,14 +94,14 @@ var commandFlags = map[string][]string{
9394
url,
9495
user,
9596
accessToken,
96-
ServerId,
97+
serverId,
9798
},
9899

99100
CreateApp: {
100101
url,
101102
user,
102103
accessToken,
103-
ServerId,
104+
serverId,
104105
DisplayNameFlag,
105106
ProjectFlag,
106107
DescriptionFlag,
@@ -113,6 +114,23 @@ var commandFlags = map[string][]string{
113114
SpecFlag,
114115
SpecVarsFlag,
115116
},
117+
118+
UpdateApp: {
119+
url,
120+
user,
121+
accessToken,
122+
serverId,
123+
DisplayNameFlag,
124+
DescriptionFlag,
125+
BusinessCriticalityFlag,
126+
MaturityLevelFlag,
127+
LabelsFlag,
128+
UserOwnersFlag,
129+
GroupOwnersFlag,
130+
SigningKeyFlag,
131+
SpecFlag,
132+
SpecVarsFlag,
133+
},
116134
}
117135

118136
func GetCommandFlags(cmdKey string) []components.Flag {

0 commit comments

Comments
 (0)