From 7e27178dc3aec36595be03608dd08ad6e91d5ae9 Mon Sep 17 00:00:00 2001 From: Tomasz Zaremba Date: Thu, 5 Oct 2023 09:05:08 +0200 Subject: [PATCH] chore: unit tests code coverage improvements --- src/cli/template_test.go | 82 ++++++++++++++++++++++ src/services/k8s/service_account.go | 28 ++++++-- src/services/k8s/service_account_test.go | 89 ++++++++++++++++++++++++ src/utils/utils_test.go | 16 +++++ 4 files changed, 208 insertions(+), 7 deletions(-) create mode 100644 src/cli/template_test.go create mode 100644 src/services/k8s/service_account_test.go create mode 100644 src/utils/utils_test.go diff --git a/src/cli/template_test.go b/src/cli/template_test.go new file mode 100644 index 0000000..39e9e0a --- /dev/null +++ b/src/cli/template_test.go @@ -0,0 +1,82 @@ +package cli + +import ( + "bytes" + "fmt" + "github.com/nearform/initium-cli/src/services/project" + "github.com/urfave/cli/v2" + "gotest.tools/v3/assert" + "os" + "path" + "testing" +) + +const root = "../../" + +const expectedGoAppDockerTemplate = `FROM golang:1.20.4 as build + +WORKDIR /go/src/app +COPY . . + +RUN go mod download +RUN go vet -v ./... +RUN go test -v ./... + +RUN CGO_ENABLED=0 go build -o /go/bin/app + +FROM gcr.io/distroless/static-debian11 + +COPY --from=build /go/bin/app / +ENTRYPOINT ["/app"] +` + +const expectedNodeAppDockerTemplate = `FROM node:20.2.0 AS build-env + +WORKDIR /app + +COPY package*.json tsconfig*.json ./ + +RUN npm i + +COPY . /app + +RUN npm run build --if-present +RUN npm test + +FROM gcr.io/distroless/nodejs20-debian11 +COPY --from=build-env /app /app +WORKDIR /app +USER nonroot +CMD ["index.js"] +` + +var projects = map[project.ProjectType]map[string]string{ + project.NodeProject: {"directory": "example", "expectedTemplate": expectedNodeAppDockerTemplate}, + project.GoProject: {"directory": ".", "expectedTemplate": expectedGoAppDockerTemplate}, +} + +func TestShouldRenderDockerTemplate(t *testing.T) { + for projectType, props := range projects { + var buffer bytes.Buffer + + cCtx := cli.Context{} + instance := icli{ + project: project.Project{ + Name: string(projectType), + Directory: path.Join(root, props["directory"]), + Resources: os.DirFS(root), + }, + Writer: &buffer, + } + + err := instance.template(&cCtx) + if err != nil { + t.Fatalf(fmt.Sprintf("Error: %v", err)) + } + + expectedTemplate := props["expectedTemplate"] + template := string(buffer.Bytes()) + + assert.Assert(t, template == expectedTemplate, "Expected %s, got %s", expectedTemplate, template) + } +} diff --git a/src/services/k8s/service_account.go b/src/services/k8s/service_account.go index 80eea75..fea7870 100644 --- a/src/services/k8s/service_account.go +++ b/src/services/k8s/service_account.go @@ -7,17 +7,31 @@ import ( ) func GetServiceAccount(resources fs.FS) error { - k8sTemplatesPath := path.Join("assets", "k8s", "serviceAccount") + serviceAccountManifest, err := getServiceAccountManifest(resources) + if err != nil { + return err + } + + fmt.Printf("%s", serviceAccountManifest) + + return nil +} +func getServiceAccountManifest(resources fs.FS) (string, error) { + manifest := "" for _, v := range []string{"cluster-role", "role-binding", "service-account", "token"} { - filecontent, err := fs.ReadFile(resources, path.Join(k8sTemplatesPath, v+".yaml")) + fileContent, err := getFileContent(v, resources) if err != nil { - return err + return "", err } - - fmt.Println("---") - fmt.Printf("%s\n", filecontent) + manifest = manifest + fmt.Sprintf("---\n%s\n", fileContent) } - return nil + return manifest, nil +} + +func getFileContent(filename string, resources fs.FS) ([]byte, error) { + k8sTemplatesPath := path.Join("assets", "k8s", "serviceAccount") + + return fs.ReadFile(resources, path.Join(k8sTemplatesPath, filename+".yaml")) } diff --git a/src/services/k8s/service_account_test.go b/src/services/k8s/service_account_test.go new file mode 100644 index 0000000..d8a9869 --- /dev/null +++ b/src/services/k8s/service_account_test.go @@ -0,0 +1,89 @@ +package k8s + +import ( + "fmt" + "gotest.tools/v3/assert" + "os" + "testing" +) + +const rootDirectory = "../../../" + +func TestShouldReturnSingleFileContent(t *testing.T) { + expectedFileContent := `apiVersion: v1 +kind: ServiceAccount +metadata: + name: initium-cli-sa` + + bytes, err := getFileContent("service-account", os.DirFS(rootDirectory)) + if err != nil { + t.Fatalf(fmt.Sprintf("Error: %s", err)) + } + fileContent := string(bytes) + + assert.Assert(t, expectedFileContent == fileContent, "Expected %s, got %s", expectedFileContent, fileContent) +} + +func TestShouldReturnServiceAccountManifest(t *testing.T) { + expectedFileContent := `--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: initium-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 +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: initium-cli +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: initium-cli +subjects: + - kind: ServiceAccount + name: initium-cli-sa + namespace: default +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: initium-cli-sa +--- +apiVersion: v1 +kind: Secret +type: kubernetes.io/service-account-token +metadata: + name: initium-cli-token + annotations: + kubernetes.io/service-account.name: "initium-cli-sa" +` + + serviceAccountManifest, err := getServiceAccountManifest(os.DirFS(rootDirectory)) + if err != nil { + t.Fatalf(fmt.Sprintf("Error: %s", err)) + } + + assert.Assert(t, expectedFileContent == serviceAccountManifest, "Expected %s, got %s", expectedFileContent, serviceAccountManifest) +} diff --git a/src/utils/utils_test.go b/src/utils/utils_test.go new file mode 100644 index 0000000..dcb77ee --- /dev/null +++ b/src/utils/utils_test.go @@ -0,0 +1,16 @@ +package utils + +import ( + "gotest.tools/v3/assert" + "testing" +) + +func TestShouldProperlyEncodeLabel(t *testing.T) { + givenLabels := []string{"feature/test", "feature/test$&", "feature/very-long-name-0123456789-0123456789-0123456789-0123456789"} + expectedLabels := []string{"initium-feature-test", "initium-feature-test--", "initium-feature-very-long-name-0123456789-0123456789-0123456-z"} + + for idx, label := range givenLabels { + encodedLabel := EncodeRFC1123(label) + assert.Check(t, encodedLabel == expectedLabels[idx], "Expected %s, got %s", expectedLabels[idx], encodedLabel) + } +}