Skip to content

Commit

Permalink
Add app push command (kyma-project#2246)
Browse files Browse the repository at this point in the history
  • Loading branch information
halamix2 authored Nov 14, 2024
1 parent 58b0e81 commit 1a2da41
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 4 deletions.
10 changes: 6 additions & 4 deletions internal/cmd/alpha/alpha.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"github.com/kyma-project/cli.v3/internal/clierror"
"github.com/kyma-project/cli.v3/internal/cmd/alpha/access"
"github.com/kyma-project/cli.v3/internal/cmd/alpha/add"
"github.com/kyma-project/cli.v3/internal/cmd/alpha/app"
"github.com/kyma-project/cli.v3/internal/cmd/alpha/hana"
"github.com/kyma-project/cli.v3/internal/cmd/alpha/modules"
"github.com/kyma-project/cli.v3/internal/cmd/alpha/oidc"
Expand All @@ -30,13 +31,14 @@ func NewAlphaCMD() (*cobra.Command, clierror.Error) {
return nil, err
}

cmd.AddCommand(access.NewAccessCMD(kymaConfig))
cmd.AddCommand(add.NewAddCMD(kymaConfig))
cmd.AddCommand(app.NewAppCMD(kymaConfig))
cmd.AddCommand(hana.NewHanaCMD(kymaConfig))
cmd.AddCommand(modules.NewModulesCMD(kymaConfig))
cmd.AddCommand(oidc.NewOIDCCMD(kymaConfig))
cmd.AddCommand(provision.NewProvisionCMD())
cmd.AddCommand(referenceinstance.NewReferenceInstanceCMD(kymaConfig))
cmd.AddCommand(access.NewAccessCMD(kymaConfig))
cmd.AddCommand(oidc.NewOIDCCMD(kymaConfig))
cmd.AddCommand(modules.NewModulesCMD(kymaConfig))
cmd.AddCommand(add.NewAddCMD(kymaConfig))
cmd.AddCommand(remove.NewRemoveCMD(kymaConfig))

cmds := kymaConfig.BuildExtensions(&cmdcommon.TemplateCommandsList{
Expand Down
19 changes: 19 additions & 0 deletions internal/cmd/alpha/app/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package app

import (
"github.com/kyma-project/cli.v3/internal/cmdcommon"
"github.com/spf13/cobra"
)

func NewAppCMD(kymaConfig *cmdcommon.KymaConfig) *cobra.Command {
cmd := &cobra.Command{
Use: "app",
Short: "Manage applications on Kubernetes cluster.",
Long: `Use this command to manage applications on the Kubernetes cluster.`,
DisableFlagsInUseLine: true,
}

cmd.AddCommand(NewAppPushCMD(kymaConfig))

return cmd
}
54 changes: 54 additions & 0 deletions internal/cmd/alpha/app/push.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package app

import (
"github.com/kyma-project/cli.v3/internal/clierror"
"github.com/kyma-project/cli.v3/internal/cmdcommon"
"github.com/kyma-project/cli.v3/internal/kube/resources"
"github.com/spf13/cobra"
)

type appPushConfig struct {
*cmdcommon.KymaConfig

name string
namespace string
image string
// containerPort int
}

func NewAppPushCMD(kymaConfig *cmdcommon.KymaConfig) *cobra.Command {
config := appPushConfig{
KymaConfig: kymaConfig,
}

cmd := &cobra.Command{
Use: "push",
Short: "Push the application to the Kubernetes cluster.",
Long: "Use this command to push the application to the Kubernetes cluster.",
Run: func(_ *cobra.Command, _ []string) {
clierror.Check(runAppPush(&config))
},
}

cmd.Flags().StringVar(&config.name, "name", "", "Name of the app")
cmd.Flags().StringVar(&config.namespace, "namespace", "default", "Namespace where app should be deployed")
cmd.Flags().StringVar(&config.image, "image", "", "Name of the image to deploy")
// cmd.Flags().IntVar(&config.containerPort, "containerPort", 80, "")
_ = cmd.MarkFlagRequired("name")
_ = cmd.MarkFlagRequired("image")

return cmd
}

func runAppPush(cfg *appPushConfig) clierror.Error {
client, clierr := cfg.GetKubeClientWithClierr()
if clierr != nil {
return clierr
}
err := resources.CreateDeployment(cfg.Ctx, client, cfg.name, cfg.namespace, cfg.image)
if err != nil {
return clierror.Wrap(err, clierror.New("failed to create deployment"))
}

return nil
}
51 changes: 51 additions & 0 deletions internal/kube/resources/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import (
"context"

"github.com/kyma-project/cli.v3/internal/kube"
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand Down Expand Up @@ -72,3 +74,52 @@ func CreateClusterRoleBinding(ctx context.Context, client kube.Client, name, nam
}
return nil
}

func CreateDeployment(ctx context.Context, client kube.Client, name, namespace, image string) error {
deployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Labels: map[string]string{
"app.kubernetes.io/name": name,
"app.kubernetes.io/created-by": "kyma-cli",
},
},
Spec: appsv1.DeploymentSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"app": name,
},
},
Template: v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Labels: map[string]string{
"app": name,
"sidecar.istio.io/inject": "false",
},
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: name,
Image: image,
Resources: v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceMemory: resource.MustParse("64Mi"),
v1.ResourceCPU: resource.MustParse("50m"),
},
Limits: v1.ResourceList{
v1.ResourceMemory: resource.MustParse("128Mi"),
v1.ResourceCPU: resource.MustParse("100m"),
},
},
},
},
},
},
},
}

_, err := client.Static().AppsV1().Deployments(namespace).Create(ctx, deployment, metav1.CreateOptions{})
return err
}
57 changes: 57 additions & 0 deletions internal/kube/resources/resources_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

kube_fake "github.com/kyma-project/cli.v3/internal/kube/fake"
"github.com/stretchr/testify/require"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -86,3 +87,59 @@ func Test_CreateClusterRoleBinding(t *testing.T) {
})
}
}

func Test_CreateDeployment(t *testing.T) {
t.Parallel()
tests := []struct {
name string
deploymentName string
namespace string
image string
wantErr bool
}{
{
name: "create deployment",
deploymentName: "deployment",
namespace: "default",
image: "nginx",
wantErr: false,
},
{
name: "do not allow creating existing deployment",
deploymentName: "existing",
namespace: "default",
image: "nginx",
wantErr: true,
},
}

ctx := context.Background()
for _, tt := range tests {
deploymentName := tt.deploymentName
namespace := tt.namespace
image := tt.image
wantErr := tt.wantErr

t.Run(tt.name, func(t *testing.T) {
existingDeployment := appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "existing",
Namespace: "default",
},
}
staticClient := k8s_fake.NewSimpleClientset(
&existingDeployment,
)
kubeClient := &kube_fake.FakeKubeClient{
TestKubernetesInterface: staticClient,
}

err := CreateDeployment(ctx, kubeClient, deploymentName, namespace, image)
if wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
})
}
}

0 comments on commit 1a2da41

Please sign in to comment.