From 0dca6159244c5cadde0c7b4789af16667164a557 Mon Sep 17 00:00:00 2001 From: Cyrill Troxler Date: Tue, 6 Feb 2024 11:35:59 +0100 Subject: [PATCH] feat: add update project command --- update/project.go | 53 +++++++++++++++++++++++++++ update/project_test.go | 81 ++++++++++++++++++++++++++++++++++++++++++ update/update.go | 3 +- 3 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 update/project.go create mode 100644 update/project_test.go diff --git a/update/project.go b/update/project.go new file mode 100644 index 0000000..110b7fd --- /dev/null +++ b/update/project.go @@ -0,0 +1,53 @@ +package update + +import ( + "context" + "fmt" + + "github.com/crossplane/crossplane-runtime/pkg/resource" + management "github.com/ninech/apis/management/v1alpha1" + "github.com/ninech/nctl/api" + "github.com/ninech/nctl/auth" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type projectCmd struct { + Name string `arg:"" default:"" help:"Name of the project to update."` + DisplayName *string `default:"" help:"Display Name of the project."` +} + +func (cmd *projectCmd) Run(ctx context.Context, client *api.Client) error { + cfg, err := auth.ReadConfig(client.KubeconfigPath, client.KubeconfigContext) + if err != nil { + if auth.IsConfigNotFoundError(err) { + return auth.ReloginNeeded(err) + } + return err + } + + project := &management.Project{ + ObjectMeta: metav1.ObjectMeta{ + Name: cmd.Name, + Namespace: cfg.Organization, + }, + } + + upd := newUpdater(client, project, management.ProjectKind, func(current resource.Managed) error { + project, ok := current.(*management.Project) + if !ok { + return fmt.Errorf("resource is of type %T, expected %T", current, management.Project{}) + } + + cmd.applyUpdates(project) + + return nil + }) + + return upd.Update(ctx) +} + +func (cmd *projectCmd) applyUpdates(project *management.Project) { + if cmd.DisplayName != nil { + project.Spec.DisplayName = *cmd.DisplayName + } +} diff --git a/update/project_test.go b/update/project_test.go new file mode 100644 index 0000000..5c20931 --- /dev/null +++ b/update/project_test.go @@ -0,0 +1,81 @@ +package update + +import ( + "context" + "os" + "testing" + + management "github.com/ninech/apis/management/v1alpha1" + "github.com/ninech/nctl/api" + "github.com/ninech/nctl/internal/test" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" +) + +func TestProject(t *testing.T) { + const ( + projectName = "some-project" + organization = "org" + ) + existingProject := &management.Project{ + ObjectMeta: metav1.ObjectMeta{ + Name: projectName, + Namespace: organization, + }, + Spec: management.ProjectSpec{}, + } + + cases := map[string]struct { + orig *management.Project + project string + cmd projectCmd + checkProject func(t *testing.T, cmd projectCmd, orig, updated *management.Project) + }{ + "all fields update": { + orig: existingProject, + project: projectName, + cmd: projectCmd{ + Name: projectName, + DisplayName: ptr.To("some display name"), + }, + checkProject: func(t *testing.T, cmd projectCmd, orig, updated *management.Project) { + assert.Equal(t, *cmd.DisplayName, updated.Spec.DisplayName) + }, + }, + } + + for name, tc := range cases { + tc := tc + + t.Run(name, func(t *testing.T) { + apiClient, err := test.SetupClient(tc.orig) + if err != nil { + t.Fatal(err) + } + apiClient.Project = tc.project + + ctx := context.Background() + + // we create a kubeconfig which does not contain a nctl config + // extension + kubeconfig, err := test.CreateTestKubeconfig(apiClient, organization) + require.NoError(t, err) + defer os.Remove(kubeconfig) + + if err := tc.cmd.Run(ctx, apiClient); err != nil { + t.Fatal(err) + } + + updated := &management.Project{} + if err := apiClient.Get(ctx, api.ObjectName(tc.orig), updated); err != nil { + t.Fatal(err) + } + + if tc.checkProject != nil { + tc.checkProject(t, tc.cmd, tc.orig, updated) + } + }) + } +} diff --git a/update/update.go b/update/update.go index e982187..8cddfc0 100644 --- a/update/update.go +++ b/update/update.go @@ -11,6 +11,7 @@ import ( type Cmd struct { Application applicationCmd `cmd:"" group:"deplo.io" name:"application" aliases:"app" help:"Update an existing deplo.io Application. (Beta - requires access)"` Config configCmd `cmd:"" group:"deplo.io" name:"config" help:"Update an existing deplo.io Project Configuration. (Beta - requires access)"` + Project projectCmd `cmd:"" group:"management.nine.ch" name:"project" help:"Update an existing Project"` } type updater struct { @@ -27,7 +28,7 @@ func newUpdater(client *api.Client, mg resource.Managed, kind string, f updateFu } func (u *updater) Update(ctx context.Context) error { - if err := u.client.Get(ctx, u.client.Name(u.mg.GetName()), u.mg); err != nil { + if err := u.client.Get(ctx, api.ObjectName(u.mg), u.mg); err != nil { return err }