From 315926bb016f6659bfff9f0c4a929b29cc9971c2 Mon Sep 17 00:00:00 2001 From: Luca Lanziani Date: Mon, 7 Aug 2023 10:19:09 +0200 Subject: [PATCH] feat: improve workflow (#59) --- README.md | 14 ++-- assets/github/onbranch.tmpl | 17 ++-- assets/github/onmain.tmpl | 3 - assets/k8s/serviceAccount/cluster-role.yaml | 26 +++++++ assets/k8s/serviceAccount/role-binding.yaml | 12 +++ .../k8s/serviceAccount/service-account.yaml | 4 + assets/k8s/serviceAccount/token.yaml | 7 ++ assets/knative/service.yaml.tmpl | 1 + src/cli/build.go | 6 +- src/cli/cli.go | 40 +++++----- src/cli/delete.go | 5 +- src/cli/deploy.go | 5 +- src/cli/flags.go | 25 ++++-- src/cli/init.go | 20 ++++- src/cli/init_test.go | 17 +--- src/cli/onbranch.go | 1 - src/cli/template.go | 5 +- src/services/docker/docker-image.go | 3 +- src/services/docker/docker.go | 46 +++++++---- src/services/git/repo.go | 77 +++++++++++++++++++ src/services/k8s/knative.go | 35 ++++++--- src/services/k8s/service_account.go | 23 ++++++ src/utils/defaults/defaults.go | 2 +- 23 files changed, 298 insertions(+), 96 deletions(-) create mode 100644 assets/k8s/serviceAccount/cluster-role.yaml create mode 100644 assets/k8s/serviceAccount/role-binding.yaml create mode 100644 assets/k8s/serviceAccount/service-account.yaml create mode 100644 assets/k8s/serviceAccount/token.yaml create mode 100644 src/services/git/repo.go create mode 100644 src/services/k8s/service_account.go diff --git a/README.md b/README.md index da1409e..ed0c4bf 100644 --- a/README.md +++ b/README.md @@ -42,10 +42,14 @@ You will be able to run the executable from These are the environment variables that you have to set in order to use the onmain, onbranch commands from your local environment ``` -export KKA_REGISTRY_PASSWORD="" -export KKA_REGISTRY_USER="lucalprojects" -export KKA_REPO_NAME="ghcr.io/llprojects/registry" +export KKA_REGISTRY_PASSWORD="" +export KKA_REGISTRY_USER="" +``` + +and + +``` export KKA_CLUSTER_ENDPOINT=$(kubectl config view -o jsonpath='{.clusters[?(@.name == "kind-k8s-kurated-addons")].cluster.server}') -export KKA_CLUSTER_TOKEN=$(kubectl get secrets ci-bot-token -o jsonpath="{.data.token}" | base64 -d) -export KKA_CLUSTER_CA_CERT=$(kubectl get secrets ci-bot-token -o jsonpath="{.data.ca\.crt}" | base64 -d) +export KKA_CLUSTER_TOKEN=$(kubectl get secrets kka-cli-token -o jsonpath="{.data.token}" | base64 -d) +export KKA_CLUSTER_CA_CERT=$(kubectl get secrets kka-cli-token -o jsonpath="{.data.ca\.crt}" | base64 -d) ``` diff --git a/assets/github/onbranch.tmpl b/assets/github/onbranch.tmpl index e0fd87c..dbc78c4 100644 --- a/assets/github/onbranch.tmpl +++ b/assets/github/onbranch.tmpl @@ -7,19 +7,19 @@ on: jobs: on_pr: + concurrency: {{ `${{ github.head_ref }}` }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 + with: + ref: {{ `${{ github.head_ref }}` }} - name: delete application - if: github.event.type == "closed" + if: github.event.action == 'closed' uses: docker://ghcr.io/nearform/k8s-kurated-addons-cli:latest with: args: onbranch --clean env: - KKA_APP_NAME: {{ .AppName }} - KKA_PROJECT_DIRECTORY: {{ .ProjectDirectory }} - KKA_REPO_NAME: {{ .Repository }} KKA_REGISTRY_USER: {{ `${{ github.actor }}` }} KKA_REGISTRY_PASSWORD: {{ `${{ secrets.GITHUB_TOKEN }}` }} KKA_CLUSTER_ENDPOINT: {{ `${{ secrets.CLUSTER_ENDPOINT }}` }} @@ -27,16 +27,13 @@ jobs: KKA_CLUSTER_CA_CERT: {{ `${{ secrets.CLUSTER_CA_CERT }}` }} - name: build and deploy application - if: github.event.type != "closed" + if: github.event.action != 'closed' uses: docker://ghcr.io/nearform/k8s-kurated-addons-cli:latest with: args: onbranch env: - KKA_APP_NAME: {{ .AppName }} - KKA_PROJECT_DIRECTORY: {{ .ProjectDirectory }} - KKA_REPO_NAME: {{ .Repository }} KKA_REGISTRY_USER: {{ `${{ github.actor }}` }} KKA_REGISTRY_PASSWORD: {{ `${{ secrets.GITHUB_TOKEN }}` }} KKA_CLUSTER_ENDPOINT: {{ `${{ secrets.CLUSTER_ENDPOINT }}` }} KKA_CLUSTER_TOKEN: {{ `${{ secrets.CLUSTER_TOKEN }}` }} - KKA_CLUSTER_CA_CERT: {{ `${{ secrets.CLUSTER_CA_CERT }}` }} \ No newline at end of file + KKA_CLUSTER_CA_CERT: {{ `${{ secrets.CLUSTER_CA_CERT }}` }} diff --git a/assets/github/onmain.tmpl b/assets/github/onmain.tmpl index 286b753..441f12d 100644 --- a/assets/github/onmain.tmpl +++ b/assets/github/onmain.tmpl @@ -17,9 +17,6 @@ jobs: with: args: onmain env: - KKA_APP_NAME: {{ .AppName }} - KKA_PROJECT_DIRECTORY: {{ .ProjectDirectory }} - KKA_REPO_NAME: {{ .Repository }} KKA_REGISTRY_USER: {{ `${{ github.actor }}` }} KKA_REGISTRY_PASSWORD: {{ `${{ secrets.GITHUB_TOKEN }}` }} KKA_CLUSTER_ENDPOINT: {{ `${{ secrets.CLUSTER_ENDPOINT }}` }} diff --git a/assets/k8s/serviceAccount/cluster-role.yaml b/assets/k8s/serviceAccount/cluster-role.yaml new file mode 100644 index 0000000..7169b81 --- /dev/null +++ b/assets/k8s/serviceAccount/cluster-role.yaml @@ -0,0 +1,26 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kka-cli +rules: + - apiGroups: + - '' + - serving.knative.dev + - apps + - networking.k8s.io + resources: + - namespaces + - deployments + - replicasets + - ingresses + - services + - secrets + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch \ No newline at end of file diff --git a/assets/k8s/serviceAccount/role-binding.yaml b/assets/k8s/serviceAccount/role-binding.yaml new file mode 100644 index 0000000..9d3fe2e --- /dev/null +++ b/assets/k8s/serviceAccount/role-binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: kka-cli +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kka-cli +subjects: + - kind: ServiceAccount + name: kka-cli-bot + namespace: default \ No newline at end of file diff --git a/assets/k8s/serviceAccount/service-account.yaml b/assets/k8s/serviceAccount/service-account.yaml new file mode 100644 index 0000000..e4a5a83 --- /dev/null +++ b/assets/k8s/serviceAccount/service-account.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kka-cli-bot \ No newline at end of file diff --git a/assets/k8s/serviceAccount/token.yaml b/assets/k8s/serviceAccount/token.yaml new file mode 100644 index 0000000..c35b784 --- /dev/null +++ b/assets/k8s/serviceAccount/token.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Secret +type: kubernetes.io/service-account-token +metadata: + name: kka-cli-token + annotations: + kubernetes.io/service-account.name: "kka-cli-bot" \ No newline at end of file diff --git a/assets/knative/service.yaml.tmpl b/assets/knative/service.yaml.tmpl index a1702b7..8c3abab 100644 --- a/assets/knative/service.yaml.tmpl +++ b/assets/knative/service.yaml.tmpl @@ -8,3 +8,4 @@ spec: spec: containers: - image: {{ .RemoteTag }} + imagePullPolicy: Always diff --git a/src/cli/build.go b/src/cli/build.go index 7e7ffc3..22076f5 100644 --- a/src/cli/build.go +++ b/src/cli/build.go @@ -8,7 +8,11 @@ import ( ) func (c *CLI) Build(cCtx *cli.Context) error { - project := c.getProject(cCtx) + project, err := c.getProject(cCtx) + if err != nil { + return err + } + logger.PrintInfo("Dockerfile Location: " + path.Join(project.Directory, c.DockerService.DockerFileName)) return c.DockerService.Build() } diff --git a/src/cli/cli.go b/src/cli/cli.go index 6bbe18f..f310235 100644 --- a/src/cli/cli.go +++ b/src/cli/cli.go @@ -4,7 +4,6 @@ import ( "embed" "io" "os" - "path" "path/filepath" "sort" @@ -13,6 +12,7 @@ import ( "github.com/charmbracelet/log" "github.com/nearform/k8s-kurated-addons-cli/src/services/docker" + "github.com/nearform/k8s-kurated-addons-cli/src/utils/defaults" "github.com/nearform/k8s-kurated-addons-cli/src/utils/logger" "github.com/urfave/cli/v2" ) @@ -38,7 +38,7 @@ func (c CLI) baseBeforeFunc(ctx *cli.Context) error { return nil } -func (c *CLI) init(cCtx *cli.Context) { +func (c *CLI) init(cCtx *cli.Context) error { appName := cCtx.String(appNameFlag) version := cCtx.String(appVersionFlag) projectDirectory := cCtx.String(projectDirectoryFlag) @@ -59,9 +59,11 @@ func (c *CLI) init(cCtx *cli.Context) { dockerImageName := appName invalidBases := []string{".", string(os.PathSeparator)} - base := filepath.Base(absProjectDirectory) - if !slices.Contains(invalidBases, base) && base != dockerImageName { - dockerImageName = appName + "/" + base + if projectDirectory != defaults.ProjectDirectory { + base := filepath.Base(absProjectDirectory) + if !slices.Contains(invalidBases, base) && base != dockerImageName { + dockerImageName = appName + "/" + base + } } dockerImage := docker.DockerImage{ @@ -71,7 +73,12 @@ func (c *CLI) init(cCtx *cli.Context) { Tag: version, } - dockerService, err := docker.New(project, dockerImage, cCtx.String(dockerFileNameFlag)) + dockerFileName := cCtx.String(dockerFileNameFlag) + if dockerFileName == "" { + dockerFileName = defaults.GeneratedDockerFile + } + + dockerService, err := docker.New(project, dockerImage, dockerFileName) if err != nil { logger.PrintError("Error creating docker service", err) } @@ -79,13 +86,17 @@ func (c *CLI) init(cCtx *cli.Context) { c.DockerService = dockerService c.dockerImage = dockerImage c.project = project + return nil } -func (c *CLI) getProject(cCtx *cli.Context) *project.Project { +func (c *CLI) getProject(cCtx *cli.Context) (*project.Project, error) { if (c.project == project.Project{}) { - c.init(cCtx) + err := c.init(cCtx) + if err != nil { + return nil, err + } } - return &c.project + return &c.project, nil } func (c CLI) Run(args []string) error { @@ -108,17 +119,6 @@ func (c CLI) Run(args []string) error { return err } - projectDirectory := ctx.String(projectDirectoryFlag) - absProjectDirectory, err := filepath.Abs(projectDirectory) - - if err != nil { - return err - } - - if ctx.String(appNameFlag) == "" { - ctx.Set(appNameFlag, path.Base(absProjectDirectory)) - } - if err := c.checkRequiredFlags(ctx, []string{}); err != nil { return err } diff --git a/src/cli/delete.go b/src/cli/delete.go index 398eeb2..40003f2 100644 --- a/src/cli/delete.go +++ b/src/cli/delete.go @@ -14,7 +14,10 @@ func (c *CLI) Delete(cCtx *cli.Context) error { if err != nil { return err } - project := c.getProject(cCtx) + project, err := c.getProject(cCtx) + if err != nil { + return err + } return knative.Clean(cCtx.String(namespaceFlag), config, project) } diff --git a/src/cli/deploy.go b/src/cli/deploy.go index beb09db..d6ec782 100644 --- a/src/cli/deploy.go +++ b/src/cli/deploy.go @@ -15,7 +15,10 @@ func (c *CLI) Deploy(cCtx *cli.Context) error { if err != nil { return err } - project := c.getProject(cCtx) + project, err := c.getProject(cCtx) + if err != nil { + return err + } return knative.Apply(cCtx.String(namespaceFlag), config, project, c.dockerImage) } diff --git a/src/cli/flags.go b/src/cli/flags.go index 6e7d2c1..0d63a38 100644 --- a/src/cli/flags.go +++ b/src/cli/flags.go @@ -7,6 +7,7 @@ import ( "os" "strings" + "github.com/nearform/k8s-kurated-addons-cli/src/services/git" "github.com/nearform/k8s-kurated-addons-cli/src/utils/defaults" "github.com/urfave/cli/v2" "gopkg.in/yaml.v2" @@ -46,7 +47,14 @@ const ( var requiredFlags []string var flags map[FlagsType]([]cli.Flag) +// This function is executed when the module is loaded func init() { + registry := "" + org, err := git.GetGithubOrg() + if err == nil { + registry = fmt.Sprintf("ghcr.io/%s", org) + } + defaultFlags := map[FlagsType]([]cli.Flag){ Build: []cli.Flag{ &cli.StringFlag{ @@ -111,9 +119,10 @@ func init() { }, App: []cli.Flag{ &cli.StringFlag{ - Name: appNameFlag, - Usage: "The name of the app", - EnvVars: []string{"KKA_APP_NAME"}, + Name: appNameFlag, + Usage: "The name of the app", + Required: true, + EnvVars: []string{"KKA_APP_NAME"}, }, &cli.StringFlag{ Name: appVersionFlag, @@ -128,15 +137,15 @@ func init() { EnvVars: []string{"KKA_PROJECT_DIRECTORY"}, }, &cli.StringFlag{ - Name: repoNameFlag, - Usage: "The base address of the container repository", - Value: defaults.RepoName, - EnvVars: []string{"KKA_REPO_NAME"}, + Name: repoNameFlag, + Usage: "The base address of the container repository", + Value: registry, + Required: registry == "", + EnvVars: []string{"KKA_REPO_NAME"}, }, &cli.StringFlag{ Name: dockerFileNameFlag, Usage: "The name of the Dockerfile", - Value: defaults.DockerfileName, EnvVars: []string{"KKA_DOCKERFILE_NAME"}, }, &cli.StringFlag{ diff --git a/src/cli/init.go b/src/cli/init.go index 2dc2e3a..141f89b 100644 --- a/src/cli/init.go +++ b/src/cli/init.go @@ -8,6 +8,7 @@ import ( "github.com/charmbracelet/log" "k8s.io/utils/strings/slices" + "github.com/nearform/k8s-kurated-addons-cli/src/services/k8s" "github.com/nearform/k8s-kurated-addons-cli/src/services/project" "github.com/urfave/cli/v2" ) @@ -15,12 +16,14 @@ import ( func (c CLI) InitGithubCMD(cCtx *cli.Context) error { logger := log.New(os.Stderr) logger.SetLevel(log.DebugLevel) + registry := cCtx.String(repoNameFlag) + options := project.InitOptions{ PipelineType: cCtx.Command.Name, DestinationFolder: cCtx.String(destinationFolderFlag), DefaultBranch: cCtx.String(defaultBranchFlag), AppName: cCtx.String(appNameFlag), - Repository: cCtx.String(repoNameFlag), + Repository: registry, ProjectDirectory: cCtx.String(projectDirectoryFlag), } data, err := project.ProjectInit(options, c.Resources) @@ -39,6 +42,7 @@ func (c CLI) InitGithubCMD(cCtx *cli.Context) error { func (c CLI) InitConfigCMD(ctx *cli.Context) error { excludedFlags := []string{ "help", + appVersionFlag, namespaceFlag, configFileFlag, projectDirectoryFlag, @@ -61,19 +65,23 @@ func (c CLI) InitConfigCMD(ctx *cli.Context) error { value := ctx.String(stringFlag.Name) if value == "" { - stringFlag.GetValue() + value = stringFlag.Value } if value == "" { fmt.Fprintf(c.Writer, "%s: null\n", stringFlag.Name) } else { - fmt.Fprintf(c.Writer, "%s: %s\n", stringFlag.Name, ctx.String(stringFlag.Name)) + fmt.Fprintf(c.Writer, "%s: %s\n", stringFlag.Name, value) } } return nil } +func (c CLI) InitServiceAccountCMD(ctx *cli.Context) error { + return k8s.GetServiceAccount(c.Resources) +} + func (c CLI) InitCMD() *cli.Command { return &cli.Command{ Name: "init", @@ -92,6 +100,12 @@ func (c CLI) InitCMD() *cli.Command { Action: c.InitConfigCMD, Before: c.baseBeforeFunc, }, + { + Name: "service-account", + Usage: "output all resources needed to create a service account", + Action: c.InitServiceAccountCMD, + Before: c.baseBeforeFunc, + }, }, } } diff --git a/src/cli/init_test.go b/src/cli/init_test.go index 4dc5f19..79baa78 100644 --- a/src/cli/init_test.go +++ b/src/cli/init_test.go @@ -8,23 +8,18 @@ import ( "testing" "github.com/charmbracelet/log" - "github.com/nearform/k8s-kurated-addons-cli/src/utils/defaults" ) func compareConfig(t *testing.T, appName string, writer io.Writer) { configTemplate := fmt.Sprintf(`app-name: %s -app-version: %s cluster-endpoint: null -default-branch: null -dockerfile-name: %s +default-branch: main +dockerfile-name: null registry-user: null -repo-name: %s +repo-name: ghcr.io/nearform runtime-version: null `, appName, - defaults.AppVersion, - defaults.DockerfileName, - defaults.RepoName, ) result := fmt.Sprint(writer.(*bytes.Buffer)) @@ -35,7 +30,6 @@ runtime-version: null } func TestInitConfig(t *testing.T) { - cli := CLI{ Writer: new(bytes.Buffer), Logger: log.NewWithOptions(os.Stderr, log.Options{ @@ -45,11 +39,8 @@ func TestInitConfig(t *testing.T) { }), } - if err := cli.Run([]string{"kka", "init", "config"}); err != nil { - t.Error(err) - } + os.Setenv("KKA_REPO_NAME", "ghcr.io/nearform") - compareConfig(t, "cli", cli.Writer) // Config file is read correctly // Generate temporary file and add app-name parameter diff --git a/src/cli/onbranch.go b/src/cli/onbranch.go index ddbb0d6..e7129f2 100644 --- a/src/cli/onbranch.go +++ b/src/cli/onbranch.go @@ -80,7 +80,6 @@ func (c CLI) OnBranchCMD() *cli.Command { } branchName := head.Name().Short() - c.Logger.Infof("Using branch %v as version and namespace", branchName) ctx.Set(appVersionFlag, utils.EncodeRFC1123(branchName)) ctx.Set(namespaceFlag, utils.EncodeRFC1123(branchName)) diff --git a/src/cli/template.go b/src/cli/template.go index 56c3927..0cd0bc6 100644 --- a/src/cli/template.go +++ b/src/cli/template.go @@ -7,7 +7,10 @@ import ( ) func (c *CLI) template(cCtx *cli.Context) error { - project := c.getProject(cCtx) + project, err := c.getProject(cCtx) + if err != nil { + return err + } content, err := project.Dockerfile() if err != nil { return fmt.Errorf("Getting docker file %v", err) diff --git a/src/services/docker/docker-image.go b/src/services/docker/docker-image.go index e0e5212..407e1a6 100644 --- a/src/services/docker/docker-image.go +++ b/src/services/docker/docker-image.go @@ -2,6 +2,7 @@ package docker import ( "fmt" + "strings" ) type DockerImage struct { @@ -12,7 +13,7 @@ type DockerImage struct { } func (dockerImage DockerImage) RemoteTag() string { - return fmt.Sprintf("%s/%s:%s", dockerImage.Registry, dockerImage.Name, dockerImage.Tag) + return fmt.Sprintf("%s/%s:%s", strings.ToLower(dockerImage.Registry), dockerImage.Name, dockerImage.Tag) } func (dockerImage DockerImage) LocalTag() string { diff --git a/src/services/docker/docker.go b/src/services/docker/docker.go index 9cc49b9..353d5f3 100644 --- a/src/services/docker/docker.go +++ b/src/services/docker/docker.go @@ -16,6 +16,7 @@ import ( "github.com/nearform/k8s-kurated-addons-cli/src/services/project" + "github.com/nearform/k8s-kurated-addons-cli/src/utils/defaults" "github.com/nearform/k8s-kurated-addons-cli/src/utils/logger" ) @@ -52,6 +53,29 @@ func getClient() (*client.Client, error) { return cli, nil } +func (ds DockerService) generateDockerfile(tarWriter *tar.Writer) error { + // Add another file to the build context from an array of bytes + fileBytes, err := ds.project.Dockerfile() + if err != nil { + return fmt.Errorf("Loading dockerfile %v", err) + } + hdr := &tar.Header{ + Name: defaults.GeneratedDockerFile, + Mode: 0600, + Size: int64(len(fileBytes)), + ModTime: time.Now(), + } + + if err := tarWriter.WriteHeader(hdr); err != nil { + return fmt.Errorf("Writing Dockerfile header %v", err) + } + if _, err := tarWriter.Write(fileBytes); err != nil { + return fmt.Errorf("Writing Dockerfile content %v", err) + } + + return nil +} + func (ds DockerService) buildContext() (*bytes.Reader, error) { // Get the context for the docker build existingBuildContext, err := archive.TarWithOptions(ds.dockerImage.Directory, &archive.TarOptions{}) @@ -81,23 +105,11 @@ func (ds DockerService) buildContext() (*bytes.Reader, error) { } } - // Add another file to the build context from an array of bytes - fileBytes, err := ds.project.Dockerfile() - if err != nil { - return nil, fmt.Errorf("Loading dockerfile %v", err) - } - hdr := &tar.Header{ - Name: "Dockerfile.kka", - Mode: 0600, - Size: int64(len(fileBytes)), - ModTime: time.Now(), - } - - if err := tarWriter.WriteHeader(hdr); err != nil { - return nil, fmt.Errorf("Writing Dockerfile header %v", err) - } - if _, err := tarWriter.Write(fileBytes); err != nil { - return nil, fmt.Errorf("Writing Dockerfile content %v", err) + // if dockerfile-name is not specified generate a dockerfile + if ds.DockerFileName == defaults.GeneratedDockerFile { + if err = ds.generateDockerfile(tarWriter); err != nil { + return nil, err + } } // Close the tar archive diff --git a/src/services/git/repo.go b/src/services/git/repo.go new file mode 100644 index 0000000..74a9677 --- /dev/null +++ b/src/services/git/repo.go @@ -0,0 +1,77 @@ +package git + +import ( + "fmt" + "os" + "strings" + + git "github.com/go-git/go-git/v5" +) + +func initRepo() (*git.Repository, error) { + wd, err := os.Getwd() + + if err != nil { + return nil, err + } + + r, err := git.PlainOpen(wd) // path to the repository + if err != nil { + return nil, err + } + + return r, nil +} + +func GetHash() (string, error) { + repo, err := initRepo() + + if err != nil { + return "", fmt.Errorf("error getting git repo %v", err) + } + + headRef, err := repo.Head() + if err != nil { + return "", fmt.Errorf("cannot get HEAD reference: %v", err) + } + + return headRef.Hash().String(), nil +} + +func GetGithubOrg() (string, error) { + repo, err := initRepo() + + if err != nil { + return "", fmt.Errorf("error getting git repo %v", err) + } + + c, err := repo.Config() + if err != nil { + return "", fmt.Errorf("error getting the repo config: %v", err) + } + + for _, remote := range c.Remotes { + for _, url := range remote.URLs { + // HTTPS (https://github.com/organization/repo.git) + if strings.HasPrefix(url, "https://github.com/") { + splitURL := strings.Split(url, "/") + if len(splitURL) > 3 { + return splitURL[3], nil + } + } + // SSH (git@github.com:organization/repo.git) + if strings.HasPrefix(url, "git@github.com:") { + splitURL := strings.Split(url, ":") + if len(splitURL) > 1 { + splitPath := strings.Split(splitURL[1], "/") + if len(splitPath) > 1 { + return splitPath[0], nil + } + } + } + } + + } + + return "", fmt.Errorf("cannot find any remote with github.com") +} diff --git a/src/services/k8s/knative.go b/src/services/k8s/knative.go index 54db873..4409dc3 100644 --- a/src/services/k8s/knative.go +++ b/src/services/k8s/knative.go @@ -76,8 +76,8 @@ func Apply(namespace string, config *rest.Config, project *project.Project, dock logger.PrintInfo("Deploying Knative service to " + config.Host) ctx, cancel := context.WithTimeout(context.Background(), time.Minute*5) defer cancel() - fmt.Println(dockerImage.RemoteTag()) - service, err := loadManifest(project, dockerImage) + + serviceManifest, err := loadManifest(project, dockerImage) if err != nil { return err } @@ -88,8 +88,8 @@ func Apply(namespace string, config *rest.Config, project *project.Project, dock return fmt.Errorf("Error creating the knative client %v", err) } - service.ObjectMeta.Namespace = namespace - service.ObjectMeta.Name = project.Name + serviceManifest.ObjectMeta.Namespace = namespace + serviceManifest.ObjectMeta.Name = project.Name client, err := kubernetes.NewForConfig(config) if err != nil { @@ -98,29 +98,44 @@ func Apply(namespace string, config *rest.Config, project *project.Project, dock _, err = client.CoreV1().Namespaces().Create(ctx, &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ - Name: service.ObjectMeta.Namespace, + Name: serviceManifest.ObjectMeta.Namespace, }, }, metav1.CreateOptions{}) if err != nil && !apimachineryErrors.IsAlreadyExists(err) { - return fmt.Errorf("cannot create namespace %s, failed with %v", service.ObjectMeta.Namespace, err) + return fmt.Errorf("cannot create namespace %s, failed with %v", serviceManifest.ObjectMeta.Namespace, err) } - getService, err := servingClient.Services(service.ObjectMeta.Namespace).Get(ctx, service.ObjectMeta.Name, metav1.GetOptions{}) + service, err := servingClient.Services(serviceManifest.ObjectMeta.Namespace).Get(ctx, serviceManifest.ObjectMeta.Name, metav1.GetOptions{}) var deployedService *servingv1.Service if err != nil { - deployedService, err = servingClient.Services(service.ObjectMeta.Namespace).Create(ctx, service, metav1.CreateOptions{}) + deployedService, err = servingClient.Services(serviceManifest.ObjectMeta.Namespace).Create(ctx, serviceManifest, metav1.CreateOptions{}) if err != nil { return fmt.Errorf("Creating Knative service %v", err) } } else { - deployedService, err = servingClient.Services(service.ObjectMeta.Namespace).Update(ctx, getService, metav1.UpdateOptions{}) + service.Spec = serviceManifest.Spec + deployedService, err = servingClient.Services(serviceManifest.ObjectMeta.Namespace).Update(ctx, service, metav1.UpdateOptions{}) if err != nil { return fmt.Errorf("Updating Knative service %v", err) } } - fmt.Printf("Knative service %q deployed successfully in namespace %s.\n", deployedService.GetObjectMeta().GetName(), service.ObjectMeta.Namespace) + fmt.Printf("Knative service %q deployed successfully in namespace %s.\n", deployedService.GetObjectMeta().GetName(), serviceManifest.ObjectMeta.Namespace) + + for { + service, err = servingClient.Services(serviceManifest.ObjectMeta.Namespace).Get(ctx, serviceManifest.ObjectMeta.Name, metav1.GetOptions{}) + if err != nil { + return err + } + if service.Status.URL != nil { + fmt.Printf("You can reach it via %s\n", service.Status.URL) + break + } + + time.Sleep(time.Millisecond * 500) + } + return nil } diff --git a/src/services/k8s/service_account.go b/src/services/k8s/service_account.go new file mode 100644 index 0000000..216075a --- /dev/null +++ b/src/services/k8s/service_account.go @@ -0,0 +1,23 @@ +package k8s + +import ( + "embed" + "fmt" + "path" +) + +func GetServiceAccount(resources embed.FS) error { + k8sTemplatesPath := path.Join("assets", "k8s", "serviceAccount") + + for _, v := range []string{"cluster-role", "role-binding", "service-account", "token"} { + filecontent, err := resources.ReadFile(path.Join(k8sTemplatesPath, v+".yaml")) + if err != nil { + return err + } + + fmt.Println("---") + fmt.Printf("%s\n", filecontent) + } + + return nil +} diff --git a/src/utils/defaults/defaults.go b/src/utils/defaults/defaults.go index 8e6c14f..494adbd 100644 --- a/src/utils/defaults/defaults.go +++ b/src/utils/defaults/defaults.go @@ -3,11 +3,11 @@ package defaults const ( ProjectDirectory string = "." RepoName string = "ghcr.io/nearform" - DockerfileName string = "Dockerfile.kka" GithubActionFolder string = ".github/workflows" GithubDefaultBranch string = "main" ConfigFile string = ".kka" AppVersion string = "latest" + GeneratedDockerFile string = "Dockerfile.kka" ) // renovate: datasource=docker depName=node