Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
402ea93
Create application command
asafgabai May 19, 2025
81bada5
Create application command
asafgabai May 19, 2025
bb83487
Create application command
asafgabai May 19, 2025
9a463db
Create application command
asafgabai May 19, 2025
9f1939d
Create application command
asafgabai May 19, 2025
9edf5a4
Create application command
asafgabai May 19, 2025
3ef91d9
Static analysis fixes
asafgabai May 19, 2025
f2106be
Create application command
asafgabai May 20, 2025
d6552a1
Create application command
asafgabai May 20, 2025
362f730
Create application command
asafgabai May 20, 2025
730d870
Create application command
asafgabai May 20, 2025
2a2d746
Update application command
asafgabai May 20, 2025
85abb33
Update application command
asafgabai May 20, 2025
a38c311
Create application command
asafgabai May 20, 2025
9f706be
Create application command
asafgabai May 20, 2025
f031ec9
Merge remote-tracking branch 'origin/APP-440-Create-application-descr…
asafgabai May 20, 2025
064c2ac
Update application command
asafgabai May 20, 2025
e7f7c58
Create application command
asafgabai May 20, 2025
2cef81c
Merge remote-tracking branch 'origin/APP-440-Create-application-descr…
asafgabai May 20, 2025
b9ec8c9
Create application command
asafgabai May 20, 2025
0b7e0c3
Create application command
asafgabai May 20, 2025
9a54ab8
Merge remote-tracking branch 'origin/APP-440-Create-application-descr…
asafgabai May 20, 2025
9741a02
Update application command
asafgabai May 20, 2025
1d39479
Merge remote-tracking branch 'origin/main' into APP-443-Update-specif…
asafgabai May 20, 2025
89ff137
Update application command
asafgabai May 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions application/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func GetJfrogApplicationCli() components.App {
version.GetCreateAppVersionCommand(appContext),
version.GetPromoteAppVersionCommand(appContext),
application.GetCreateAppCommand(appContext),
application.GetUpdateAppCommand(appContext),
},
)
return appEntity
Expand Down
6 changes: 3 additions & 3 deletions application/commands/application/create_app_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
type createAppCommand struct {
serverDetails *coreConfig.ServerDetails
applicationService applications.ApplicationService
requestBody *model.CreateAppRequest
requestBody *model.AppDescriptor
}

func (cac *createAppCommand) Run() error {
Expand All @@ -40,7 +40,7 @@ func (cac *createAppCommand) CommandName() string {
return commands.CreateApp
}

func (cac *createAppCommand) buildRequestPayload(ctx *components.Context) (*model.CreateAppRequest, error) {
func (cac *createAppCommand) buildRequestPayload(ctx *components.Context) (*model.AppDescriptor, error) {
applicationKey := ctx.Arguments[0]
applicationName := ctx.GetStringFlagValue(commands.ApplicationNameFlag)
if applicationName == "" {
Expand Down Expand Up @@ -81,7 +81,7 @@ func (cac *createAppCommand) buildRequestPayload(ctx *components.Context) (*mode
return nil, err
}

return &model.CreateAppRequest{
return &model.AppDescriptor{
ApplicationName: applicationName,
ApplicationKey: applicationKey,
Description: description,
Expand Down
4 changes: 2 additions & 2 deletions application/commands/application/create_app_cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func TestCreateAppCommand_Run(t *testing.T) {
defer ctrl.Finish()

serverDetails := &config.ServerDetails{Url: "https://example.com"}
requestPayload := &model.CreateAppRequest{
requestPayload := &model.AppDescriptor{
ApplicationKey: "app-key",
ApplicationName: "app-name",
ProjectKey: "proj-key",
Expand All @@ -44,7 +44,7 @@ func TestCreateAppCommand_Error(t *testing.T) {
defer ctrl.Finish()

serverDetails := &config.ServerDetails{Url: "https://example.com"}
requestPayload := &model.CreateAppRequest{
requestPayload := &model.AppDescriptor{
ApplicationKey: "app-key",
ApplicationName: "app-name",
ProjectKey: "proj-key",
Expand Down
124 changes: 124 additions & 0 deletions application/commands/application/update_app_cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package application

import (
pluginsCommon "github.com/jfrog/jfrog-cli-core/v2/plugins/common"

"github.com/jfrog/jfrog-cli-application/application/app"
"github.com/jfrog/jfrog-cli-application/application/commands"
"github.com/jfrog/jfrog-cli-application/application/commands/utils"
"github.com/jfrog/jfrog-cli-application/application/common"
"github.com/jfrog/jfrog-cli-application/application/model"
"github.com/jfrog/jfrog-cli-application/application/service"
"github.com/jfrog/jfrog-cli-application/application/service/applications"
commonCLiCommands "github.com/jfrog/jfrog-cli-core/v2/common/commands"
"github.com/jfrog/jfrog-cli-core/v2/plugins/components"
coreConfig "github.com/jfrog/jfrog-cli-core/v2/utils/config"
)

const UpdateApp = "update-app"

type updateAppCommand struct {
serverDetails *coreConfig.ServerDetails
applicationService applications.ApplicationService
requestBody *model.AppDescriptor
}

func (uac *updateAppCommand) Run() error {
ctx, err := service.NewContext(*uac.serverDetails)
if err != nil {
return err
}

return uac.applicationService.UpdateApplication(ctx, uac.requestBody)
}

func (uac *updateAppCommand) ServerDetails() (*coreConfig.ServerDetails, error) {
return uac.serverDetails, nil
}

func (uac *updateAppCommand) CommandName() string {
return UpdateApp
}

func (uac *updateAppCommand) buildRequestPayload(ctx *components.Context) (*model.AppDescriptor, error) {
applicationKey := ctx.Arguments[0]
applicationName := ctx.GetStringFlagValue(commands.ApplicationNameFlag)

businessCriticalityStr := ctx.GetStringFlagValue(commands.BusinessCriticalityFlag)
businessCriticality, err := utils.ValidateEnumFlag(
commands.BusinessCriticalityFlag,
businessCriticalityStr,
"",
model.BusinessCriticalityValues)
if err != nil {
return nil, err
}

maturityLevelStr := ctx.GetStringFlagValue(commands.MaturityLevelFlag)
maturityLevel, err := utils.ValidateEnumFlag(
commands.MaturityLevelFlag,
maturityLevelStr,
model.MaturityLevelUnspecified,
model.MaturityLevelValues)
if err != nil {
return nil, err
}

description := ctx.GetStringFlagValue(commands.DescriptionFlag)
userOwners := utils.ParseSliceFlag(ctx.GetStringFlagValue(commands.UserOwnersFlag))
groupOwners := utils.ParseSliceFlag(ctx.GetStringFlagValue(commands.GroupOwnersFlag))
labelsMap, err := utils.ParseMapFlag(ctx.GetStringFlagValue(commands.LabelsFlag))
if err != nil {
return nil, err
}

return &model.AppDescriptor{
ApplicationKey: applicationKey,
ApplicationName: applicationName,
Description: description,
MaturityLevel: maturityLevel,
BusinessCriticality: businessCriticality,
Labels: labelsMap,
UserOwners: userOwners,
GroupOwners: groupOwners,
}, nil
}

func (uac *updateAppCommand) prepareAndRunCommand(ctx *components.Context) error {
if len(ctx.Arguments) != 1 {
return pluginsCommon.WrongNumberOfArgumentsHandler(ctx)
}

var err error
uac.requestBody, err = uac.buildRequestPayload(ctx)
if err != nil {
return err
}

uac.serverDetails, err = utils.ServerDetailsByFlags(ctx)
if err != nil {
return err
}

return commonCLiCommands.Exec(uac)
}

func GetUpdateAppCommand(appContext app.Context) components.Command {
cmd := &updateAppCommand{
applicationService: appContext.GetApplicationService(),
}
return components.Command{
Name: "update",
Description: "Update an existing application",
Category: common.CategoryApplication,
Arguments: []components.Argument{
{
Name: "application-key",
Description: "The key of the application to update",
Optional: false,
},
},
Flags: commands.GetCommandFlags(commands.UpdateApp),
Action: cmd.prepareAndRunCommand,
}
}
104 changes: 104 additions & 0 deletions application/commands/application/update_app_cmd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package application

import (
"errors"
"flag"
"testing"

"github.com/urfave/cli"

"github.com/jfrog/jfrog-cli-application/application/model"
mockapps "github.com/jfrog/jfrog-cli-application/application/service/applications/mocks"
"github.com/jfrog/jfrog-cli-core/v2/plugins/components"
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
"github.com/stretchr/testify/assert"
"go.uber.org/mock/gomock"
)

func TestUpdateAppCommand_Run(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

serverDetails := &config.ServerDetails{Url: "https://example.com"}
appKey := "app-key"
requestPayload := &model.AppDescriptor{
ApplicationKey: appKey,
ApplicationName: "app-name",
Description: "Updated description",
MaturityLevel: "production",
BusinessCriticality: "high",
Labels: map[string]string{
"environment": "production",
"region": "us-east",
},
UserOwners: []string{"JohnD", "Dave Rice"},
GroupOwners: []string{"DevOps"},
}

mockAppService := mockapps.NewMockApplicationService(ctrl)
mockAppService.EXPECT().UpdateApplication(gomock.Any(), requestPayload).Return(nil).Times(1)

cmd := &updateAppCommand{
applicationService: mockAppService,
serverDetails: serverDetails,
requestBody: requestPayload,
}

err := cmd.Run()
assert.NoError(t, err)
}

func TestUpdateAppCommand_Run_Error(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

serverDetails := &config.ServerDetails{Url: "https://example.com"}
appKey := "app-key"
requestPayload := &model.AppDescriptor{
ApplicationKey: appKey,
ApplicationName: "app-name",
Description: "Updated description",
MaturityLevel: "production",
BusinessCriticality: "high",
Labels: map[string]string{
"environment": "production",
"region": "us-east",
},
UserOwners: []string{"JohnD", "Dave Rice"},
GroupOwners: []string{"DevOps"},
}

mockAppService := mockapps.NewMockApplicationService(ctrl)
mockAppService.EXPECT().UpdateApplication(gomock.Any(), requestPayload).Return(errors.New("failed to update application. Status code: 500")).Times(1)

cmd := &updateAppCommand{
applicationService: mockAppService,
serverDetails: serverDetails,
requestBody: requestPayload,
}

err := cmd.Run()
assert.Error(t, err)
assert.Equal(t, "failed to update application. Status code: 500", err.Error())
}

func TestUpdateAppCommand_WrongNumberOfArguments(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
ctx := cli.NewContext(app, set, nil)

mockAppService := mockapps.NewMockApplicationService(ctrl)
cmd := &updateAppCommand{
applicationService: mockAppService,
}

// Test with no arguments
context, err := components.ConvertContext(ctx)
assert.NoError(t, err)

err = cmd.prepareAndRunCommand(context)
assert.Error(t, err)
assert.Contains(t, err.Error(), "Wrong number of arguments")
}
30 changes: 24 additions & 6 deletions application/commands/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ const (
CreateAppVersion = "create-app-version"
PromoteAppVersion = "promote-app-version"
CreateApp = "create-app"
UpdateApp = "update-app"
)

const (
ServerId = "server-id"
serverId = "server-id"
url = "url"
user = "user"
accessToken = "access-token"
Expand All @@ -42,7 +43,7 @@ const (
// Flag keys mapped to their corresponding components.Flag definition.
var flagsMap = map[string]components.Flag{
// Common commands flags
ServerId: components.NewStringFlag(ServerId, "Server ID configured using the config command.", func(f *components.StringFlag) { f.Mandatory = false }),
serverId: components.NewStringFlag(serverId, "Server ID configured using the config command.", func(f *components.StringFlag) { f.Mandatory = false }),
url: components.NewStringFlag(url, "JFrog Platform URL.", func(f *components.StringFlag) { f.Mandatory = false }),
user: components.NewStringFlag(user, "JFrog username.", func(f *components.StringFlag) { f.Mandatory = false }),
accessToken: components.NewStringFlag(accessToken, "JFrog access token.", func(f *components.StringFlag) { f.Mandatory = false }),
Expand Down Expand Up @@ -71,7 +72,7 @@ var commandFlags = map[string][]string{
url,
user,
accessToken,
ServerId,
serverId,
ApplicationKeyFlag,
PackageTypeFlag,
PackageNameFlag,
Expand All @@ -84,7 +85,7 @@ var commandFlags = map[string][]string{
url,
user,
accessToken,
ServerId,
serverId,
ApplicationKeyFlag,
StageVarsFlag,
},
Expand All @@ -93,14 +94,14 @@ var commandFlags = map[string][]string{
url,
user,
accessToken,
ServerId,
serverId,
},

CreateApp: {
url,
user,
accessToken,
ServerId,
serverId,
ApplicationNameFlag,
ProjectFlag,
DescriptionFlag,
Expand All @@ -113,6 +114,23 @@ var commandFlags = map[string][]string{
SpecFlag,
SpecVarsFlag,
},

UpdateApp: {
url,
user,
accessToken,
serverId,
ApplicationNameFlag,
DescriptionFlag,
BusinessCriticalityFlag,
MaturityLevelFlag,
LabelsFlag,
UserOwnersFlag,
GroupOwnersFlag,
SigningKeyFlag,
SpecFlag,
SpecVarsFlag,
},
}

func GetCommandFlags(cmdKey string) []components.Flag {
Expand Down
Loading