From 1f30a0367b82ef5174ab5de45c2deb10f17308f1 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Fri, 13 Aug 2021 00:09:39 -0600 Subject: [PATCH 01/55] add bootstrap settings to group yaml projects list --- config/samples/gitlab_v1alpha1_group.yaml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/config/samples/gitlab_v1alpha1_group.yaml b/config/samples/gitlab_v1alpha1_group.yaml index ff643e9..b395a66 100644 --- a/config/samples/gitlab_v1alpha1_group.yaml +++ b/config/samples/gitlab_v1alpha1_group.yaml @@ -22,6 +22,8 @@ spec: - key: "MANIFEST_IMAGE" value: "joshtest2" ciConfigurationPath: "joshtest-path32" + bootstrapWithSourceCodeRepo: + language: "react" - name: group-sample2-project-josh-app-backend projectName: "JoshApp Backend" fullPath: "platform-one/Tron/joshapp/joshapp-be-2" @@ -29,6 +31,16 @@ spec: - key: "MANIFEST_IMAGE" value: "joshtest-be" ciConfigurationPath: "joshtest-path-be" - - - + bootstrapWithSourceCodeRepo: + language: "java" + - name: group-sample2-project-josh-app-manifest + projectName: "JoshApp Manifest" + fullPath: "platform-one/Tron/joshapp/joshapp-manifest" + bootstrapWithManifestRepo: + services: + - name: "frontend" + containerRegistry: "pathToContainerRegistry" + port: 8080 + - name: "backend" + containerRegistry: "pathToContainerRegistry" + port: 9991 \ No newline at end of file -- GitLab From cf4d6a2cbf0bb138a16e7ceab1c2d53c29f1a421 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Fri, 13 Aug 2021 02:51:17 -0600 Subject: [PATCH 02/55] add types for project bootstrap --- apis/gitlab/v1alpha1/common_types.go | 44 ++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100755 apis/gitlab/v1alpha1/common_types.go diff --git a/apis/gitlab/v1alpha1/common_types.go b/apis/gitlab/v1alpha1/common_types.go new file mode 100755 index 0000000..a47950e --- /dev/null +++ b/apis/gitlab/v1alpha1/common_types.go @@ -0,0 +1,44 @@ +/* +Copyright 2021. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +// import ( +// metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +// ) + +// BootstrapWithSourceCodeRepo string key to an existing pre-built code stack +type BootstrapWithSourceCodeRepo struct { + + // Language is a string key to an existing pre-built code stack + // +kubebuilder:validation:Required + Language string `json:"language"` +} + +// BootstrapWithManifestRepo string key to an existing pre-built code stack +type BootstrapWithManifestRepo struct { + + // Language is a string key to an existing pre-built code stack + // +kubebuilder:validation:Required + Services []services `json:"services"` +} + +// services (private) manifest representation of a deployable container +type services struct { + Name string `json:"name"` + ContainerRegistry string `json:"containerRegistry"` + Port int `json:"integer"` +} \ No newline at end of file -- GitLab From 6bf65d6db7af97588e5b15405713d296227e334c Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Mon, 16 Aug 2021 19:42:35 -0600 Subject: [PATCH 03/55] readme for gitlab integration test --- integration-tests/gitlab/api/README.md | 10 ++++++++++ .../gitlab/api/gitlab_api_groups_test.go | 11 +++++++++++ 2 files changed, 21 insertions(+) create mode 100644 integration-tests/gitlab/api/README.md diff --git a/integration-tests/gitlab/api/README.md b/integration-tests/gitlab/api/README.md new file mode 100644 index 0000000..2c605f9 --- /dev/null +++ b/integration-tests/gitlab/api/README.md @@ -0,0 +1,10 @@ +## Gitlab Integration Tests + +### Setup +- gitlab root level group creation + - it may be necessary to create the root leve integration test group by hand using the web ui admin interface! + - there is a gitlab instance setting that prevents api from creating root level groups + - https://gitlab.bigbang.dev/admin/groups/new + - path := "integration-root-group" + - name := "integration root group" + - description := "Integration Test Root Level Group" \ No newline at end of file diff --git a/integration-tests/gitlab/api/gitlab_api_groups_test.go b/integration-tests/gitlab/api/gitlab_api_groups_test.go index eed1073..bfa3af4 100644 --- a/integration-tests/gitlab/api/gitlab_api_groups_test.go +++ b/integration-tests/gitlab/api/gitlab_api_groups_test.go @@ -2,6 +2,12 @@ package api +// it may be necessary to create the root leve integration test group by hand using admin interface! +// https://gitlab.bigbang.dev/admin/groups/new +// path := "integration-root-group" +// name := "integration root group" +// description := "Integration Test Root Level Group" + import ( "errors" "fmt" @@ -43,10 +49,15 @@ func TestClient_GetGroups(t *testing.T) { t.Errorf("ClientImpl.GetGroups() error = %v", err) return } + for i, item := range got { + t.Logf("GetGroups - index %d name %s", i, item.Path) + } t.Logf("GetGroups - number of groups %d", len(got)) }) } +// Create root level group if does not already exist +// get group id of root level group func TestClient_AddRootGroup(t *testing.T) { t.Run("test", func(t *testing.T) { c, err := getClientGroups() -- GitLab From 05aa1980dd625fb5ee59ff4c3d06a00cb1cfdca2 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Mon, 16 Aug 2021 19:55:20 -0600 Subject: [PATCH 04/55] add integration test yaml files --- integration-tests/{gitlab/api => }/README.md | 14 ++++-- .../kubernetes/group_config_test1.yaml | 46 +++++++++++++++++++ .../kubernetes/project_config_test1.yaml | 20 ++++++++ 3 files changed, 77 insertions(+), 3 deletions(-) rename integration-tests/{gitlab/api => }/README.md (65%) create mode 100644 integration-tests/kubernetes/group_config_test1.yaml create mode 100644 integration-tests/kubernetes/project_config_test1.yaml diff --git a/integration-tests/gitlab/api/README.md b/integration-tests/README.md similarity index 65% rename from integration-tests/gitlab/api/README.md rename to integration-tests/README.md index 2c605f9..99ffaeb 100644 --- a/integration-tests/gitlab/api/README.md +++ b/integration-tests/README.md @@ -1,10 +1,18 @@ -## Gitlab Integration Tests +## Valkyrie Integration Testing -### Setup + +### Gitlab Integration Testing +#### Setup - gitlab root level group creation - it may be necessary to create the root leve integration test group by hand using the web ui admin interface! - there is a gitlab instance setting that prevents api from creating root level groups - https://gitlab.bigbang.dev/admin/groups/new - path := "integration-root-group" - name := "integration root group" - - description := "Integration Test Root Level Group" \ No newline at end of file + - description := "Integration Test Root Level Group" + +#### Components +- Groups +- Users +- Projects +- Merge Requests \ No newline at end of file diff --git a/integration-tests/kubernetes/group_config_test1.yaml b/integration-tests/kubernetes/group_config_test1.yaml new file mode 100644 index 0000000..b395a66 --- /dev/null +++ b/integration-tests/kubernetes/group_config_test1.yaml @@ -0,0 +1,46 @@ +apiVersion: gitlab.valkyrie.dso.mil/v1alpha1 +kind: Group +metadata: + name: group-sample2 + namespace: default +spec: + name: "JoshApp Group" + fullPath: "platform-one/Tron/joshapp" + gitlabCredentialsName: gitlab-credentials-sample + ciVariables: + - key: "KUSTOMIZE_PRODUCTION_PATH" + value: "il4/overlays/production" + - key: "KUSTOMIZE_STAGING_PATH" + value: "il4/overlays/staging" + - key: "MANIFEST_REPO_URL" + value: "code.il2.dso.mil/tron/products/tempest/tempest-manifests.git" + projects: + - name: group-sample2-project-josh-app-ui + projectName: "JoshApp UI 24" + fullPath: "platform-one/Tron/joshapp/joshapp-ui-2" + ciVariables: + - key: "MANIFEST_IMAGE" + value: "joshtest2" + ciConfigurationPath: "joshtest-path32" + bootstrapWithSourceCodeRepo: + language: "react" + - name: group-sample2-project-josh-app-backend + projectName: "JoshApp Backend" + fullPath: "platform-one/Tron/joshapp/joshapp-be-2" + ciVariables: + - key: "MANIFEST_IMAGE" + value: "joshtest-be" + ciConfigurationPath: "joshtest-path-be" + bootstrapWithSourceCodeRepo: + language: "java" + - name: group-sample2-project-josh-app-manifest + projectName: "JoshApp Manifest" + fullPath: "platform-one/Tron/joshapp/joshapp-manifest" + bootstrapWithManifestRepo: + services: + - name: "frontend" + containerRegistry: "pathToContainerRegistry" + port: 8080 + - name: "backend" + containerRegistry: "pathToContainerRegistry" + port: 9991 \ No newline at end of file diff --git a/integration-tests/kubernetes/project_config_test1.yaml b/integration-tests/kubernetes/project_config_test1.yaml new file mode 100644 index 0000000..779a3c1 --- /dev/null +++ b/integration-tests/kubernetes/project_config_test1.yaml @@ -0,0 +1,20 @@ +apiVersion: gitlab.valkyrie.dso.mil/v1alpha1 +kind: Project +metadata: + name: project-sample-3 +spec: + groupId: 15 + name: "tempest-ui3" + fullPath: "platform-one/Tron/tempest3/tempest-ui3" + gitlabCredentialsName: gitlab-credentials-sample + ciVariables: + - key: "MANIFEST_IMAGE" + value: "test3" + - key: "NEW_VAR" + value: "test_var" + ciConfigurationPath: "test-path3" + twistlockConfiguration: + repository: "platform-one/Tron/tempest3/tempest-ui3" + registryHostname: "registry.il2.dsop.io" + registryCredentialId: "test_basic" + credentialName: twistlockcredential-sample -- GitLab From 584e51a51b9711939d799bfb102232e8f35c1f45 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Tue, 17 Aug 2021 09:17:27 -0600 Subject: [PATCH 05/55] formatting --- README.md | 3 ++ apis/gitlab/v1alpha1/common_types.go | 6 ++-- apis/gitlab/v1alpha1/zz_generated.deepcopy.go | 35 +++++++++++++++++++ 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6796609..d6358ec 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,9 @@ gitlab gitlab-registry ["istio-system/main"] ["registry.bigbang.dev - example - `export RLOG_CONF_FILE=$(pwd)/rlog.conf` ### Run Golang lint fmt vet +- install linter on local machine + - insure ~/go/bin is on the local machine path + - `go get -u golang.org/x/lint/golint` - use make - `make fmt vet lint` - run linter diff --git a/apis/gitlab/v1alpha1/common_types.go b/apis/gitlab/v1alpha1/common_types.go index a47950e..04ca12f 100755 --- a/apis/gitlab/v1alpha1/common_types.go +++ b/apis/gitlab/v1alpha1/common_types.go @@ -38,7 +38,7 @@ type BootstrapWithManifestRepo struct { // services (private) manifest representation of a deployable container type services struct { - Name string `json:"name"` + Name string `json:"name"` ContainerRegistry string `json:"containerRegistry"` - Port int `json:"integer"` -} \ No newline at end of file + Port int `json:"integer"` +} diff --git a/apis/gitlab/v1alpha1/zz_generated.deepcopy.go b/apis/gitlab/v1alpha1/zz_generated.deepcopy.go index 3f215b5..9359bdc 100644 --- a/apis/gitlab/v1alpha1/zz_generated.deepcopy.go +++ b/apis/gitlab/v1alpha1/zz_generated.deepcopy.go @@ -25,6 +25,41 @@ import ( twistlockv1alpha1 "valkyrie.dso.mil/valkyrie-api/apis/twistlock/v1alpha1" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BootstrapWithManifestRepo) DeepCopyInto(out *BootstrapWithManifestRepo) { + *out = *in + if in.Services != nil { + in, out := &in.Services, &out.Services + *out = make([]services, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapWithManifestRepo. +func (in *BootstrapWithManifestRepo) DeepCopy() *BootstrapWithManifestRepo { + if in == nil { + return nil + } + out := new(BootstrapWithManifestRepo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BootstrapWithSourceCodeRepo) DeepCopyInto(out *BootstrapWithSourceCodeRepo) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BootstrapWithSourceCodeRepo. +func (in *BootstrapWithSourceCodeRepo) DeepCopy() *BootstrapWithSourceCodeRepo { + if in == nil { + return nil + } + out := new(BootstrapWithSourceCodeRepo) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CICDVariable) DeepCopyInto(out *CICDVariable) { *out = *in -- GitLab From d001008ecaf253f9bfbe7afe47c31d179ea7fe1c Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Tue, 17 Aug 2021 11:20:06 -0600 Subject: [PATCH 06/55] add properties for bootstrap --- apis/gitlab/v1alpha1/common_types.go | 2 +- apis/gitlab/v1alpha1/group_types.go | 8 +++++ apis/gitlab/v1alpha1/project_types.go | 8 +++++ apis/gitlab/v1alpha1/zz_generated.deepcopy.go | 4 +++ .../bases/gitlab.valkyrie.dso.mil_groups.yaml | 35 +++++++++++++++++++ .../gitlab.valkyrie.dso.mil_projects.yaml | 35 +++++++++++++++++++ .../kubernetes/group_config_test1.yaml | 6 ++-- .../kubernetes/project_config_test1.yaml | 12 +++---- 8 files changed, 100 insertions(+), 10 deletions(-) diff --git a/apis/gitlab/v1alpha1/common_types.go b/apis/gitlab/v1alpha1/common_types.go index 04ca12f..efbbb60 100755 --- a/apis/gitlab/v1alpha1/common_types.go +++ b/apis/gitlab/v1alpha1/common_types.go @@ -40,5 +40,5 @@ type BootstrapWithManifestRepo struct { type services struct { Name string `json:"name"` ContainerRegistry string `json:"containerRegistry"` - Port int `json:"integer"` + Port int `json:"port"` } diff --git a/apis/gitlab/v1alpha1/group_types.go b/apis/gitlab/v1alpha1/group_types.go index 9043d47..aee03ea 100755 --- a/apis/gitlab/v1alpha1/group_types.go +++ b/apis/gitlab/v1alpha1/group_types.go @@ -70,6 +70,14 @@ type ProjectTemplate struct { // +optional // +kubebuilder:validation:Required CiConfigurationPath string `json:"ciConfigurationPath"` + + //BootstrapWithManifestRepo + // +optional + BootstrapWithManifestRepo BootstrapWithManifestRepo `json:"bootstrapWithManifestRepo"` + + //BootstrapWithSourceCodeRepo + // +optional + BootstrapWithSourceCodeRepo BootstrapWithSourceCodeRepo `json:"bootstrapWithSourceCodeRepo"` } // GroupStatus defines the observed state of Group diff --git a/apis/gitlab/v1alpha1/project_types.go b/apis/gitlab/v1alpha1/project_types.go index cd8e6f3..89968c5 100755 --- a/apis/gitlab/v1alpha1/project_types.go +++ b/apis/gitlab/v1alpha1/project_types.go @@ -64,6 +64,14 @@ type ProjectSpec struct { // +optional // +kubebuilder:validation:Required TwistlockConfiguration *v1alpha1.TwistlockPipelineConfigurationSpec `json:"twistlockConfiguration"` + + //BootstrapWithManifestRepo + // +optional + BootstrapWithManifestRepo BootstrapWithManifestRepo `json:"bootstrapWithManifestRepo"` + + //BootstrapWithSourceCodeRepo + // +optional + BootstrapWithSourceCodeRepo BootstrapWithSourceCodeRepo `json:"bootstrapWithSourceCodeRepo"` } // ProjectStatus defines the observed state of Project diff --git a/apis/gitlab/v1alpha1/zz_generated.deepcopy.go b/apis/gitlab/v1alpha1/zz_generated.deepcopy.go index 9359bdc..f8534b9 100644 --- a/apis/gitlab/v1alpha1/zz_generated.deepcopy.go +++ b/apis/gitlab/v1alpha1/zz_generated.deepcopy.go @@ -546,6 +546,8 @@ func (in *ProjectSpec) DeepCopyInto(out *ProjectSpec) { *out = new(twistlockv1alpha1.TwistlockPipelineConfigurationSpec) **out = **in } + in.BootstrapWithManifestRepo.DeepCopyInto(&out.BootstrapWithManifestRepo) + out.BootstrapWithSourceCodeRepo = in.BootstrapWithSourceCodeRepo } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProjectSpec. @@ -586,6 +588,8 @@ func (in *ProjectTemplate) DeepCopyInto(out *ProjectTemplate) { *out = make([]CICDVariable, len(*in)) copy(*out, *in) } + in.BootstrapWithManifestRepo.DeepCopyInto(&out.BootstrapWithManifestRepo) + out.BootstrapWithSourceCodeRepo = in.BootstrapWithSourceCodeRepo } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProjectTemplate. diff --git a/config/crd/bases/gitlab.valkyrie.dso.mil_groups.yaml b/config/crd/bases/gitlab.valkyrie.dso.mil_groups.yaml index aab7886..4305ea3 100644 --- a/config/crd/bases/gitlab.valkyrie.dso.mil_groups.yaml +++ b/config/crd/bases/gitlab.valkyrie.dso.mil_groups.yaml @@ -73,6 +73,41 @@ spec: description: ProjectTemplate defines the template for creating new Project properties: + bootstrapWithManifestRepo: + description: BootstrapWithManifestRepo + properties: + services: + description: Language is a string key to an existing pre-built + code stack + items: + description: services (private) manifest representation + of a deployable container + properties: + containerRegistry: + type: string + name: + type: string + port: + type: integer + required: + - containerRegistry + - name + - port + type: object + type: array + required: + - services + type: object + bootstrapWithSourceCodeRepo: + description: BootstrapWithSourceCodeRepo + properties: + language: + description: Language is a string key to an existing pre-built + code stack + type: string + required: + - language + type: object ciConfigurationPath: description: CiConfigurationPath is the Gitlab path to the CI configuration file in the CI/CD Settings of the project diff --git a/config/crd/bases/gitlab.valkyrie.dso.mil_projects.yaml b/config/crd/bases/gitlab.valkyrie.dso.mil_projects.yaml index bc35143..e5b85f2 100644 --- a/config/crd/bases/gitlab.valkyrie.dso.mil_projects.yaml +++ b/config/crd/bases/gitlab.valkyrie.dso.mil_projects.yaml @@ -36,6 +36,41 @@ spec: spec: description: ProjectSpec defines the desired state of Project properties: + bootstrapWithManifestRepo: + description: BootstrapWithManifestRepo + properties: + services: + description: Language is a string key to an existing pre-built + code stack + items: + description: services (private) manifest representation of a + deployable container + properties: + containerRegistry: + type: string + name: + type: string + port: + type: integer + required: + - containerRegistry + - name + - port + type: object + type: array + required: + - services + type: object + bootstrapWithSourceCodeRepo: + description: BootstrapWithSourceCodeRepo + properties: + language: + description: Language is a string key to an existing pre-built + code stack + type: string + required: + - language + type: object ciConfigurationPath: description: CiConfigurationPath is the Gitlab path to the CI configuration file in the CI/CD Settings of the project diff --git a/integration-tests/kubernetes/group_config_test1.yaml b/integration-tests/kubernetes/group_config_test1.yaml index b395a66..e84b1b2 100644 --- a/integration-tests/kubernetes/group_config_test1.yaml +++ b/integration-tests/kubernetes/group_config_test1.yaml @@ -1,11 +1,11 @@ apiVersion: gitlab.valkyrie.dso.mil/v1alpha1 kind: Group metadata: - name: group-sample2 + name: group-test-1 namespace: default spec: - name: "JoshApp Group" - fullPath: "platform-one/Tron/joshapp" + name: "Test Group1" + fullPath: "platform-one/my-team/group-1" gitlabCredentialsName: gitlab-credentials-sample ciVariables: - key: "KUSTOMIZE_PRODUCTION_PATH" diff --git a/integration-tests/kubernetes/project_config_test1.yaml b/integration-tests/kubernetes/project_config_test1.yaml index 779a3c1..d23c828 100644 --- a/integration-tests/kubernetes/project_config_test1.yaml +++ b/integration-tests/kubernetes/project_config_test1.yaml @@ -1,7 +1,7 @@ apiVersion: gitlab.valkyrie.dso.mil/v1alpha1 kind: Project metadata: - name: project-sample-3 + name: project-test-1 spec: groupId: 15 name: "tempest-ui3" @@ -9,12 +9,12 @@ spec: gitlabCredentialsName: gitlab-credentials-sample ciVariables: - key: "MANIFEST_IMAGE" - value: "test3" + value: "manifest-image-1" - key: "NEW_VAR" - value: "test_var" - ciConfigurationPath: "test-path3" + value: "test-var-1" + ciConfigurationPath: "ci-config-path-string" twistlockConfiguration: - repository: "platform-one/Tron/tempest3/tempest-ui3" - registryHostname: "registry.il2.dsop.io" + repository: "platform-one/group1/group2/repository-test" + registryHostname: "registry.il2.dso.io" registryCredentialId: "test_basic" credentialName: twistlockcredential-sample -- GitLab From 75600e6ea41c6bb21178a2ffcd11433db11dc806 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Tue, 17 Aug 2021 14:33:47 -0600 Subject: [PATCH 07/55] test bootstrap types --- apis/gitlab/v1alpha1/group_types.go | 4 +-- apis/gitlab/v1alpha1/project_types.go | 4 +-- apis/gitlab/v1alpha1/zz_generated.deepcopy.go | 24 +++++++++++++++--- config/samples/gitlab_v1alpha1_project.yaml | 2 ++ .../kubernetes/group_config_test1.yaml | 1 + .../kubernetes/project_config_test1.yaml | 25 +++++++++++++------ 6 files changed, 45 insertions(+), 15 deletions(-) diff --git a/apis/gitlab/v1alpha1/group_types.go b/apis/gitlab/v1alpha1/group_types.go index aee03ea..19be8bc 100755 --- a/apis/gitlab/v1alpha1/group_types.go +++ b/apis/gitlab/v1alpha1/group_types.go @@ -73,11 +73,11 @@ type ProjectTemplate struct { //BootstrapWithManifestRepo // +optional - BootstrapWithManifestRepo BootstrapWithManifestRepo `json:"bootstrapWithManifestRepo"` + BootstrapWithManifestRepo *BootstrapWithManifestRepo `json:"bootstrapWithManifestRepo"` //BootstrapWithSourceCodeRepo // +optional - BootstrapWithSourceCodeRepo BootstrapWithSourceCodeRepo `json:"bootstrapWithSourceCodeRepo"` + BootstrapWithSourceCodeRepo *BootstrapWithSourceCodeRepo `json:"bootstrapWithSourceCodeRepo"` } // GroupStatus defines the observed state of Group diff --git a/apis/gitlab/v1alpha1/project_types.go b/apis/gitlab/v1alpha1/project_types.go index 89968c5..8774bd8 100755 --- a/apis/gitlab/v1alpha1/project_types.go +++ b/apis/gitlab/v1alpha1/project_types.go @@ -67,11 +67,11 @@ type ProjectSpec struct { //BootstrapWithManifestRepo // +optional - BootstrapWithManifestRepo BootstrapWithManifestRepo `json:"bootstrapWithManifestRepo"` + BootstrapWithManifestRepo *BootstrapWithManifestRepo `json:"bootstrapWithManifestRepo"` //BootstrapWithSourceCodeRepo // +optional - BootstrapWithSourceCodeRepo BootstrapWithSourceCodeRepo `json:"bootstrapWithSourceCodeRepo"` + BootstrapWithSourceCodeRepo *BootstrapWithSourceCodeRepo `json:"bootstrapWithSourceCodeRepo"` } // ProjectStatus defines the observed state of Project diff --git a/apis/gitlab/v1alpha1/zz_generated.deepcopy.go b/apis/gitlab/v1alpha1/zz_generated.deepcopy.go index f8534b9..e43ab4a 100644 --- a/apis/gitlab/v1alpha1/zz_generated.deepcopy.go +++ b/apis/gitlab/v1alpha1/zz_generated.deepcopy.go @@ -546,8 +546,16 @@ func (in *ProjectSpec) DeepCopyInto(out *ProjectSpec) { *out = new(twistlockv1alpha1.TwistlockPipelineConfigurationSpec) **out = **in } - in.BootstrapWithManifestRepo.DeepCopyInto(&out.BootstrapWithManifestRepo) - out.BootstrapWithSourceCodeRepo = in.BootstrapWithSourceCodeRepo + if in.BootstrapWithManifestRepo != nil { + in, out := &in.BootstrapWithManifestRepo, &out.BootstrapWithManifestRepo + *out = new(BootstrapWithManifestRepo) + (*in).DeepCopyInto(*out) + } + if in.BootstrapWithSourceCodeRepo != nil { + in, out := &in.BootstrapWithSourceCodeRepo, &out.BootstrapWithSourceCodeRepo + *out = new(BootstrapWithSourceCodeRepo) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProjectSpec. @@ -588,8 +596,16 @@ func (in *ProjectTemplate) DeepCopyInto(out *ProjectTemplate) { *out = make([]CICDVariable, len(*in)) copy(*out, *in) } - in.BootstrapWithManifestRepo.DeepCopyInto(&out.BootstrapWithManifestRepo) - out.BootstrapWithSourceCodeRepo = in.BootstrapWithSourceCodeRepo + if in.BootstrapWithManifestRepo != nil { + in, out := &in.BootstrapWithManifestRepo, &out.BootstrapWithManifestRepo + *out = new(BootstrapWithManifestRepo) + (*in).DeepCopyInto(*out) + } + if in.BootstrapWithSourceCodeRepo != nil { + in, out := &in.BootstrapWithSourceCodeRepo, &out.BootstrapWithSourceCodeRepo + *out = new(BootstrapWithSourceCodeRepo) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProjectTemplate. diff --git a/config/samples/gitlab_v1alpha1_project.yaml b/config/samples/gitlab_v1alpha1_project.yaml index 779a3c1..1c5239a 100644 --- a/config/samples/gitlab_v1alpha1_project.yaml +++ b/config/samples/gitlab_v1alpha1_project.yaml @@ -13,6 +13,8 @@ spec: - key: "NEW_VAR" value: "test_var" ciConfigurationPath: "test-path3" + bootstrapWithSourceCodeRepo: + language: "react" twistlockConfiguration: repository: "platform-one/Tron/tempest3/tempest-ui3" registryHostname: "registry.il2.dsop.io" diff --git a/integration-tests/kubernetes/group_config_test1.yaml b/integration-tests/kubernetes/group_config_test1.yaml index e84b1b2..94c776c 100644 --- a/integration-tests/kubernetes/group_config_test1.yaml +++ b/integration-tests/kubernetes/group_config_test1.yaml @@ -5,6 +5,7 @@ metadata: namespace: default spec: name: "Test Group1" + # parent group must already exist fullPath: "platform-one/my-team/group-1" gitlabCredentialsName: gitlab-credentials-sample ciVariables: diff --git a/integration-tests/kubernetes/project_config_test1.yaml b/integration-tests/kubernetes/project_config_test1.yaml index d23c828..61a67f3 100644 --- a/integration-tests/kubernetes/project_config_test1.yaml +++ b/integration-tests/kubernetes/project_config_test1.yaml @@ -3,9 +3,10 @@ kind: Project metadata: name: project-test-1 spec: + # must match full path parent group groupId: 15 - name: "tempest-ui3" - fullPath: "platform-one/Tron/tempest3/tempest-ui3" + name: "project-spec-name-1" + fullPath: "platform-one/my-team/group-1/project-1" gitlabCredentialsName: gitlab-credentials-sample ciVariables: - key: "MANIFEST_IMAGE" @@ -13,8 +14,18 @@ spec: - key: "NEW_VAR" value: "test-var-1" ciConfigurationPath: "ci-config-path-string" - twistlockConfiguration: - repository: "platform-one/group1/group2/repository-test" - registryHostname: "registry.il2.dso.io" - registryCredentialId: "test_basic" - credentialName: twistlockcredential-sample + bootstrapWithSourceCodeRepo: + language: "react" + bootstrapWithManifestRepo: + services: + - name: "frontend" + containerRegistry: "pathToContainerRegistry" + port: 8080 + - name: "backend" + containerRegistry: "pathToContainerRegistry" + port: 9991 + # twistlockConfiguration: + # repository: "platform-one/group1/group2/repository-test" + # registryHostname: "registry.il2.dso.io" + # registryCredentialId: "test_basic" + # credentialName: twistlockcredential-sample -- GitLab From 3c53748da08a47af99f83f5c2ec5ce4098494b4c Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Tue, 17 Aug 2021 17:19:40 -0600 Subject: [PATCH 08/55] add getrepositorytree method --- README.md | 7 ++ clients/gitlab/client.go | 18 +++++ clients/gitlab/client_test.go | 145 +++++++++++++++++++++++++++++++++- 3 files changed, 167 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d6358ec..e753724 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,13 @@ make test go tool cover -html=cover.out -o coverage.html open coverage.html ``` +- targeted testing + - example: test clients/gitlab +``` +go test -v ./clients/gitlab/... -coverprofile cover.out +go tool cover -html=./cover.out -o ./coverage.html +open coverage.html +``` ### Integration testing - integration tests may require setting environment variables - integration tests may require availability of service diff --git a/clients/gitlab/client.go b/clients/gitlab/client.go index 6450c8a..591a32e 100644 --- a/clients/gitlab/client.go +++ b/clients/gitlab/client.go @@ -947,6 +947,24 @@ func (r ClientImpl) DeleteProject(projectID int, waitInterval int, waitCount int return returnStatusCode, nil } + +// GetRepositoryTree - List Tree of Repository contents +func (r ClientImpl) GetRepositoryTree(projectID int) ([]*gogitlab.TreeNode, int, error) { + logPrefix := "GetRepositoryTree" + opts := gogitlab.ListTreeOptions{} + + treeNodes, res, err := r.client.Repositories.ListTree(projectID, &opts) + + if err != nil { + processError(logPrefix, err) + return nil, 0, err + } + + rlog.Infof("%s: treenode count: %d", logPrefix, len(treeNodes)) + processComplete(logPrefix, res.StatusCode) + return treeNodes, res.StatusCode, nil +} + func setStatusCode(done bool) int { if done { return http.StatusOK diff --git a/clients/gitlab/client_test.go b/clients/gitlab/client_test.go index 9cff64a..d6b33ab 100644 --- a/clients/gitlab/client_test.go +++ b/clients/gitlab/client_test.go @@ -1965,6 +1965,42 @@ func TestClientImpl_DeleteGroupVariable(t *testing.T) { httpmock.NewJsonResponderOrPanic(200, nil), ) + + counter := 0 + + // Mock Output + testValue := "testValue" + testVariableType := gogitlab.EnvVariableType + testProtected := true + testMasked := true + testEnvironmentScope := "*" + testGroupVariable := gogitlab.GroupVariable{ + Key: testKey, + Value: testValue, + VariableType: testVariableType, + Protected: testProtected, + Masked: testMasked, + EnvironmentScope: testEnvironmentScope, + } + testGroupVariableArray := []gogitlab.GroupVariable{ + testGroupVariable, + } + + + // setup a mock that will change response on every 4th call + // used to simulate waiting for a delete to complete + httpmock.RegisterResponder("GET", + `=~^https://test/api/v4/groups.*`, + func(req *http.Request) (*http.Response, error) { + counter = counter + 1 + if counter%4 == 0 { + return httpmock.NewJsonResponse(http.StatusNotFound, testGroupVariableArray) + } + return httpmock.NewJsonResponse(http.StatusAccepted, testGroupVariableArray) + }, + ) + + // test objects testAPIUrl := "https://test/api/v4/" testToken := "token" @@ -1978,6 +2014,8 @@ func TestClientImpl_DeleteGroupVariable(t *testing.T) { type args struct { groupID int key string + waitInterval int + waitCount int } tests := []struct { name string @@ -1996,8 +2034,26 @@ func TestClientImpl_DeleteGroupVariable(t *testing.T) { args: args{ groupID: testGroupID, key: testKey, + waitInterval: 1000, + waitCount: 10, }, - want: 200, + want: http.StatusOK, + wantErr: false, + }, + { + name: "Test Delete Group Variable Timeout", + fields: fields{ + client: testGitlabClient, + token: testToken, + apiURL: testAPIUrl, + }, + args: args{ + groupID: testGroupID, + key: testKey, + waitInterval: 1000, + waitCount: 1, + }, + want: http.StatusRequestTimeout, wantErr: false, }, } @@ -2008,7 +2064,7 @@ func TestClientImpl_DeleteGroupVariable(t *testing.T) { token: tt.fields.token, apiURL: tt.fields.apiURL, } - got, err := r.DeleteGroupVariable(tt.args.groupID, tt.args.key, 0, 0) + got, err := r.DeleteGroupVariable(tt.args.groupID, tt.args.key, tt.args.waitInterval, tt.args.waitCount) if (err != nil) != tt.wantErr { t.Errorf("DeleteGroupVariable() error = %v, wantErr %v", err, tt.wantErr) return @@ -2607,7 +2663,6 @@ func TestClientImpl_GetProjectVariables(t *testing.T) { } type args struct { projectID int - key string } tests := []struct { name string @@ -2653,3 +2708,87 @@ func TestClientImpl_GetProjectVariables(t *testing.T) { }) } } + +func TestClientImpl_GetRepositoryTree(t *testing.T) { + // setup a http client for use in mocking + testHTTPClient := &http.Client{} + httpmock.ActivateNonDefault(testHTTPClient) + defer httpmock.DeactivateAndReset() + + // Mock Output + testNodeTree := []*gogitlab.TreeNode{ + { + ID: "1", + Name: "Name", + Type: "Type", + Path: "Path", + Mode: "Mode", + }} + + // Inputs + testProjectID := 1 + + httpmock.RegisterResponder("GET", + fmt.Sprintf(`https://test/api/v4/projects/%d/repository/tree`, testProjectID), + httpmock.NewJsonResponderOrPanic(200, testNodeTree), + ) + + // test objects + testAPIUrl := "https://test/api/v4/" + testToken := "token" + // create a gitlab ClientImpl object, inject http client to allow for mocking using httpmock + testGitlabClient, _ := gogitlab.NewClient(testToken, gogitlab.WithBaseURL(testAPIUrl), gogitlab.WithHTTPClient(testHTTPClient)) + + + type fields struct { + client *gogitlab.Client + token string + apiURL string + } + type args struct { + projectID int + } + tests := []struct { + name string + fields fields + args args + want []*gogitlab.TreeNode + want1 int + wantErr bool + }{ + { + name: "Test GetRepositoryTree", + fields: fields{ + client: testGitlabClient, + token: testToken, + apiURL: testAPIUrl, + }, + args: args{ + projectID: testProjectID, + }, + want: testNodeTree, + want1: 200, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + r := ClientImpl{ + client: tt.fields.client, + token: tt.fields.token, + apiURL: tt.fields.apiURL, + } + got, got1, err := r.GetRepositoryTree(tt.args.projectID) + if (err != nil) != tt.wantErr { + t.Errorf("ClientImpl.GetRepositoryTree() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("ClientImpl.GetRepositoryTree() got = %v, want %v", got, tt.want) + } + if got1 != tt.want1 { + t.Errorf("ClientImpl.GetRepositoryTree() got1 = %v, want %v", got1, tt.want1) + } + }) + } +} -- GitLab From 2261e69a4578d15dd138221134731342ff4ad21d Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Tue, 17 Aug 2021 17:32:14 -0600 Subject: [PATCH 09/55] format --- clients/gitlab/client.go | 3 +-- clients/gitlab/client_test.go | 30 +++++++++++++----------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/clients/gitlab/client.go b/clients/gitlab/client.go index 591a32e..afa5e34 100644 --- a/clients/gitlab/client.go +++ b/clients/gitlab/client.go @@ -947,7 +947,6 @@ func (r ClientImpl) DeleteProject(projectID int, waitInterval int, waitCount int return returnStatusCode, nil } - // GetRepositoryTree - List Tree of Repository contents func (r ClientImpl) GetRepositoryTree(projectID int) ([]*gogitlab.TreeNode, int, error) { logPrefix := "GetRepositoryTree" @@ -959,7 +958,7 @@ func (r ClientImpl) GetRepositoryTree(projectID int) ([]*gogitlab.TreeNode, int, processError(logPrefix, err) return nil, 0, err } - + rlog.Infof("%s: treenode count: %d", logPrefix, len(treeNodes)) processComplete(logPrefix, res.StatusCode) return treeNodes, res.StatusCode, nil diff --git a/clients/gitlab/client_test.go b/clients/gitlab/client_test.go index d6b33ab..916908b 100644 --- a/clients/gitlab/client_test.go +++ b/clients/gitlab/client_test.go @@ -1965,7 +1965,6 @@ func TestClientImpl_DeleteGroupVariable(t *testing.T) { httpmock.NewJsonResponderOrPanic(200, nil), ) - counter := 0 // Mock Output @@ -1986,7 +1985,6 @@ func TestClientImpl_DeleteGroupVariable(t *testing.T) { testGroupVariable, } - // setup a mock that will change response on every 4th call // used to simulate waiting for a delete to complete httpmock.RegisterResponder("GET", @@ -2000,7 +1998,6 @@ func TestClientImpl_DeleteGroupVariable(t *testing.T) { }, ) - // test objects testAPIUrl := "https://test/api/v4/" testToken := "token" @@ -2012,8 +2009,8 @@ func TestClientImpl_DeleteGroupVariable(t *testing.T) { apiURL string } type args struct { - groupID int - key string + groupID int + key string waitInterval int waitCount int } @@ -2032,10 +2029,10 @@ func TestClientImpl_DeleteGroupVariable(t *testing.T) { apiURL: testAPIUrl, }, args: args{ - groupID: testGroupID, - key: testKey, - waitInterval: 1000, - waitCount: 10, + groupID: testGroupID, + key: testKey, + waitInterval: 1000, + waitCount: 10, }, want: http.StatusOK, wantErr: false, @@ -2048,10 +2045,10 @@ func TestClientImpl_DeleteGroupVariable(t *testing.T) { apiURL: testAPIUrl, }, args: args{ - groupID: testGroupID, - key: testKey, - waitInterval: 1000, - waitCount: 1, + groupID: testGroupID, + key: testKey, + waitInterval: 1000, + waitCount: 1, }, want: http.StatusRequestTimeout, wantErr: false, @@ -2714,16 +2711,16 @@ func TestClientImpl_GetRepositoryTree(t *testing.T) { testHTTPClient := &http.Client{} httpmock.ActivateNonDefault(testHTTPClient) defer httpmock.DeactivateAndReset() - + // Mock Output testNodeTree := []*gogitlab.TreeNode{ { - ID: "1", + ID: "1", Name: "Name", Type: "Type", Path: "Path", Mode: "Mode", - }} + }} // Inputs testProjectID := 1 @@ -2739,7 +2736,6 @@ func TestClientImpl_GetRepositoryTree(t *testing.T) { // create a gitlab ClientImpl object, inject http client to allow for mocking using httpmock testGitlabClient, _ := gogitlab.NewClient(testToken, gogitlab.WithBaseURL(testAPIUrl), gogitlab.WithHTTPClient(testHTTPClient)) - type fields struct { client *gogitlab.Client token string -- GitLab From cbe120fe39b022e86509b3552c21ad7a23da0b9f Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Tue, 17 Aug 2021 18:08:33 -0600 Subject: [PATCH 10/55] add test for delete --- clients/gitlab/client_test.go | 69 +++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 8 deletions(-) diff --git a/clients/gitlab/client_test.go b/clients/gitlab/client_test.go index 916908b..a52d142 100644 --- a/clients/gitlab/client_test.go +++ b/clients/gitlab/client_test.go @@ -2287,7 +2287,7 @@ func TestClientImpl_DeleteProjectVariable(t *testing.T) { httpmock.RegisterResponder("DELETE", fmt.Sprintf(`https://test/api/v4/projects/%d/variables/%s`, testProjectID, testKey), - httpmock.NewJsonResponderOrPanic(200, nil), + httpmock.NewJsonResponderOrPanic(http.StatusOK, nil), ) // test objects @@ -2296,14 +2296,49 @@ func TestClientImpl_DeleteProjectVariable(t *testing.T) { // create a gitlab ClientImpl object, inject http client to allow for mocking using httpmock testGitlabClient, _ := gogitlab.NewClient(testToken, gogitlab.WithBaseURL(testAPIUrl), gogitlab.WithHTTPClient(testHTTPClient)) + counter := 0 + + // Mock Output + testValue := "testValue" + testVariableType := gogitlab.EnvVariableType + testProtected := true + testMasked := true + testEnvironmentScope := "*" + testProjectVariable := gogitlab.ProjectVariable{ + Key: testKey, + Value: testValue, + VariableType: testVariableType, + Protected: testProtected, + Masked: testMasked, + EnvironmentScope: testEnvironmentScope, + } + testGroupVariableArray := []gogitlab.ProjectVariable{ + testProjectVariable, + } + + // setup a mock that will change response on every 4th call + // used to simulate waiting for a delete to complete + httpmock.RegisterResponder("GET", + `=~^https://test/api/v4/project.*`, + func(req *http.Request) (*http.Response, error) { + counter = counter + 1 + if counter%4 == 0 { + return httpmock.NewJsonResponse(http.StatusNotFound, testGroupVariableArray) + } + return httpmock.NewJsonResponse(http.StatusAccepted, testGroupVariableArray) + }, + ) + type fields struct { client *gogitlab.Client token string apiURL string } type args struct { - projectID int - key string + projectID int + key string + waitInterval int + waitCount int } tests := []struct { name string @@ -2313,17 +2348,35 @@ func TestClientImpl_DeleteProjectVariable(t *testing.T) { wantErr bool }{ { - name: "Test DeleteProjectVariable", + name: "Test Delete Project Variable", fields: fields{ client: testGitlabClient, token: testToken, apiURL: testAPIUrl, }, args: args{ - projectID: testProjectID, - key: testKey, + projectID: testProjectID, + key: testKey, + waitInterval: 1000, + waitCount: 10, }, - want: 200, + want: http.StatusOK, + wantErr: false, + }, + { + name: "Test Delete Project Variable Timeout", + fields: fields{ + client: testGitlabClient, + token: testToken, + apiURL: testAPIUrl, + }, + args: args{ + projectID: testProjectID, + key: testKey, + waitInterval: 1000, + waitCount: 1, + }, + want: http.StatusRequestTimeout, wantErr: false, }, } @@ -2334,7 +2387,7 @@ func TestClientImpl_DeleteProjectVariable(t *testing.T) { token: tt.fields.token, apiURL: tt.fields.apiURL, } - got, err := r.DeleteProjectVariable(tt.args.projectID, tt.args.key, 0, 0) + got, err := r.DeleteProjectVariable(tt.args.projectID, tt.args.key, tt.args.waitInterval, tt.args.waitCount) if (err != nil) != tt.wantErr { t.Errorf("DeleteProjectVariable() error = %v, wantErr %v", err, tt.wantErr) return -- GitLab From 0ca55b75c80d41a8748049ffb5416ab819cd1fb4 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Wed, 18 Aug 2021 16:03:36 -0600 Subject: [PATCH 11/55] add getRepositoryTree integration test --- clients/gitlab/client.go | 12 ++- controllers/gitlab/mocks_test.go | 8 ++ .../gitlab/api/gitlab_api_projects_test.go | 87 ++++++++++++++++++- 3 files changed, 105 insertions(+), 2 deletions(-) diff --git a/clients/gitlab/client.go b/clients/gitlab/client.go index afa5e34..dd4c33f 100644 --- a/clients/gitlab/client.go +++ b/clients/gitlab/client.go @@ -37,6 +37,7 @@ package gitlab import ( "net/http" + "strings" "time" "github.com/romana/rlog" @@ -84,6 +85,7 @@ type Client interface { GetMergeRequests(projectID int, sourceBranch string, targetBranch string) ([]*gogitlab.MergeRequest, error) CreateMergeRequest(projectID int, mrOptions *gogitlab.CreateMergeRequestOptions) (*gogitlab.MergeRequest, error) CloseMergeRequest(projectID int, mergeRequestID int) error + GetRepositoryTree(projectID int) ([]*gogitlab.TreeNode, int, error) } // ClientImpl - @@ -949,17 +951,25 @@ func (r ClientImpl) DeleteProject(projectID int, waitInterval int, waitCount int // GetRepositoryTree - List Tree of Repository contents func (r ClientImpl) GetRepositoryTree(projectID int) ([]*gogitlab.TreeNode, int, error) { + // if project not found with return error + // if tree not found - that is the project exists but the repository does NOT exists ( not initialized ) + // then response code is statusnocontent (408) and treenode is nil + // if tree DOES exist but thre are no files, then returns statusOK 200 and an list with lentgh 0 logPrefix := "GetRepositoryTree" opts := gogitlab.ListTreeOptions{} treeNodes, res, err := r.client.Repositories.ListTree(projectID, &opts) if err != nil { + errString := strings.ToUpper(err.Error()) + if strings.Contains(errString, "TREE NOT FOUND") { + return nil, http.StatusNoContent, nil + } processError(logPrefix, err) return nil, 0, err } - rlog.Infof("%s: treenode count: %d", logPrefix, len(treeNodes)) + rlog.Debugf("%s: treenode count: %d", logPrefix, len(treeNodes)) processComplete(logPrefix, res.StatusCode) return treeNodes, res.StatusCode, nil } diff --git a/controllers/gitlab/mocks_test.go b/controllers/gitlab/mocks_test.go index d0da8d4..550eb27 100755 --- a/controllers/gitlab/mocks_test.go +++ b/controllers/gitlab/mocks_test.go @@ -440,6 +440,7 @@ type MockGitlabClient struct { getProjectVariableFunction func(projectID int, key string) (*gitlab.ProjectVariable, int, error) deleteGroupFunction func(groupID int, waitInterval int, waitCount int) (int, error) deleteProjectFunction func(projectID int, waitInterval int, waitCount int) (int, error) + getRepositoryTree func(projectID int) ([]*gitlab.TreeNode, int, error) } func (m *MockGitlabClient) GetGroupVariable(groupID int, key string) (*gitlab.GroupVariable, int, error) { @@ -906,6 +907,13 @@ func (m *MockRepoClient) DeleteRemoteBranch(branchName string) (err error) { return nil } +func (m *MockGitlabClient) GetRepositoryTree(projectID int) ([]*gitlab.TreeNode, int, error) { + if m.getRepositoryTree != nil { + return m.getRepositoryTree(projectID) + } + return nil, http.StatusBadRequest, nil +} + type MockClientConfiguration struct { GitlabClient gitlabClient.Client SetupClientFunction func(client client.Client, credentialsName string) (gitlabClient.Client, error) diff --git a/integration-tests/gitlab/api/gitlab_api_projects_test.go b/integration-tests/gitlab/api/gitlab_api_projects_test.go index 9921d69..0b3f406 100644 --- a/integration-tests/gitlab/api/gitlab_api_projects_test.go +++ b/integration-tests/gitlab/api/gitlab_api_projects_test.go @@ -13,10 +13,12 @@ import ( gitlab "valkyrie.dso.mil/valkyrie-api/clients/gitlab" ) -const projectsTestItemCount = 65 +// the get page size is 50 so we want something > 50 so we make sure to test paging +const projectsTestItemCount = 55 const testProjectsPrefix = "IntTestProject" var integrationRootGroupIDProjects = 0 +var integrationRootProjectIDProjects = 0 // getClientProjects - func getClientProjects() (gitlab.ClientImpl, error) { @@ -104,6 +106,32 @@ func TestClient_AddRootGroup_Projects(t *testing.T) { } }) } +func TestClient_deleteProjectsIfExist(t *testing.T) { + t.Run("test", func(t *testing.T) { + c, err := getClientProjects() + if err != nil { + t.Errorf("ClientImpl.getClient() error = %v", err) + return + } + + search := testProjectsPrefix + projectList, err := c.GetProjects(&search) + if err != nil { + t.Errorf("ClientImpl.GetProjects() error = %v", err) + return + } + + for x := 0; x < len(projectList); x++ { + project := projectList[x] + statusCode, err := c.DeleteProject(project.ID, 100, 1200) + + if err == nil { + t.Logf("DeleteProject %s %d", project.Name, statusCode) + } + } + + }) +} // add groups under the integration test root level group func TestClient_AddProjects(t *testing.T) { @@ -139,6 +167,63 @@ func TestClient_AddProjects(t *testing.T) { }) } +func TestClient_AddProject_More_Test(t *testing.T) { + t.Run("test", func(t *testing.T) { + c, err := getClientProjects() + if err != nil { + t.Errorf("ClientImpl.getClientProjects() error = %v", err) + return + } + + path := testProjectsPrefix + "-repo-test" + name := testProjectsPrefix + "-repo test " + description := "Integration Test Repository" + configPath := "a/b/config.yml@group1/group2/project" + + projectOpts := gogitlab.CreateProjectOptions{ + Name: &name, + Path: &path, + Description: &description, + NamespaceID: &integrationRootGroupIDProjects, + CIConfigPath: &configPath, + } + got, statusCode, err := c.AddProject(projectOpts) + + if err != nil { + t.Errorf("ClientImpl.AddProject() error = %v %d", err, statusCode) + } else { + t.Logf("AddProject %s %s %s %s %d", got.Name, got.Path, got.PathWithNamespace, got.WebURL, statusCode) + // save test project id + integrationRootProjectIDProjects = got.ID + } + + }) +} + +// requies integrationRootProjectIDProjects created from TestClient_AddProject_More_Test +func TestClient_GetRepositoryTree(t *testing.T) { + t.Run("test", func(t *testing.T) { + c, err := getClientProjects() + if err != nil { + t.Errorf("ClientImpl.getClientRepository() error = %v", err) + return + } + projectID := integrationRootProjectIDProjects + got, responseCode, err := c.GetRepositoryTree(projectID) + if err != nil { + t.Errorf("ClientImpl.GetRepositoryTree() project ID %d responseCode %d error = %v", integrationRootProjectIDProjects, responseCode, err) + return + } + treeLen := -1 + + if got != nil { + treeLen = len(got) + + } + t.Logf("GetRepositoryTree - project ID %d resturn code: %d number of files %d", projectID, responseCode, treeLen) + }) +} + func TestClient_UpdateProject(t *testing.T) { t.Run("test", func(t *testing.T) { c, err := getClientProjects() -- GitLab From 065ff00296b867fb36f40bd2466c8bd79077f4ab Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Wed, 18 Aug 2021 16:07:03 -0600 Subject: [PATCH 12/55] mark with integration tag --- integration-tests/git/git_api_adhoc_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/integration-tests/git/git_api_adhoc_test.go b/integration-tests/git/git_api_adhoc_test.go index 1da65e1..38b2daa 100644 --- a/integration-tests/git/git_api_adhoc_test.go +++ b/integration-tests/git/git_api_adhoc_test.go @@ -1,3 +1,5 @@ +// +build integration + package git import ( -- GitLab From 56dc7c0a0f179571ebadbb1218c689d0e53b3344 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Thu, 19 Aug 2021 09:12:08 -0600 Subject: [PATCH 13/55] fix merge --- apis/gitlab/v1alpha1/zz_generated.deepcopy.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/apis/gitlab/v1alpha1/zz_generated.deepcopy.go b/apis/gitlab/v1alpha1/zz_generated.deepcopy.go index 03869de..910746d 100644 --- a/apis/gitlab/v1alpha1/zz_generated.deepcopy.go +++ b/apis/gitlab/v1alpha1/zz_generated.deepcopy.go @@ -542,11 +542,6 @@ func (in *ProjectSpec) DeepCopyInto(out *ProjectSpec) { *out = make([]CICDVariable, len(*in)) copy(*out, *in) } - if in.TwistlockConfiguration != nil { - in, out := &in.TwistlockConfiguration, &out.TwistlockConfiguration - *out = new(twistlockv1alpha1.TwistlockPipelineConfigurationSpec) - **out = **in - } if in.BootstrapWithManifestRepo != nil { in, out := &in.BootstrapWithManifestRepo, &out.BootstrapWithManifestRepo *out = new(BootstrapWithManifestRepo) @@ -555,6 +550,12 @@ func (in *ProjectSpec) DeepCopyInto(out *ProjectSpec) { if in.BootstrapWithSourceCodeRepo != nil { in, out := &in.BootstrapWithSourceCodeRepo, &out.BootstrapWithSourceCodeRepo *out = new(BootstrapWithSourceCodeRepo) + } + if in.TwistlockConfiguration != nil { + in, out := &in.TwistlockConfiguration, &out.TwistlockConfiguration + *out = new(twistlockv1alpha1.TwistlockPipelineConfigurationSpec) + **out = **in + } if in.FortifyConfiguration != nil { in, out := &in.FortifyConfiguration, &out.FortifyConfiguration *out = new(fortifyv1alpha1.FortifyPipelineConfigurationSpec) @@ -565,7 +566,7 @@ func (in *ProjectSpec) DeepCopyInto(out *ProjectSpec) { // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProjectSpec. func (in *ProjectSpec) DeepCopy() *ProjectSpec { if in == nil { - return nilgit a + return nil } out := new(ProjectSpec) in.DeepCopyInto(out) -- GitLab From 36fefb669fcaf00090c29004b246b29d5bfd88bc Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Thu, 19 Aug 2021 09:14:24 -0600 Subject: [PATCH 14/55] fix merge --- apis/gitlab/v1alpha1/project_types.go | 9 ++++----- apis/gitlab/v1alpha1/zz_generated.deepcopy.go | 3 +++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/apis/gitlab/v1alpha1/project_types.go b/apis/gitlab/v1alpha1/project_types.go index 906196d..d49ff6c 100755 --- a/apis/gitlab/v1alpha1/project_types.go +++ b/apis/gitlab/v1alpha1/project_types.go @@ -61,11 +61,6 @@ type ProjectSpec struct { // +kubebuilder:validation:Required CiConfigurationPath string `json:"ciConfigurationPath"` - //TwistlockConfiguration is the Twistlock setting used to create a registry setting in Twistlock - // +optional - // +kubebuilder:validation:Required - TwistlockConfiguration *v1alpha1.TwistlockPipelineConfigurationSpec `json:"twistlockConfiguration"` - //BootstrapWithManifestRepo // +optional BootstrapWithManifestRepo *BootstrapWithManifestRepo `json:"bootstrapWithManifestRepo"` @@ -73,6 +68,10 @@ type ProjectSpec struct { //BootstrapWithSourceCodeRepo // +optional BootstrapWithSourceCodeRepo *BootstrapWithSourceCodeRepo `json:"bootstrapWithSourceCodeRepo"` + + //TwistlockConfiguration is the Twistlock setting used to create a registry setting in Twistlock + // +optional + // +kubebuilder:validation:Required TwistlockConfiguration *twistlockv1.TwistlockPipelineConfigurationSpec `json:"twistlockConfiguration"` //FortifyConfiguration is used to create a new application project in Fortify diff --git a/apis/gitlab/v1alpha1/zz_generated.deepcopy.go b/apis/gitlab/v1alpha1/zz_generated.deepcopy.go index 910746d..1db7210 100644 --- a/apis/gitlab/v1alpha1/zz_generated.deepcopy.go +++ b/apis/gitlab/v1alpha1/zz_generated.deepcopy.go @@ -550,6 +550,7 @@ func (in *ProjectSpec) DeepCopyInto(out *ProjectSpec) { if in.BootstrapWithSourceCodeRepo != nil { in, out := &in.BootstrapWithSourceCodeRepo, &out.BootstrapWithSourceCodeRepo *out = new(BootstrapWithSourceCodeRepo) + **out = **in } if in.TwistlockConfiguration != nil { in, out := &in.TwistlockConfiguration, &out.TwistlockConfiguration @@ -609,6 +610,8 @@ func (in *ProjectTemplate) DeepCopyInto(out *ProjectTemplate) { if in.BootstrapWithSourceCodeRepo != nil { in, out := &in.BootstrapWithSourceCodeRepo, &out.BootstrapWithSourceCodeRepo *out = new(BootstrapWithSourceCodeRepo) + **out = **in + } if in.TwistlockConfiguration != nil { in, out := &in.TwistlockConfiguration, &out.TwistlockConfiguration *out = new(twistlockv1alpha1.TwistlockPipelineConfigurationSpec) -- GitLab From 19dfce71e60b9451d10c9aa1932f5cb1417631fa Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Mon, 23 Aug 2021 10:57:45 -0600 Subject: [PATCH 15/55] git add path --- clients/git/repo_client.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/clients/git/repo_client.go b/clients/git/repo_client.go index 78a3fdd..1dc3b69 100644 --- a/clients/git/repo_client.go +++ b/clients/git/repo_client.go @@ -16,6 +16,7 @@ type RepoClient interface { CheckoutOrCreateBranch(branchName string) (err error) GetFileSystem() *billy.Filesystem AddFile(filePath string) (err error) + AddPath(filePath string) (err error) Commit(message string) (err error) Push() (err error) DeleteRemoteBranch(branchName string) (err error) @@ -89,6 +90,16 @@ func (c *RepoClientImpl) AddFile(filePath string) (err error) { return } +//AddPath adds entire path +func (c *RepoClientImpl) AddPath(filePath string) (err error) { + w, err := c.repo.Worktree() + if err != nil { + return + } + err = w.AddGlob(filePath) + return +} + //Commit commits the changes with a message func (c *RepoClientImpl) Commit(message string) (err error) { w, err := c.repo.Worktree() -- GitLab From 63ef16a789190a49692c596d8215f7599704d26b Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Mon, 23 Aug 2021 13:50:14 -0600 Subject: [PATCH 16/55] git repo client addpath --- clients/git/repo_client_test.go | 36 +++++++++++++++++++++++++++++++- controllers/gitlab/mocks_test.go | 8 +++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/clients/git/repo_client_test.go b/clients/git/repo_client_test.go index 394212c..6d6d4a7 100644 --- a/clients/git/repo_client_test.go +++ b/clients/git/repo_client_test.go @@ -1,12 +1,13 @@ package git import ( + "testing" + "github.com/go-git/go-billy/v5/memfs" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/config" "github.com/go-git/go-git/v5/plumbing/transport/http" "github.com/go-git/go-git/v5/storage/memory" - "testing" ) func TestRepoClientImpl_CheckoutOrCreateBranch(t *testing.T) { @@ -62,6 +63,39 @@ func TestRepoClientImpl_AddFile(t *testing.T) { } } +func TestRepoClientImpl_AddPath(t *testing.T) { + fileSystem := memfs.New() + auth := &http.BasicAuth{ + Username: "username", + Password: "token", + } + memStorage := memory.NewStorage() + repo, err := git.Init(memStorage, fileSystem) + if err != nil { + panic(err) + } + client := RepoClientImpl{ + repo: repo, + fs: &fileSystem, + auth: auth, + } + + err = client.AddPath("test_not_found") + if err == nil { + t.Fatal("expect find not found error, but got no error") + } + + fileSystem.Create("new_file1") + fileSystem.MkdirAll("dir1/dir2/dir3", 0755) + fileSystem.Create("dir1/new_file2") + fileSystem.Create("dir1/new_file22") + fileSystem.Create("dir1/dir2/new_file3") + err = client.AddPath("dir1") + if err != nil { + t.Fatalf("expect no error but got %v", err) + } +} + func TestRepoClientImpl_Commit(t *testing.T) { fileSystem := memfs.New() auth := &http.BasicAuth{ diff --git a/controllers/gitlab/mocks_test.go b/controllers/gitlab/mocks_test.go index bcbc4bf..99949a1 100755 --- a/controllers/gitlab/mocks_test.go +++ b/controllers/gitlab/mocks_test.go @@ -862,6 +862,7 @@ func (m *MockGitlabClient) UpdateGroup(id int, options *gitlab.UpdateGroupOption type MockRepoClient struct { checkoutBranchFunc func(branchName string) error addFileFunc func(filePath string) error + addPathFunc func(filePath string) error commitFunc func(message string) error pushFunc func() error deleteRemoteBranchFunc func(branchName string) error @@ -886,6 +887,13 @@ func (m *MockRepoClient) AddFile(filePath string) (err error) { return nil } +func (m *MockRepoClient) AddPath(filePath string) (err error) { + if m.addPathFunc != nil { + return m.addPathFunc(filePath) + } + return nil +} + func (m *MockRepoClient) Commit(message string) (err error) { if m.commitFunc != nil { return m.commitFunc(message) -- GitLab From 0800b99784ec407136807064cfd62291e7a976bb Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Mon, 23 Aug 2021 21:10:08 -0600 Subject: [PATCH 17/55] update int tests to use main setup and teardown --- README.md | 2 + .../{git => gitclient}/git_api_adhoc_test.go | 33 ++----- integration-tests/gitclient/git_main_test.go | 71 ++++++++++++++ .../gitlab/api/gitlab_api_adhoc_test.go | 52 ++-------- .../gitlab/api/gitlab_api_groups_test.go | 53 ++-------- .../gitlab/api/gitlab_api_mr_test.go | 59 +++-------- .../gitlab/api/gitlab_api_projects_test.go | 71 ++------------ .../gitlab/api/gitlab_api_users_test.go | 48 ++------- .../gitlab/api/gitlab_main_test.go | 97 +++++++++++++++++++ 9 files changed, 221 insertions(+), 265 deletions(-) rename integration-tests/{git => gitclient}/git_api_adhoc_test.go (72%) create mode 100644 integration-tests/gitclient/git_main_test.go create mode 100644 integration-tests/gitlab/api/gitlab_main_test.go diff --git a/README.md b/README.md index 95b711b..0ac3d7a 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,8 @@ package integration - `go test -v -tags "integration" ./integration-tests/...` - clean test cache - `go clean -testcache` +- run specific tests as follows - note inclusion of main_test.go which has setup code + - `go test -v -tags "integration" ./integration-tests/gitlab/api/gitlab_api_mr_test.go ./integration-tests/gitlab/api/gitlab_main_test.go` ### Gitlab Groups Controller Setup 1) Create a secret that holds the credential for Gitlab API diff --git a/integration-tests/git/git_api_adhoc_test.go b/integration-tests/gitclient/git_api_adhoc_test.go similarity index 72% rename from integration-tests/git/git_api_adhoc_test.go rename to integration-tests/gitclient/git_api_adhoc_test.go index 38b2daa..96530bd 100644 --- a/integration-tests/git/git_api_adhoc_test.go +++ b/integration-tests/gitclient/git_api_adhoc_test.go @@ -1,38 +1,18 @@ // +build integration -package git +package gitclient import ( "bufio" - "errors" "fmt" - "os" "strings" "testing" - git2 "valkyrie.dso.mil/valkyrie-api/clients/git" + "valkyrie.dso.mil/valkyrie-api/clients/git" ) func TestGit(t *testing.T) { - username, ok := os.LookupEnv("GITLAB_INT_TEST_USERNAME") - if !ok { - fmt.Printf("%v", errors.New("env variable GITLAB_INT_TEST_USERNAME undefinded")) - return - } - - token, ok := os.LookupEnv("GITLAB_INT_TEST_TOKEN") - if !ok { - fmt.Printf("%v", errors.New("env variable GITLAB_INT_TEST_TOKEN undefinded")) - return - } - - repository, ok := os.LookupEnv("GITLAB_INT_TEST_REPOSITORY") - if !ok { - fmt.Printf("%v", errors.New("env variable GITLAB_INT_TEST_REPOSITORY undefinded")) - return - } - - client, err := git2.NewClient(username, token, repository) + client, err := git.NewClient(GitUsername, GitToken, GitRepoURL) if err != nil { fmt.Printf("%v", err) return @@ -57,6 +37,7 @@ func TestGit(t *testing.T) { fmt.Printf("%v", err) return } + tempFile, err := fs.Create("temp_file") if err != nil { fmt.Printf("%v", err) @@ -93,6 +74,10 @@ func TestGit(t *testing.T) { } tempFile, err = fs.Open(dnsFilePath) + if err != nil { + fmt.Printf("%v", err) + } + fmt.Println("======================") scanner2 := bufio.NewScanner(tempFile) for scanner2.Scan() { @@ -118,5 +103,5 @@ func TestGit(t *testing.T) { if err != nil { return } - return + } diff --git a/integration-tests/gitclient/git_main_test.go b/integration-tests/gitclient/git_main_test.go new file mode 100644 index 0000000..27d2a89 --- /dev/null +++ b/integration-tests/gitclient/git_main_test.go @@ -0,0 +1,71 @@ +// +build integration + +package gitclient + +// go test -v -tags "integration" ./integration-tests/git + +import ( + "errors" + "fmt" + "os" + "testing" +) + +var WorkingDir string = "" +var GitUsername string = "" +var GitToken string = "" +var GitRepoURL string = "" + +// Notes: +// teststring string `json:"-"` // - means dont override struct +// `json:"impact_level,omitempty dont output to json if empty +// TemplateConfigApplication - + +// TestMain - setup and teardown reusable code. wraps around other tests +func TestMain(m *testing.M) { + + // setup environment for testing + err := packageSetup() + if err != nil { + fmt.Printf("packageSetup error: %v\n", err) + os.Exit(1) + } + + // run tests + resultCode := m.Run() + + packageTeardown() + + os.Exit(resultCode) +} + +// packageSetup - setup environment for integration testing +func packageSetup() error { + WorkingDir, _ = os.Getwd() + var ok bool + GitUsername, ok = os.LookupEnv("GITLAB_INT_TEST_USERNAME") + if !ok { + err := errors.New("env variable GITLAB_INT_TEST_USERNAME undefined") + + return err + } + + GitToken, ok = os.LookupEnv("GITLAB_INT_TEST_TOKEN") + if !ok { + err := errors.New("env variable GITLAB_INT_TEST_TOKEN undefined") + + return err + } + + GitRepoURL, ok = os.LookupEnv("GITLAB_INT_TEST_REPOSITORY") + if !ok { + err := errors.New("env variable GITLAB_INT_TEST_REPOSITORY undefined") + + return err + } + return nil +} + +func packageTeardown() error { + return nil +} diff --git a/integration-tests/gitlab/api/gitlab_api_adhoc_test.go b/integration-tests/gitlab/api/gitlab_api_adhoc_test.go index 4009153..4e411c0 100644 --- a/integration-tests/gitlab/api/gitlab_api_adhoc_test.go +++ b/integration-tests/gitlab/api/gitlab_api_adhoc_test.go @@ -3,32 +3,12 @@ package api import ( - "errors" - "os" "testing" - gitlab "valkyrie.dso.mil/valkyrie-api/clients/gitlab" ) -// getClient_AdHoc - -func getClient_AdHoc() (gitlab.ClientImpl, error) { - gitlabAPIURL, ok := os.LookupEnv("GITLAB_API_URL") - if !ok { - return gitlab.ClientImpl{}, errors.New("env variable GITLAB_API_URL undefinded") - } - gitlabAPIToken, ok := os.LookupEnv("GITLAB_API_TOKEN") - if !ok { - return gitlab.ClientImpl{}, errors.New("env variable GITLAB_API_TOKEN undefinded") - } - var client, _ = gitlab.NewClient(gitlabAPIURL, gitlabAPIToken, nil) - return client, nil -} func TestClient_AdHoc_getUsers_All(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClient_AdHoc() - if err != nil { - t.Errorf("ClientImpl.GetUsers() error = %v", err) - return - } + c := GitlabClient got, err := c.GetUsers(nil) if err != nil { t.Errorf("ClientImpl.GetUsers() error = %v", err) @@ -42,11 +22,7 @@ func TestClient_AdHoc_getUsers_All(t *testing.T) { } func TestClient_AdHoc_getUsers_Search(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClient_AdHoc() - if err != nil { - t.Errorf("ClientImpl.GetUsers() error = %v", err) - return - } + c := GitlabClient search := "ghost" got, err := c.GetUsers(&search) if err != nil { @@ -61,11 +37,7 @@ func TestClient_AdHoc_getUsers_Search(t *testing.T) { } func TestClient_AdHoc_getUsers_None(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClient_AdHoc() - if err != nil { - t.Errorf("ClientImpl.GetUsers() error = %v", err) - return - } + c := GitlabClient search := "notfound" got, err := c.GetUsers(&search) if err != nil { @@ -81,11 +53,7 @@ func TestClient_AdHoc_getUsers_None(t *testing.T) { func TestClient_AdHoc_getGroups_All(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClient_AdHoc() - if err != nil { - t.Errorf("ClientImpl.getClient() error = %v", err) - return - } + c := GitlabClient got, err := c.GetGroups(nil) if err != nil { @@ -100,11 +68,7 @@ func TestClient_AdHoc_getGroups_All(t *testing.T) { } func TestClient_AdHoc_getGroups_Search(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClient_AdHoc() - if err != nil { - t.Errorf("ClientImpl.getClient() error = %v", err) - return - } + c := GitlabClient s := string("test") got, err := c.GetGroups(&s) if err != nil { @@ -120,11 +84,7 @@ func TestClient_AdHoc_getGroups_Search(t *testing.T) { func TestClient_AdHoc_getProjects_ALL(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClient_AdHoc() - if err != nil { - t.Errorf("ClientImpl.getClient() error = %v", err) - return - } + c := GitlabClient got, err := c.GetProjects(nil) if err != nil { t.Errorf("ClientImpl.GetProjects() error = %v", err) diff --git a/integration-tests/gitlab/api/gitlab_api_groups_test.go b/integration-tests/gitlab/api/gitlab_api_groups_test.go index bfa3af4..e051b1e 100644 --- a/integration-tests/gitlab/api/gitlab_api_groups_test.go +++ b/integration-tests/gitlab/api/gitlab_api_groups_test.go @@ -9,41 +9,20 @@ package api // description := "Integration Test Root Level Group" import ( - "errors" "fmt" "net/http" - "os" "testing" gogitlab "github.com/xanzy/go-gitlab" - gitlab "valkyrie.dso.mil/valkyrie-api/clients/gitlab" ) const groupsTestItemCount = 65 - var integrationRootGroupID = 0 -// getClientGroups - -func getClientGroups() (gitlab.ClientImpl, error) { - gitlabAPIURL, ok := os.LookupEnv("GITLAB_API_URL") - if !ok { - return gitlab.ClientImpl{}, errors.New("env variable GITLAB_API_URL undefinded") - } - gitlabAPIToken, ok := os.LookupEnv("GITLAB_API_TOKEN") - if !ok { - return gitlab.ClientImpl{}, errors.New("env variable GITLAB_API_TOKEN undefinded") - } - var client, _ = gitlab.NewClient(gitlabAPIURL, gitlabAPIToken, nil) - return client, nil -} func TestClient_GetGroups(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientGroups() - if err != nil { - t.Errorf("ClientImpl.getClient() error = %v", err) - return - } + c := GitlabClient got, err := c.GetGroups(nil) if err != nil { t.Errorf("ClientImpl.GetGroups() error = %v", err) @@ -60,11 +39,7 @@ func TestClient_GetGroups(t *testing.T) { // get group id of root level group func TestClient_AddRootGroup(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientGroups() - if err != nil { - t.Errorf("ClientImpl.getClient() error = %v", err) - return - } + c := GitlabClient path := "integration-root-group" name := "integration root group" @@ -98,11 +73,7 @@ func TestClient_AddRootGroup(t *testing.T) { // add groups under the integration test root level group func TestClient_AddGroups(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientGroups() - if err != nil { - t.Errorf("ClientImpl.getClient() error = %v", err) - return - } + c := GitlabClient for i := 1; i <= groupsTestItemCount; i++ { path := "test-group-" + fmt.Sprintf("%d", i) @@ -128,11 +99,7 @@ func TestClient_AddGroups(t *testing.T) { func TestClient_UpdateGroup(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientGroups() - if err != nil { - t.Errorf("ClientImpl.GetUsers() error = %v", err) - return - } + c := GitlabClient // create a group to contain test objects groupPath1 := "test-update-group-01" @@ -207,11 +174,7 @@ func TestClient_UpdateGroup(t *testing.T) { func TestClient_GetGroups2(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientGroups() - if err != nil { - t.Errorf("ClientImpl.getClient() error = %v", err) - return - } + c := GitlabClient got, err := c.GetGroups(nil) if err != nil { t.Errorf("ClientImpl.GetGroups() error = %v", err) @@ -223,11 +186,7 @@ func TestClient_GetGroups2(t *testing.T) { func TestClient_deleteGroups(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientGroups() - if err != nil { - t.Errorf("ClientImpl.getClient() error = %v", err) - return - } + c := GitlabClient search := "test-group" groupList, err := c.GetGroups(&search) diff --git a/integration-tests/gitlab/api/gitlab_api_mr_test.go b/integration-tests/gitlab/api/gitlab_api_mr_test.go index 31d9b18..be33bce 100644 --- a/integration-tests/gitlab/api/gitlab_api_mr_test.go +++ b/integration-tests/gitlab/api/gitlab_api_mr_test.go @@ -3,50 +3,14 @@ package api import ( - "os" - "errors" gitlab2 "github.com/xanzy/go-gitlab" "testing" - "valkyrie.dso.mil/valkyrie-api/clients/gitlab" ) -// getClient_AdHoc - -func getmrclientAdhoc() (gitlab.ClientImpl, error) { - gitlabAPIURL, ok := os.LookupEnv("GITLAB_API_URL") - if !ok { - return gitlab.ClientImpl{}, errors.New("env variable GITLAB_API_URL undefinded") - } - gitlabAPIToken, ok := os.LookupEnv("GITLAB_API_TOKEN") - if !ok { - return gitlab.ClientImpl{}, errors.New("env variable GITLAB_API_TOKEN undefinded") - } - client, err := gitlab.NewClient(gitlabAPIURL, gitlabAPIToken, nil) - return client, err -} - -func TestDeleteMR(t *testing.T) { - t.Run("test", func(t *testing.T) { - c, err := getmrclientAdhoc() - if err != nil { - t.Errorf("Create Client error = %v", err) - return - } - err = c.CloseMergeRequest(4548, 2) - if err != nil { - t.Errorf("Client.DeleteMergeRequest error = %v", err) - return - } - }) -} - func TestGetMRs(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getmrclientAdhoc() - if err != nil { - t.Errorf("Create Client error = %v", err) - return - } - got, err := c.GetMergeRequests(4548, "josh4", "staging") + c := GitlabClient + got, err := c.GetMergeRequests(GitlabIntTestRepositoryID, "josh4", "staging") if err != nil { t.Errorf("Client.GetMergeRequests error = %v", err) return @@ -60,11 +24,7 @@ func TestGetMRs(t *testing.T) { func TestCreateMR(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getmrclientAdhoc() - if err != nil { - t.Errorf("Create Client error = %v", err) - return - } + c := GitlabClient title := "Valkyrie Test" description := "Created by Valkyrie" @@ -72,7 +32,7 @@ func TestCreateMR(t *testing.T) { targetBranch := "staging" removeSourceBranch := true squash := true - got, err := c.CreateMergeRequest(4548, &gitlab2.CreateMergeRequestOptions{ + got, err := c.CreateMergeRequest(GitlabIntTestRepositoryID, &gitlab2.CreateMergeRequestOptions{ Title: &title, Description: &description, SourceBranch: &sourceBranch, @@ -91,3 +51,14 @@ func TestCreateMR(t *testing.T) { t.Logf("MR: [%d, %s, %s, %s, %s]", got.ProjectID, got.State, got.Title, got.SourceBranch, got.TargetBranch) }) } + +func TestDeleteMR(t *testing.T) { + t.Run("test", func(t *testing.T) { + c := GitlabClient + err := c.CloseMergeRequest(GitlabIntTestRepositoryID, 2) + if err != nil { + t.Errorf("Client.DeleteMergeRequest error = %v", err) + return + } + }) +} \ No newline at end of file diff --git a/integration-tests/gitlab/api/gitlab_api_projects_test.go b/integration-tests/gitlab/api/gitlab_api_projects_test.go index 0b3f406..4e3b812 100644 --- a/integration-tests/gitlab/api/gitlab_api_projects_test.go +++ b/integration-tests/gitlab/api/gitlab_api_projects_test.go @@ -3,14 +3,11 @@ package api import ( - "errors" "fmt" "net/http" - "os" "testing" gogitlab "github.com/xanzy/go-gitlab" - gitlab "valkyrie.dso.mil/valkyrie-api/clients/gitlab" ) // the get page size is 50 so we want something > 50 so we make sure to test paging @@ -20,27 +17,9 @@ const testProjectsPrefix = "IntTestProject" var integrationRootGroupIDProjects = 0 var integrationRootProjectIDProjects = 0 -// getClientProjects - -func getClientProjects() (gitlab.ClientImpl, error) { - gitlabAPIURL, ok := os.LookupEnv("GITLAB_API_URL") - if !ok { - return gitlab.ClientImpl{}, errors.New("env variable GITLAB_API_URL undefinded") - } - gitlabAPIToken, ok := os.LookupEnv("GITLAB_API_TOKEN") - if !ok { - return gitlab.ClientImpl{}, errors.New("env variable GITLAB_API_TOKEN undefinded") - } - var client, _ = gitlab.NewClient(gitlabAPIURL, gitlabAPIToken, nil) - return client, nil -} - func TestClient_GetProjects(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientProjects() - if err != nil { - t.Errorf("ClientImpl.getClientProjects() error = %v", err) - return - } + c := GitlabClient got, err := c.GetProjects(nil) if err != nil { t.Errorf("ClientImpl.GetProjects() error = %v", err) @@ -52,11 +31,7 @@ func TestClient_GetProjects(t *testing.T) { func TestClient_GetProjects_Search(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientProjects() - if err != nil { - t.Errorf("ClientImpl.getClientProjects() error = %v", err) - return - } + c := GitlabClient searchString := "monitor" @@ -72,11 +47,7 @@ func TestClient_GetProjects_Search(t *testing.T) { // Insure the integration test root level group exists func TestClient_AddRootGroup_Projects(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientProjects() - if err != nil { - t.Errorf("ClientImpl.getClientProjects() error = %v", err) - return - } + c := GitlabClient path := "integration-root-group" name := "integration root group" @@ -108,11 +79,7 @@ func TestClient_AddRootGroup_Projects(t *testing.T) { } func TestClient_deleteProjectsIfExist(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientProjects() - if err != nil { - t.Errorf("ClientImpl.getClient() error = %v", err) - return - } + c := GitlabClient search := testProjectsPrefix projectList, err := c.GetProjects(&search) @@ -136,11 +103,7 @@ func TestClient_deleteProjectsIfExist(t *testing.T) { // add groups under the integration test root level group func TestClient_AddProjects(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientProjects() - if err != nil { - t.Errorf("ClientImpl.getClientProjects() error = %v", err) - return - } + c := GitlabClient for i := 1; i <= projectsTestItemCount; i++ { path := testProjectsPrefix + "-project-" + fmt.Sprintf("%d", i) @@ -169,11 +132,7 @@ func TestClient_AddProjects(t *testing.T) { func TestClient_AddProject_More_Test(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientProjects() - if err != nil { - t.Errorf("ClientImpl.getClientProjects() error = %v", err) - return - } + c := GitlabClient path := testProjectsPrefix + "-repo-test" name := testProjectsPrefix + "-repo test " @@ -203,11 +162,7 @@ func TestClient_AddProject_More_Test(t *testing.T) { // requies integrationRootProjectIDProjects created from TestClient_AddProject_More_Test func TestClient_GetRepositoryTree(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientProjects() - if err != nil { - t.Errorf("ClientImpl.getClientRepository() error = %v", err) - return - } + c := GitlabClient projectID := integrationRootProjectIDProjects got, responseCode, err := c.GetRepositoryTree(projectID) if err != nil { @@ -226,11 +181,7 @@ func TestClient_GetRepositoryTree(t *testing.T) { func TestClient_UpdateProject(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientProjects() - if err != nil { - t.Errorf("ClientImpl.getClientProjects() error = %v", err) - return - } + c := GitlabClient // create a group to contain test objects path := testProjectsPrefix + "-project-update" @@ -269,11 +220,7 @@ func TestClient_UpdateProject(t *testing.T) { func TestClient_deleteProjects(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientProjects() - if err != nil { - t.Errorf("ClientImpl.getClient() error = %v", err) - return - } + c := GitlabClient search := testProjectsPrefix projectList, err := c.GetProjects(&search) diff --git a/integration-tests/gitlab/api/gitlab_api_users_test.go b/integration-tests/gitlab/api/gitlab_api_users_test.go index 4f69285..f905a7a 100644 --- a/integration-tests/gitlab/api/gitlab_api_users_test.go +++ b/integration-tests/gitlab/api/gitlab_api_users_test.go @@ -3,40 +3,20 @@ package api import ( - "errors" "fmt" - "os" "testing" gogitlab "github.com/xanzy/go-gitlab" - gitlab "valkyrie.dso.mil/valkyrie-api/clients/gitlab" ) const testItemCount = 65 const testUserPrefix = "IntTestUser" -// getClient - -func getClientUsers() (gitlab.ClientImpl, error) { - gitlabAPIURL, ok := os.LookupEnv("GITLAB_API_URL") - if !ok { - return gitlab.ClientImpl{}, errors.New("env variable GITLAB_API_URL undefinded") - } - gitlabAPIToken, ok := os.LookupEnv("GITLAB_API_TOKEN") - if !ok { - return gitlab.ClientImpl{}, errors.New("env variable GITLAB_API_TOKEN undefinded") - } - var client, _ = gitlab.NewClient(gitlabAPIURL, gitlabAPIToken, nil) - return client, nil -} - //TestClient_getUsers - func TestClient_getUsers(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientUsers() - if err != nil { - t.Errorf("ClientImpl.GetUsers() error = %v", err) - return - } + c := GitlabClient + got, err := c.GetUsers(nil) if err != nil { t.Errorf("ClientImpl.GetUsers() error = %v", err) @@ -49,11 +29,7 @@ func TestClient_getUsers(t *testing.T) { // TestClient_addUsers - func TestClient_addUsers(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientUsers() - if err != nil { - t.Errorf("ClientImpl.GetUsers() error = %v", err) - return - } + c := GitlabClient for i := 1; i <= testItemCount; i++ { username := testUserPrefix + fmt.Sprintf("%d", i) @@ -80,11 +56,7 @@ func TestClient_addUsers(t *testing.T) { func TestClient_UpdateUser(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientUsers() - if err != nil { - t.Errorf("ClientImpl.GetUsers() error = %v", err) - return - } + c := GitlabClient // create a user username := testUserPrefix + "update01" name := "test update user name 01" @@ -145,11 +117,7 @@ func TestClient_UpdateUser(t *testing.T) { } func TestClient_getUsersCount(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientUsers() - if err != nil { - t.Errorf("ClientImpl.getClient() error = %v", err) - return - } + c := GitlabClient got, err := c.GetUsers(nil) if err != nil { t.Errorf("ClientImpl.GetUsers() error = %v", err) @@ -160,11 +128,7 @@ func TestClient_getUsersCount(t *testing.T) { } func TestClient_deleteUsers(t *testing.T) { t.Run("test", func(t *testing.T) { - c, err := getClientUsers() - if err != nil { - t.Errorf("ClientImpl.GetUsers() error = %v", err) - return - } + c := GitlabClient for i := 1; i <= testItemCount; i++ { username := testUserPrefix + fmt.Sprintf("%d", i) diff --git a/integration-tests/gitlab/api/gitlab_main_test.go b/integration-tests/gitlab/api/gitlab_main_test.go new file mode 100644 index 0000000..dd78db8 --- /dev/null +++ b/integration-tests/gitlab/api/gitlab_main_test.go @@ -0,0 +1,97 @@ +// +build integration + +package api + +// go test -v -tags "integration" ./integration-tests/gitlab/api + +import ( + "errors" + "fmt" + "net/http" + "net/url" + "os" + "strings" + "testing" + + gogitlab "github.com/xanzy/go-gitlab" + "valkyrie.dso.mil/valkyrie-api/clients/gitlab" +) + +var WorkingDir string = "" +var GitlabAPIToken string = "" +var GitlabAPIURL string = "" +var GitlabClient gitlab.ClientImpl +var GitlabIntTestRepository string = "" +var GitlabIntTestRepositoryID int + +// TestMain - setup and teardown reusable code. wraps around other tests +func TestMain(m *testing.M) { + + // setup environment for testing + err := packageSetup() + if err != nil { + fmt.Printf("packageSetup error: %v\n", err) + os.Exit(1) + } + + // run tests + resultCode := m.Run() + + packageTeardown() + + os.Exit(resultCode) +} + +// packageSetup - setup environment for integration testing +func packageSetup() error { + WorkingDir, _ = os.Getwd() + var ok bool + var err error + + GitlabAPIURL, ok = os.LookupEnv("GITLAB_API_URL") + if !ok { + err = errors.New("env variable GITLAB_API_URL undefined") + return err + } + + GitlabAPIToken, ok = os.LookupEnv("GITLAB_API_TOKEN") + if !ok { + err:= errors.New("env variable GITLAB_API_TOKEN undefined") + return err + } + + GitlabIntTestRepository, ok = os.LookupEnv("GITLAB_INT_TEST_REPOSITORY") + if !ok { + err:= errors.New("env variable GITLAB_INT_TEST_REPOSITORY undefined") + return err + } + + GitlabClient, err = gitlab.NewClient(GitlabAPIURL, GitlabAPIToken, nil) + if err != nil { + return err + } + + url, err := url.Parse(GitlabIntTestRepository) + if err != nil { + return err + } + + var project *gogitlab.Project = nil + var responseCode int + + var urlPath = strings.TrimLeft(url.Path,"/") + project, responseCode, err = GitlabClient.GetProjectByFullPath(&urlPath) + if err != nil { + return err + } + if responseCode != http.StatusFound { + err:= fmt.Errorf("bad response code %d for GetProjectByFullPath path %s", responseCode, urlPath) + return err + } + GitlabIntTestRepositoryID = project.ID + return nil +} + +func packageTeardown() error { + return nil +} -- GitLab From dc5f0c8765a59d24962a41f63146a2ec0e5373e5 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Tue, 24 Aug 2021 11:06:09 -0600 Subject: [PATCH 18/55] update int tests to reuse global vars and setup --- .../gitlab/api/gitlab_api_groups_test.go | 56 ++--------- .../gitlab/api/gitlab_api_projects_test.go | 95 ++----------------- .../gitlab/api/gitlab_api_repository_test.go | 62 ++++++++++++ .../gitlab/api/gitlab_api_users_test.go | 2 +- .../gitlab/api/gitlab_main_test.go | 66 +++++++++++-- 5 files changed, 135 insertions(+), 146 deletions(-) create mode 100644 integration-tests/gitlab/api/gitlab_api_repository_test.go diff --git a/integration-tests/gitlab/api/gitlab_api_groups_test.go b/integration-tests/gitlab/api/gitlab_api_groups_test.go index e051b1e..2461542 100644 --- a/integration-tests/gitlab/api/gitlab_api_groups_test.go +++ b/integration-tests/gitlab/api/gitlab_api_groups_test.go @@ -2,24 +2,15 @@ package api -// it may be necessary to create the root leve integration test group by hand using admin interface! -// https://gitlab.bigbang.dev/admin/groups/new -// path := "integration-root-group" -// name := "integration root group" -// description := "Integration Test Root Level Group" - import ( "fmt" - "net/http" "testing" gogitlab "github.com/xanzy/go-gitlab" ) const groupsTestItemCount = 65 -var integrationRootGroupID = 0 - - +const testProjectsPrefix = "IntTestTemp-Group-" func TestClient_GetGroups(t *testing.T) { t.Run("test", func(t *testing.T) { c := GitlabClient @@ -35,55 +26,20 @@ func TestClient_GetGroups(t *testing.T) { }) } -// Create root level group if does not already exist -// get group id of root level group -func TestClient_AddRootGroup(t *testing.T) { - t.Run("test", func(t *testing.T) { - c := GitlabClient - - path := "integration-root-group" - name := "integration root group" - description := "Integration Test Root Level Group" - - group, statusCode, err := c.GetGroupByFullPath(&path) - if err != nil { - // dont fail if group already exists - t.Errorf("ClientImpl.GetGroupByFullPath() error = %v %d", err, statusCode) - return - } - - if statusCode == http.StatusFound { - integrationRootGroupID = group.ID - t.Logf("AddGroup %s %s %s %s %d", group.Name, group.Path, group.FullPath, group.WebURL, statusCode) - } else { - groupOpts := gogitlab.CreateGroupOptions{Name: &name, Path: &path, Description: &description} - got, statusCode, err := c.AddGroup(groupOpts) - - if err != nil { - // dont fail if group already exists - t.Logf("ClientImpl.AddGroup() error = %v %d", err, statusCode) - } else { - integrationRootGroupID = got.ID - t.Logf("AddGroup %s %s %s %s %d", got.Name, got.Path, got.FullPath, got.WebURL, statusCode) - } - } - }) -} - // add groups under the integration test root level group func TestClient_AddGroups(t *testing.T) { t.Run("test", func(t *testing.T) { c := GitlabClient for i := 1; i <= groupsTestItemCount; i++ { - path := "test-group-" + fmt.Sprintf("%d", i) - name := "test group " + fmt.Sprintf("%d", i) + path := testProjectsPrefix + fmt.Sprintf("%d", i) + name := testProjectsPrefix + fmt.Sprintf("%d", i) description := "My fancy test group " + fmt.Sprintf("%d", i) groupOpts := gogitlab.CreateGroupOptions{Name: &name, Path: &path, Description: &description, - ParentID: &integrationRootGroupID, + ParentID: &GitlabIntTestRootGroupID, } got, statusCode, err := c.AddGroup(groupOpts) @@ -109,7 +65,7 @@ func TestClient_UpdateGroup(t *testing.T) { Name: &groupName1, Path: &groupPath1, Description: &groupDescription1, - ParentID: &integrationRootGroupID, + ParentID: &GitlabIntTestRootGroupID, } group1, statusCode, err := c.AddGroup(groupOpts1) if err != nil { @@ -188,7 +144,7 @@ func TestClient_deleteGroups(t *testing.T) { t.Run("test", func(t *testing.T) { c := GitlabClient - search := "test-group" + search := testProjectsPrefix groupList, err := c.GetGroups(&search) if err != nil { t.Errorf("ClientImpl.GetGroups() error = %v", err) diff --git a/integration-tests/gitlab/api/gitlab_api_projects_test.go b/integration-tests/gitlab/api/gitlab_api_projects_test.go index 4e3b812..3e66835 100644 --- a/integration-tests/gitlab/api/gitlab_api_projects_test.go +++ b/integration-tests/gitlab/api/gitlab_api_projects_test.go @@ -4,7 +4,6 @@ package api import ( "fmt" - "net/http" "testing" gogitlab "github.com/xanzy/go-gitlab" @@ -12,10 +11,10 @@ import ( // the get page size is 50 so we want something > 50 so we make sure to test paging const projectsTestItemCount = 55 -const testProjectsPrefix = "IntTestProject" +const testProjectsPrefix = "IntTestTemp-Project-" -var integrationRootGroupIDProjects = 0 var integrationRootProjectIDProjects = 0 +var integrationProjectIDRepository = 0 func TestClient_GetProjects(t *testing.T) { t.Run("test", func(t *testing.T) { @@ -33,6 +32,7 @@ func TestClient_GetProjects_Search(t *testing.T) { t.Run("test", func(t *testing.T) { c := GitlabClient + // this should be found as gitlab has a hidden project with the string monitory searchString := "monitor" got, err := c.GetProjects(&searchString) @@ -44,39 +44,7 @@ func TestClient_GetProjects_Search(t *testing.T) { }) } -// Insure the integration test root level group exists -func TestClient_AddRootGroup_Projects(t *testing.T) { - t.Run("test", func(t *testing.T) { - c := GitlabClient - - path := "integration-root-group" - name := "integration root group" - description := "Integration Test Root Level Group" - - group, statusCode, err := c.GetGroupByFullPath(&path) - if err != nil { - // dont fail if group already exists - t.Errorf("ClientImpl.GetGroupByFullPath() error = %v %d", err, statusCode) - return - } - - if statusCode == http.StatusFound { - integrationRootGroupIDProjects = group.ID - t.Logf("AddGroup %s %s %s %s %d", group.Name, group.Path, group.FullPath, group.WebURL, statusCode) - } else { - groupOpts := gogitlab.CreateGroupOptions{Name: &name, Path: &path, Description: &description} - got, statusCode, err := c.AddGroup(groupOpts) - if err != nil { - // dont fail if group already exists - t.Logf("ClientImpl.AddGroup() error = %v %d", err, statusCode) - } else { - integrationRootGroupIDProjects = got.ID - t.Logf("AddGroup %s %s %s %s %d", got.Name, got.Path, got.FullPath, got.WebURL, statusCode) - } - } - }) -} func TestClient_deleteProjectsIfExist(t *testing.T) { t.Run("test", func(t *testing.T) { c := GitlabClient @@ -106,8 +74,8 @@ func TestClient_AddProjects(t *testing.T) { c := GitlabClient for i := 1; i <= projectsTestItemCount; i++ { - path := testProjectsPrefix + "-project-" + fmt.Sprintf("%d", i) - name := testProjectsPrefix + " project " + fmt.Sprintf("%d", i) + path := testProjectsPrefix + fmt.Sprintf("%d", i) + name := testProjectsPrefix + fmt.Sprintf("%d", i) description := "My fancy test project " + fmt.Sprintf("%d", i) configPath := "a/b/config.yml@group1/group2/project" @@ -115,7 +83,7 @@ func TestClient_AddProjects(t *testing.T) { Name: &name, Path: &path, Description: &description, - NamespaceID: &integrationRootGroupIDProjects, + NamespaceID: &GitlabIntTestRootGroupID, CIConfigPath: &configPath, } got, statusCode, err := c.AddProject(projectOpts) @@ -130,55 +98,6 @@ func TestClient_AddProjects(t *testing.T) { }) } -func TestClient_AddProject_More_Test(t *testing.T) { - t.Run("test", func(t *testing.T) { - c := GitlabClient - - path := testProjectsPrefix + "-repo-test" - name := testProjectsPrefix + "-repo test " - description := "Integration Test Repository" - configPath := "a/b/config.yml@group1/group2/project" - - projectOpts := gogitlab.CreateProjectOptions{ - Name: &name, - Path: &path, - Description: &description, - NamespaceID: &integrationRootGroupIDProjects, - CIConfigPath: &configPath, - } - got, statusCode, err := c.AddProject(projectOpts) - - if err != nil { - t.Errorf("ClientImpl.AddProject() error = %v %d", err, statusCode) - } else { - t.Logf("AddProject %s %s %s %s %d", got.Name, got.Path, got.PathWithNamespace, got.WebURL, statusCode) - // save test project id - integrationRootProjectIDProjects = got.ID - } - - }) -} - -// requies integrationRootProjectIDProjects created from TestClient_AddProject_More_Test -func TestClient_GetRepositoryTree(t *testing.T) { - t.Run("test", func(t *testing.T) { - c := GitlabClient - projectID := integrationRootProjectIDProjects - got, responseCode, err := c.GetRepositoryTree(projectID) - if err != nil { - t.Errorf("ClientImpl.GetRepositoryTree() project ID %d responseCode %d error = %v", integrationRootProjectIDProjects, responseCode, err) - return - } - treeLen := -1 - - if got != nil { - treeLen = len(got) - - } - t.Logf("GetRepositoryTree - project ID %d resturn code: %d number of files %d", projectID, responseCode, treeLen) - }) -} - func TestClient_UpdateProject(t *testing.T) { t.Run("test", func(t *testing.T) { c := GitlabClient @@ -192,7 +111,7 @@ func TestClient_UpdateProject(t *testing.T) { Name: &name, Path: &path, Description: &description, - NamespaceID: &integrationRootGroupIDProjects, + NamespaceID: &GitlabIntTestRootGroupID, } newProject, statusCode, err := c.AddProject(projectOpts) if err != nil { diff --git a/integration-tests/gitlab/api/gitlab_api_repository_test.go b/integration-tests/gitlab/api/gitlab_api_repository_test.go new file mode 100644 index 0000000..b71a897 --- /dev/null +++ b/integration-tests/gitlab/api/gitlab_api_repository_test.go @@ -0,0 +1,62 @@ +// +build integration + +package api + +import ( + "testing" + + gogitlab "github.com/xanzy/go-gitlab" +) + +var testProjectsPrefix = "int-test-" +var integrationProjectIDRepository = 0 +func TestClient_AddProject_More_Test(t *testing.T) { + t.Run("test", func(t *testing.T) { + c := GitlabClient + + path := testProjectsPrefix + "-repo-test" + name := testProjectsPrefix + "-repo test " + description := "Integration Test Repository" + configPath := "a/b/config.yml@group1/group2/project" + + projectOpts := gogitlab.CreateProjectOptions{ + Name: &name, + Path: &path, + Description: &description, + NamespaceID: &GitlabIntTestRootGroupID, + CIConfigPath: &configPath, + } + got, statusCode, err := c.AddProject(projectOpts) + + if err != nil { + t.Errorf("ClientImpl.TestClient_AddProject_More_Test() error = %v %d", err, statusCode) + } else { + t.Logf("AddProject %s %s %s %s %d", got.Name, got.Path, got.PathWithNamespace, got.WebURL, statusCode) + // save test project id + integrationProjectIDRepository = got.ID + } + + }) +} + +// requies integrationRootProjectIDProjects created from TestClient_AddProject_More_Test +func TestClient_GetRepositoryTree(t *testing.T) { + t.Run("test", func(t *testing.T) { + c := GitlabClient + projectID := integrationRootProjectIDProjects + got, responseCode, err := c.GetRepositoryTree(projectID) + if err != nil { + t.Errorf("ClientImpl.GetRepositoryTree() project ID %d responseCode %d error = %v", integrationRootProjectIDProjects, responseCode, err) + return + } + treeLen := -1 + + if got != nil { + treeLen = len(got) + + } + t.Logf("GetRepositoryTree - project ID %d resturn code: %d number of files %d", projectID, responseCode, treeLen) + }) +} + + diff --git a/integration-tests/gitlab/api/gitlab_api_users_test.go b/integration-tests/gitlab/api/gitlab_api_users_test.go index f905a7a..933cb53 100644 --- a/integration-tests/gitlab/api/gitlab_api_users_test.go +++ b/integration-tests/gitlab/api/gitlab_api_users_test.go @@ -10,7 +10,7 @@ import ( ) const testItemCount = 65 -const testUserPrefix = "IntTestUser" +const testUserPrefix = "IntTestTemp-User-" //TestClient_getUsers - func TestClient_getUsers(t *testing.T) { diff --git a/integration-tests/gitlab/api/gitlab_main_test.go b/integration-tests/gitlab/api/gitlab_main_test.go index dd78db8..fb7a4e9 100644 --- a/integration-tests/gitlab/api/gitlab_main_test.go +++ b/integration-tests/gitlab/api/gitlab_main_test.go @@ -22,7 +22,9 @@ var GitlabAPIToken string = "" var GitlabAPIURL string = "" var GitlabClient gitlab.ClientImpl var GitlabIntTestRepository string = "" -var GitlabIntTestRepositoryID int +var GitlabIntTestRepositoryID int = 0 +var GitlabIntTestRootGroup string = "" +var GitlabIntTestRootGroupID int = 0 // TestMain - setup and teardown reusable code. wraps around other tests func TestMain(m *testing.M) { @@ -56,16 +58,22 @@ func packageSetup() error { GitlabAPIToken, ok = os.LookupEnv("GITLAB_API_TOKEN") if !ok { - err:= errors.New("env variable GITLAB_API_TOKEN undefined") + err := errors.New("env variable GITLAB_API_TOKEN undefined") return err } GitlabIntTestRepository, ok = os.LookupEnv("GITLAB_INT_TEST_REPOSITORY") if !ok { - err:= errors.New("env variable GITLAB_INT_TEST_REPOSITORY undefined") + err := errors.New("env variable GITLAB_INT_TEST_REPOSITORY undefined") return err } - + + GitlabIntTestRootGroup, ok = os.LookupEnv("GITLAB_INT_TEST_ROOT_GROUP") + if !ok { + err := errors.New("env variable GITLAB_INT_TEST_ROOT_GROUP undefined") + return err + } + GitlabClient, err = gitlab.NewClient(GitlabAPIURL, GitlabAPIToken, nil) if err != nil { return err @@ -79,19 +87,63 @@ func packageSetup() error { var project *gogitlab.Project = nil var responseCode int - var urlPath = strings.TrimLeft(url.Path,"/") + var urlPath = strings.TrimLeft(url.Path, "/") project, responseCode, err = GitlabClient.GetProjectByFullPath(&urlPath) if err != nil { return err } if responseCode != http.StatusFound { - err:= fmt.Errorf("bad response code %d for GetProjectByFullPath path %s", responseCode, urlPath) + err := fmt.Errorf("bad response code %d for GetProjectByFullPath path %s", responseCode, urlPath) return err } GitlabIntTestRepositoryID = project.ID + + // insure a root group exists in gitlab + err = AddRootGroup() + if err != nil { + return err + } + return nil } -func packageTeardown() error { +func packageTeardown() error { + return nil +} + +// Insure the integration test root level group exists +func AddRootGroup() error { + + c := GitlabClient + + path := GitlabIntTestRootGroup + name := GitlabIntTestRootGroup + description := "Integration Test Root Level Group" + + group, statusCode, err := c.GetGroupByFullPath(&path) + if err != nil { + // dont fail if group already exists + fmt.Printf("AddRootGroup GetGroupByFullPath error = %v %d\n", err, statusCode) + return err + } + + if statusCode == http.StatusFound { + // root group found + GitlabIntTestRootGroupID = group.ID + fmt.Printf("AddRootGroup Group Found: %s %s %s %s %d \n", group.Name, group.Path, group.FullPath, group.WebURL, statusCode) + } else { + // try to create root group + groupOpts := gogitlab.CreateGroupOptions{Name: &name, Path: &path, Description: &description} + got, statusCode, err := c.AddGroup(groupOpts) + + if err != nil { + // dont fail if group already exists + fmt.Printf("Error! AddRootGroup %s error = %v %d\n", path, err, statusCode) + return err + } else { + GitlabIntTestRootGroupID = got.ID + fmt.Printf("AddGroup %s %s %s %s %d \n", got.Name, got.Path, got.FullPath, got.WebURL, statusCode) + } + } return nil } -- GitLab From e24d9eb95cd0087f65b7cd426e82b0fbdbf1370a Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Tue, 24 Aug 2021 14:51:12 -0600 Subject: [PATCH 19/55] consolidate integration test setup --- integration-tests/README.md | 10 +- integration-tests/custom/p1/p1_groups_test.go | 20 +-- integration-tests/custom/p1/p1_main_test.go | 142 ++++++++++-------- .../custom/p1/p1_projects_test.go | 35 +---- .../gitlab/api/gitlab_api_groups_test.go | 8 +- .../gitlab/api/gitlab_api_projects_test.go | 1 - .../gitlab/api/gitlab_api_repository_test.go | 53 +++++-- 7 files changed, 147 insertions(+), 122 deletions(-) diff --git a/integration-tests/README.md b/integration-tests/README.md index 99ffaeb..91007c6 100644 --- a/integration-tests/README.md +++ b/integration-tests/README.md @@ -1,10 +1,16 @@ ## Valkyrie Integration Testing - +- Clear testing cache + - `go clean -cache` +- Running tests + - `go test -tags "integration" ./integration-tests/...` + - `go test -tags "integration" ./integration-tests/custom/p1/...` + - `go test -tags "integration" ./integration-tests/gitlab/api/gitlab_api_repository_test.go ./integration-tests/gitlab/api/gitlab_main_test.go` + - `go test -v -tags "integration" ./integration-tests/gitlab/api/gitlab_api_repository_test.go ./integration-tests/gitlab/api/gitlab_main_test.go` ### Gitlab Integration Testing #### Setup - gitlab root level group creation - - it may be necessary to create the root leve integration test group by hand using the web ui admin interface! + - it may be necessary to create the root level integration test group by hand using the web ui admin interface! - there is a gitlab instance setting that prevents api from creating root level groups - https://gitlab.bigbang.dev/admin/groups/new - path := "integration-root-group" diff --git a/integration-tests/custom/p1/p1_groups_test.go b/integration-tests/custom/p1/p1_groups_test.go index e90c129..a0948bb 100644 --- a/integration-tests/custom/p1/p1_groups_test.go +++ b/integration-tests/custom/p1/p1_groups_test.go @@ -11,7 +11,7 @@ import ( /* -P1Config is initialized in the TestMain wrapper method +p1Config is initialized in the TestMain wrapper method */ const integrationTestGroupPath = "int-test-group" @@ -21,12 +21,12 @@ func Test_P1_AddGroup(t *testing.T) { t.Run("test", func(t *testing.T) { groupSpec := v1alpha1.GroupSpec{ Name: "My Test Group", - FullPath: p1IntegrationRootGroupPath + "/" + integrationTestGroupPath, + FullPath: p1Config.GitlabIntTestRootGroupPath + "/" + integrationTestGroupPath, } creds := custom_p1.GitlabCredentials{ - ServerURL: P1Config.gitlabAPIURL, - ServerToken: P1Config.gitlabAPIToken, + ServerURL: p1Config.GitlabAPIURL, + ServerToken: p1Config.GitlabAPIToken, } err := custom_p1.CreateGroup(creds, groupSpec, nil) @@ -44,12 +44,12 @@ func Test_P1_UpdateGroup(t *testing.T) { t.Run("test", func(t *testing.T) { groupSpec := v1alpha1.GroupSpec{ Name: "My Test Updated Group", - FullPath: p1IntegrationRootGroupPath + "/" + integrationTestGroupPath, + FullPath: p1Config.GitlabIntTestRootGroupPath + "/" + integrationTestGroupPath, } creds := custom_p1.GitlabCredentials{ - ServerURL: P1Config.gitlabAPIURL, - ServerToken: P1Config.gitlabAPIToken, + ServerURL: p1Config.GitlabAPIURL, + ServerToken: p1Config.GitlabAPIToken, } err := custom_p1.UpdateGroup(creds, groupSpec, nil) @@ -65,12 +65,12 @@ func Test_P1_DeleteGroup(t *testing.T) { logPrefix := "Test_P1_DeleteGroup" t.Run("test", func(t *testing.T) { groupSpec := v1alpha1.GroupSpec{ - FullPath: p1IntegrationRootGroupPath + "/" + integrationTestGroupPath, + FullPath: p1Config.GitlabIntTestRootGroupPath + "/" + integrationTestGroupPath, } creds := custom_p1.GitlabCredentials{ - ServerURL: P1Config.gitlabAPIURL, - ServerToken: P1Config.gitlabAPIToken, + ServerURL: p1Config.GitlabAPIURL, + ServerToken: p1Config.GitlabAPIToken, } err := custom_p1.DeleteGroup(creds, groupSpec, nil) diff --git a/integration-tests/custom/p1/p1_main_test.go b/integration-tests/custom/p1/p1_main_test.go index ef8487f..163265b 100644 --- a/integration-tests/custom/p1/p1_main_test.go +++ b/integration-tests/custom/p1/p1_main_test.go @@ -6,25 +6,15 @@ import ( "errors" "fmt" "net/http" + "net/url" "os" + "strings" "testing" - "github.com/romana/rlog" gogitlab "github.com/xanzy/go-gitlab" gitlab "valkyrie.dso.mil/valkyrie-api/clients/gitlab" ) -// pathname for root group used in integration testing -const p1IntegrationRootGroupPath = "integration-root-group" - -// configuration obect to be shared for integration testing -var P1Config struct { - gitlabAPIURL string - gitlabAPIToken string - testProjectGroupPath string - integrationRootGroupID int -} - // TestMain - setup and teardown reusable code. wraps around other tests func TestMain(m *testing.M) { @@ -43,99 +33,119 @@ func TestMain(m *testing.M) { os.Exit(resultCode) } +type P1Config struct { + WorkingDir string + GitlabAPIToken string + GitlabAPIURL string + GitlabClient gitlab.ClientImpl + GitlabIntTestRepository string + GitlabIntTestRepositoryID int + GitlabIntTestRootGroupPath string + GitlabIntTestRootGroupID int +} + +var p1Config P1Config + // packageSetup - setup environment for integration testing func packageSetup() error { + p1Config.WorkingDir, _ = os.Getwd() + var ok bool var err error - // initialize - P1Config.testProjectGroupPath = p1IntegrationRootGroupPath - // read env variables - err = getEnvVariables() - if err != nil { + p1Config.GitlabAPIURL, ok = os.LookupEnv("GITLAB_API_URL") + if !ok { + err = errors.New("env variable GITLAB_API_URL undefined") return err } - // add gitlab root group if does not exist - err = addRootGroup() - if err != nil { + p1Config.GitlabAPIToken, ok = os.LookupEnv("GITLAB_API_TOKEN") + if !ok { + err := errors.New("env variable GITLAB_API_TOKEN undefined") return err } - return nil -} -func packageTeardown() { - -} - -// getEnvVariables - read environment variables -func getEnvVariables() error { - gitlabAPIURL, ok := os.LookupEnv("GITLAB_API_URL") + p1Config.GitlabIntTestRepository, ok = os.LookupEnv("GITLAB_INT_TEST_REPOSITORY") if !ok { - return errors.New("env variable GITLAB_API_URL undefinded") + err := errors.New("env variable GITLAB_INT_TEST_REPOSITORY undefined") + return err } - gitlabAPIToken, ok := os.LookupEnv("GITLAB_API_TOKEN") + p1Config.GitlabIntTestRootGroupPath, ok = os.LookupEnv("GITLAB_INT_TEST_ROOT_GROUP_PATH") if !ok { - return errors.New("env variable GITLAB_API_TOKEN undefinded") + err := errors.New("env variable GITLAB_INT_TEST_ROOT_GROUP undefined") + return err } - // set values in package scoped config object - P1Config.gitlabAPIToken = gitlabAPIToken - P1Config.gitlabAPIURL = gitlabAPIURL + p1Config.GitlabClient, err = gitlab.NewClient(p1Config.GitlabAPIURL, p1Config.GitlabAPIToken, nil) + if err != nil { + return err + } - return nil -} + url, err := url.Parse(p1Config.GitlabIntTestRepository) + if err != nil { + return err + } + + var project *gogitlab.Project = nil + var responseCode int -// addRootGroup - add a integration test root group if it does not exist -func addRootGroup() error { + var urlPath = strings.TrimLeft(url.Path, "/") + project, responseCode, err = p1Config.GitlabClient.GetProjectByFullPath(&urlPath) + if err != nil { + return err + } + if responseCode != http.StatusFound { + err := fmt.Errorf("bad response code %d for GetProjectByFullPath path %s", responseCode, urlPath) + return err + } + p1Config.GitlabIntTestRepositoryID = project.ID - c, err := getClient() + // insure a root group exists in gitlab + err = AddRootGroup() if err != nil { return err } - // create root integration test group if does not yet exists - path := P1Config.testProjectGroupPath - name := "integration root group" + return nil +} + +func packageTeardown() error { + return nil +} + +// Insure the integration test root level group exists +func AddRootGroup() error { + + c := p1Config.GitlabClient + + path := p1Config.GitlabIntTestRootGroupPath + name := p1Config.GitlabIntTestRootGroupPath description := "Integration Test Root Level Group" group, statusCode, err := c.GetGroupByFullPath(&path) if err != nil { + // dont fail if group already exists + fmt.Printf("AddRootGroup GetGroupByFullPath error = %v %d\n", err, statusCode) return err } if statusCode == http.StatusFound { - P1Config.integrationRootGroupID = group.ID - rlog.Debugf("AddGroup %s %s %s %s %d", group.Name, group.Path, group.FullPath, group.WebURL, statusCode) + // root group found + p1Config.GitlabIntTestRootGroupID = group.ID + fmt.Printf("AddRootGroup Group Found: %s %s %s %s %d \n", group.Name, group.Path, group.FullPath, group.WebURL, statusCode) } else { + // try to create root group groupOpts := gogitlab.CreateGroupOptions{Name: &name, Path: &path, Description: &description} got, statusCode, err := c.AddGroup(groupOpts) if err != nil { // dont fail if group already exists - rlog.Warnf("AddGroup() error = %v %d", err, statusCode) + fmt.Printf("Error! AddRootGroup %s error = %v %d\n", path, err, statusCode) + return err } else { - P1Config.integrationRootGroupID = got.ID - rlog.Debugf("AddGroup %s %s %s %s %d", got.Name, got.Path, got.FullPath, got.WebURL, statusCode) + p1Config.GitlabIntTestRootGroupID = got.ID + fmt.Printf("AddGroup %s %s %s %s %d \n", got.Name, got.Path, got.FullPath, got.WebURL, statusCode) } } return nil } - -// getClient - create a gitlab client object -func getClient() (gitlab.ClientImpl, error) { - gitlabAPIURL, ok := os.LookupEnv("GITLAB_API_URL") - if !ok { - return gitlab.ClientImpl{}, errors.New("env variable GITLAB_API_URL undefinded") - } - gitlabAPIToken, ok := os.LookupEnv("GITLAB_API_TOKEN") - if !ok { - return gitlab.ClientImpl{}, errors.New("env variable GITLAB_API_TOKEN undefinded") - } - client, err := gitlab.NewClient(gitlabAPIURL, gitlabAPIToken, nil) - if err != nil { - return gitlab.ClientImpl{}, err - } - return client, nil - -} diff --git a/integration-tests/custom/p1/p1_projects_test.go b/integration-tests/custom/p1/p1_projects_test.go index a0c08f5..45ff894 100644 --- a/integration-tests/custom/p1/p1_projects_test.go +++ b/integration-tests/custom/p1/p1_projects_test.go @@ -21,13 +21,12 @@ func Test_P1_AddProject(t *testing.T) { t.Run("test", func(t *testing.T) { projectSpec := v1alpha1.ProjectSpec{ Name: "My Test Project", - FullPath: p1IntegrationRootGroupPath + "/" + integrationTestProjectPath, - Language: custom_p1.LangTypeAngular, + FullPath: p1Config.GitlabIntTestRootGroupPath + "/" + integrationTestProjectPath, } creds := custom_p1.GitlabCredentials{ - ServerURL: P1Config.gitlabAPIURL, - ServerToken: P1Config.gitlabAPIToken, + ServerURL: p1Config.GitlabAPIURL, + ServerToken: p1Config.GitlabAPIToken, } var err error @@ -53,13 +52,12 @@ func Test_P1_UpdateProject(t *testing.T) { t.Run("test", func(t *testing.T) { projectSpec := v1alpha1.ProjectSpec{ Name: "My Test Updated Project", - FullPath: p1IntegrationRootGroupPath + "/" + integrationTestProjectPath, - Language: custom_p1.LangTypeJavaMaven, + FullPath: p1Config.GitlabIntTestRootGroupPath + "/" + integrationTestProjectPath, } creds := custom_p1.GitlabCredentials{ - ServerURL: P1Config.gitlabAPIURL, - ServerToken: P1Config.gitlabAPIToken, + ServerURL: p1Config.GitlabAPIURL, + ServerToken: p1Config.GitlabAPIToken, } err := custom_p1.UpdateProject(creds, projectSpec, nil) @@ -70,24 +68,3 @@ func Test_P1_UpdateProject(t *testing.T) { t.Logf("%s update project %v", logPrefix, projectSpec) }) } - -// func Test_P1_DeleteProject(t *testing.T) { -// logPrefix := "Test_P1_DeleteProject" -// t.Run("test", func(t *testing.T) { -// projectSpec := v1alpha1.ProjectSpec{ -// FullPath: p1IntegrationRootGroupPath + "/" + integrationTestProjectPath, -// } - -// creds := custom_p1.GitlabCredentials{ -// ServerURL: P1Config.gitlabAPIURL, -// ServerToken: P1Config.gitlabAPIToken, -// } - -// err := custom_p1.DeleteProject(creds, projectSpec, nil) -// if err != nil { -// t.Errorf("DeleteProject() error = %v", err) -// return -// } -// t.Logf("%s deleted project %v", logPrefix, projectSpec) -// }) -// } diff --git a/integration-tests/gitlab/api/gitlab_api_groups_test.go b/integration-tests/gitlab/api/gitlab_api_groups_test.go index 2461542..a7b4b4a 100644 --- a/integration-tests/gitlab/api/gitlab_api_groups_test.go +++ b/integration-tests/gitlab/api/gitlab_api_groups_test.go @@ -10,7 +10,7 @@ import ( ) const groupsTestItemCount = 65 -const testProjectsPrefix = "IntTestTemp-Group-" +const testGroupsPrefix = "IntTestTemp-Group-" func TestClient_GetGroups(t *testing.T) { t.Run("test", func(t *testing.T) { c := GitlabClient @@ -32,8 +32,8 @@ func TestClient_AddGroups(t *testing.T) { c := GitlabClient for i := 1; i <= groupsTestItemCount; i++ { - path := testProjectsPrefix + fmt.Sprintf("%d", i) - name := testProjectsPrefix + fmt.Sprintf("%d", i) + path := testGroupsPrefix + fmt.Sprintf("%d", i) + name := testGroupsPrefix + fmt.Sprintf("%d", i) description := "My fancy test group " + fmt.Sprintf("%d", i) groupOpts := gogitlab.CreateGroupOptions{Name: &name, @@ -144,7 +144,7 @@ func TestClient_deleteGroups(t *testing.T) { t.Run("test", func(t *testing.T) { c := GitlabClient - search := testProjectsPrefix + search := testGroupsPrefix groupList, err := c.GetGroups(&search) if err != nil { t.Errorf("ClientImpl.GetGroups() error = %v", err) diff --git a/integration-tests/gitlab/api/gitlab_api_projects_test.go b/integration-tests/gitlab/api/gitlab_api_projects_test.go index 3e66835..078e29e 100644 --- a/integration-tests/gitlab/api/gitlab_api_projects_test.go +++ b/integration-tests/gitlab/api/gitlab_api_projects_test.go @@ -14,7 +14,6 @@ const projectsTestItemCount = 55 const testProjectsPrefix = "IntTestTemp-Project-" var integrationRootProjectIDProjects = 0 -var integrationProjectIDRepository = 0 func TestClient_GetProjects(t *testing.T) { t.Run("test", func(t *testing.T) { diff --git a/integration-tests/gitlab/api/gitlab_api_repository_test.go b/integration-tests/gitlab/api/gitlab_api_repository_test.go index b71a897..cdff0d9 100644 --- a/integration-tests/gitlab/api/gitlab_api_repository_test.go +++ b/integration-tests/gitlab/api/gitlab_api_repository_test.go @@ -3,19 +3,20 @@ package api import ( + "net/http" "testing" gogitlab "github.com/xanzy/go-gitlab" ) -var testProjectsPrefix = "int-test-" +var testProjectsRepoPrefix = "int-test-repo" var integrationProjectIDRepository = 0 -func TestClient_AddProject_More_Test(t *testing.T) { +func TestClient_AddProject_Repository(t *testing.T) { t.Run("test", func(t *testing.T) { c := GitlabClient - path := testProjectsPrefix + "-repo-test" - name := testProjectsPrefix + "-repo test " + path := testProjectsRepoPrefix + "-test" + name := testProjectsRepoPrefix + " test " description := "Integration Test Repository" configPath := "a/b/config.yml@group1/group2/project" @@ -29,13 +30,15 @@ func TestClient_AddProject_More_Test(t *testing.T) { got, statusCode, err := c.AddProject(projectOpts) if err != nil { - t.Errorf("ClientImpl.TestClient_AddProject_More_Test() error = %v %d", err, statusCode) + t.Errorf("Error! TestClient_AddProject_Repository() = %v %d", err, statusCode) } else { t.Logf("AddProject %s %s %s %s %d", got.Name, got.Path, got.PathWithNamespace, got.WebURL, statusCode) // save test project id + if (statusCode == http.StatusOK) { + t.Logf("Status OK") + } integrationProjectIDRepository = got.ID } - }) } @@ -43,20 +46,50 @@ func TestClient_AddProject_More_Test(t *testing.T) { func TestClient_GetRepositoryTree(t *testing.T) { t.Run("test", func(t *testing.T) { c := GitlabClient - projectID := integrationRootProjectIDProjects + projectID := integrationProjectIDRepository got, responseCode, err := c.GetRepositoryTree(projectID) + if err != nil { - t.Errorf("ClientImpl.GetRepositoryTree() project ID %d responseCode %d error = %v", integrationRootProjectIDProjects, responseCode, err) + t.Errorf("ClientImpl.GetRepositoryTree() project ID %d responseCode %d error = %v", integrationProjectIDRepository, responseCode, err) return } - treeLen := -1 + treeLen := -1 if got != nil { treeLen = len(got) + } + if (responseCode == http.StatusNoContent) { + t.Logf("GetRepositoryTree - responseCode StatusNoContent") } - t.Logf("GetRepositoryTree - project ID %d resturn code: %d number of files %d", projectID, responseCode, treeLen) + + t.Logf("GetRepositoryTree - project ID %d responseCode: %d number of files %d", projectID, responseCode, treeLen) }) } +// Add a file to the Repo + +// Get tree again + +func TestClient_deleteProjectsIfExistRepo(t *testing.T) { + t.Run("test", func(t *testing.T) { + c := GitlabClient + search := testProjectsRepoPrefix + projectList, err := c.GetProjects(&search) + if err != nil { + t.Errorf("ClientImpl.GetProjects() error = %v", err) + return + } + + for x := 0; x < len(projectList); x++ { + project := projectList[x] + statusCode, err := c.DeleteProject(project.ID, 100, 1200) + + if err == nil { + t.Logf("DeleteProject %s %d", project.Name, statusCode) + } + } + + }) +} \ No newline at end of file -- GitLab From 0ae4a08faafe26f60b2cf60e89e2327fa131bd49 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Tue, 24 Aug 2021 22:31:48 -0600 Subject: [PATCH 20/55] fix integration tests and merge request tests --- custom/p1/project.go | 1 + integration-tests/custom/p1/p1_main_test.go | 85 ++++++++--- integration-tests/gitclient/git_main_test.go | 4 +- .../gitlab/api/gitlab_api_adhoc_test.go | 13 +- .../gitlab/api/gitlab_api_groups_test.go | 14 +- .../gitlab/api/gitlab_api_mr_test.go | 37 +++-- .../gitlab/api/gitlab_api_projects_test.go | 17 ++- .../gitlab/api/gitlab_api_repository_test.go | 53 ++++--- .../gitlab/api/gitlab_api_users_test.go | 10 +- .../gitlab/api/gitlab_main_test.go | 133 +++++++++++++----- scripts/valkyrie_env.sh | 17 ++- 11 files changed, 263 insertions(+), 121 deletions(-) diff --git a/custom/p1/project.go b/custom/p1/project.go index 4c26055..257eb3f 100644 --- a/custom/p1/project.go +++ b/custom/p1/project.go @@ -85,6 +85,7 @@ func CreateProject(gitlabCredentials GitlabCredentials, projectSpec apigitlab.Pr WikiEnabled: &boolTrue, JobsEnabled: &boolTrue, SnippetsEnabled: &boolTrue, + InitializeWithReadme: &boolTrue, IssuesAccessLevel: &enabledAccessControl, RepositoryAccessLevel: &enabledAccessControl, MergeRequestsAccessLevel: &enabledAccessControl, diff --git a/integration-tests/custom/p1/p1_main_test.go b/integration-tests/custom/p1/p1_main_test.go index 163265b..8d3339c 100644 --- a/integration-tests/custom/p1/p1_main_test.go +++ b/integration-tests/custom/p1/p1_main_test.go @@ -35,10 +35,14 @@ func TestMain(m *testing.M) { type P1Config struct { WorkingDir string + GitlabIntTestUsername string + GitlabIntTestToken string GitlabAPIToken string GitlabAPIURL string GitlabClient gitlab.ClientImpl - GitlabIntTestRepository string + GitlabIntTestProjectPath string + GitlabIntTestProjectURL string + GitlabIntTestRepositoryURL string GitlabIntTestRepositoryID int GitlabIntTestRootGroupPath string GitlabIntTestRootGroupID int @@ -64,44 +68,37 @@ func packageSetup() error { return err } - p1Config.GitlabIntTestRepository, ok = os.LookupEnv("GITLAB_INT_TEST_REPOSITORY") + p1Config.GitlabIntTestRepositoryURL, ok = os.LookupEnv("GITLAB_INT_TEST_REPOSITORY_URL") if !ok { - err := errors.New("env variable GITLAB_INT_TEST_REPOSITORY undefined") + err := errors.New("env variable GITLAB_INT_TEST_REPOSITORY_URL undefined") return err } - p1Config.GitlabIntTestRootGroupPath, ok = os.LookupEnv("GITLAB_INT_TEST_ROOT_GROUP_PATH") + p1Config.GitlabIntTestProjectURL, ok = os.LookupEnv("GITLAB_INT_TEST_PROJECT_URL") if !ok { - err := errors.New("env variable GITLAB_INT_TEST_ROOT_GROUP undefined") + err := errors.New("env variable GITLAB_INT_TEST_PROJECT_URL undefined") return err } - p1Config.GitlabClient, err = gitlab.NewClient(p1Config.GitlabAPIURL, p1Config.GitlabAPIToken, nil) - if err != nil { + p1Config.GitlabIntTestRootGroupPath, ok = os.LookupEnv("GITLAB_INT_TEST_ROOT_GROUP_PATH") + if !ok { + err := errors.New("env variable GITLAB_INT_TEST_ROOT_GROUP_PATH undefined") return err } - url, err := url.Parse(p1Config.GitlabIntTestRepository) + p1Config.GitlabClient, err = gitlab.NewClient(p1Config.GitlabAPIURL, p1Config.GitlabAPIToken, nil) if err != nil { return err } - var project *gogitlab.Project = nil - var responseCode int - - var urlPath = strings.TrimLeft(url.Path, "/") - project, responseCode, err = p1Config.GitlabClient.GetProjectByFullPath(&urlPath) + // insure a root group exists in gitlab + err = addRootGroup() if err != nil { return err } - if responseCode != http.StatusFound { - err := fmt.Errorf("bad response code %d for GetProjectByFullPath path %s", responseCode, urlPath) - return err - } - p1Config.GitlabIntTestRepositoryID = project.ID - // insure a root group exists in gitlab - err = AddRootGroup() + // insure a test project exists in root group + p1Config.GitlabIntTestRepositoryID, err = addIntTestProject(p1Config.GitlabIntTestProjectURL) if err != nil { return err } @@ -114,7 +111,7 @@ func packageTeardown() error { } // Insure the integration test root level group exists -func AddRootGroup() error { +func addRootGroup() error { c := p1Config.GitlabClient @@ -149,3 +146,49 @@ func AddRootGroup() error { } return nil } + +// Insure the integration test project exists +func addIntTestProject(projectUrl string) (int, error) { + + var project *gogitlab.Project = nil + var responseCode int + + url, err := url.Parse(projectUrl) + if err != nil { + return 0, err + } + + var urlPath = strings.TrimLeft(url.Path, "/") + project, responseCode, err = p1Config.GitlabClient.GetProjectByFullPath(&urlPath) + if err != nil { + return 0, err + } + + if responseCode == http.StatusFound { + return project.ID, nil + } else { + path := p1Config.GitlabIntTestProjectPath + name := p1Config.GitlabIntTestProjectPath + description := "Integration Test Project" + configPath := "a/b/config.yml@group1/group2/project" + initializeWithReadme := true + + projectOpts := gogitlab.CreateProjectOptions{ + Name: &name, + Path: &path, + Description: &description, + NamespaceID: &p1Config.GitlabIntTestRootGroupID, + CIConfigPath: &configPath, + InitializeWithReadme: &initializeWithReadme, + } + got, statusCode, err := p1Config.GitlabClient.AddProject(projectOpts) + + if err != nil { + fmt.Printf("ClientImpl.AddProject() error = %v %d \n", err, statusCode) + return 0, err + } + + fmt.Printf("AddProject %s %s %s %s %d", got.Name, got.Path, got.PathWithNamespace, got.WebURL, statusCode) + return got.ID, nil + } +} diff --git a/integration-tests/gitclient/git_main_test.go b/integration-tests/gitclient/git_main_test.go index 27d2a89..eaeeecf 100644 --- a/integration-tests/gitclient/git_main_test.go +++ b/integration-tests/gitclient/git_main_test.go @@ -57,9 +57,9 @@ func packageSetup() error { return err } - GitRepoURL, ok = os.LookupEnv("GITLAB_INT_TEST_REPOSITORY") + GitRepoURL, ok = os.LookupEnv("GITLAB_INT_TEST_REPOSITORY_URL") if !ok { - err := errors.New("env variable GITLAB_INT_TEST_REPOSITORY undefined") + err := errors.New("env variable GITLAB_INT_TEST_REPOSITORY_URL undefined") return err } diff --git a/integration-tests/gitlab/api/gitlab_api_adhoc_test.go b/integration-tests/gitlab/api/gitlab_api_adhoc_test.go index 4e411c0..fb4db3f 100644 --- a/integration-tests/gitlab/api/gitlab_api_adhoc_test.go +++ b/integration-tests/gitlab/api/gitlab_api_adhoc_test.go @@ -1,3 +1,4 @@ + // +build integration package api @@ -8,7 +9,7 @@ import ( func TestClient_AdHoc_getUsers_All(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient got, err := c.GetUsers(nil) if err != nil { t.Errorf("ClientImpl.GetUsers() error = %v", err) @@ -22,7 +23,7 @@ func TestClient_AdHoc_getUsers_All(t *testing.T) { } func TestClient_AdHoc_getUsers_Search(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient search := "ghost" got, err := c.GetUsers(&search) if err != nil { @@ -37,7 +38,7 @@ func TestClient_AdHoc_getUsers_Search(t *testing.T) { } func TestClient_AdHoc_getUsers_None(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient search := "notfound" got, err := c.GetUsers(&search) if err != nil { @@ -53,7 +54,7 @@ func TestClient_AdHoc_getUsers_None(t *testing.T) { func TestClient_AdHoc_getGroups_All(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient got, err := c.GetGroups(nil) if err != nil { @@ -68,7 +69,7 @@ func TestClient_AdHoc_getGroups_All(t *testing.T) { } func TestClient_AdHoc_getGroups_Search(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient s := string("test") got, err := c.GetGroups(&s) if err != nil { @@ -84,7 +85,7 @@ func TestClient_AdHoc_getGroups_Search(t *testing.T) { func TestClient_AdHoc_getProjects_ALL(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient got, err := c.GetProjects(nil) if err != nil { t.Errorf("ClientImpl.GetProjects() error = %v", err) diff --git a/integration-tests/gitlab/api/gitlab_api_groups_test.go b/integration-tests/gitlab/api/gitlab_api_groups_test.go index a7b4b4a..cadb0dc 100644 --- a/integration-tests/gitlab/api/gitlab_api_groups_test.go +++ b/integration-tests/gitlab/api/gitlab_api_groups_test.go @@ -13,7 +13,7 @@ const groupsTestItemCount = 65 const testGroupsPrefix = "IntTestTemp-Group-" func TestClient_GetGroups(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient got, err := c.GetGroups(nil) if err != nil { t.Errorf("ClientImpl.GetGroups() error = %v", err) @@ -29,7 +29,7 @@ func TestClient_GetGroups(t *testing.T) { // add groups under the integration test root level group func TestClient_AddGroups(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient for i := 1; i <= groupsTestItemCount; i++ { path := testGroupsPrefix + fmt.Sprintf("%d", i) @@ -39,7 +39,7 @@ func TestClient_AddGroups(t *testing.T) { groupOpts := gogitlab.CreateGroupOptions{Name: &name, Path: &path, Description: &description, - ParentID: &GitlabIntTestRootGroupID, + ParentID: &gitlabAPITestConfig.GitlabIntTestRootGroupID, } got, statusCode, err := c.AddGroup(groupOpts) @@ -55,7 +55,7 @@ func TestClient_AddGroups(t *testing.T) { func TestClient_UpdateGroup(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient // create a group to contain test objects groupPath1 := "test-update-group-01" @@ -65,7 +65,7 @@ func TestClient_UpdateGroup(t *testing.T) { Name: &groupName1, Path: &groupPath1, Description: &groupDescription1, - ParentID: &GitlabIntTestRootGroupID, + ParentID: &gitlabAPITestConfig.GitlabIntTestRootGroupID, } group1, statusCode, err := c.AddGroup(groupOpts1) if err != nil { @@ -130,7 +130,7 @@ func TestClient_UpdateGroup(t *testing.T) { func TestClient_GetGroups2(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient got, err := c.GetGroups(nil) if err != nil { t.Errorf("ClientImpl.GetGroups() error = %v", err) @@ -142,7 +142,7 @@ func TestClient_GetGroups2(t *testing.T) { func TestClient_deleteGroups(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient search := testGroupsPrefix groupList, err := c.GetGroups(&search) diff --git a/integration-tests/gitlab/api/gitlab_api_mr_test.go b/integration-tests/gitlab/api/gitlab_api_mr_test.go index be33bce..88dfec5 100644 --- a/integration-tests/gitlab/api/gitlab_api_mr_test.go +++ b/integration-tests/gitlab/api/gitlab_api_mr_test.go @@ -7,32 +7,39 @@ import ( "testing" ) +var mrIID int = 0 +var sourceBranch = "josh-branch" +var targetBranch = "master" + func TestGetMRs(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient - got, err := c.GetMergeRequests(GitlabIntTestRepositoryID, "josh4", "staging") + c := gitlabAPITestConfig.GitlabClient + got, err := c.GetMergeRequests(gitlabAPITestConfig.GitlabIntTestRepositoryID, sourceBranch, targetBranch) if err != nil { t.Errorf("Client.GetMergeRequests error = %v", err) return } - t.Logf("GetMRs %d", len(got)) - for x := 0; x < len(got); x++ { - t.Logf("MR: [%d, %s, %s, %s, %s, %d]", got[x].ID, got[x].State, got[x].Title, got[x].SourceBranch, got[x].TargetBranch, got[x].ProjectID) + t.Logf("GetMergeRequests count: %d", len(got)) + for _, mr := range got { + t.Logf("MR: [%d, %d, %s, %s, %s, %s, %d]", mr.ID, mr.IID, mr.State, mr.Title, mr.SourceBranch, mr.TargetBranch, mr.ProjectID) + if mr.State == "opened" { + mrIID = mr.IID + } } }) } func TestCreateMR(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient title := "Valkyrie Test" description := "Created by Valkyrie" sourceBranch := "josh-branch" - targetBranch := "staging" + targetBranch := "master" removeSourceBranch := true squash := true - got, err := c.CreateMergeRequest(GitlabIntTestRepositoryID, &gitlab2.CreateMergeRequestOptions{ + got, err := c.CreateMergeRequest(gitlabAPITestConfig.GitlabIntTestRepositoryID, &gitlab2.CreateMergeRequestOptions{ Title: &title, Description: &description, SourceBranch: &sourceBranch, @@ -44,20 +51,20 @@ func TestCreateMR(t *testing.T) { Squash: &squash, }) if err != nil { - t.Errorf("Client.GetMergeRequests error = %v", err) + t.Errorf("Client.CreateMergeRequest error = %v", err) return } - - t.Logf("MR: [%d, %s, %s, %s, %s]", got.ProjectID, got.State, got.Title, got.SourceBranch, got.TargetBranch) + mrIID = got.IID + t.Logf("MR: [%d, %d, %s, %s, %s, %s]", got.ID, got.IID, got.State, got.Title, got.SourceBranch, got.TargetBranch) }) } -func TestDeleteMR(t *testing.T) { +func TestCloseMR(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient - err := c.CloseMergeRequest(GitlabIntTestRepositoryID, 2) + c := gitlabAPITestConfig.GitlabClient + err := c.CloseMergeRequest(gitlabAPITestConfig.GitlabIntTestRepositoryID, mrIID) if err != nil { - t.Errorf("Client.DeleteMergeRequest error = %v", err) + t.Errorf("Client.CloseMergeRequest error = %v", err) return } }) diff --git a/integration-tests/gitlab/api/gitlab_api_projects_test.go b/integration-tests/gitlab/api/gitlab_api_projects_test.go index 078e29e..8f87dc7 100644 --- a/integration-tests/gitlab/api/gitlab_api_projects_test.go +++ b/integration-tests/gitlab/api/gitlab_api_projects_test.go @@ -17,7 +17,7 @@ var integrationRootProjectIDProjects = 0 func TestClient_GetProjects(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient got, err := c.GetProjects(nil) if err != nil { t.Errorf("ClientImpl.GetProjects() error = %v", err) @@ -29,7 +29,7 @@ func TestClient_GetProjects(t *testing.T) { func TestClient_GetProjects_Search(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient // this should be found as gitlab has a hidden project with the string monitory searchString := "monitor" @@ -43,10 +43,9 @@ func TestClient_GetProjects_Search(t *testing.T) { }) } - func TestClient_deleteProjectsIfExist(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient search := testProjectsPrefix projectList, err := c.GetProjects(&search) @@ -70,7 +69,7 @@ func TestClient_deleteProjectsIfExist(t *testing.T) { // add groups under the integration test root level group func TestClient_AddProjects(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient for i := 1; i <= projectsTestItemCount; i++ { path := testProjectsPrefix + fmt.Sprintf("%d", i) @@ -82,7 +81,7 @@ func TestClient_AddProjects(t *testing.T) { Name: &name, Path: &path, Description: &description, - NamespaceID: &GitlabIntTestRootGroupID, + NamespaceID: &gitlabAPITestConfig.GitlabIntTestRootGroupID, CIConfigPath: &configPath, } got, statusCode, err := c.AddProject(projectOpts) @@ -99,7 +98,7 @@ func TestClient_AddProjects(t *testing.T) { func TestClient_UpdateProject(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient // create a group to contain test objects path := testProjectsPrefix + "-project-update" @@ -110,7 +109,7 @@ func TestClient_UpdateProject(t *testing.T) { Name: &name, Path: &path, Description: &description, - NamespaceID: &GitlabIntTestRootGroupID, + NamespaceID: &gitlabAPITestConfig.GitlabIntTestRootGroupID, } newProject, statusCode, err := c.AddProject(projectOpts) if err != nil { @@ -138,7 +137,7 @@ func TestClient_UpdateProject(t *testing.T) { func TestClient_deleteProjects(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient search := testProjectsPrefix projectList, err := c.GetProjects(&search) diff --git a/integration-tests/gitlab/api/gitlab_api_repository_test.go b/integration-tests/gitlab/api/gitlab_api_repository_test.go index cdff0d9..d93489d 100644 --- a/integration-tests/gitlab/api/gitlab_api_repository_test.go +++ b/integration-tests/gitlab/api/gitlab_api_repository_test.go @@ -3,29 +3,32 @@ package api import ( + gogitlab "github.com/xanzy/go-gitlab" "net/http" "testing" - - gogitlab "github.com/xanzy/go-gitlab" + "valkyrie.dso.mil/valkyrie-api/clients/git" ) var testProjectsRepoPrefix = "int-test-repo" var integrationProjectIDRepository = 0 + func TestClient_AddProject_Repository(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient path := testProjectsRepoPrefix + "-test" name := testProjectsRepoPrefix + " test " description := "Integration Test Repository" configPath := "a/b/config.yml@group1/group2/project" + trueValue := true projectOpts := gogitlab.CreateProjectOptions{ - Name: &name, - Path: &path, - Description: &description, - NamespaceID: &GitlabIntTestRootGroupID, - CIConfigPath: &configPath, + Name: &name, + Path: &path, + Description: &description, + NamespaceID: &gitlabAPITestConfig.GitlabIntTestRootGroupID, + CIConfigPath: &configPath, + InitializeWithReadme: &trueValue, } got, statusCode, err := c.AddProject(projectOpts) @@ -34,10 +37,10 @@ func TestClient_AddProject_Repository(t *testing.T) { } else { t.Logf("AddProject %s %s %s %s %d", got.Name, got.Path, got.PathWithNamespace, got.WebURL, statusCode) // save test project id - if (statusCode == http.StatusOK) { + if statusCode == http.StatusOK { t.Logf("Status OK") - } - integrationProjectIDRepository = got.ID + } + integrationProjectIDRepository = got.ID } }) } @@ -45,10 +48,10 @@ func TestClient_AddProject_Repository(t *testing.T) { // requies integrationRootProjectIDProjects created from TestClient_AddProject_More_Test func TestClient_GetRepositoryTree(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient projectID := integrationProjectIDRepository got, responseCode, err := c.GetRepositoryTree(projectID) - + if err != nil { t.Errorf("ClientImpl.GetRepositoryTree() project ID %d responseCode %d error = %v", integrationProjectIDRepository, responseCode, err) return @@ -59,7 +62,7 @@ func TestClient_GetRepositoryTree(t *testing.T) { treeLen = len(got) } - if (responseCode == http.StatusNoContent) { + if responseCode == http.StatusNoContent { t.Logf("GetRepositoryTree - responseCode StatusNoContent") } @@ -67,13 +70,31 @@ func TestClient_GetRepositoryTree(t *testing.T) { }) } +func TestClient_AddFilesToRepository(t *testing.T) { + client, err := git.NewClient(gitlabAPITestConfig.GitlabIntTestUsername, gitlabAPITestConfig.GitlabIntTestToken, gitlabAPITestConfig.GitlabIntTestRepositoryURL) + if err != nil { + t.Errorf("%v", err) + return + } + + err = client.CheckoutOrCreateBranch("master") + if err != nil { + t.Errorf("%v", err) + return + } + + err = client.AddPath("/tmp/test") + err = client.Commit("commit message") + err = client.Push() +} + // Add a file to the Repo // Get tree again func TestClient_deleteProjectsIfExistRepo(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient search := testProjectsRepoPrefix projectList, err := c.GetProjects(&search) @@ -92,4 +113,4 @@ func TestClient_deleteProjectsIfExistRepo(t *testing.T) { } }) -} \ No newline at end of file +} diff --git a/integration-tests/gitlab/api/gitlab_api_users_test.go b/integration-tests/gitlab/api/gitlab_api_users_test.go index 933cb53..c47d9e4 100644 --- a/integration-tests/gitlab/api/gitlab_api_users_test.go +++ b/integration-tests/gitlab/api/gitlab_api_users_test.go @@ -15,7 +15,7 @@ const testUserPrefix = "IntTestTemp-User-" //TestClient_getUsers - func TestClient_getUsers(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient got, err := c.GetUsers(nil) if err != nil { @@ -29,7 +29,7 @@ func TestClient_getUsers(t *testing.T) { // TestClient_addUsers - func TestClient_addUsers(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient for i := 1; i <= testItemCount; i++ { username := testUserPrefix + fmt.Sprintf("%d", i) @@ -56,7 +56,7 @@ func TestClient_addUsers(t *testing.T) { func TestClient_UpdateUser(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient // create a user username := testUserPrefix + "update01" name := "test update user name 01" @@ -117,7 +117,7 @@ func TestClient_UpdateUser(t *testing.T) { } func TestClient_getUsersCount(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient got, err := c.GetUsers(nil) if err != nil { t.Errorf("ClientImpl.GetUsers() error = %v", err) @@ -128,7 +128,7 @@ func TestClient_getUsersCount(t *testing.T) { } func TestClient_deleteUsers(t *testing.T) { t.Run("test", func(t *testing.T) { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient for i := 1; i <= testItemCount; i++ { username := testUserPrefix + fmt.Sprintf("%d", i) diff --git a/integration-tests/gitlab/api/gitlab_main_test.go b/integration-tests/gitlab/api/gitlab_main_test.go index fb7a4e9..05d1e22 100644 --- a/integration-tests/gitlab/api/gitlab_main_test.go +++ b/integration-tests/gitlab/api/gitlab_main_test.go @@ -17,14 +17,22 @@ import ( "valkyrie.dso.mil/valkyrie-api/clients/gitlab" ) -var WorkingDir string = "" -var GitlabAPIToken string = "" -var GitlabAPIURL string = "" -var GitlabClient gitlab.ClientImpl -var GitlabIntTestRepository string = "" -var GitlabIntTestRepositoryID int = 0 -var GitlabIntTestRootGroup string = "" -var GitlabIntTestRootGroupID int = 0 +type gitlabAPITestConfigType struct { + WorkingDir string + GitlabIntTestUsername string + GitlabIntTestToken string + GitlabAPIToken string + GitlabAPIURL string + GitlabClient gitlab.ClientImpl + GitlabIntTestProjectPath string + GitlabIntTestProjectURL string + GitlabIntTestRepositoryURL string + GitlabIntTestRepositoryID int + GitlabIntTestRootGroupPath string + GitlabIntTestRootGroupID int +} + +var gitlabAPITestConfig gitlabAPITestConfigType // TestMain - setup and teardown reusable code. wraps around other tests func TestMain(m *testing.M) { @@ -46,60 +54,71 @@ func TestMain(m *testing.M) { // packageSetup - setup environment for integration testing func packageSetup() error { - WorkingDir, _ = os.Getwd() + gitlabAPITestConfig.WorkingDir, _ = os.Getwd() var ok bool var err error - GitlabAPIURL, ok = os.LookupEnv("GITLAB_API_URL") + gitlabAPITestConfig.GitlabAPIURL, ok = os.LookupEnv("GITLAB_API_URL") if !ok { err = errors.New("env variable GITLAB_API_URL undefined") return err } - GitlabAPIToken, ok = os.LookupEnv("GITLAB_API_TOKEN") + gitlabAPITestConfig.GitlabAPIToken, ok = os.LookupEnv("GITLAB_API_TOKEN") if !ok { err := errors.New("env variable GITLAB_API_TOKEN undefined") return err } - GitlabIntTestRepository, ok = os.LookupEnv("GITLAB_INT_TEST_REPOSITORY") + gitlabAPITestConfig.GitlabIntTestProjectURL, ok = os.LookupEnv("GITLAB_INT_TEST_PROJECT_URL") if !ok { - err := errors.New("env variable GITLAB_INT_TEST_REPOSITORY undefined") + err := errors.New("env variable GITLAB_INT_TEST_PROJECT_URL undefined") return err } - GitlabIntTestRootGroup, ok = os.LookupEnv("GITLAB_INT_TEST_ROOT_GROUP") + gitlabAPITestConfig.GitlabIntTestProjectPath, ok = os.LookupEnv("GITLAB_INT_TEST_PROJECT_PATH") if !ok { - err := errors.New("env variable GITLAB_INT_TEST_ROOT_GROUP undefined") + err := errors.New("env variable GITLAB_INT_TEST_PROJECT_PATH undefined") return err } - GitlabClient, err = gitlab.NewClient(GitlabAPIURL, GitlabAPIToken, nil) - if err != nil { + gitlabAPITestConfig.GitlabIntTestRepositoryURL, ok = os.LookupEnv("GITLAB_INT_TEST_REPOSITORY_URL") + if !ok { + err := errors.New("env variable GITLAB_INT_TEST_REPOSITORY_URL undefined") return err } - url, err := url.Parse(GitlabIntTestRepository) - if err != nil { + gitlabAPITestConfig.GitlabIntTestRootGroupPath, ok = os.LookupEnv("GITLAB_INT_TEST_ROOT_GROUP_PATH") + if !ok { + err := errors.New("env variable GITLAB_INT_TEST_ROOT_GROUP_PATH undefined") return err } - var project *gogitlab.Project = nil - var responseCode int + gitlabAPITestConfig.GitlabIntTestUsername, ok = os.LookupEnv("GITLAB_INT_TEST_USERNAME") + if !ok { + err := errors.New("env variable GITLAB_INT_TEST_USERNAME undefined") + return err + } - var urlPath = strings.TrimLeft(url.Path, "/") - project, responseCode, err = GitlabClient.GetProjectByFullPath(&urlPath) - if err != nil { + gitlabAPITestConfig.GitlabIntTestToken, ok = os.LookupEnv("GITLAB_INT_TEST_TOKEN") + if !ok { + err := errors.New("env variable GITLAB_INT_TEST_TOKEN undefined") return err } - if responseCode != http.StatusFound { - err := fmt.Errorf("bad response code %d for GetProjectByFullPath path %s", responseCode, urlPath) + + gitlabAPITestConfig.GitlabClient, err = gitlab.NewClient(gitlabAPITestConfig.GitlabAPIURL, gitlabAPITestConfig.GitlabAPIToken, nil) + if err != nil { return err } - GitlabIntTestRepositoryID = project.ID // insure a root group exists in gitlab - err = AddRootGroup() + err = addRootGroup() + if err != nil { + return err + } + + // insure a test project exists in root group + gitlabAPITestConfig.GitlabIntTestRepositoryID, err = addIntTestProject(gitlabAPITestConfig.GitlabIntTestProjectURL) if err != nil { return err } @@ -112,12 +131,12 @@ func packageTeardown() error { } // Insure the integration test root level group exists -func AddRootGroup() error { +func addRootGroup() error { - c := GitlabClient + c := gitlabAPITestConfig.GitlabClient - path := GitlabIntTestRootGroup - name := GitlabIntTestRootGroup + path := gitlabAPITestConfig.GitlabIntTestRootGroupPath + name := gitlabAPITestConfig.GitlabIntTestRootGroupPath description := "Integration Test Root Level Group" group, statusCode, err := c.GetGroupByFullPath(&path) @@ -129,7 +148,7 @@ func AddRootGroup() error { if statusCode == http.StatusFound { // root group found - GitlabIntTestRootGroupID = group.ID + gitlabAPITestConfig.GitlabIntTestRootGroupID = group.ID fmt.Printf("AddRootGroup Group Found: %s %s %s %s %d \n", group.Name, group.Path, group.FullPath, group.WebURL, statusCode) } else { // try to create root group @@ -141,9 +160,55 @@ func AddRootGroup() error { fmt.Printf("Error! AddRootGroup %s error = %v %d\n", path, err, statusCode) return err } else { - GitlabIntTestRootGroupID = got.ID + gitlabAPITestConfig.GitlabIntTestRootGroupID = got.ID fmt.Printf("AddGroup %s %s %s %s %d \n", got.Name, got.Path, got.FullPath, got.WebURL, statusCode) } } return nil } + +// Insure the integration test project exists +func addIntTestProject(projectUrl string) (int, error) { + + var project *gogitlab.Project = nil + var responseCode int + + url, err := url.Parse(projectUrl) + if err != nil { + return 0, err + } + + var urlPath = strings.TrimLeft(url.Path, "/") + project, responseCode, err = gitlabAPITestConfig.GitlabClient.GetProjectByFullPath(&urlPath) + if err != nil { + return 0, err + } + + if responseCode == http.StatusFound { + return project.ID, nil + } else { + path := gitlabAPITestConfig.GitlabIntTestProjectPath + name := gitlabAPITestConfig.GitlabIntTestProjectPath + description := "Integration Test Project" + configPath := "a/b/config.yml@group1/group2/project" + initializeWithReadme := true + + projectOpts := gogitlab.CreateProjectOptions{ + Name: &name, + Path: &path, + Description: &description, + NamespaceID: &gitlabAPITestConfig.GitlabIntTestRootGroupID, + CIConfigPath: &configPath, + InitializeWithReadme: &initializeWithReadme, + } + got, statusCode, err := gitlabAPITestConfig.GitlabClient.AddProject(projectOpts) + + if err != nil { + fmt.Printf("ClientImpl.AddProject() error = %v %d \n", err, statusCode) + return 0, err + } + + fmt.Printf("AddProject %s %s %s %s %d", got.Name, got.Path, got.PathWithNamespace, got.WebURL, statusCode) + return got.ID, nil + } +} diff --git a/scripts/valkyrie_env.sh b/scripts/valkyrie_env.sh index 61fd97e..e351895 100644 --- a/scripts/valkyrie_env.sh +++ b/scripts/valkyrie_env.sh @@ -1,11 +1,16 @@ #!/bin/env bash -# setup env for developer cluster -# set env for integration testing - -export GITLAB_API_URL="https://gitlab.bigbang.dev/api/v4" +# environment variables for Valkyrie integration testing +# AWS dev cluster +# create necessary tokens and update CHANGEME +export GITLAB_HOSTNAME=gitlab.bigbang.dev +export GITLAB_API_URL="https://${GITLAB_HOSTNAME}/api/v4" export GITLAB_API_TOKEN=CHANGEME - -export GITLAB_INT_TEST_REPOSITORY=https://gitlab.bigbang.dev/integration-root-group/int-test-project +export GITLAB_INT_TEST_PROJECT_PATH=integration-test-project +# make sure this root level group exists +export GITLAB_INT_TEST_ROOT_GROUP_PATH=integration-root-group +export GITLAB_INT_TEST_PROJECT_URL=https://${GITLAB_HOSTNAME}/${GITLAB_INT_TEST_ROOT_GROUP_PATH}/${GITLAB_INT_TEST_PROJECT_PATH} +export GITLAB_INT_TEST_REPOSITORY_URL=https://${GITLAB_HOSTNAME}/${GITLAB_INT_TEST_ROOT_GROUP_PATH}/${GITLAB_INT_TEST_PROJECT_PATH} +# make sure this user exists as admin export GITLAB_INT_TEST_USERNAME=integration_test_user export GITLAB_INT_TEST_TOKEN=CHANGEME -- GitLab From e08feefb7bf6bfdc432e19415524b6cf967833ec Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Thu, 26 Aug 2021 11:39:28 -0600 Subject: [PATCH 21/55] cleanup after merge minor cleanup --- Makefile | 7 +- clients/git/repo_client.go | 13 +-- clients/git/repo_client_test.go | 33 ------ .../gitclient/git_api_adhoc_test.go | 107 ------------------ integration-tests/gitclient/git_main_test.go | 71 ------------ .../gitlab/api/gitlab_api_repository_test.go | 7 +- rlog.conf | 2 +- 7 files changed, 10 insertions(+), 230 deletions(-) delete mode 100644 integration-tests/gitclient/git_api_adhoc_test.go delete mode 100644 integration-tests/gitclient/git_main_test.go diff --git a/Makefile b/Makefile index de0adfa..dc687d6 100644 --- a/Makefile +++ b/Makefile @@ -63,9 +63,10 @@ test: ## manifests generate ## Run tests. source ${ENVTEST_ASSETS_DIR}/setup-envtest.sh; fetch_envtest_tools $(ENVTEST_ASSETS_DIR); setup_envtest_env $(ENVTEST_ASSETS_DIR); go test ./... -coverprofile cover.out ; go tool cover -html=./cover.out -o ./coverage.html integration: ## integration tests - @go clean --cache - @find ./integration-tests -type d | xargs -I {} bash -c "echo \"\"; echo \"Integration test dir: {}\"; go test -tags \"integration\" {}" - + @echo "Running Integration Test. Be patient. Some tests may take up to 2 minutes." + @go clean -testcache + @go test -tags "integration" ./integration-tests/... + ##@ Build build: generate fmt vet ## Build manager binary. diff --git a/clients/git/repo_client.go b/clients/git/repo_client.go index 828ada0..723590e 100644 --- a/clients/git/repo_client.go +++ b/clients/git/repo_client.go @@ -24,7 +24,6 @@ type RepoClient interface { CheckoutOrCreateBranch(branchName string) (err error) GetFileSystem() *billy.Filesystem AddFile(filePath string) (err error) - AddPath(filePath string) (err error) Commit(message string) (err error) Push(branchName string) (err error) DeleteRemoteBranch(branchName string) (err error) @@ -112,7 +111,7 @@ func (c *RepoClientImpl) CheckoutOrCreateBranch(branchName string) (err error) { if err != nil { // got an error - try to create it in local context - rlog.Warnf("CheckoutOrCreateBranch - checkout with create false failed %v", err) + rlog.Debugf("CheckoutOrCreateBranch - checkout with create false failed %v", err) err = w.Checkout(&git.CheckoutOptions{Create: true, Force: false, Branch: branchRefName}) if err != nil { return @@ -137,16 +136,6 @@ func (c *RepoClientImpl) AddFile(filePath string) (err error) { return } -//AddPath adds entire path -func (c *RepoClientImpl) AddPath(filePath string) (err error) { - w, err := c.repo.Worktree() - if err != nil { - return - } - err = w.AddGlob(filePath) - return -} - //Commit commits the changes with a message func (c *RepoClientImpl) Commit(message string) (err error) { w, err := c.repo.Worktree() diff --git a/clients/git/repo_client_test.go b/clients/git/repo_client_test.go index 6d6d4a7..2dc4b79 100644 --- a/clients/git/repo_client_test.go +++ b/clients/git/repo_client_test.go @@ -63,39 +63,6 @@ func TestRepoClientImpl_AddFile(t *testing.T) { } } -func TestRepoClientImpl_AddPath(t *testing.T) { - fileSystem := memfs.New() - auth := &http.BasicAuth{ - Username: "username", - Password: "token", - } - memStorage := memory.NewStorage() - repo, err := git.Init(memStorage, fileSystem) - if err != nil { - panic(err) - } - client := RepoClientImpl{ - repo: repo, - fs: &fileSystem, - auth: auth, - } - - err = client.AddPath("test_not_found") - if err == nil { - t.Fatal("expect find not found error, but got no error") - } - - fileSystem.Create("new_file1") - fileSystem.MkdirAll("dir1/dir2/dir3", 0755) - fileSystem.Create("dir1/new_file2") - fileSystem.Create("dir1/new_file22") - fileSystem.Create("dir1/dir2/new_file3") - err = client.AddPath("dir1") - if err != nil { - t.Fatalf("expect no error but got %v", err) - } -} - func TestRepoClientImpl_Commit(t *testing.T) { fileSystem := memfs.New() auth := &http.BasicAuth{ diff --git a/integration-tests/gitclient/git_api_adhoc_test.go b/integration-tests/gitclient/git_api_adhoc_test.go deleted file mode 100644 index 96530bd..0000000 --- a/integration-tests/gitclient/git_api_adhoc_test.go +++ /dev/null @@ -1,107 +0,0 @@ -// +build integration - -package gitclient - -import ( - "bufio" - "fmt" - "strings" - "testing" - "valkyrie.dso.mil/valkyrie-api/clients/git" -) - -func TestGit(t *testing.T) { - - client, err := git.NewClient(GitUsername, GitToken, GitRepoURL) - if err != nil { - fmt.Printf("%v", err) - return - } - - err = client.DeleteRemoteBranch("josh4") - if err != nil { - fmt.Printf("%v", err) - return - } - - err = client.CheckoutOrCreateBranch("josh4") - if err != nil { - fmt.Printf("%v", err) - return - } - - fs := *client.GetFileSystem() - dnsFilePath := "staging/dns/configuration/db.staging.dso.mil" - dnsFile, err := fs.Open(dnsFilePath) - if err != nil { - fmt.Printf("%v", err) - return - } - - tempFile, err := fs.Create("temp_file") - if err != nil { - fmt.Printf("%v", err) - return - } - - scanner := bufio.NewScanner(dnsFile) - var done bool - for scanner.Scan() { - line := scanner.Text() - count, err := tempFile.Write(scanner.Bytes()) - tempFile.Write([]byte("\n")) - if err != nil { - fmt.Printf("%v", err) - } - fmt.Printf("written %d bytes", count) - - if !done && strings.Contains(line, "-il2 ") { - tempFile.Write([]byte("I am here...\n")) - done = true - } - } - - if err := scanner.Err(); err != nil { - fmt.Printf("%v", err) - } - - tempFile.Close() - dnsFile.Close() - - err = fs.Rename("temp_file", dnsFilePath) - if err != nil { - fmt.Printf("%v", err) - } - - tempFile, err = fs.Open(dnsFilePath) - if err != nil { - fmt.Printf("%v", err) - } - - fmt.Println("======================") - scanner2 := bufio.NewScanner(tempFile) - for scanner2.Scan() { - line := scanner2.Text() - fmt.Println(line) - } - - tempFile.Close() - - err = client.AddFile(dnsFilePath) - if err != nil { - fmt.Printf("%v", err) - return - } - - err = client.Commit("Add new entry for new site - Valkyrie") - if err != nil { - fmt.Printf("%v", err) - return - } - - err = client.Push() - if err != nil { - return - } - -} diff --git a/integration-tests/gitclient/git_main_test.go b/integration-tests/gitclient/git_main_test.go deleted file mode 100644 index eaeeecf..0000000 --- a/integration-tests/gitclient/git_main_test.go +++ /dev/null @@ -1,71 +0,0 @@ -// +build integration - -package gitclient - -// go test -v -tags "integration" ./integration-tests/git - -import ( - "errors" - "fmt" - "os" - "testing" -) - -var WorkingDir string = "" -var GitUsername string = "" -var GitToken string = "" -var GitRepoURL string = "" - -// Notes: -// teststring string `json:"-"` // - means dont override struct -// `json:"impact_level,omitempty dont output to json if empty -// TemplateConfigApplication - - -// TestMain - setup and teardown reusable code. wraps around other tests -func TestMain(m *testing.M) { - - // setup environment for testing - err := packageSetup() - if err != nil { - fmt.Printf("packageSetup error: %v\n", err) - os.Exit(1) - } - - // run tests - resultCode := m.Run() - - packageTeardown() - - os.Exit(resultCode) -} - -// packageSetup - setup environment for integration testing -func packageSetup() error { - WorkingDir, _ = os.Getwd() - var ok bool - GitUsername, ok = os.LookupEnv("GITLAB_INT_TEST_USERNAME") - if !ok { - err := errors.New("env variable GITLAB_INT_TEST_USERNAME undefined") - - return err - } - - GitToken, ok = os.LookupEnv("GITLAB_INT_TEST_TOKEN") - if !ok { - err := errors.New("env variable GITLAB_INT_TEST_TOKEN undefined") - - return err - } - - GitRepoURL, ok = os.LookupEnv("GITLAB_INT_TEST_REPOSITORY_URL") - if !ok { - err := errors.New("env variable GITLAB_INT_TEST_REPOSITORY_URL undefined") - - return err - } - return nil -} - -func packageTeardown() error { - return nil -} diff --git a/integration-tests/gitlab/api/gitlab_api_repository_test.go b/integration-tests/gitlab/api/gitlab_api_repository_test.go index d93489d..4ea6455 100644 --- a/integration-tests/gitlab/api/gitlab_api_repository_test.go +++ b/integration-tests/gitlab/api/gitlab_api_repository_test.go @@ -71,21 +71,22 @@ func TestClient_GetRepositoryTree(t *testing.T) { } func TestClient_AddFilesToRepository(t *testing.T) { + branch := "testAddFile" client, err := git.NewClient(gitlabAPITestConfig.GitlabIntTestUsername, gitlabAPITestConfig.GitlabIntTestToken, gitlabAPITestConfig.GitlabIntTestRepositoryURL) if err != nil { t.Errorf("%v", err) return } - err = client.CheckoutOrCreateBranch("master") + err = client.CheckoutOrCreateBranch(branch) if err != nil { t.Errorf("%v", err) return } - err = client.AddPath("/tmp/test") + err = client.AddFile("/tmp/test") err = client.Commit("commit message") - err = client.Push() + err = client.Push(branch) } // Add a file to the Repo diff --git a/rlog.conf b/rlog.conf index 3af4f5c..9e97895 100644 --- a/rlog.conf +++ b/rlog.conf @@ -1,7 +1,7 @@ # Comment lines start with a '#' # any variable can be prefixed with ! to prevent override by ENV variables # export RLOG_CONF_FILE= -RLOG_LOG_LEVEL = DEBUG +RLOG_LOG_LEVEL = WARN RLOG_LOG_STREAM = stdout # time format - RLOG_TIME_FORMAT="2006/01/06 15:04:05.00" -- GitLab From ce9740be26f3fa21f2610e7edccd572d9df59d0d Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Thu, 26 Aug 2021 13:06:32 -0600 Subject: [PATCH 22/55] update add to repo --- integration-tests/gitlab/api/gitlab_api_repository_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/gitlab/api/gitlab_api_repository_test.go b/integration-tests/gitlab/api/gitlab_api_repository_test.go index 4ea6455..0b35926 100644 --- a/integration-tests/gitlab/api/gitlab_api_repository_test.go +++ b/integration-tests/gitlab/api/gitlab_api_repository_test.go @@ -71,7 +71,7 @@ func TestClient_GetRepositoryTree(t *testing.T) { } func TestClient_AddFilesToRepository(t *testing.T) { - branch := "testAddFile" + branch := "testAddFileToRepository" client, err := git.NewClient(gitlabAPITestConfig.GitlabIntTestUsername, gitlabAPITestConfig.GitlabIntTestToken, gitlabAPITestConfig.GitlabIntTestRepositoryURL) if err != nil { t.Errorf("%v", err) -- GitLab From ce7fbc5d7b3f9396af981b54fc6088fa9f3fa92a Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Fri, 27 Aug 2021 09:30:50 -0600 Subject: [PATCH 23/55] add tar file for int testing --- .../gitclient/data/dso-dns-staging.tar.gz | Bin 0 -> 115712 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 integration-tests/gitclient/data/dso-dns-staging.tar.gz diff --git a/integration-tests/gitclient/data/dso-dns-staging.tar.gz b/integration-tests/gitclient/data/dso-dns-staging.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..768fee64da64a51547ffcbf4c4a96f6f84b53e97 GIT binary patch literal 115712 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 E|IUJA@c;k- literal 0 HcmV?d00001 -- GitLab From a4b8d38f226625d7933015c92fd947e859cdb7f3 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Fri, 27 Aug 2021 13:54:32 -0600 Subject: [PATCH 24/55] some success with od file system in git --- clients/git/repo_client.go | 30 +++-- clients/utils/datetime_utils.go | 16 +++ clients/utils/file_utils.go | 35 +++++ go.mod | 1 - .../gitclient/gitclient_addpath_test.go | 120 ++++++++++++++++++ .../gitclient/gitclient_branch_test.go | 32 +---- .../gitclient/gitclient_main_test.go | 13 +- 7 files changed, 208 insertions(+), 39 deletions(-) create mode 100644 clients/utils/datetime_utils.go create mode 100644 clients/utils/file_utils.go create mode 100644 integration-tests/gitclient/gitclient_addpath_test.go diff --git a/clients/git/repo_client.go b/clients/git/repo_client.go index 723590e..2e8def0 100644 --- a/clients/git/repo_client.go +++ b/clients/git/repo_client.go @@ -38,27 +38,33 @@ type RepoClientImpl struct { //NewClient creates an new client to manage the repo. Using memoryFS by default func NewClient(username string, token string, repoURL string) (client *RepoClientImpl, err error) { - return NewClientFS(username, token, repoURL, true) + return newClientFS(username, token, repoURL, true, "") } -//NewClientFS creates an new client to manage the repo. -func NewClientFS(username string, token string, repoURL string, memoryFs bool) (client *RepoClientImpl, err error) { +//NewClientOSFS creates an new client to manage the repo. Using OS FS +func NewClientOSFS(username string, token string, repoURL string, osPath string) (client *RepoClientImpl, err error) { + return newClientFS(username, token, repoURL, false, osPath) +} + +// newClientFS creates an new client to manage the repo. +func newClientFS(username string, token string, repoURL string, memoryFs bool, osPath string) (client *RepoClientImpl, err error) { auth := http.BasicAuth{ Username: username, Password: token, } var fs billy.Filesystem - var s storage.Storer + var storer storage.Storer if memoryFs { fs = memfs.New() - s = memory.NewStorage() + storer = memory.NewStorage() } else { - // TODO: test and fix use of os file system - fs = osfs.New("/tmp/test") - s = filesystem.NewStorage(fs, cache.NewObjectLRUDefault()) + rlog.Debugf("newClientFS - creating git fs at path: %s", osPath) + fs = osfs.New(osPath) + dot, _ := fs.Chroot(".git") + storer = filesystem.NewStorage(dot, cache.NewObjectLRUDefault()) } - r, err := git.Clone(s, fs, &git.CloneOptions{ + r, err := git.Clone(storer, fs, &git.CloneOptions{ URL: repoURL, RemoteName: remoteName, Auth: &auth, @@ -96,10 +102,12 @@ func (c *RepoClientImpl) CheckoutOrCreateBranch(branchName string) (err error) { return } err = c.repo.Fetch(&git.FetchOptions{ - Auth: c.auth, - RefSpecs: []config.RefSpec{"refs/*:refs/*", "HEAD:refs/heads/HEAD"}, + Auth: c.auth, + RemoteName: remoteName, + RefSpecs: []config.RefSpec{"refs/*:refs/*", "HEAD:refs/heads/HEAD"}, }) if err != nil { + rlog.Errorf("CheckoutOrCreateBranch - Fetch - Error %v", err) return } diff --git a/clients/utils/datetime_utils.go b/clients/utils/datetime_utils.go new file mode 100644 index 0000000..e0f0e4b --- /dev/null +++ b/clients/utils/datetime_utils.go @@ -0,0 +1,16 @@ +package utils + +import ( + "time" + + "github.com/romana/rlog" +) + +// DateTimeUTC - generate ISO date time string UTC +func DateTimeUTC() string { + loc, _ := time.LoadLocation("UTC") + now := time.Now().In(loc) + dt := now.String() + rlog.Debugf("DateTimeUTC Location: %s DateTime String: %s", loc, dt) + return dt +} diff --git a/clients/utils/file_utils.go b/clients/utils/file_utils.go new file mode 100644 index 0000000..8d6578f --- /dev/null +++ b/clients/utils/file_utils.go @@ -0,0 +1,35 @@ +package utils + +import ( + "io/ioutil" + "os" + + "github.com/romana/rlog" +) + +//TempRoot - temp directory root for current OS +var TempRoot = os.TempDir() + string(os.PathSeparator) + "valkyrie-temp" + +// Function pointers - allows for easy mocking of functions +var osMkdirAll = os.MkdirAll + +// processError - helper +func processError(logPrefix string, err error) { + rlog.Warnf("%s error: %v", logPrefix, err) +} + +// CreateTempDir helper to create temporary directory +func CreateTempDir(prefix string, rootDir string) (tempDir string, err error) { + logPrefix := "createTempDir" + err = osMkdirAll(rootDir, 0770) + if err != nil { + processError(logPrefix, err) + return "", err + } + tempDir, err = ioutil.TempDir(rootDir, prefix) + if err != nil { + processError(logPrefix, err) + return "", err + } + return tempDir, nil +} diff --git a/go.mod b/go.mod index 94da99e..511fda4 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module valkyrie.dso.mil/valkyrie-api go 1.15 require ( - github.com/emirpasic/gods v1.12.0 github.com/go-git/go-billy/v5 v5.3.1 github.com/go-git/go-git/v5 v5.4.2 github.com/go-logr/logr v0.3.0 diff --git a/integration-tests/gitclient/gitclient_addpath_test.go b/integration-tests/gitclient/gitclient_addpath_test.go new file mode 100644 index 0000000..340e2e3 --- /dev/null +++ b/integration-tests/gitclient/gitclient_addpath_test.go @@ -0,0 +1,120 @@ +package gitclient + +import ( + "fmt" + + "testing" + + "valkyrie.dso.mil/valkyrie-api/clients/git" + "valkyrie.dso.mil/valkyrie-api/clients/utils" +) + +func TestGit_AddPath_Create_Branch(t *testing.T) { + var branch = "testCreateBranchOSFS" + + tempDir, err := utils.CreateTempDir("git-", utils.TempRoot) + if err != nil { + t.Errorf("Error - CreateTempDir %v", err) + return + } + t.Logf("TestGit_AddPath_Create_Branch - Created temp dir %s", tempDir) + + client, err := git.NewClientOSFS( + gitclientTestConfig.GitlabIntTestUsername, + gitclientTestConfig.GitlabIntTestToken, + gitclientTestConfig.GitlabIntTestRepositoryURL, + tempDir, + ) + if err != nil { + t.Errorf("Error - TestGit_AddPath_Create_Branch - NewClientOSFS %v", err) + return + } + // If remote does NOT already exist, then this is a LOCAL Branch only until pushed + err = client.CheckoutOrCreateBranch(branch) + if err != nil { + t.Errorf("Error - TestGit_AddPath_Create_Branch - CheckoutOrCreateBranch %v", err) + return + } + + // push to remote to create remote branch if does NOT already + err = client.Push(branch) + //if already up-to-date, then it's already deleted + if err != nil && err.Error() == "already up-to-date" { + t.Logf("Push branch %s - already exists", branch) + err = nil + } + if err != nil { + t.Errorf("Push %v", err) + return + } + t.Logf("Checkout and Push branch %s - success", branch) + +} + +func TestGit_AddPath_Checkout_AddNewFile_Push(t *testing.T) { + branch := "testAddFileOSFS" + + tempDir, err := utils.CreateTempDir("git", utils.TempRoot) + if err != nil { + t.Errorf("NewClient %v", err) + return + } + + // create the git client + client, err := git.NewClientOSFS( + gitclientTestConfig.GitlabIntTestUsername, + gitclientTestConfig.GitlabIntTestToken, + gitclientTestConfig.GitlabIntTestRepositoryURL, + tempDir, + ) + if err != nil { + t.Errorf("%v", err) + return + } + t.Logf("Created git client for repo %s", gitclientTestConfig.GitlabIntTestRepositoryURL) + + err = client.CheckoutOrCreateBranch(branch) + if err != nil { + t.Errorf("%v", err) + return + } + t.Logf("Checked out branch %s", branch) + logGitStatus(t, client) + + fs := *client.GetFileSystem() + + newFilePath := "test.txt" + newFile, err := fs.Create(newFilePath) + if err != nil { + t.Errorf("%v", err) + return + } + _, err = newFile.Write([]byte(utils.DateTimeUTC())) + if err != nil { + t.Errorf("%v", err) + return + } + newFile.Close() + logGitStatus(t, client) + + err = client.AddFile(newFilePath) + if err != nil { + t.Errorf("%v", err) + return + } + logGitStatus(t, client) + + commitMessage := fmt.Sprintf("Add new file - Valkyrie %s", utils.DateTimeUTC()) + err = client.Commit(commitMessage) + if err != nil { + t.Errorf("%v", err) + return + } + logGitStatus(t, client) + + err = client.Push(branch) + if err != nil { + t.Errorf("%v", err) + return + } +} diff --git a/integration-tests/gitclient/gitclient_branch_test.go b/integration-tests/gitclient/gitclient_branch_test.go index 5336c6f..aa83843 100644 --- a/integration-tests/gitclient/gitclient_branch_test.go +++ b/integration-tests/gitclient/gitclient_branch_test.go @@ -7,9 +7,9 @@ import ( "fmt" "strings" "testing" - "time" "valkyrie.dso.mil/valkyrie-api/clients/git" + "valkyrie.dso.mil/valkyrie-api/clients/utils" ) func TestGit_Create_Branch(t *testing.T) { @@ -21,14 +21,14 @@ func TestGit_Create_Branch(t *testing.T) { gitclientTestConfig.GitlabIntTestRepositoryURL, ) if err != nil { - t.Errorf("NewClient %v", err) + t.Errorf("Error NewClient %v", err) return } // If remote does NOT already exist, then this is a LOCAL Branch only until pushed err = client.CheckoutOrCreateBranch(branch) if err != nil { - t.Errorf(" CheckoutOrCreateBranch %v", err) + t.Errorf("Error CheckoutOrCreateBranch %v", err) return } @@ -127,7 +127,7 @@ func TestGit_Checkout_AddNewFile_Push(t *testing.T) { t.Errorf("%v", err) return } - _, err = newFile.Write([]byte(dateTimeUTC())) + _, err = newFile.Write([]byte(utils.DateTimeUTC())) if err != nil { t.Errorf("%v", err) return @@ -142,7 +142,7 @@ func TestGit_Checkout_AddNewFile_Push(t *testing.T) { } logGitStatus(t, client) - commitMessage := fmt.Sprintf("Add new file - Valkyrie %s", dateTimeUTC()) + commitMessage := fmt.Sprintf("Add new file - Valkyrie %s", utils.DateTimeUTC()) err = client.Commit(commitMessage) if err != nil { t.Errorf("%v", err) @@ -192,9 +192,9 @@ func TestGit_Checkout_UpdateFile_Push(t *testing.T) { } t.Logf("Checked out and Create branch %s", branch) - // Add + // Add fs := *client.GetFileSystem() - + dnsFilePath := "staging/dns/configuration/db.staging.dso.mil" dnsFile, err := fs.Open(dnsFilePath) if err != nil { @@ -266,22 +266,4 @@ func TestGit_Checkout_UpdateFile_Push(t *testing.T) { if err != nil { return } - -} - -func dateTimeUTC() string { - loc, _ := time.LoadLocation("UTC") - now := time.Now().In(loc) - dt := now.String() - return dt -} - -func logGitStatus(t *testing.T, client *git.RepoClientImpl) { - status, err := client.Status() - if err != nil { - t.Errorf("%v", err) - return - } - t.Logf("working tree status: %s", status) - } diff --git a/integration-tests/gitclient/gitclient_main_test.go b/integration-tests/gitclient/gitclient_main_test.go index 274c01c..9392910 100644 --- a/integration-tests/gitclient/gitclient_main_test.go +++ b/integration-tests/gitclient/gitclient_main_test.go @@ -1,5 +1,3 @@ -// +build integration - package gitclient import ( @@ -7,6 +5,7 @@ import ( "fmt" "os" "testing" + "valkyrie.dso.mil/valkyrie-api/clients/git" ) type gitclientTestConfigType struct { @@ -63,3 +62,13 @@ func packageSetup() error { func packageTeardown() error { return nil } + +func logGitStatus(t *testing.T, client *git.RepoClientImpl) { + status, err := client.Status() + if err != nil { + t.Errorf("%v", err) + return + } + t.Logf("working tree status: %s", status) + +} -- GitLab From c9f7c3d899f0d2fbfdec88fbe5f515f571466dd7 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Fri, 27 Aug 2021 14:33:24 -0600 Subject: [PATCH 25/55] fix int test scope --- .../gitclient/gitclient_addpath_test.go | 85 ++++++++++++++++++- .../gitclient/gitclient_main_test.go | 2 + 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/integration-tests/gitclient/gitclient_addpath_test.go b/integration-tests/gitclient/gitclient_addpath_test.go index 340e2e3..c8a0a88 100644 --- a/integration-tests/gitclient/gitclient_addpath_test.go +++ b/integration-tests/gitclient/gitclient_addpath_test.go @@ -1,18 +1,21 @@ +// +build integration + package gitclient import ( "fmt" + "os" "testing" "valkyrie.dso.mil/valkyrie-api/clients/git" "valkyrie.dso.mil/valkyrie-api/clients/utils" ) - +var directoryPrefix = "git-" func TestGit_AddPath_Create_Branch(t *testing.T) { var branch = "testCreateBranchOSFS" - tempDir, err := utils.CreateTempDir("git-", utils.TempRoot) + tempDir, err := utils.CreateTempDir(directoryPrefix, utils.TempRoot) if err != nil { t.Errorf("Error - CreateTempDir %v", err) return @@ -54,7 +57,7 @@ func TestGit_AddPath_Create_Branch(t *testing.T) { func TestGit_AddPath_Checkout_AddNewFile_Push(t *testing.T) { branch := "testAddFileOSFS" - tempDir, err := utils.CreateTempDir("git", utils.TempRoot) + tempDir, err := utils.CreateTempDir(directoryPrefix, utils.TempRoot) if err != nil { t.Errorf("NewClient %v", err) return @@ -118,3 +121,79 @@ func TestGit_AddPath_Checkout_AddNewFile_Push(t *testing.T) { return } } + +func TestGit_AddPath_Checkout_AddNewTree_Push(t *testing.T) { + branch := "testAddFileOSFS" + + tempDir, err := utils.CreateTempDir(directoryPrefix, utils.TempRoot) + if err != nil { + t.Errorf("NewClient %v", err) + return + } + + // create the git client + client, err := git.NewClientOSFS( + gitclientTestConfig.GitlabIntTestUsername, + gitclientTestConfig.GitlabIntTestToken, + gitclientTestConfig.GitlabIntTestRepositoryURL, + tempDir, + ) + if err != nil { + t.Errorf("%v", err) + return + } + t.Logf("Created git client for repo %s", gitclientTestConfig.GitlabIntTestRepositoryURL) + + err = client.CheckoutOrCreateBranch(branch) + if err != nil { + t.Errorf("%v", err) + return + } + t.Logf("Checked out branch %s", branch) + logGitStatus(t, client) + + // add content to the working tree + newPath := "adam" + os.Chdir(tempDir) + os.Mkdir(newPath, 0755) + os.Chdir(newPath) + f, err := os.Create("adam.txt") // creates a file at current directory + if err != nil { + t.Errorf("%v", err) + return + } + + // f, err := os.OpenFile("test.txt", os.O_APPEND|os.O_WRONLY, 0644) + // if err != nil { + // fmt.Println(err) + // return + // } + newLine := "This file made by Adam. \nUpdated" + utils.DateTimeUTC() + _, err = fmt.Fprintln(f, newLine) + if err != nil { + t.Errorf("%v", err) + return + } + f.Close() + + err = client.AddFile(newPath) + if err != nil { + t.Errorf("%v", err) + return + } + logGitStatus(t, client) + + commitMessage := fmt.Sprintf("Add new directory - Valkyrie %s", utils.DateTimeUTC()) + err = client.Commit(commitMessage) + if err != nil { + t.Errorf("%v", err) + return + } + logGitStatus(t, client) + + err = client.Push(branch) + if err != nil { + t.Errorf("%v", err) + return + } +} diff --git a/integration-tests/gitclient/gitclient_main_test.go b/integration-tests/gitclient/gitclient_main_test.go index 9392910..d10e1f3 100644 --- a/integration-tests/gitclient/gitclient_main_test.go +++ b/integration-tests/gitclient/gitclient_main_test.go @@ -1,3 +1,5 @@ +// +build integration + package gitclient import ( -- GitLab From d22544a8656d78fe11dd8390df8b00bfa60461de Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Fri, 27 Aug 2021 14:50:14 -0600 Subject: [PATCH 26/55] test coverage --- README.md | 6 ++++++ clients/utils/datetime_utils_test.go | 30 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 clients/utils/datetime_utils_test.go diff --git a/README.md b/README.md index 82edb37..4c9ff61 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,12 @@ go test -v ./clients/gitlab/... -coverprofile cover.out go tool cover -html=./cover.out -o ./coverage.html open coverage.html ``` + - example: test util package +``` + go test -v -coverprofile cover.out ./clients/utils/datetime_utils_test.go ./clients/utils/datetime_utils.go + go tool cover -html=./cover.out -o ./coverage.html + open coverage.html + ``` ### Integration testing - setup environmant - start any tunnelling, sshuttle command needed to enable network connectivity to the cluster or resources under test diff --git a/clients/utils/datetime_utils_test.go b/clients/utils/datetime_utils_test.go new file mode 100644 index 0000000..5684e3b --- /dev/null +++ b/clients/utils/datetime_utils_test.go @@ -0,0 +1,30 @@ +package utils + +import ( + "testing" +) + +func TestDateTime_Test_1(t *testing.T) { + tests := []struct { + name string + // define a function prototype as the 'type' + checkFunc func(client *string) bool + }{ + {name: "dateTimeTest1", checkFunc: checkString}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := DateTimeUTC() + if !tt.checkFunc(&got) { + t.Errorf("DateTimeUTC() = %v, want %v", "object", "failed checkFunc") + } + }) + } +} + +func checkString(v *string) bool { + if v == nil { + return false + } + return true +} \ No newline at end of file -- GitLab From 0d4b5a1527f1735b003dbcfd93fee21984596cac Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Fri, 27 Aug 2021 15:21:25 -0600 Subject: [PATCH 27/55] unit test --- clients/utils/datetime_utils_test.go | 2 +- clients/utils/file_utils_test.go | 63 ++++++++++++++++++++++++++++ custom/template/template_test.go | 1 - 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 clients/utils/file_utils_test.go diff --git a/clients/utils/datetime_utils_test.go b/clients/utils/datetime_utils_test.go index 5684e3b..e41d5c9 100644 --- a/clients/utils/datetime_utils_test.go +++ b/clients/utils/datetime_utils_test.go @@ -27,4 +27,4 @@ func checkString(v *string) bool { return false } return true -} \ No newline at end of file +} diff --git a/clients/utils/file_utils_test.go b/clients/utils/file_utils_test.go new file mode 100644 index 0000000..555d440 --- /dev/null +++ b/clients/utils/file_utils_test.go @@ -0,0 +1,63 @@ +package utils + +import ( + "errors" + "os" + "strings" + "testing" +) + +func TestFileUtils_CreateTempDir(t *testing.T) { + type args struct { + prefix string + rootDir string + } + tests := []struct { + name string + args args + wantTempDir string + wantErr bool + mockKey string + }{ + {name: "test pass 1", args: args{prefix: "prefix_", rootDir: "/tmp"}, wantTempDir: "/tmp/prefix_", wantErr: false, mockKey: ""}, + {name: "test error 1", args: args{prefix: "pref/ix_", rootDir: "/tmp"}, wantTempDir: "/tmp/pref/ix_", wantErr: true}, + {name: "test error 2", args: args{prefix: "prefix_", rootDir: "/xx"}, wantTempDir: "/xx/prefix_", wantErr: true}, + {name: "test error 2", args: args{prefix: "prefix_", rootDir: "/xx"}, wantTempDir: "/xx/prefix_", wantErr: true, mockKey: "osMkdirAll"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + osMkdirAllOrig := os.MkdirAll + if tt.mockKey == "osMkdirAll" { + osMkdirAll = osMkdirAllBad + } + gotTempDir, err := CreateTempDir(tt.args.prefix, tt.args.rootDir) + if err != nil { + if tt.wantErr { + t.Logf("createTempDir() EXPECTED error = %v, wantErr %v", err, tt.wantErr) + } else { + t.Errorf("createTempDir() UNEXPECTED error = %v, wantErr %v", err, tt.wantErr) + } + return + } + if !strings.HasPrefix(gotTempDir, tt.wantTempDir) { + t.Errorf("createTempDir() = %v, want %v", gotTempDir, tt.wantTempDir) + } + os.RemoveAll(gotTempDir) + if tt.mockKey == "osMkdirAll" { + osMkdirAll = osMkdirAllOrig + } + }) + } +} + +// mock used to create an error in createTempDir +var testCounter = 1 + +func osMkdirAllBad(path string, mode os.FileMode) error { + println(testCounter) + if testCounter == 1 { + return errors.New("test error") + } + testCounter = testCounter - 1 + return os.MkdirAll(path, mode) +} diff --git a/custom/template/template_test.go b/custom/template/template_test.go index 991181a..913393b 100644 --- a/custom/template/template_test.go +++ b/custom/template/template_test.go @@ -2,7 +2,6 @@ package template import ( "errors" - // "io/fs" "os" "strings" "testing" -- GitLab From 77d1acebd0e0bf86bb5089a68adcf7ac837fd8fd Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Mon, 30 Aug 2021 14:44:41 -0600 Subject: [PATCH 28/55] initial p1 project bootstrap method --- clients/git/repo_client_test.go | 2 + custom/p1/project_bootstrap.go | 123 ++++++++++++++++++ integration-tests/custom/p1/p1_groups_test.go | 5 - integration-tests/custom/p1/p1_main_test.go | 58 ++++----- .../custom/p1/p1_projects_bootstrap_test.go | 44 +++++++ .../custom/p1/p1_projects_test.go | 5 - 6 files changed, 197 insertions(+), 40 deletions(-) create mode 100644 custom/p1/project_bootstrap.go create mode 100644 integration-tests/custom/p1/p1_projects_bootstrap_test.go diff --git a/clients/git/repo_client_test.go b/clients/git/repo_client_test.go index 2dc4b79..9a65a88 100644 --- a/clients/git/repo_client_test.go +++ b/clients/git/repo_client_test.go @@ -1,5 +1,7 @@ package git +// reference: https://github.com/src-d/go-git/blob/master/repository_test.go + import ( "testing" diff --git a/custom/p1/project_bootstrap.go b/custom/p1/project_bootstrap.go new file mode 100644 index 0000000..9309c74 --- /dev/null +++ b/custom/p1/project_bootstrap.go @@ -0,0 +1,123 @@ +package p1 + +import ( + "fmt" + "strings" + + "github.com/romana/rlog" + gogitlab "github.com/xanzy/go-gitlab" + "valkyrie.dso.mil/valkyrie-api/clients/git" + "valkyrie.dso.mil/valkyrie-api/clients/gitlab" + "valkyrie.dso.mil/valkyrie-api/clients/utils" +) + +var directoryPrefix = "bootstrap-" +var newRepoInitializeFile = "README.md" + +// by default bootstrap to the master branch +var defaultBootstrapBranch = "master" + +func processProjectBootstrapError(logPrefix string, err error) { + rlog.Warnf("%s error: %v", logPrefix, err) +} + +// BootstrapProject - +func BootstrapProject(gitlabCredentials GitlabCredentials, projectID int, filePath string) (err error) { + err = BootstrapProjectwithBranch(gitlabCredentials, projectID, filePath, defaultBootstrapBranch) + return +} + +//BootstrapProjectwithBranch add filepath to an existing gitlab project ID repository +func BootstrapProjectwithBranch(gitlabCredentials GitlabCredentials, projectID int, filePath string, branch string) error { + logPrefix := "BootstrapProjectwithBranch" + // gitlab username token credentials to use for git ops + gitlabUsername := "oauth2" + gitlabToken := gitlabCredentials.ServerToken + + // create a gitlab client + gitlabClient, err := gitlab.NewClient(gitlabCredentials.ServerURL, gitlabCredentials.ServerToken, nil) + if err != nil { + processProjectBootstrapError(logPrefix+" gitlab.NewClient", err) + return err + } + + project, _, err := gitlabClient.GetProject(projectID) + if err != nil { + processProjectBootstrapError(logPrefix+" gitlabClient.GetProject", err) + return err + } + gitlabRepositoryURL := project.HTTPURLToRepo + + // check that repo is empty. otherwise return err + fileTree, _, err := gitlabClient.GetRepositoryTree(projectID) + if err != nil { + processProjectBootstrapError(logPrefix+" gitlabClient.GetRepositoryTree", err) + return err + } + if !repoIsEmpty(fileTree) { + err = fmt.Errorf("Repository %s not empty", project.PathWithNamespace) + return err + } + + // clone project + // copy filePath to clone root + // git add + // git commit + // git push + + // be sure to cleanup temp directory + tempDir, err := utils.CreateTempDir(directoryPrefix, utils.TempRoot) + if err != nil { + rlog.Errorf("Error - CreateTempDir %v", err) + return err + } + rlog.Debugf("TestGit_AddPath_Create_Branch - Created temp dir %s", tempDir) + + client, err := git.NewClientOSFS( + gitlabUsername, + gitlabToken, + gitlabRepositoryURL, + tempDir, + ) + if err != nil { + rlog.Errorf("Error - TestGit_AddPath_Create_Branch - NewClientOSFS %v", err) + return err + } + // If remote does NOT already exist, then this is a LOCAL Branch only until pushed + err = client.CheckoutOrCreateBranch(branch) + if err != nil { + rlog.Errorf("Error - TestGit_AddPath_Create_Branch - CheckoutOrCreateBranch %v", err) + return err + } + + // push to remote to create remote branch if does NOT already + err = client.Push(branch) + //if already up-to-date, then it's already deleted + if err != nil && err.Error() == "already up-to-date" { + rlog.Debugf(logPrefix+" CheckoutOrCreateBranch %s - already exists", branch) + err = nil + } + if err != nil { + rlog.Errorf("Push %v", err) + return err + } + rlog.Debugf("Checkout and Push branch %s - success", branch) + return nil +} + +// repoIsEmpty - test if repo is effectively empty +func repoIsEmpty(fileTree []*gogitlab.TreeNode) bool { + // if no files and repo is initialized + if len(fileTree) == 0 { + return true + } + // if only one file and it is the newRepoInitializeFile + if len(fileTree) == 1 { + file := fileTree[0] + if strings.EqualFold(file.Name, newRepoInitializeFile) { + return true + } + } + // repo is NOT empty + return false +} diff --git a/integration-tests/custom/p1/p1_groups_test.go b/integration-tests/custom/p1/p1_groups_test.go index a0948bb..6a1f9a1 100644 --- a/integration-tests/custom/p1/p1_groups_test.go +++ b/integration-tests/custom/p1/p1_groups_test.go @@ -9,11 +9,6 @@ import ( custom_p1 "valkyrie.dso.mil/valkyrie-api/custom/p1" ) -/* - -p1Config is initialized in the TestMain wrapper method - -*/ const integrationTestGroupPath = "int-test-group" func Test_P1_AddGroup(t *testing.T) { diff --git a/integration-tests/custom/p1/p1_main_test.go b/integration-tests/custom/p1/p1_main_test.go index 8d3339c..bfdad85 100644 --- a/integration-tests/custom/p1/p1_main_test.go +++ b/integration-tests/custom/p1/p1_main_test.go @@ -1,5 +1,3 @@ -// +build integration - package integration import ( @@ -139,21 +137,21 @@ func addRootGroup() error { // dont fail if group already exists fmt.Printf("Error! AddRootGroup %s error = %v %d\n", path, err, statusCode) return err - } else { - p1Config.GitlabIntTestRootGroupID = got.ID - fmt.Printf("AddGroup %s %s %s %s %d \n", got.Name, got.Path, got.FullPath, got.WebURL, statusCode) } + p1Config.GitlabIntTestRootGroupID = got.ID + fmt.Printf("AddGroup %s %s %s %s %d \n", got.Name, got.Path, got.FullPath, got.WebURL, statusCode) + } return nil } // Insure the integration test project exists -func addIntTestProject(projectUrl string) (int, error) { +func addIntTestProject(projectURL string) (int, error) { var project *gogitlab.Project = nil var responseCode int - url, err := url.Parse(projectUrl) + url, err := url.Parse(projectURL) if err != nil { return 0, err } @@ -166,29 +164,29 @@ func addIntTestProject(projectUrl string) (int, error) { if responseCode == http.StatusFound { return project.ID, nil - } else { - path := p1Config.GitlabIntTestProjectPath - name := p1Config.GitlabIntTestProjectPath - description := "Integration Test Project" - configPath := "a/b/config.yml@group1/group2/project" - initializeWithReadme := true - - projectOpts := gogitlab.CreateProjectOptions{ - Name: &name, - Path: &path, - Description: &description, - NamespaceID: &p1Config.GitlabIntTestRootGroupID, - CIConfigPath: &configPath, - InitializeWithReadme: &initializeWithReadme, - } - got, statusCode, err := p1Config.GitlabClient.AddProject(projectOpts) - - if err != nil { - fmt.Printf("ClientImpl.AddProject() error = %v %d \n", err, statusCode) - return 0, err - } + } + path := p1Config.GitlabIntTestProjectPath + name := p1Config.GitlabIntTestProjectPath + description := "Integration Test Project" + configPath := "a/b/config.yml@group1/group2/project" + initializeWithReadme := true + + projectOpts := gogitlab.CreateProjectOptions{ + Name: &name, + Path: &path, + Description: &description, + NamespaceID: &p1Config.GitlabIntTestRootGroupID, + CIConfigPath: &configPath, + InitializeWithReadme: &initializeWithReadme, + } + got, statusCode, err := p1Config.GitlabClient.AddProject(projectOpts) - fmt.Printf("AddProject %s %s %s %s %d", got.Name, got.Path, got.PathWithNamespace, got.WebURL, statusCode) - return got.ID, nil + if err != nil { + fmt.Printf("ClientImpl.AddProject() error = %v %d \n", err, statusCode) + return 0, err } + + fmt.Printf("AddProject %s %s %s %s %d", got.Name, got.Path, got.PathWithNamespace, got.WebURL, statusCode) + return got.ID, nil + } diff --git a/integration-tests/custom/p1/p1_projects_bootstrap_test.go b/integration-tests/custom/p1/p1_projects_bootstrap_test.go new file mode 100644 index 0000000..9c059d5 --- /dev/null +++ b/integration-tests/custom/p1/p1_projects_bootstrap_test.go @@ -0,0 +1,44 @@ +package integration + +import ( + "testing" + + "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" + custom_p1 "valkyrie.dso.mil/valkyrie-api/custom/p1" +) + +// go clean -testcache && go test -tags "integration" ./integration-tests/custom/p1/p1_main_test.go ./integration-tests/custom/p1/p1_projects_bootstrap_test.go + +const integrationTestProjectBootstrapPath = "int-test-bootstrap-project" + +// Delete bootstrap test project if exists and re-create empty clean project +func Test_P1_ProjectBootstrap_DeleteAndAddProject(t *testing.T) { + logPrefix := "Test_P1_AddProject" + t.Run("test", func(t *testing.T) { + projectSpec := v1alpha1.ProjectSpec{ + Name: "My Project Bootstrap Test Project", + FullPath: p1Config.GitlabIntTestRootGroupPath + "/" + integrationTestProjectBootstrapPath, + } + + creds := custom_p1.GitlabCredentials{ + ServerURL: p1Config.GitlabAPIURL, + ServerToken: p1Config.GitlabAPIToken, + } + + var err error + + err = custom_p1.DeleteProject(creds, projectSpec, nil) + if err != nil { + t.Logf("DeleteProject() error = %v", err) + } + t.Logf("%s deleted project %v", logPrefix, projectSpec) + + err = custom_p1.CreateProject(creds, projectSpec, nil) + if err != nil { + t.Errorf("CreateProject() error = %v", err) + return + } + + t.Logf("%s created project %v", logPrefix, projectSpec) + }) +} diff --git a/integration-tests/custom/p1/p1_projects_test.go b/integration-tests/custom/p1/p1_projects_test.go index 45ff894..bd5b4e7 100644 --- a/integration-tests/custom/p1/p1_projects_test.go +++ b/integration-tests/custom/p1/p1_projects_test.go @@ -9,11 +9,6 @@ import ( custom_p1 "valkyrie.dso.mil/valkyrie-api/custom/p1" ) -/* - -P1Config is initialized in the TestMain wrapper method - -*/ const integrationTestProjectPath = "int-test-project" func Test_P1_AddProject(t *testing.T) { -- GitLab From 982acc584240156517cc7fc526aff87f81511275 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Mon, 30 Aug 2021 16:32:03 -0600 Subject: [PATCH 29/55] add return project id to create project --- custom/p1/project.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/custom/p1/project.go b/custom/p1/project.go index 257eb3f..522aae6 100644 --- a/custom/p1/project.go +++ b/custom/p1/project.go @@ -33,20 +33,20 @@ func logProjectStart(logPrefix string, projectSpec apigitlab.ProjectSpec) { } // CreateProject - -func CreateProject(gitlabCredentials GitlabCredentials, projectSpec apigitlab.ProjectSpec, httpClient *http.Client) error { +func CreateProject(gitlabCredentials GitlabCredentials, projectSpec apigitlab.ProjectSpec, httpClient *http.Client) (int, error) { logPrefix := "CreateProject" logProjectStart(logPrefix, projectSpec) err := ValidateGitlabPath(projectSpec.FullPath) if err != nil { processProjectError(logPrefix, err) - return err + return 0, err } client, err := gitlab.NewClient(gitlabCredentials.ServerURL, gitlabCredentials.ServerToken, httpClient) if err != nil { processProjectError(logPrefix, err) - return err + return 0, err } // Identify parent Group for project @@ -57,15 +57,15 @@ func CreateProject(gitlabCredentials GitlabCredentials, projectSpec apigitlab.Pr parentGroup, statusCode, err := client.GetGroupByFullPath(&groupFullPath) if err != nil { - return fmt.Errorf("failed to find group with fullPath %s. error: %v", groupFullPath, err) + return 0, fmt.Errorf("failed to find group with fullPath %s. error: %v", groupFullPath, err) } if statusCode != http.StatusFound { - return fmt.Errorf("failed to find group with fullPath %s. status code: %d", groupFullPath, statusCode) + return 0, fmt.Errorf("failed to find group with fullPath %s. status code: %d", groupFullPath, statusCode) } ciConfigPath, err := generateCIConfigPath(projectPath, groupFullPath) if err != nil { - return fmt.Errorf("failed to generateCIConfigPath: %v", err) + return 0, fmt.Errorf("failed to generateCIConfigPath: %v", err) } projectOptions := gogitlab.CreateProjectOptions{ @@ -105,15 +105,15 @@ func CreateProject(gitlabCredentials GitlabCredentials, projectSpec apigitlab.Pr project, statusCode, err := client.AddProject(projectOptions) if err != nil { - return fmt.Errorf("failed to add project with name %s to group path %s. error: %v", *projectOptions.Name, groupFullPath, err) + return 0, fmt.Errorf("failed to add project with name %s to group path %s. error: %v", *projectOptions.Name, groupFullPath, err) } if statusCode != http.StatusCreated { - return fmt.Errorf(fmt.Sprintf("Failed to add project with name %s to group path %s. statusCode: %d", *projectOptions.Name, groupFullPath, statusCode)) + return 0, fmt.Errorf(fmt.Sprintf("Failed to add project with name %s to group path %s. statusCode: %d", *projectOptions.Name, groupFullPath, statusCode)) } rlog.Debugf("Added project %s to path %s with status code %d", project.Name, project.NameWithNamespace, statusCode) - return nil + return project.ID, nil } // UpdateProject - @@ -195,7 +195,7 @@ func DeleteProject(gitlabCredentials GitlabCredentials, projectSpec apigitlab.Pr } if statusCode != http.StatusFound { - return fmt.Errorf("failed to find project with fullPath %s", projectFullPath) + return fmt.Errorf("project not found (%d) fullPath %s", http.StatusNotFound, projectFullPath) } // delete and wait for delete to complete up to 500ms * 240 tries -- GitLab From c55327e72659fb1ed3b10b64783fe5ed0c41a4a9 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Mon, 30 Aug 2021 16:36:05 -0600 Subject: [PATCH 30/55] capture work on bootstrap project --- custom/p1/project_bootstrap.go | 2 +- custom/p1/project_test.go | 3 ++- .../custom/p1/p1_projects_bootstrap_test.go | 13 ++++++++++--- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/custom/p1/project_bootstrap.go b/custom/p1/project_bootstrap.go index 9309c74..26dfe5a 100644 --- a/custom/p1/project_bootstrap.go +++ b/custom/p1/project_bootstrap.go @@ -55,7 +55,7 @@ func BootstrapProjectwithBranch(gitlabCredentials GitlabCredentials, projectID i return err } if !repoIsEmpty(fileTree) { - err = fmt.Errorf("Repository %s not empty", project.PathWithNamespace) + err = fmt.Errorf("repository %s not empty", project.PathWithNamespace) return err } diff --git a/custom/p1/project_test.go b/custom/p1/project_test.go index f512615..3cedb05 100644 --- a/custom/p1/project_test.go +++ b/custom/p1/project_test.go @@ -64,7 +64,8 @@ func TestCreateProject(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := CreateProject(tt.args.gitlabCredentials, tt.args.projectSpec, tt.args.httpClient); (err != nil) != tt.wantErr { + _, err := CreateProject(tt.args.gitlabCredentials, tt.args.projectSpec, tt.args.httpClient) + if (err != nil) != tt.wantErr { t.Errorf("CreateProject() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/integration-tests/custom/p1/p1_projects_bootstrap_test.go b/integration-tests/custom/p1/p1_projects_bootstrap_test.go index 9c059d5..4cf7200 100644 --- a/integration-tests/custom/p1/p1_projects_bootstrap_test.go +++ b/integration-tests/custom/p1/p1_projects_bootstrap_test.go @@ -1,6 +1,7 @@ package integration import ( + "strings" "testing" "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" @@ -28,17 +29,23 @@ func Test_P1_ProjectBootstrap_DeleteAndAddProject(t *testing.T) { var err error err = custom_p1.DeleteProject(creds, projectSpec, nil) + if err != nil && strings.Contains(err.Error(), "not found") { + t.Logf("DeleteProject- project not found %s", projectSpec.FullPath) + err = nil + } if err != nil { t.Logf("DeleteProject() error = %v", err) } - t.Logf("%s deleted project %v", logPrefix, projectSpec) + t.Logf("%s deleted project %s", logPrefix, projectSpec.FullPath) - err = custom_p1.CreateProject(creds, projectSpec, nil) + projectID, err := custom_p1.CreateProject(creds, projectSpec, nil) if err != nil { t.Errorf("CreateProject() error = %v", err) return } - t.Logf("%s created project %v", logPrefix, projectSpec) + t.Logf("%s created project %v", logPrefix, projectSpec.FullPath) + + custom_p1.BootstrapProject(creds, projectID, "/tmp/test") }) } -- GitLab From 224d0d9859816d816e75f5890a859d4ac7e8bd1d Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Mon, 30 Aug 2021 17:30:16 -0600 Subject: [PATCH 31/55] first successful bootstrap --- clients/utils/file_utils.go | 43 +++++++++++++++++++ custom/p1/project_bootstrap.go | 33 +++++++++++--- .../custom/p1/p1_projects_bootstrap_test.go | 25 ++++++++++- 3 files changed, 94 insertions(+), 7 deletions(-) diff --git a/clients/utils/file_utils.go b/clients/utils/file_utils.go index 8d6578f..d130826 100644 --- a/clients/utils/file_utils.go +++ b/clients/utils/file_utils.go @@ -1,8 +1,12 @@ package utils import ( + "fmt" + "io" "io/ioutil" "os" + "os/exec" + "strings" "github.com/romana/rlog" ) @@ -33,3 +37,42 @@ func CreateTempDir(prefix string, rootDir string) (tempDir string, err error) { } return tempDir, nil } + +// CopyFile +func CopyFile(src, dst string) (int64, error) { + sourceFileStat, err := os.Stat(src) + if err != nil { + return 0, err + } + + if !sourceFileStat.Mode().IsRegular() { + return 0, fmt.Errorf("%s is not a regular file", src) + } + + source, err := os.Open(src) + if err != nil { + return 0, err + } + defer source.Close() + + destination, err := os.Create(dst) + if err != nil { + return 0, err + } + defer destination.Close() + nBytes, err := io.Copy(destination, source) + return nBytes, err +} + +//CopyDir - copy directory contents recursively using exec +func CopyDir(srcPath string, dstPath string) error { + // copy source folder to temp directory + separator := fmt.Sprintf("%c", os.PathSeparator) + srcPath = strings.TrimRight(srcPath,separator) + dstPath = strings.TrimRight(dstPath,separator) + _, err := exec.Command("cp", "-r", srcPath+separator, dstPath + separator).Output() + if err != nil { + return err + } + return nil +} diff --git a/custom/p1/project_bootstrap.go b/custom/p1/project_bootstrap.go index 26dfe5a..64e06c3 100644 --- a/custom/p1/project_bootstrap.go +++ b/custom/p1/project_bootstrap.go @@ -22,13 +22,13 @@ func processProjectBootstrapError(logPrefix string, err error) { } // BootstrapProject - -func BootstrapProject(gitlabCredentials GitlabCredentials, projectID int, filePath string) (err error) { - err = BootstrapProjectwithBranch(gitlabCredentials, projectID, filePath, defaultBootstrapBranch) +func BootstrapProject(gitlabCredentials GitlabCredentials, projectID int, sourcePath string) (err error) { + err = BootstrapProjectwithBranch(gitlabCredentials, projectID, sourcePath, defaultBootstrapBranch) return } //BootstrapProjectwithBranch add filepath to an existing gitlab project ID repository -func BootstrapProjectwithBranch(gitlabCredentials GitlabCredentials, projectID int, filePath string, branch string) error { +func BootstrapProjectwithBranch(gitlabCredentials GitlabCredentials, projectID int, sourcePath string, branch string) error { logPrefix := "BootstrapProjectwithBranch" // gitlab username token credentials to use for git ops gitlabUsername := "oauth2" @@ -66,18 +66,18 @@ func BootstrapProjectwithBranch(gitlabCredentials GitlabCredentials, projectID i // git push // be sure to cleanup temp directory - tempDir, err := utils.CreateTempDir(directoryPrefix, utils.TempRoot) + workDir, err := utils.CreateTempDir(directoryPrefix, utils.TempRoot) if err != nil { rlog.Errorf("Error - CreateTempDir %v", err) return err } - rlog.Debugf("TestGit_AddPath_Create_Branch - Created temp dir %s", tempDir) + rlog.Debugf("TestGit_AddPath_Create_Branch - Created temp workDir %s", workDir) client, err := git.NewClientOSFS( gitlabUsername, gitlabToken, gitlabRepositoryURL, - tempDir, + workDir, ) if err != nil { rlog.Errorf("Error - TestGit_AddPath_Create_Branch - NewClientOSFS %v", err) @@ -90,6 +90,27 @@ func BootstrapProjectwithBranch(gitlabCredentials GitlabCredentials, projectID i return err } + // copy files from sourcePath to root of repository + err = utils.CopyDir(sourcePath, workDir) + if err != nil { + rlog.Errorf("Error - TestGit_AddPath_Create_Branch - CheckoutOrCreateBranch %v", err) + return err + } + + rlog.Errorf("sourcePath %s", sourcePath) + rlog.Errorf("tempDir %s", workDir) + // add everything in working tree + err = client.AddFile(".") + if err != nil { + rlog.Errorf("Error - TestGit_AddPath_Create_Branch - CheckoutOrCreateBranch %v", err) + return err + } + err = client.Commit("Valkyrie - Bootstrap") + if err != nil { + rlog.Errorf("Error - TestGit_AddPath_Create_Branch - CheckoutOrCreateBranch %v", err) + return err + } + // push to remote to create remote branch if does NOT already err = client.Push(branch) //if already up-to-date, then it's already deleted diff --git a/integration-tests/custom/p1/p1_projects_bootstrap_test.go b/integration-tests/custom/p1/p1_projects_bootstrap_test.go index 4cf7200..c39b267 100644 --- a/integration-tests/custom/p1/p1_projects_bootstrap_test.go +++ b/integration-tests/custom/p1/p1_projects_bootstrap_test.go @@ -1,10 +1,12 @@ package integration import ( + // "os" "strings" "testing" "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" + "valkyrie.dso.mil/valkyrie-api/clients/utils" custom_p1 "valkyrie.dso.mil/valkyrie-api/custom/p1" ) @@ -46,6 +48,27 @@ func Test_P1_ProjectBootstrap_DeleteAndAddProject(t *testing.T) { t.Logf("%s created project %v", logPrefix, projectSpec.FullPath) - custom_p1.BootstrapProject(creds, projectID, "/tmp/test") + // be sure to cleanup temp directory + tempDir, err := utils.CreateTempDir("int-test-", utils.TempRoot) + if err != nil { + t.Errorf("Error - CreateTempDir %v", err) + return + } + + err = utils.CopyDir("./", tempDir) + if err != nil { + t.Errorf("Error - CopyDir %v", err) + return + } + t.Logf("temp directory %s", tempDir) + err = custom_p1.BootstrapProject(creds, projectID, tempDir) + if err != nil { + t.Errorf("Error - BootstrapProject %v", err) + return + } + // cleanup + + // os.RemoveAll(tempDir) + t.Logf("Bootstrap completed") }) } -- GitLab From 7e9f3d2cfe84fb009027c745643d9125966f5217 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Mon, 30 Aug 2021 21:16:36 -0600 Subject: [PATCH 32/55] clean data folders --- clients/utils/file_utils.go | 8 ++++---- integration-tests/custom/p1/p1_main_test.go | 2 ++ .../custom/p1/p1_projects_bootstrap_test.go | 4 ++-- .../gitclient/data/dso-dns-staging.tar.gz | Bin 115712 -> 0 bytes 4 files changed, 8 insertions(+), 6 deletions(-) delete mode 100644 integration-tests/gitclient/data/dso-dns-staging.tar.gz diff --git a/clients/utils/file_utils.go b/clients/utils/file_utils.go index d130826..7346ccb 100644 --- a/clients/utils/file_utils.go +++ b/clients/utils/file_utils.go @@ -13,6 +13,7 @@ import ( //TempRoot - temp directory root for current OS var TempRoot = os.TempDir() + string(os.PathSeparator) + "valkyrie-temp" +var PathSeparator = fmt.Sprintf("%c", os.PathSeparator) // Function pointers - allows for easy mocking of functions var osMkdirAll = os.MkdirAll @@ -67,10 +68,9 @@ func CopyFile(src, dst string) (int64, error) { //CopyDir - copy directory contents recursively using exec func CopyDir(srcPath string, dstPath string) error { // copy source folder to temp directory - separator := fmt.Sprintf("%c", os.PathSeparator) - srcPath = strings.TrimRight(srcPath,separator) - dstPath = strings.TrimRight(dstPath,separator) - _, err := exec.Command("cp", "-r", srcPath+separator, dstPath + separator).Output() + srcPath = strings.TrimRight(srcPath, PathSeparator) + dstPath = strings.TrimRight(dstPath, PathSeparator) + _, err := exec.Command("cp", "-r", srcPath+PathSeparator, dstPath+PathSeparator).Output() if err != nil { return err } diff --git a/integration-tests/custom/p1/p1_main_test.go b/integration-tests/custom/p1/p1_main_test.go index bfdad85..1291946 100644 --- a/integration-tests/custom/p1/p1_main_test.go +++ b/integration-tests/custom/p1/p1_main_test.go @@ -9,6 +9,7 @@ import ( "strings" "testing" + "github.com/romana/rlog" gogitlab "github.com/xanzy/go-gitlab" gitlab "valkyrie.dso.mil/valkyrie-api/clients/gitlab" ) @@ -51,6 +52,7 @@ var p1Config P1Config // packageSetup - setup environment for integration testing func packageSetup() error { p1Config.WorkingDir, _ = os.Getwd() + rlog.Errorf("Working Dir %s", p1Config.WorkingDir) var ok bool var err error diff --git a/integration-tests/custom/p1/p1_projects_bootstrap_test.go b/integration-tests/custom/p1/p1_projects_bootstrap_test.go index c39b267..86573ee 100644 --- a/integration-tests/custom/p1/p1_projects_bootstrap_test.go +++ b/integration-tests/custom/p1/p1_projects_bootstrap_test.go @@ -1,7 +1,6 @@ package integration import ( - // "os" "strings" "testing" @@ -55,7 +54,8 @@ func Test_P1_ProjectBootstrap_DeleteAndAddProject(t *testing.T) { return } - err = utils.CopyDir("./", tempDir) + testDataPath := p1Config.WorkingDir + utils.PathSeparator + "data" + err = utils.CopyDir(testDataPath, tempDir) if err != nil { t.Errorf("Error - CopyDir %v", err) return diff --git a/integration-tests/gitclient/data/dso-dns-staging.tar.gz b/integration-tests/gitclient/data/dso-dns-staging.tar.gz deleted file mode 100644 index 768fee64da64a51547ffcbf4c4a96f6f84b53e97..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 115712 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 E|IUJA@c;k- -- GitLab From 5d682c9ef7b4de0732a297214632dd49a4499488 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Tue, 31 Aug 2021 17:42:39 -0600 Subject: [PATCH 33/55] update gitclient integration test --- clients/git/repo_client.go | 4 + clients/utils/file_utils.go | 4 +- .../custom/p1/data/angular-world.tar.gz | Bin 0 -> 679424 bytes integration-tests/custom/p1/p1_main_test.go | 2 + .../custom/p1/p1_projects_bootstrap_test.go | 2 + .../custom/p1/p1_projects_test.go | 6 +- .../gitclient/data/angular-world.tar.gz | Bin 0 -> 679424 bytes .../gitclient/data/angular-world.zip | Bin 0 -> 165105 bytes .../gitclient/data/dso-dns-staging.tar.gz | Bin 0 -> 29696 bytes .../gitclient/gitclient_addpath_test.go | 5 - .../gitclient/gitclient_branch_test.go | 113 ------------ .../gitclient/gitclient_dnsupdate_test.go | 124 +++++++++++++ .../gitclient/gitclient_main_test.go | 166 +++++++++++++++++- .../gitlab/api/gitlab_api_mr_test.go | 4 +- .../gitlab/api/gitlab_main_test.go | 25 +-- 15 files changed, 314 insertions(+), 141 deletions(-) create mode 100644 integration-tests/custom/p1/data/angular-world.tar.gz create mode 100644 integration-tests/gitclient/data/angular-world.tar.gz create mode 100644 integration-tests/gitclient/data/angular-world.zip create mode 100644 integration-tests/gitclient/data/dso-dns-staging.tar.gz create mode 100644 integration-tests/gitclient/gitclient_dnsupdate_test.go diff --git a/clients/git/repo_client.go b/clients/git/repo_client.go index 2e8def0..30cb422 100644 --- a/clients/git/repo_client.go +++ b/clients/git/repo_client.go @@ -106,6 +106,10 @@ func (c *RepoClientImpl) CheckoutOrCreateBranch(branchName string) (err error) { RemoteName: remoteName, RefSpecs: []config.RefSpec{"refs/*:refs/*", "HEAD:refs/heads/HEAD"}, }) + //if already up-to-date, then it's no an error + if err != nil && err.Error() == "already up-to-date" { + err = nil + } if err != nil { rlog.Errorf("CheckoutOrCreateBranch - Fetch - Error %v", err) return diff --git a/clients/utils/file_utils.go b/clients/utils/file_utils.go index 7346ccb..1ee13d1 100644 --- a/clients/utils/file_utils.go +++ b/clients/utils/file_utils.go @@ -13,6 +13,8 @@ import ( //TempRoot - temp directory root for current OS var TempRoot = os.TempDir() + string(os.PathSeparator) + "valkyrie-temp" + +//PathSeparator - string value of os.PathSeparator var PathSeparator = fmt.Sprintf("%c", os.PathSeparator) // Function pointers - allows for easy mocking of functions @@ -39,7 +41,7 @@ func CreateTempDir(prefix string, rootDir string) (tempDir string, err error) { return tempDir, nil } -// CopyFile +// CopyFile - Copy a single file from locaton to another using full paths func CopyFile(src, dst string) (int64, error) { sourceFileStat, err := os.Stat(src) if err != nil { diff --git a/integration-tests/custom/p1/data/angular-world.tar.gz b/integration-tests/custom/p1/data/angular-world.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..4e671867b8ea1083570ea3a040ff4fa6c3480185 GIT binary patch literal 679424 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 ZR0(HT;n61UEcY1%&LD6GfmaBD{~rexAC3S3 literal 0 HcmV?d00001 diff --git a/integration-tests/custom/p1/p1_main_test.go b/integration-tests/custom/p1/p1_main_test.go index 1291946..7524bc4 100644 --- a/integration-tests/custom/p1/p1_main_test.go +++ b/integration-tests/custom/p1/p1_main_test.go @@ -1,3 +1,5 @@ +// +build integration + package integration import ( diff --git a/integration-tests/custom/p1/p1_projects_bootstrap_test.go b/integration-tests/custom/p1/p1_projects_bootstrap_test.go index 86573ee..47919e8 100644 --- a/integration-tests/custom/p1/p1_projects_bootstrap_test.go +++ b/integration-tests/custom/p1/p1_projects_bootstrap_test.go @@ -1,3 +1,5 @@ +// +build integration + package integration import ( diff --git a/integration-tests/custom/p1/p1_projects_test.go b/integration-tests/custom/p1/p1_projects_test.go index bd5b4e7..cf5e5c4 100644 --- a/integration-tests/custom/p1/p1_projects_test.go +++ b/integration-tests/custom/p1/p1_projects_test.go @@ -30,15 +30,15 @@ func Test_P1_AddProject(t *testing.T) { if err != nil { t.Logf("DeleteProject() error = %v", err) } - t.Logf("%s deleted project %v", logPrefix, projectSpec) + t.Logf("%s deleted project with fullpath %v", logPrefix, projectSpec) - err = custom_p1.CreateProject(creds, projectSpec, nil) + projectID, err := custom_p1.CreateProject(creds, projectSpec, nil) if err != nil { t.Errorf("CreateProject() error = %v", err) return } - t.Logf("%s created project %v", logPrefix, projectSpec) + t.Logf("%s created project with id %d fullpath %v", logPrefix, projectID, projectSpec) }) } diff --git a/integration-tests/gitclient/data/angular-world.tar.gz b/integration-tests/gitclient/data/angular-world.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..4e671867b8ea1083570ea3a040ff4fa6c3480185 GIT binary patch literal 679424 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 ZR0(HT;n61UEcY1%&LD6GfmaBD{~rexAC3S3 literal 0 HcmV?d00001 diff --git a/integration-tests/gitclient/data/angular-world.zip b/integration-tests/gitclient/data/angular-world.zip new file mode 100644 index 0000000000000000000000000000000000000000..57354662cdf876acdf21c0b8671f19db8a473d2e GIT binary patch literal 165105 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 &g8OoqTjQWC~^^_R` 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

@i;tn<=#GWB`rp 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 y Date: Wed, 1 Sep 2021 09:25:45 -0600 Subject: [PATCH 34/55] add untar support. make dns integration test repeatable --- clients/utils/file_utils.go | 87 +++++++++++++++ .../gitclient/gitclient_addpath_test.go | 14 +-- .../gitclient/gitclient_dnsupdate_test.go | 102 ++++++++++++++++-- .../gitclient/gitclient_main_test.go | 62 ++++++----- .../gitlab/api/gitlab_main_test.go | 2 +- 5 files changed, 220 insertions(+), 47 deletions(-) diff --git a/clients/utils/file_utils.go b/clients/utils/file_utils.go index 1ee13d1..5470184 100644 --- a/clients/utils/file_utils.go +++ b/clients/utils/file_utils.go @@ -78,3 +78,90 @@ func CopyDir(srcPath string, dstPath string) error { } return nil } + +// DeleteDir - +func DeleteDir(path string) error { + err := os.RemoveAll(path) + if err != nil { + rlog.Warnf("error is RemoveAll %v", err) + return err + } + return nil +} + +// CreateTempDirWithFile - create tempdir and populate with filePath +// filePath may be a single file, a directory, or a zip or tar.gz file +func CreateTempDirWithFile(filePath string, prefix string) (string, error) { + tempDir, err := CreateTempDir(prefix, TempRoot) + if err != nil { + return "", err + } + stat, err := os.Stat(filePath) + if err != nil { + // try to cleanup + DeleteDir(tempDir) + return "", err + } + + // if is file + if !stat.IsDir() { + + targetPath := tempDir + PathSeparator + stat.Name() + _, err = CopyFile(filePath, targetPath) + if err != nil { + // try to cleanup + DeleteDir(tempDir) + return "", err + } + if strings.HasSuffix(filePath, ".zip") { + // process zip file + } else { + if strings.HasSuffix(filePath, ".tar.gz") { + // process tar gz file + } else { + // process regular file + } + } + } else { + // process directory + } + return tempDir, nil +} + +// UnTarFile - decompress .tar.gz file to dstPath directory +func UnTarFile(filePath string, dstPath string) error { + if !IsFile(filePath) { + return fmt.Errorf("path is not a valid file: %s", filePath) + } + // clean up target dir path - insure has only one trailig separator + dstPath = strings.TrimRight(dstPath, PathSeparator) + PathSeparator + _, err := exec.Command("tar", "-xvf", filePath, "--directory", dstPath).Output() + if err != nil { + return err + } + return nil +} + +// IsFile - test if a path is a file using stat +func IsFile(filePath string) bool { + stat, err := os.Stat(filePath) + if err != nil { + return false + } + if !stat.IsDir() { + return true + } + return false +} + +// IsDir - test if a path is a directory using stat +func IsDir(filePath string) bool { + stat, err := os.Stat(filePath) + if err != nil { + return false + } + if stat.IsDir() { + return true + } + return false +} diff --git a/integration-tests/gitclient/gitclient_addpath_test.go b/integration-tests/gitclient/gitclient_addpath_test.go index dde8400..61d4ab4 100644 --- a/integration-tests/gitclient/gitclient_addpath_test.go +++ b/integration-tests/gitclient/gitclient_addpath_test.go @@ -11,7 +11,9 @@ import ( "valkyrie.dso.mil/valkyrie-api/clients/git" "valkyrie.dso.mil/valkyrie-api/clients/utils" ) + var directoryPrefix = "git-" + func TestGit_AddPath_Create_Branch(t *testing.T) { var branch = "testCreateBranchOSFS" @@ -157,18 +159,18 @@ func TestGit_AddPath_Checkout_AddNewTree_Push(t *testing.T) { os.Chdir(tempDir) os.Mkdir(newPath, 0755) os.Chdir(newPath) - f, err := os.Create("adam.txt") // creates a file at current directory + f, err := os.Create("adam.txt") // creates a file at current directory if err != nil { t.Errorf("%v", err) return } - - newLine := "This file made by Adam. \nUpdated" + utils.DateTimeUTC() - _, err = fmt.Fprintln(f, newLine) - if err != nil { + + newLine := "This file made by Adam. \nUpdated" + utils.DateTimeUTC() + _, err = fmt.Fprintln(f, newLine) + if err != nil { t.Errorf("%v", err) return - } + } f.Close() err = client.AddFile(newPath) diff --git a/integration-tests/gitclient/gitclient_dnsupdate_test.go b/integration-tests/gitclient/gitclient_dnsupdate_test.go index cc791d9..7552fdf 100644 --- a/integration-tests/gitclient/gitclient_dnsupdate_test.go +++ b/integration-tests/gitclient/gitclient_dnsupdate_test.go @@ -5,19 +5,32 @@ package gitclient import ( "bufio" "fmt" + "os" "strings" "testing" "valkyrie.dso.mil/valkyrie-api/clients/git" + "valkyrie.dso.mil/valkyrie-api/clients/utils" ) -func TestGit_Checkout_UpdateDNSFile_Push(t *testing.T) { - branch := "testDnsUpdate" +var dnsTestBranch string = "integrationTestDNS" + +// go clean -testcache && go test -v -tags "integration" ./integration-tests/gitclient/gitclient_main_test.go ./integration-tests/gitclient/gitclient_dnsupdate_test.go +// setup environment for this test. create a branch with test files already in the branch +func TestGit_DNS_Setup(t *testing.T) { + branch := dnsTestBranch // create the git client - client, err := git.NewClient( + workingDir, err := utils.CreateTempDir("dns-test-", utils.TempRoot) + if err != nil { + t.Errorf("%v", err) + return + } + // create client using OS FS + client, err := git.NewClientOSFS( gitclientTestConfig.GitlabIntTestUsername, gitclientTestConfig.GitlabIntTestToken, gitclientTestConfig.GitlabIntTestRepositoryURL, + workingDir, ) if err != nil { t.Errorf("%v", err) @@ -25,7 +38,7 @@ func TestGit_Checkout_UpdateDNSFile_Push(t *testing.T) { } t.Logf("Created git client for repo %s", gitclientTestConfig.GitlabIntTestRepositoryURL) - // checkout and delete the branch + // SETUP initial STATE - checkout and delete the branch err = client.CheckoutOrCreateBranch(branch) if err != nil { t.Errorf("%v", err) @@ -38,8 +51,81 @@ func TestGit_Checkout_UpdateDNSFile_Push(t *testing.T) { t.Errorf("Error %v", err) return } - t.Logf("Delete remote branch %s", branch) + t.Logf("Deleted remote branch %s", branch) + + // Create a NEW fresh branch + err = client.CheckoutOrCreateBranch(branch) + if err != nil { + t.Errorf("Error %v", err) + return + } + t.Logf("Checked out and created a NEW branch %s", branch) + + // ADD test files to new branch + t.Logf("git working dir %s", gitclientTestConfig.WorkingDir) + dataFileName := "dso-dns-staging.tar.gz" + dataFile := gitclientTestConfig.WorkingDir + utils.PathSeparator + "data" + utils.PathSeparator + "dso-dns-staging.tar.gz" + tempDataDir, err := utils.CreateTempDirWithFile(dataFile, "prefix-") + if err != nil { + t.Errorf("Error %v", err) + return + } + err = utils.CopyDir(tempDataDir, workingDir) + if err != nil { + t.Errorf("Error %v", err) + return + } + + // decompress the test file in the working dir + tarFile := workingDir + utils.PathSeparator + dataFileName + err = utils.UnTarFile(tarFile, workingDir) + if err != nil { + t.Errorf("Error %v", err) + return + } + err = os.Remove(tarFile) + if err != nil { + t.Errorf("Error %v", err) + return + } + + + // Add everything in the workingDir to the git index + err = client.AddFile(".") + if err != nil { + t.Errorf("Error %v", err) + return + } + err = client.Commit(fmt.Sprintf("Add integration test data %s", utils.DateTimeUTC())) + if err != nil { + t.Errorf("Error %v", err) + return + } + err = client.Push(branch) + if err != nil { + t.Errorf("Error %v", err) + return + } + + // cleanup + utils.DeleteDir(tempDataDir) +} +func TestGit_Checkout_UpdateDNSFile_Push(t *testing.T) { + branch := dnsTestBranch + + // create the git client with in memory FS + client, err := git.NewClient( + gitclientTestConfig.GitlabIntTestUsername, + gitclientTestConfig.GitlabIntTestToken, + gitclientTestConfig.GitlabIntTestRepositoryURL, + ) + if err != nil { + t.Errorf("%v", err) + return + } + t.Logf("Created git client for repo %s", gitclientTestConfig.GitlabIntTestRepositoryURL) + // Create a branch err = client.CheckoutOrCreateBranch(branch) if err != nil { t.Errorf("Error %v", err) @@ -47,10 +133,10 @@ func TestGit_Checkout_UpdateDNSFile_Push(t *testing.T) { } t.Logf("Checked out and Create branch %s", branch) - // Add + // process dns file fs := *client.GetFileSystem() - dnsFilePath := "staging/dns/configuration/db.staging.dso.mil" + dnsFilePath := "dso-dns-staging/staging/dns/configuration/db.staging.dso.mil" dnsFile, err := fs.Open(dnsFilePath) if err != nil { t.Errorf("%v", err) @@ -75,7 +161,7 @@ func TestGit_Checkout_UpdateDNSFile_Push(t *testing.T) { t.Logf("written %d bytes", count) if !done && strings.Contains(line, "-il2 ") { - tempFile.Write([]byte("I am here...\n")) + tempFile.Write([]byte("int-test-a-record\n")) done = true } } diff --git a/integration-tests/gitclient/gitclient_main_test.go b/integration-tests/gitclient/gitclient_main_test.go index 895918a..9192ebc 100644 --- a/integration-tests/gitclient/gitclient_main_test.go +++ b/integration-tests/gitclient/gitclient_main_test.go @@ -60,7 +60,6 @@ func packageSetup() error { configObject := &gitclientTestConfig configObject.WorkingDir, _ = os.Getwd() - configObject.GitlabAPIURL, ok = os.LookupEnv("GITLAB_API_URL") if !ok { err = errors.New("env variable GITLAB_API_URL undefined") @@ -114,8 +113,8 @@ func packageSetup() error { return err } - rlog.Debugf("configObject %v",configObject) - + rlog.Debugf("configObject %v", configObject) + // insure a root group exists in gitlab err = addRootGroup() if err != nil { @@ -145,7 +144,6 @@ func logGitStatus(t *testing.T, client *git.RepoClientImpl) { } - // Insure the integration test root level group exists func addRootGroup() error { configObject := &gitclientTestConfig @@ -175,21 +173,21 @@ func addRootGroup() error { // dont fail if group already exists fmt.Printf("Error! AddRootGroup %s error = %v %d\n", path, err, statusCode) return err - } else { - configObject.GitlabIntTestRootGroupID = got.ID - fmt.Printf("AddGroup %s %s %s %s %d \n", got.Name, got.Path, got.FullPath, got.WebURL, statusCode) } + configObject.GitlabIntTestRootGroupID = got.ID + fmt.Printf("AddGroup %s %s %s %s %d \n", got.Name, got.Path, got.FullPath, got.WebURL, statusCode) + } return nil } // Insure the integration test project exists -func addIntTestProject(projectUrl string) (int, error) { +func addIntTestProject(projectURL string) (int, error) { configObject := &gitclientTestConfig var project *gogitlab.Project = nil var responseCode int - url, err := url.Parse(projectUrl) + url, err := url.Parse(projectURL) if err != nil { return 0, err } @@ -202,29 +200,29 @@ func addIntTestProject(projectUrl string) (int, error) { if responseCode == http.StatusFound { return project.ID, nil - } else { - path := configObject.GitlabIntTestProjectPath - name := configObject.GitlabIntTestProjectPath - description := "Integration Test Project" - configPath := "a/b/config.yml@group1/group2/project" - initializeWithReadme := true - - projectOpts := gogitlab.CreateProjectOptions{ - Name: &name, - Path: &path, - Description: &description, - NamespaceID: &configObject.GitlabIntTestRootGroupID, - CIConfigPath: &configPath, - InitializeWithReadme: &initializeWithReadme, - } - got, statusCode, err := configObject.GitlabClient.AddProject(projectOpts) + } + path := configObject.GitlabIntTestProjectPath + name := configObject.GitlabIntTestProjectPath + description := "Integration Test Project" + configPath := "a/b/config.yml@group1/group2/project" + initializeWithReadme := true - if err != nil { - fmt.Printf("ClientImpl.AddProject() error = %v %d \n", err, statusCode) - return 0, err - } + projectOpts := gogitlab.CreateProjectOptions{ + Name: &name, + Path: &path, + Description: &description, + NamespaceID: &configObject.GitlabIntTestRootGroupID, + CIConfigPath: &configPath, + InitializeWithReadme: &initializeWithReadme, + } + got, statusCode, err := configObject.GitlabClient.AddProject(projectOpts) - fmt.Printf("AddProject %s %s %s %s %d", got.Name, got.Path, got.PathWithNamespace, got.WebURL, statusCode) - return got.ID, nil + if err != nil { + fmt.Printf("ClientImpl.AddProject() error = %v %d \n", err, statusCode) + return 0, err } -} \ No newline at end of file + + fmt.Printf("AddProject %s %s %s %s %d", got.Name, got.Path, got.PathWithNamespace, got.WebURL, statusCode) + return got.ID, nil + +} diff --git a/integration-tests/gitlab/api/gitlab_main_test.go b/integration-tests/gitlab/api/gitlab_main_test.go index 7fae977..30c9b15 100644 --- a/integration-tests/gitlab/api/gitlab_main_test.go +++ b/integration-tests/gitlab/api/gitlab_main_test.go @@ -57,7 +57,7 @@ func packageSetup() error { var ok bool var err error - configObject := gitlabAPITestConfig + configObject := &gitlabAPITestConfig configObject.WorkingDir, _ = os.Getwd() -- GitLab From c34a807d881adf753c801e57f5334411cb2e1e85 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Wed, 1 Sep 2021 10:24:47 -0600 Subject: [PATCH 35/55] add decompress option. linting. --- clients/utils/datetime_utils_test.go | 5 +- clients/utils/file_utils.go | 85 ++++++++++++++----- .../gitclient/gitclient_dnsupdate_test.go | 21 +---- 3 files changed, 68 insertions(+), 43 deletions(-) diff --git a/clients/utils/datetime_utils_test.go b/clients/utils/datetime_utils_test.go index e41d5c9..4eadc93 100644 --- a/clients/utils/datetime_utils_test.go +++ b/clients/utils/datetime_utils_test.go @@ -23,8 +23,5 @@ func TestDateTime_Test_1(t *testing.T) { } func checkString(v *string) bool { - if v == nil { - return false - } - return true + return v != nil } diff --git a/clients/utils/file_utils.go b/clients/utils/file_utils.go index 5470184..23ad81d 100644 --- a/clients/utils/file_utils.go +++ b/clients/utils/file_utils.go @@ -42,29 +42,33 @@ func CreateTempDir(prefix string, rootDir string) (tempDir string, err error) { } // CopyFile - Copy a single file from locaton to another using full paths -func CopyFile(src, dst string) (int64, error) { +func CopyFile(src, dst string) error { sourceFileStat, err := os.Stat(src) if err != nil { - return 0, err + return err } if !sourceFileStat.Mode().IsRegular() { - return 0, fmt.Errorf("%s is not a regular file", src) + return fmt.Errorf("%s is not a regular file", src) } source, err := os.Open(src) if err != nil { - return 0, err + return err } defer source.Close() destination, err := os.Create(dst) if err != nil { - return 0, err + return err } defer destination.Close() - nBytes, err := io.Copy(destination, source) - return nBytes, err + + _, err = io.Copy(destination, source) + if err != nil { + return err + } + return nil } //CopyDir - copy directory contents recursively using exec @@ -91,7 +95,7 @@ func DeleteDir(path string) error { // CreateTempDirWithFile - create tempdir and populate with filePath // filePath may be a single file, a directory, or a zip or tar.gz file -func CreateTempDirWithFile(filePath string, prefix string) (string, error) { +func CreateTempDirWithFile(filePath string, prefix string, decompress bool) (string, error) { tempDir, err := CreateTempDir(prefix, TempRoot) if err != nil { return "", err @@ -105,25 +109,48 @@ func CreateTempDirWithFile(filePath string, prefix string) (string, error) { // if is file if !stat.IsDir() { - - targetPath := tempDir + PathSeparator + stat.Name() - _, err = CopyFile(filePath, targetPath) + if decompress { + if strings.HasSuffix(filePath, ".zip") { + err = UnZipFile(filePath, tempDir) + if err != nil { + // try to cleanup + DeleteDir(tempDir) + return "", err + } + } else { + if strings.HasSuffix(filePath, ".tar.gz") { + err = UnTarFile(filePath, tempDir) + if err != nil { + // try to cleanup + DeleteDir(tempDir) + return "", err + } + } else { + targetFullPath := tempDir + PathSeparator + stat.Name() + err = CopyFile(filePath, targetFullPath) + if err != nil { + // try to cleanup + DeleteDir(tempDir) + return "", err + } + } + } + } else { + targetFullPath := tempDir + PathSeparator + stat.Name() + err = CopyFile(filePath, targetFullPath) + if err != nil { + // try to cleanup + DeleteDir(tempDir) + return "", err + } + } + } else { + err = CopyDir(filePath, tempDir) if err != nil { // try to cleanup DeleteDir(tempDir) return "", err } - if strings.HasSuffix(filePath, ".zip") { - // process zip file - } else { - if strings.HasSuffix(filePath, ".tar.gz") { - // process tar gz file - } else { - // process regular file - } - } - } else { - // process directory } return tempDir, nil } @@ -142,6 +169,20 @@ func UnTarFile(filePath string, dstPath string) error { return nil } +// UnZipFile - decompress .zip file to dstPath directory +func UnZipFile(filePath string, dstPath string) error { + if !IsFile(filePath) { + return fmt.Errorf("path is not a valid file: %s", filePath) + } + // clean up target dir path - insure has only one trailig separator + dstPath = strings.TrimRight(dstPath, PathSeparator) + PathSeparator + _, err := exec.Command("unzip", filePath, "-d", dstPath).Output() + if err != nil { + return err + } + return nil +} + // IsFile - test if a path is a file using stat func IsFile(filePath string) bool { stat, err := os.Stat(filePath) diff --git a/integration-tests/gitclient/gitclient_dnsupdate_test.go b/integration-tests/gitclient/gitclient_dnsupdate_test.go index 7552fdf..8bfbe09 100644 --- a/integration-tests/gitclient/gitclient_dnsupdate_test.go +++ b/integration-tests/gitclient/gitclient_dnsupdate_test.go @@ -5,7 +5,6 @@ package gitclient import ( "bufio" "fmt" - "os" "strings" "testing" @@ -63,9 +62,11 @@ func TestGit_DNS_Setup(t *testing.T) { // ADD test files to new branch t.Logf("git working dir %s", gitclientTestConfig.WorkingDir) + dataFileName := "dso-dns-staging.tar.gz" - dataFile := gitclientTestConfig.WorkingDir + utils.PathSeparator + "data" + utils.PathSeparator + "dso-dns-staging.tar.gz" - tempDataDir, err := utils.CreateTempDirWithFile(dataFile, "prefix-") + dataFile := gitclientTestConfig.WorkingDir + utils.PathSeparator + "data" + utils.PathSeparator + dataFileName + // create a tempdir and decompress dataFile into tempDir + tempDataDir, err := utils.CreateTempDirWithFile(dataFile, "prefix-", true) if err != nil { t.Errorf("Error %v", err) return @@ -76,20 +77,6 @@ func TestGit_DNS_Setup(t *testing.T) { return } - // decompress the test file in the working dir - tarFile := workingDir + utils.PathSeparator + dataFileName - err = utils.UnTarFile(tarFile, workingDir) - if err != nil { - t.Errorf("Error %v", err) - return - } - err = os.Remove(tarFile) - if err != nil { - t.Errorf("Error %v", err) - return - } - - // Add everything in the workingDir to the git index err = client.AddFile(".") if err != nil { -- GitLab From c834f3675d80ef3857d472cbe5d8aa8750b60a22 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Tue, 7 Sep 2021 17:05:39 -0600 Subject: [PATCH 36/55] add gitlab token private to credentials spec --- apis/gitlab/clientConfiguration.go | 17 ++-- .../v1alpha1/gitlabcredentials_types.go | 3 + clients/utils/file_utils.go | 9 ++ controllers/gitlab/group_controller.go | 73 +++++++------- controllers/gitlab/group_controller_test.go | 94 +++++++++---------- controllers/gitlab/mocks_test.go | 9 +- controllers/gitlab/project_controller.go | 18 +++- controllers/gitlab/project_controller_test.go | 5 +- custom/p1/group_test.go | 9 +- custom/p1/project_bootstrap.go | 55 ++++++++--- custom/p1/project_test.go | 9 +- custom/p1/types.go | 5 +- 12 files changed, 183 insertions(+), 123 deletions(-) diff --git a/apis/gitlab/clientConfiguration.go b/apis/gitlab/clientConfiguration.go index ccd22b8..39d6fb0 100755 --- a/apis/gitlab/clientConfiguration.go +++ b/apis/gitlab/clientConfiguration.go @@ -7,7 +7,7 @@ import ( "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - gitlabv1alpha1 "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" + gitlabAPIVer "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" gitlabClient "valkyrie.dso.mil/valkyrie-api/clients/gitlab" ) @@ -20,7 +20,7 @@ const ( // ClientConfiguration represents an object whose purpose is to setup a Gitlab client given type ClientConfiguration interface { // SetupClient pulls the GitlabCredentials from Kubernetes and supplies the Gitlab user and access token. - SetupClient(client client.Client, credentialsName string) (gitlabClient.Client, error) + SetupClient(client client.Client, credentialsName string) (gitlabClient.Client, *gitlabAPIVer.GitlabCredentials, error) } // ClientConfigurationImpl is the default implementation for the ClientConfiguration interface @@ -33,17 +33,17 @@ type ClientConfigurationImpl struct { // SetupClient looks up the gitlab credentials to get the access token and username for connecting to Gitlab // on behalf of the reconciler. -func (c ClientConfigurationImpl) SetupClient(client client.Client, credentialsName string) (gitlabClient.Client, error) { +func (c ClientConfigurationImpl) SetupClient(client client.Client, credentialsName string) (gitlabClient.Client, *gitlabAPIVer.GitlabCredentials, error) { // Get the Gitlab Credentials var gitLabCredentialsName = types.NamespacedName{ Namespace: c.Req.Namespace, Name: credentialsName, } - var gitlabCredentials gitlabv1alpha1.GitlabCredentials + var gitlabCredentials gitlabAPIVer.GitlabCredentials if err := client.Get(c.Ctx, gitLabCredentialsName, &gitlabCredentials); err != nil { c.Log.Error(err, errorUnableToFetchGitlabCredentials) - return nil, err + return nil, nil, err } var secretName = types.NamespacedName{ @@ -55,19 +55,20 @@ func (c ClientConfigurationImpl) SetupClient(client client.Client, credentialsNa // Get the Secret if err := client.Get(c.Ctx, secretName, &secret); err != nil { c.Log.Error(err, errorUnableToFetchSecret) - return nil, err + return nil, nil, err } // Login to Gitlab var accessToken = string(secret.Data[gitlabCredentials.Spec.AccessTokenKey]) + gitlabCredentials.Spec.AccessTokenPrivate = accessToken var returnClient gitlabClient.Client var err error if returnClient, err = gitlabClient.NewClient(gitlabCredentials.Spec.URL, accessToken, nil); err != nil { c.Log.Error(err, errorUnableToCreateGitlabClient, "username", gitlabCredentials.Spec.Username, "url", gitlabCredentials.Spec.URL) - return nil, err + return nil, nil, err } - return returnClient, nil + return returnClient, &gitlabCredentials, nil } diff --git a/apis/gitlab/v1alpha1/gitlabcredentials_types.go b/apis/gitlab/v1alpha1/gitlabcredentials_types.go index 161386a..8181c02 100644 --- a/apis/gitlab/v1alpha1/gitlabcredentials_types.go +++ b/apis/gitlab/v1alpha1/gitlabcredentials_types.go @@ -35,6 +35,9 @@ type GitlabCredentialsSpec struct { //AccessTokenKey is the key of the secret data that contains the Gitlab Access Token for the user. AccessTokenKey string `json:"accessTokenKey"` + + //AccessTokenPrivate omit json marshalling. + AccessTokenPrivate string `json:"-"` } // GitlabCredentialsStatus defines the observed state of GitlabCredentials diff --git a/clients/utils/file_utils.go b/clients/utils/file_utils.go index 23ad81d..a79a776 100644 --- a/clients/utils/file_utils.go +++ b/clients/utils/file_utils.go @@ -206,3 +206,12 @@ func IsDir(filePath string) bool { } return false } + +// CurrentDir - get current dir +func CurrentDir() (string, error) { + path, err := os.Getwd() + if err != nil { + return "", err + } + return path, nil +} diff --git a/controllers/gitlab/group_controller.go b/controllers/gitlab/group_controller.go index 50ed36e..2a43100 100644 --- a/controllers/gitlab/group_controller.go +++ b/controllers/gitlab/group_controller.go @@ -31,8 +31,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" "strings" "time" - apisGitlab "valkyrie.dso.mil/valkyrie-api/apis/gitlab" - gitlabv1alpha1 "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" + gitlabAPI "valkyrie.dso.mil/valkyrie-api/apis/gitlab" + gitlabAPIVer "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" gitlabClient "valkyrie.dso.mil/valkyrie-api/clients/gitlab" ) @@ -83,7 +83,8 @@ type GroupReconciler struct { Log logr.Logger Scheme *runtime.Scheme gitlabClient gitlabClient.Client - gitlabClientConfiguration apisGitlab.ClientConfiguration + gitlabCredentials *gitlabAPIVer.GitlabCredentials + gitlabClientConfiguration gitlabAPI.ClientConfiguration } //+kubebuilder:rbac:groups=gitlab.valkyrie.dso.mil,resources=groups,verbs=get;list;watch;create;update;patch;delete @@ -102,7 +103,7 @@ func (r *GroupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl log.Info("in Group Controller") var err error - group := &gitlabv1alpha1.Group{} + group := &gitlabAPIVer.Group{} // Get the Group Object if err = r.Get(ctx, req.NamespacedName, group); err != nil { @@ -116,13 +117,13 @@ func (r *GroupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl // Do a nil check here so we can use mock gitlabClients if r.gitlabClient == nil { if r.gitlabClientConfiguration == nil { - r.gitlabClientConfiguration = apisGitlab.ClientConfigurationImpl{ + r.gitlabClientConfiguration = gitlabAPI.ClientConfigurationImpl{ Log: log, Ctx: ctx, Req: req, } } - if r.gitlabClient, err = r.gitlabClientConfiguration.SetupClient(r.Client, group.Spec.GitlabCredentialsName); err != nil { + if r.gitlabClient, r.gitlabCredentials, err = r.gitlabClientConfiguration.SetupClient(r.Client, group.Spec.GitlabCredentialsName); err != nil { log.Error(err, errorUnableToSetupGitlabClient) _ = r.updateState(ctx, group, errorUnableToSetupGitlabClient, log) return ctrl.Result{Requeue: true}, err @@ -279,7 +280,7 @@ func (r *GroupReconciler) groupExistsByID(groupID int) (bool, *gitlab.Group, err return false, nil, nil } -func getPaths(group *gitlabv1alpha1.Group) (parentGroupPath string, path string) { +func getPaths(group *gitlabAPIVer.Group) (parentGroupPath string, path string) { lastSlashIndex := strings.LastIndex(group.Spec.FullPath, "/") if lastSlashIndex == -1 { return "", "" @@ -288,7 +289,7 @@ func getPaths(group *gitlabv1alpha1.Group) (parentGroupPath string, path string) } //createGroup assumes the parent group already exists, if not, it will error out -func (r *GroupReconciler) createGroup(group *gitlabv1alpha1.Group) (*gitlab.Group, int, error) { +func (r *GroupReconciler) createGroup(group *gitlabAPIVer.Group) (*gitlab.Group, int, error) { //find parent group first parentGroupPath, groupPath := getPaths(group) @@ -316,7 +317,7 @@ func (r *GroupReconciler) createGroup(group *gitlabv1alpha1.Group) (*gitlab.Grou return gitlabGroup, statusCode, err } -func (r *GroupReconciler) updateGroup(id int, group *gitlabv1alpha1.Group) (*gitlab.Group, int, error) { +func (r *GroupReconciler) updateGroup(id int, group *gitlabAPIVer.Group) (*gitlab.Group, int, error) { _, groupPath := getPaths(group) gitlabGroup, statusCode, err := r.gitlabClient.UpdateGroup(id, &gitlab.UpdateGroupOptions{ @@ -328,12 +329,12 @@ func (r *GroupReconciler) updateGroup(id int, group *gitlabv1alpha1.Group) (*git return gitlabGroup, statusCode, err } -func getDNSMergerRequestResourceName(group *gitlabv1alpha1.Group) string { +func getDNSMergerRequestResourceName(group *gitlabAPIVer.Group) string { return group.Name + "-dns-mr" } -func (r *GroupReconciler) processDNSMergeRequest(ctx context.Context, group *gitlabv1alpha1.Group, log logr.Logger) (err error) { - var dnsMr *gitlabv1alpha1.DNSRepoMergeRequest +func (r *GroupReconciler) processDNSMergeRequest(ctx context.Context, group *gitlabAPIVer.Group, log logr.Logger) (err error) { + var dnsMr *gitlabAPIVer.DNSRepoMergeRequest dnsMrResourceName := getDNSMergerRequestResourceName(group) //gets the resource @@ -363,8 +364,8 @@ func (r *GroupReconciler) processDNSMergeRequest(ctx context.Context, group *git return nil } -func (r *GroupReconciler) getDNSMergeRequestResource(ctx context.Context, group *gitlabv1alpha1.Group, log logr.Logger) (*gitlabv1alpha1.DNSRepoMergeRequest, error) { - var dnsMR gitlabv1alpha1.DNSRepoMergeRequest +func (r *GroupReconciler) getDNSMergeRequestResource(ctx context.Context, group *gitlabAPIVer.Group, log logr.Logger) (*gitlabAPIVer.DNSRepoMergeRequest, error) { + var dnsMR gitlabAPIVer.DNSRepoMergeRequest resourceName := getDNSMergerRequestResourceName(group) dnsMRName := types.NamespacedName{ Namespace: group.Namespace, @@ -380,11 +381,11 @@ func (r *GroupReconciler) getDNSMergeRequestResource(ctx context.Context, group return &dnsMR, nil } -func (r *GroupReconciler) createDNSMergeRequestResource(ctx context.Context, group *gitlabv1alpha1.Group, log logr.Logger) error { +func (r *GroupReconciler) createDNSMergeRequestResource(ctx context.Context, group *gitlabAPIVer.Group, log logr.Logger) error { blockOwnerDeletion := true managingController := true resourceName := getDNSMergerRequestResourceName(group) - err := r.Create(ctx, &gitlabv1alpha1.DNSRepoMergeRequest{ + err := r.Create(ctx, &gitlabAPIVer.DNSRepoMergeRequest{ ObjectMeta: ctrl.ObjectMeta{ Name: resourceName, Namespace: group.Namespace, @@ -408,9 +409,9 @@ func (r *GroupReconciler) createDNSMergeRequestResource(ctx context.Context, gro return err } -func (r *GroupReconciler) deleteDNSMergeRequestResource(ctx context.Context, group *gitlabv1alpha1.Group, log logr.Logger) (err error) { +func (r *GroupReconciler) deleteDNSMergeRequestResource(ctx context.Context, group *gitlabAPIVer.Group, log logr.Logger) (err error) { //check if resource exits - var dnsMrResource *gitlabv1alpha1.DNSRepoMergeRequest + var dnsMrResource *gitlabAPIVer.DNSRepoMergeRequest if dnsMrResource, err = r.getDNSMergeRequestResource(ctx, group, log); err != nil { return err } @@ -426,7 +427,7 @@ func (r *GroupReconciler) deleteDNSMergeRequestResource(ctx context.Context, gro return nil } -func (r *GroupReconciler) processProjects(ctx context.Context, group *gitlabv1alpha1.Group, log logr.Logger) error { +func (r *GroupReconciler) processProjects(ctx context.Context, group *gitlabAPIVer.Group, log logr.Logger) error { var projectResourceNames = make([]string, len(group.Spec.ProjectTemplates)) for i, projectTemplate := range group.Spec.ProjectTemplates { projectResourceNames[i] = projectTemplate.Name @@ -454,7 +455,7 @@ func (r *GroupReconciler) processProjects(ctx context.Context, group *gitlabv1al return nil } -func (r *GroupReconciler) cleanUpProjects(ctx context.Context, group *gitlabv1alpha1.Group, projectResourceNames []string, log logr.Logger) error { +func (r *GroupReconciler) cleanUpProjects(ctx context.Context, group *gitlabAPIVer.Group, projectResourceNames []string, log logr.Logger) error { projectsToDelete := getElementsNotContained(group.Status.ProjectResourceNames, projectResourceNames) for _, projectToDelete := range projectsToDelete { if project, foundProject, err := r.getProject(ctx, group.Namespace, projectToDelete); err != nil { @@ -500,7 +501,7 @@ func getElementsNotContained(a []string, b []string) []string { return keys } -func (r *GroupReconciler) deleteProjects(ctx context.Context, group *gitlabv1alpha1.Group, templates []gitlabv1alpha1.ProjectTemplate, log logr.Logger) error { +func (r *GroupReconciler) deleteProjects(ctx context.Context, group *gitlabAPIVer.Group, templates []gitlabAPIVer.ProjectTemplate, log logr.Logger) error { for _, template := range templates { // if it's not found we'll consider it gone and not worry about it. if project, foundProject, err := r.getProject(ctx, group.Namespace, template.Name); err != nil { @@ -516,8 +517,8 @@ func (r *GroupReconciler) deleteProjects(ctx context.Context, group *gitlabv1alp return nil } -func (r *GroupReconciler) getProject(ctx context.Context, namespace string, name string) (*gitlabv1alpha1.Project, bool, error) { - var project gitlabv1alpha1.Project +func (r *GroupReconciler) getProject(ctx context.Context, namespace string, name string) (*gitlabAPIVer.Project, bool, error) { + var project gitlabAPIVer.Project projectName := types.NamespacedName{ Namespace: namespace, Name: name, @@ -532,10 +533,10 @@ func (r *GroupReconciler) getProject(ctx context.Context, namespace string, name return &project, true, err } -func (r *GroupReconciler) createProject(ctx context.Context, group *gitlabv1alpha1.Group, template gitlabv1alpha1.ProjectTemplate) error { +func (r *GroupReconciler) createProject(ctx context.Context, group *gitlabAPIVer.Group, template gitlabAPIVer.ProjectTemplate) error { blockOwnerDeletion := true managingController := true - return r.Create(ctx, &gitlabv1alpha1.Project{ + return r.Create(ctx, &gitlabAPIVer.Project{ ObjectMeta: ctrl.ObjectMeta{ Name: template.Name, Namespace: group.Namespace, @@ -554,8 +555,8 @@ func (r *GroupReconciler) createProject(ctx context.Context, group *gitlabv1alph }) } -func getProjectSpec(group *gitlabv1alpha1.Group, template gitlabv1alpha1.ProjectTemplate) gitlabv1alpha1.ProjectSpec { - return gitlabv1alpha1.ProjectSpec{ +func getProjectSpec(group *gitlabAPIVer.Group, template gitlabAPIVer.ProjectTemplate) gitlabAPIVer.ProjectSpec { + return gitlabAPIVer.ProjectSpec{ GroupID: *group.Status.ID, Name: template.ProjectName, FullPath: template.FullPath, @@ -567,12 +568,12 @@ func getProjectSpec(group *gitlabv1alpha1.Group, template gitlabv1alpha1.Project } } -func (r *GroupReconciler) updateProject(ctx context.Context, group *gitlabv1alpha1.Group, template gitlabv1alpha1.ProjectTemplate, project *gitlabv1alpha1.Project) (*gitlabv1alpha1.Project, error) { +func (r *GroupReconciler) updateProject(ctx context.Context, group *gitlabAPIVer.Group, template gitlabAPIVer.ProjectTemplate, project *gitlabAPIVer.Project) (*gitlabAPIVer.Project, error) { project.Spec = getProjectSpec(group, template) return project, r.Update(ctx, project) } -func (r *GroupReconciler) updateStatus(ctx context.Context, group *gitlabv1alpha1.Group) error { +func (r *GroupReconciler) updateStatus(ctx context.Context, group *gitlabAPIVer.Group) error { group.Status.LastUpdatedTime = &metav1.Time{ Time: time.Now(), } @@ -588,14 +589,14 @@ func (r *GroupReconciler) updateStatus(ctx context.Context, group *gitlabv1alpha func (r *GroupReconciler) SetupWithManager(mgr ctrl.Manager) error { pred := predicate.GenerationChangedPredicate{} return ctrl.NewControllerManagedBy(mgr). - For(&gitlabv1alpha1.Group{}). + For(&gitlabAPIVer.Group{}). //owns cause any update to the created Project to run the reconcile method...not exactly what we need - //Owns(&gitlabv1alpha1.Project{}). + //Owns(&gitlabAPIVer.Project{}). WithEventFilter(pred). Complete(r) } -func (r *GroupReconciler) updateCiVariable(ID int, variableToUpdate gitlabv1alpha1.CICDVariable, groupVariable *gitlab.GroupVariable, log logr.Logger) error { +func (r *GroupReconciler) updateCiVariable(ID int, variableToUpdate gitlabAPIVer.CICDVariable, groupVariable *gitlab.GroupVariable, log logr.Logger) error { //if value needs to be updated, update it option := gitlab.UpdateGroupVariableOptions{ Value: &variableToUpdate.Value, @@ -614,7 +615,7 @@ func (r *GroupReconciler) updateCiVariable(ID int, variableToUpdate gitlabv1alph return nil } -func (r *GroupReconciler) updateCiVariables(ID int, group *gitlabv1alpha1.Group, log logr.Logger) error { +func (r *GroupReconciler) updateCiVariables(ID int, group *gitlabAPIVer.Group, log logr.Logger) error { var variablesToUpdate = group.Spec.CIVariables var err error var existingGroupVariable *gitlab.GroupVariable @@ -643,7 +644,7 @@ func (r *GroupReconciler) updateCiVariables(ID int, group *gitlabv1alpha1.Group, } // CreateCiVariable - -func (r *GroupReconciler) CreateCiVariable(ID int, variableToCreate gitlabv1alpha1.CICDVariable) (statusCode int, err error) { +func (r *GroupReconciler) CreateCiVariable(ID int, variableToCreate gitlabAPIVer.CICDVariable) (statusCode int, err error) { envType := gitlab.EnvVariableType protected := true masked := false @@ -660,7 +661,7 @@ func (r *GroupReconciler) CreateCiVariable(ID int, variableToCreate gitlabv1alph return statusCode, err } -func (r *GroupReconciler) updateState(ctx context.Context, group *gitlabv1alpha1.Group, state string, log logr.Logger) error { +func (r *GroupReconciler) updateState(ctx context.Context, group *gitlabAPIVer.Group, state string, log logr.Logger) error { group.Status.State = state if err := r.Status().Update(ctx, group); err != nil { log.Error(err, errorWhileUpdatingGroupState, "group", group) @@ -669,7 +670,7 @@ func (r *GroupReconciler) updateState(ctx context.Context, group *gitlabv1alpha1 return nil } -func (r *GroupReconciler) deleteProjectsAndGitlabGroup(ctx context.Context, group *gitlabv1alpha1.Group, log logr.Logger) error { +func (r *GroupReconciler) deleteProjectsAndGitlabGroup(ctx context.Context, group *gitlabAPIVer.Group, log logr.Logger) error { var err error groupID := group.Status.ID diff --git a/controllers/gitlab/group_controller_test.go b/controllers/gitlab/group_controller_test.go index 2f23e49..00bd090 100755 --- a/controllers/gitlab/group_controller_test.go +++ b/controllers/gitlab/group_controller_test.go @@ -11,7 +11,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "time" apisGitlab "valkyrie.dso.mil/valkyrie-api/apis/gitlab" - gitlabv1alpha1 "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" + gitlabAPIVer "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" gitlabClient "valkyrie.dso.mil/valkyrie-api/clients/gitlab" ) @@ -49,17 +49,17 @@ func getGreenGroupControllerDeleteRequest() ctrl.Request { } } -func getGreenGroup() *gitlabv1alpha1.Group { - returnGroup := &gitlabv1alpha1.Group{ +func getGreenGroup() *gitlabAPIVer.Group { + returnGroup := &gitlabAPIVer.Group{ TypeMeta: metav1.TypeMeta{}, ObjectMeta: metav1.ObjectMeta{ Annotations: make(map[string]string), }, - Spec: gitlabv1alpha1.GroupSpec{ + Spec: gitlabAPIVer.GroupSpec{ FullPath: "/greenGroup", Name: "greenGroup", GitlabCredentialsName: "greenCredentialsName", - CIVariables: []gitlabv1alpha1.CICDVariable{ + CIVariables: []gitlabAPIVer.CICDVariable{ { Key: kustomizeProductionPathVariableName, Value: "/kustomize/prod/path", @@ -73,14 +73,14 @@ func getGreenGroup() *gitlabv1alpha1.Group { Value: manifestRepoURLVariableValue, }, }, - DNSRepoMergeRequestSpec: &gitlabv1alpha1.DNSRepoMergeRequestSpec{ + DNSRepoMergeRequestSpec: &gitlabAPIVer.DNSRepoMergeRequestSpec{ RepoCredentialName: "test", AppHostname: "greenapp", TargetEnvironment: "il2", }, - ProjectTemplates: make([]gitlabv1alpha1.ProjectTemplate, 0), + ProjectTemplates: make([]gitlabAPIVer.ProjectTemplate, 0), }, - Status: gitlabv1alpha1.GroupStatus{ + Status: gitlabAPIVer.GroupStatus{ CreatedTime: &metav1.Time{ Time: time.Now(), }, @@ -90,7 +90,7 @@ func getGreenGroup() *gitlabv1alpha1.Group { State: "", }, } - returnGroup.Spec.ProjectTemplates = append(returnGroup.Spec.ProjectTemplates, gitlabv1alpha1.ProjectTemplate{ + returnGroup.Spec.ProjectTemplates = append(returnGroup.Spec.ProjectTemplates, gitlabAPIVer.ProjectTemplate{ Name: "Project resource name", ProjectName: "A Green Project", FullPath: "full path", @@ -100,7 +100,7 @@ func getGreenGroup() *gitlabv1alpha1.Group { } func getGroupControllerWithMocksInGreenTestState() (*GroupReconciler, *MockLogger, *MockClientConfiguration, *MockClient, *MockGitlabClient) { - builder := gitlabv1alpha1.SchemeBuilder.Register(&gitlabv1alpha1.Group{}, &gitlabv1alpha1.GroupList{}) + builder := gitlabAPIVer.SchemeBuilder.Register(&gitlabAPIVer.Group{}, &gitlabAPIVer.GroupList{}) scheme, _ := builder.Build() loggerMock := MockLogger{ WithValuesKeysAndValues: nil, @@ -170,17 +170,17 @@ func getGroupControllerWithMocksInGreenTestState() (*GroupReconciler, *MockLogge return &sut, &loggerMock, &configurationMock, &clientMock, &gitlabClientMock } -func getToDeleteGroup() *gitlabv1alpha1.Group { - toDeleteGroup := &gitlabv1alpha1.Group{ +func getToDeleteGroup() *gitlabAPIVer.Group { + toDeleteGroup := &gitlabAPIVer.Group{ TypeMeta: metav1.TypeMeta{}, ObjectMeta: metav1.ObjectMeta{ Annotations: make(map[string]string), }, - Spec: gitlabv1alpha1.GroupSpec{ + Spec: gitlabAPIVer.GroupSpec{ FullPath: "/greenDeleteGroup", Name: "greenDeleteGroup", GitlabCredentialsName: "greenCredentialsName", - CIVariables: []gitlabv1alpha1.CICDVariable{ + CIVariables: []gitlabAPIVer.CICDVariable{ { Key: kustomizeProductionPathVariableName, Value: "/kustomize/prod/path", @@ -194,14 +194,14 @@ func getToDeleteGroup() *gitlabv1alpha1.Group { Value: manifestRepoURLVariableValue, }, }, - DNSRepoMergeRequestSpec: &gitlabv1alpha1.DNSRepoMergeRequestSpec{ + DNSRepoMergeRequestSpec: &gitlabAPIVer.DNSRepoMergeRequestSpec{ RepoCredentialName: "test", AppHostname: "testdelete", TargetEnvironment: "il2", }, - ProjectTemplates: make([]gitlabv1alpha1.ProjectTemplate, 0), + ProjectTemplates: make([]gitlabAPIVer.ProjectTemplate, 0), }, - Status: gitlabv1alpha1.GroupStatus{ + Status: gitlabAPIVer.GroupStatus{ CreatedTime: &metav1.Time{ Time: time.Now(), }, @@ -214,7 +214,7 @@ func getToDeleteGroup() *gitlabv1alpha1.Group { toDeleteGroup.Spec.Name = toDeleteGreenGroupName toDeleteGroup.Namespace = toDeleteGreenGroupNamespace toDeleteGroup.Spec.FullPath = "/greenDeleteGroup" - toDeleteGroup.Spec.ProjectTemplates = append(toDeleteGroup.Spec.ProjectTemplates, gitlabv1alpha1.ProjectTemplate{ + toDeleteGroup.Spec.ProjectTemplates = append(toDeleteGroup.Spec.ProjectTemplates, gitlabAPIVer.ProjectTemplate{ Name: "project-resource-name", ProjectName: "A Green Project to Delete", FullPath: "full path", @@ -267,13 +267,13 @@ var _ = Describe("Reconcile", func() { }) // Finish the Delete - group := sut.Client.(*MockClient).expectedObjects[getGreenGroupControllerDeleteRequest().NamespacedName].(*gitlabv1alpha1.Group) + group := sut.Client.(*MockClient).expectedObjects[getGreenGroupControllerDeleteRequest().NamespacedName].(*gitlabAPIVer.Group) group.SetDeletionTimestamp(&metav1.Time{Time: time.Now()}) group.Finalizers = append(group.Finalizers, groupFinalizerName) groupIDToDelete := toDeleteGreenGroupID group.Status.ID = &groupIDToDelete - sut.Client.(*MockClient).expectedObjects[types.NamespacedName{Namespace: group.Namespace, Name: getDNSMergerRequestResourceName(group)}] = &gitlabv1alpha1.DNSRepoMergeRequest{} + sut.Client.(*MockClient).expectedObjects[types.NamespacedName{Namespace: group.Namespace, Name: getDNSMergerRequestResourceName(group)}] = &gitlabAPIVer.DNSRepoMergeRequest{} result, err = sut.Reconcile(context.TODO(), getGreenGroupControllerDeleteRequest()) It("should not request a requeue", func() { @@ -317,8 +317,8 @@ var _ = Describe("Reconcile", func() { }) Context("gitlab client configuration fails", func() { sut, logger, clientConfiguration, _, _ := getGroupControllerWithMocksInGreenTestState() - clientConfiguration.SetupClientFunction = func(client client.Client, credentialsName string) (gitlabClient.Client, error) { - return nil, &MockError{message: "setupClient Failed"} + clientConfiguration.SetupClientFunction = func(client client.Client, credentialsName string) (gitlabClient.Client, *gitlabAPIVer.GitlabCredentials, error) { + return nil, nil, &MockError{message: "setupClient Failed"} } result, err := sut.Reconcile(context.TODO(), getGreenGroupControllerRequest()) It("should log the error", func() { @@ -332,7 +332,7 @@ var _ = Describe("Reconcile", func() { Expect(err).ToNot(BeNil()) }) It("should update the state of the object", func() { - Expect(sut.Status().(*MockStatusWriter).updatedObject.(*gitlabv1alpha1.Group).Status.State).To(Equal(errorUnableToSetupGitlabClient)) + Expect(sut.Status().(*MockStatusWriter).updatedObject.(*gitlabAPIVer.Group).Status.State).To(Equal(errorUnableToSetupGitlabClient)) }) }) Context("groupExistsByPath fails", func() { @@ -360,7 +360,7 @@ var _ = Describe("Reconcile", func() { Expect(err).NotTo(BeNil()) }) It("should update the state of the object", func() { - Expect(sut.Status().(*MockStatusWriter).updatedObject.(*gitlabv1alpha1.Group).Status.State).To(Equal(errorWhileCreatingGitlabGroup)) + Expect(sut.Status().(*MockStatusWriter).updatedObject.(*gitlabAPIVer.Group).Status.State).To(Equal(errorWhileCreatingGitlabGroup)) }) }) Context("createGroup fails", func() { @@ -392,7 +392,7 @@ var _ = Describe("Reconcile", func() { Expect(err).NotTo(BeNil()) }) It("should update the state of the object", func() { - Expect(sut.Status().(*MockStatusWriter).updatedObject.(*gitlabv1alpha1.Group).Status.State).To(Equal(errorWhileCreatingGitlabGroup)) + Expect(sut.Status().(*MockStatusWriter).updatedObject.(*gitlabAPIVer.Group).Status.State).To(Equal(errorWhileCreatingGitlabGroup)) }) }) Context("updateGroup fails", func() { @@ -403,7 +403,7 @@ var _ = Describe("Reconcile", func() { message: "Error", } } - group := sut.Client.(*MockClient).expectedObjects[getGreenGroupControllerRequest().NamespacedName].(*gitlabv1alpha1.Group) + group := sut.Client.(*MockClient).expectedObjects[getGreenGroupControllerRequest().NamespacedName].(*gitlabAPIVer.Group) groupID := greenGroupID group.Status.ID = &groupID @@ -419,7 +419,7 @@ var _ = Describe("Reconcile", func() { Expect(err).NotTo(BeNil()) }) It("should update the state of the object", func() { - Expect(sut.Status().(*MockStatusWriter).updatedObject.(*gitlabv1alpha1.Group).Status.State).To(Equal(errorWhileUpdatingGitlabGroup)) + Expect(sut.Status().(*MockStatusWriter).updatedObject.(*gitlabAPIVer.Group).Status.State).To(Equal(errorWhileUpdatingGitlabGroup)) }) }) Context("getGroupVariable fails", func() { @@ -439,7 +439,7 @@ var _ = Describe("Reconcile", func() { Expect(err).ToNot(BeNil()) }) It("should update the state of the object", func() { - Expect(sut.Status().(*MockStatusWriter).updatedObject.(*gitlabv1alpha1.Group).Status.State).To(Equal(errorWhileUpdatingGitlabGroupCiVariables)) + Expect(sut.Status().(*MockStatusWriter).updatedObject.(*gitlabAPIVer.Group).Status.State).To(Equal(errorWhileUpdatingGitlabGroupCiVariables)) }) }) Context("createCiVariable fails", func() { @@ -459,7 +459,7 @@ var _ = Describe("Reconcile", func() { Expect(err).ToNot(BeNil()) }) It("should update the state of the object", func() { - Expect(sut.Status().(*MockStatusWriter).updatedObject.(*gitlabv1alpha1.Group).Status.State).To(Equal(errorWhileUpdatingGitlabGroupCiVariables)) + Expect(sut.Status().(*MockStatusWriter).updatedObject.(*gitlabAPIVer.Group).Status.State).To(Equal(errorWhileUpdatingGitlabGroupCiVariables)) }) }) Context("updateGroupVariable fails", func() { @@ -467,7 +467,7 @@ var _ = Describe("Reconcile", func() { gitlabClient.updateGroupVariableFunction = func(groupID int, key string, options gitlab.UpdateGroupVariableOptions) (*gitlab.GroupVariable, int, error) { return nil, 500, &MockError{"updateGroupVariable mocked error"} } - group := sut.Client.(*MockClient).expectedObjects[getGreenGroupControllerRequest().NamespacedName].(*gitlabv1alpha1.Group) + group := sut.Client.(*MockClient).expectedObjects[getGreenGroupControllerRequest().NamespacedName].(*gitlabAPIVer.Group) groupID := greenGroupID group.Status.ID = &groupID @@ -484,7 +484,7 @@ var _ = Describe("Reconcile", func() { Expect(err).ToNot(BeNil()) }) It("should update the state of the object", func() { - Expect(sut.Status().(*MockStatusWriter).updatedObject.(*gitlabv1alpha1.Group).Status.State).To(Equal(errorWhileUpdatingGitlabGroupCiVariables)) + Expect(sut.Status().(*MockStatusWriter).updatedObject.(*gitlabAPIVer.Group).Status.State).To(Equal(errorWhileUpdatingGitlabGroupCiVariables)) }) }) Context("processProjects fails", func() { @@ -492,14 +492,14 @@ var _ = Describe("Reconcile", func() { kubernetesClient.createFunction = func(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { switch obj.(type) { - case *gitlabv1alpha1.Project: + case *gitlabAPIVer.Project: return &MockError{message: "processProjects Fails"} } return nil } kubernetesClient.UpdateFunction = func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { switch obj.(type) { - case *gitlabv1alpha1.Project: + case *gitlabAPIVer.Project: return &MockError{message: "processProjects Fails"} } return nil @@ -620,9 +620,9 @@ var _ = Describe("createGroup", func() { sut.gitlabClient = gitlabClient group, statusCode, err := sut.createGroup( - &gitlabv1alpha1.Group{ + &gitlabAPIVer.Group{ ObjectMeta: ctrl.ObjectMeta{Annotations: make(map[string]string)}, - Spec: gitlabv1alpha1.GroupSpec{Name: "a group"}, + Spec: gitlabAPIVer.GroupSpec{Name: "a group"}, }) It("should return the gitlab group created", func() { Expect(group).To(Equal(expectedGroup)) @@ -652,10 +652,10 @@ var _ = Describe("updateGroup", func() { group, response, err := sut.updateGroup( 1, - &gitlabv1alpha1.Group{ + &gitlabAPIVer.Group{ ObjectMeta: ctrl.ObjectMeta{Annotations: make(map[string]string)}, - Spec: gitlabv1alpha1.GroupSpec{Name: "a group"}, - Status: gitlabv1alpha1.GroupStatus{ + Spec: gitlabAPIVer.GroupSpec{Name: "a group"}, + Status: gitlabAPIVer.GroupStatus{ CreatedTime: &metav1.Time{}, LastUpdatedTime: &metav1.Time{}, State: "", @@ -673,7 +673,7 @@ var _ = Describe("updateGroup", func() { }) var _ = Describe("SetupWithManager", func() { - builder := gitlabv1alpha1.SchemeBuilder.Register(&gitlabv1alpha1.Group{}, &gitlabv1alpha1.GroupList{}) + builder := gitlabAPIVer.SchemeBuilder.Register(&gitlabAPIVer.Group{}, &gitlabAPIVer.GroupList{}) scheme, _ := builder.Build() loggerMock := MockLogger{ WithValuesKeysAndValues: nil, @@ -702,7 +702,7 @@ var _ = Describe("updateStatus", func() { When("group id is not 0", func() { sut, _, _, _, _ := getGroupControllerWithMocksInGreenTestState() - group := gitlabv1alpha1.Group{Status: gitlabv1alpha1.GroupStatus{ + group := gitlabAPIVer.Group{Status: gitlabAPIVer.GroupStatus{ CreatedTime: &metav1.Time{}, LastUpdatedTime: &metav1.Time{}, State: "", @@ -716,11 +716,11 @@ var _ = Describe("updateStatus", func() { }) var _ = Describe("updateProject", func() { - template := gitlabv1alpha1.ProjectTemplate{ + template := gitlabAPIVer.ProjectTemplate{ Name: "a project", } - project := gitlabv1alpha1.Project{Spec: gitlabv1alpha1.ProjectSpec{}} - builder := gitlabv1alpha1.SchemeBuilder.Register(&gitlabv1alpha1.Group{}, &gitlabv1alpha1.GroupList{}) + project := gitlabAPIVer.Project{Spec: gitlabAPIVer.ProjectSpec{}} + builder := gitlabAPIVer.SchemeBuilder.Register(&gitlabAPIVer.Group{}, &gitlabAPIVer.GroupList{}) scheme, _ := builder.Build() loggerMock := MockLogger{ WithValuesKeysAndValues: nil, @@ -746,11 +746,11 @@ var _ = Describe("updateProject", func() { } groupID := 1 - group := gitlabv1alpha1.Group{ - Spec: gitlabv1alpha1.GroupSpec{ + group := gitlabAPIVer.Group{ + Spec: gitlabAPIVer.GroupSpec{ GitlabCredentialsName: "test", }, - Status: gitlabv1alpha1.GroupStatus{ + Status: gitlabAPIVer.GroupStatus{ ID: &groupID, }, } @@ -777,7 +777,7 @@ var _ = Describe("CreateCiVariable", func() { sut.gitlabClient = gitlabClient statusCode, err := sut.CreateCiVariable(1, - gitlabv1alpha1.CICDVariable{ + gitlabAPIVer.CICDVariable{ Key: "variable", Value: "testvalue", }, diff --git a/controllers/gitlab/mocks_test.go b/controllers/gitlab/mocks_test.go index 8790525..359b8c8 100755 --- a/controllers/gitlab/mocks_test.go +++ b/controllers/gitlab/mocks_test.go @@ -21,6 +21,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/scheme" "sigs.k8s.io/controller-runtime/pkg/webhook" "time" + gitlabAPIVer "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" gitlabClient "valkyrie.dso.mil/valkyrie-api/clients/gitlab" "valkyrie.dso.mil/valkyrie-api/controllers" ) @@ -924,18 +925,18 @@ func (m *MockGitlabClient) GetRepositoryTree(projectID int) ([]*gitlab.TreeNode, type MockClientConfiguration struct { GitlabClient gitlabClient.Client - SetupClientFunction func(client client.Client, credentialsName string) (gitlabClient.Client, error) + SetupClientFunction func(client client.Client, credentialsName string) (gitlabClient.Client, *gitlabAPIVer.GitlabCredentials, error) SetupClientCalled bool } -func (m *MockClientConfiguration) SetupClient(client client.Client, credentialsName string) (gitlabClient.Client, error) { +func (m *MockClientConfiguration) SetupClient(client client.Client, credentialsName string) (gitlabClient.Client, *gitlabAPIVer.GitlabCredentials, error) { m.SetupClientCalled = true if m.SetupClientFunction == nil { if m.GitlabClient == nil { - return &MockGitlabClient{}, nil + return &MockGitlabClient{}, nil, nil } - return m.GitlabClient, nil + return m.GitlabClient, nil, nil } return m.SetupClientFunction(client, credentialsName) diff --git a/controllers/gitlab/project_controller.go b/controllers/gitlab/project_controller.go index 01148ee..7305f38 100644 --- a/controllers/gitlab/project_controller.go +++ b/controllers/gitlab/project_controller.go @@ -29,10 +29,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" "strings" fortifyv1 "valkyrie.dso.mil/valkyrie-api/apis/fortify/v1alpha1" - apisGitlab "valkyrie.dso.mil/valkyrie-api/apis/gitlab" + gitlabAPI "valkyrie.dso.mil/valkyrie-api/apis/gitlab" "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" + gitlabAPIVer "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" twistlockv1alpha1 "valkyrie.dso.mil/valkyrie-api/apis/twistlock/v1alpha1" gitlabClient "valkyrie.dso.mil/valkyrie-api/clients/gitlab" + customImpl "valkyrie.dso.mil/valkyrie-api/custom/p1" ) // ProjectReconciler reconciles a Project object @@ -41,7 +43,8 @@ type ProjectReconciler struct { Log logr.Logger Scheme *runtime.Scheme gitlabClient gitlabClient.Client - gitlabClientConfiguration apisGitlab.ClientConfiguration + gitlabCredentials *gitlabAPIVer.GitlabCredentials + gitlabClientConfiguration gitlabAPI.ClientConfiguration } //+kubebuilder:rbac:groups=gitlab.valkyrie.dso.mil,resources=projects,verbs=get;list;watch;create;update;patch;delete @@ -104,13 +107,13 @@ func (r *ProjectReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct // Do a nil check here so we can use mock gitlabClients if r.gitlabClient == nil { if r.gitlabClientConfiguration == nil { - r.gitlabClientConfiguration = apisGitlab.ClientConfigurationImpl{ + r.gitlabClientConfiguration = gitlabAPI.ClientConfigurationImpl{ Log: log, Ctx: ctx, Req: req, } } - if r.gitlabClient, err = r.gitlabClientConfiguration.SetupClient(r.Client, project.Spec.GitlabCredentialsName); err != nil { + if r.gitlabClient, r.gitlabCredentials, err = r.gitlabClientConfiguration.SetupClient(r.Client, project.Spec.GitlabCredentialsName); err != nil { log.Error(err, errorUnableToSetupGitlabClient) _ = r.updateStatus(ctx, project, errorUnableToSetupGitlabClient, log) return ctrl.Result{Requeue: true}, err @@ -214,6 +217,13 @@ func (r *ProjectReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct return ctrl.Result{Requeue: true}, err } + // project should exists - check bootstrap manifest + if project.Spec.BootstrapWithManifestRepo != nil { + // get token from gitlabCredentials + customImpl.BootstrapProjectWithManifest(r.gitlabCredentials, gitlabProject.ID, *project.Spec.BootstrapWithManifestRepo) + + } + if err = r.updateCiVariables(*id, project, log); err != nil { log.Error(err, errorUpdatingProjectVariableInGitlab) _ = r.updateStatus(ctx, project, errorUpdatingProjectVariableInGitlab, log) diff --git a/controllers/gitlab/project_controller_test.go b/controllers/gitlab/project_controller_test.go index 355eb70..4ae00ba 100644 --- a/controllers/gitlab/project_controller_test.go +++ b/controllers/gitlab/project_controller_test.go @@ -12,6 +12,7 @@ import ( fortifyv1 "valkyrie.dso.mil/valkyrie-api/apis/fortify/v1alpha1" apisGitlab "valkyrie.dso.mil/valkyrie-api/apis/gitlab" "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" + gitlabAPIVer "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" twistlockv1 "valkyrie.dso.mil/valkyrie-api/apis/twistlock/v1alpha1" gitlabClient "valkyrie.dso.mil/valkyrie-api/clients/gitlab" ) @@ -163,8 +164,8 @@ var _ = Describe("reconcile", func() { request := getRequestWithDefaultNamespacedTestProject() sut.gitlabClient = nil sut.gitlabClientConfiguration = &MockClientConfiguration{ - SetupClientFunction: func(client client.Client, credentialsName string) (gitlabClient.Client, error) { - return nil, &MockError{message: "SetupClientFunction fails."} + SetupClientFunction: func(client client.Client, credentialsName string) (gitlabClient.Client, *gitlabAPIVer.GitlabCredentials, error) { + return nil, nil, &MockError{message: "SetupClientFunction fails."} }, } result, err := sut.Reconcile(context.TODO(), request) diff --git a/custom/p1/group_test.go b/custom/p1/group_test.go index adddbb1..6d11584 100644 --- a/custom/p1/group_test.go +++ b/custom/p1/group_test.go @@ -35,6 +35,7 @@ func TestCreateGroup(t *testing.T) { // test objects testAPIUrl := "https://test/api/v4/" testToken := "token" + testUsername := "username" testGroupSpec := apigitlab.GroupSpec{FullPath: testGroupFullPath, Name: "Group Name"} type args struct { @@ -47,7 +48,7 @@ func TestCreateGroup(t *testing.T) { args args wantErr bool }{ - {name: "test", args: args{gitlabCredentials: GitlabCredentials{testAPIUrl, testToken}, groupSpec: testGroupSpec, httpClient: testHTTPClient}, wantErr: false}, + {name: "test", args: args{gitlabCredentials: GitlabCredentials{testAPIUrl, testUsername, testToken}, groupSpec: testGroupSpec, httpClient: testHTTPClient}, wantErr: false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -95,6 +96,7 @@ func TestDeleteGroup(t *testing.T) { // test objects testAPIUrl := "https://test/api/v4/" testToken := "token" + testUsername := "username" testGroupSpec := apigitlab.GroupSpec{FullPath: testGroupFullPath, Name: "Group Name"} type args struct { @@ -107,7 +109,7 @@ func TestDeleteGroup(t *testing.T) { args args wantErr bool }{ - {name: "test", args: args{gitlabCredentials: GitlabCredentials{testAPIUrl, testToken}, groupSpec: testGroupSpec, httpClient: testHTTPClient}, wantErr: false}, + {name: "test", args: args{gitlabCredentials: GitlabCredentials{testAPIUrl, testUsername, testToken}, groupSpec: testGroupSpec, httpClient: testHTTPClient}, wantErr: false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -147,6 +149,7 @@ func TestUpdateGroup(t *testing.T) { // test objects testAPIUrl := "https://test/api/v4/" testToken := "token" + testUsername := "username" testGroupSpec := apigitlab.GroupSpec{FullPath: testGroupFullPath, Name: "Group Name"} type args struct { @@ -159,7 +162,7 @@ func TestUpdateGroup(t *testing.T) { args args wantErr bool }{ - {name: "test", args: args{gitlabCredentials: GitlabCredentials{testAPIUrl, testToken}, groupSpec: testGroupSpec, httpClient: testHTTPClient}, wantErr: false}, + {name: "test", args: args{gitlabCredentials: GitlabCredentials{testAPIUrl, testUsername, testToken}, groupSpec: testGroupSpec, httpClient: testHTTPClient}, wantErr: false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/custom/p1/project_bootstrap.go b/custom/p1/project_bootstrap.go index 64e06c3..5d46319 100644 --- a/custom/p1/project_bootstrap.go +++ b/custom/p1/project_bootstrap.go @@ -6,30 +6,63 @@ import ( "github.com/romana/rlog" gogitlab "github.com/xanzy/go-gitlab" + gitlabAPIVer "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" "valkyrie.dso.mil/valkyrie-api/clients/git" "valkyrie.dso.mil/valkyrie-api/clients/gitlab" "valkyrie.dso.mil/valkyrie-api/clients/utils" + templateCustom "valkyrie.dso.mil/valkyrie-api/custom/template" + templateConfig "valkyrie.dso.mil/valkyrie-api/custom/template/configurations" ) var directoryPrefix = "bootstrap-" var newRepoInitializeFile = "README.md" -// by default bootstrap to the master branch -var defaultBootstrapBranch = "master" +// DefaultBootstrapBranch - by default bootstrap to the master branch +var DefaultBootstrapBranch = "master" func processProjectBootstrapError(logPrefix string, err error) { rlog.Warnf("%s error: %v", logPrefix, err) } -// BootstrapProject - -func BootstrapProject(gitlabCredentials GitlabCredentials, projectID int, sourcePath string) (err error) { - err = BootstrapProjectwithBranch(gitlabCredentials, projectID, sourcePath, defaultBootstrapBranch) +// BootstrapProjectWithManifest - +func BootstrapProjectWithManifest(gitlabCredentials *gitlabAPIVer.GitlabCredentials, projectID int, bootstrapConfig gitlabAPIVer.BootstrapWithManifestRepo) (err error) { + logPrefix := "BootstrapProjectWithManfiest" + // create sourcePath with content + templateConfigObj := templateConfig.Microservice{ + ProjectName: "PROJECT_NAME", + } + + RootDir, err := utils.CurrentDir() + if err != nil { + processProjectBootstrapError(logPrefix+" gitlab.NewClient", err) + return err + } + + var templatePath string = RootDir + "/resources/templates/manifests/mission-bootstrap/integrations" + templateOutputDirectory, err := templateCustom.ProcessCookieCutterFile(templatePath, &templateConfigObj) + if err != nil { + processProjectBootstrapError(logPrefix+" gitlab.NewClient", err) + return err + } + + // checkitall in + var gitlabCreds GitlabCredentials + gitlabCreds.ServerURL = gitlabCredentials.Spec.URL + gitlabCreds.ServerUsername = gitlabCredentials.Spec.Username + gitlabCreds.ServerToken = gitlabCredentials.Spec.AccessTokenPrivate + err = BootstrapProject(gitlabCreds, projectID, templateOutputDirectory, DefaultBootstrapBranch) return } -//BootstrapProjectwithBranch add filepath to an existing gitlab project ID repository -func BootstrapProjectwithBranch(gitlabCredentials GitlabCredentials, projectID int, sourcePath string, branch string) error { - logPrefix := "BootstrapProjectwithBranch" +//BootstrapProject add filepath to an existing gitlab project ID repository +func BootstrapProject(gitlabCredentials GitlabCredentials, projectID int, sourcePath string, branch string) error { + logPrefix := "BootstrapProject" + // clone project + // copy filePath to clone root + // git add + // git commit + // git push + // gitlab username token credentials to use for git ops gitlabUsername := "oauth2" gitlabToken := gitlabCredentials.ServerToken @@ -59,12 +92,6 @@ func BootstrapProjectwithBranch(gitlabCredentials GitlabCredentials, projectID i return err } - // clone project - // copy filePath to clone root - // git add - // git commit - // git push - // be sure to cleanup temp directory workDir, err := utils.CreateTempDir(directoryPrefix, utils.TempRoot) if err != nil { diff --git a/custom/p1/project_test.go b/custom/p1/project_test.go index 3cedb05..c7c343d 100644 --- a/custom/p1/project_test.go +++ b/custom/p1/project_test.go @@ -48,6 +48,7 @@ func TestCreateProject(t *testing.T) { // test objects testAPIUrl := "https://test/api/v4/" testToken := "token" + testUsername := "username" testProjectSpec := apigitlab.ProjectSpec{Name: "Project Name", FullPath: testProjectFullPath} type args struct { @@ -60,7 +61,7 @@ func TestCreateProject(t *testing.T) { args args wantErr bool }{ - {name: "test", args: args{gitlabCredentials: GitlabCredentials{testAPIUrl, testToken}, projectSpec: testProjectSpec, httpClient: testHTTPClient}, wantErr: false}, + {name: "test", args: args{gitlabCredentials: GitlabCredentials{testAPIUrl, testUsername, testToken}, projectSpec: testProjectSpec, httpClient: testHTTPClient}, wantErr: false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -110,6 +111,7 @@ func TestDeleteProject(t *testing.T) { // test objects testAPIUrl := "https://test/api/v4/" testToken := "token" + testUsername := "username" testProjectSpec := apigitlab.ProjectSpec{Name: "Project Name", FullPath: testProjectFullPath} type args struct { @@ -122,7 +124,7 @@ func TestDeleteProject(t *testing.T) { args args wantErr bool }{ - {name: "test", args: args{gitlabCredentials: GitlabCredentials{testAPIUrl, testToken}, projectSpec: testProjectSpec, httpClient: testHTTPClient}, wantErr: false}, + {name: "test", args: args{gitlabCredentials: GitlabCredentials{testAPIUrl, testUsername, testToken}, projectSpec: testProjectSpec, httpClient: testHTTPClient}, wantErr: false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -173,6 +175,7 @@ func TestUpdateProject(t *testing.T) { // test objects testAPIUrl := "https://test/api/v4/" testToken := "token" + testUsername := "username" testProjectSpec := apigitlab.ProjectSpec{Name: "Project Name", FullPath: testProjectFullPath} type args struct { @@ -185,7 +188,7 @@ func TestUpdateProject(t *testing.T) { args args wantErr bool }{ - {name: "test", args: args{gitlabCredentials: GitlabCredentials{testAPIUrl, testToken}, projectSpec: testProjectSpec, httpClient: testHTTPClient}, wantErr: false}, + {name: "test", args: args{gitlabCredentials: GitlabCredentials{testAPIUrl, testUsername, testToken}, projectSpec: testProjectSpec, httpClient: testHTTPClient}, wantErr: false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/custom/p1/types.go b/custom/p1/types.go index 705e692..5832c05 100644 --- a/custom/p1/types.go +++ b/custom/p1/types.go @@ -6,8 +6,9 @@ import ( // GitlabCredentials - type GitlabCredentials struct { - ServerURL string - ServerToken string + ServerURL string + ServerUsername string + ServerToken string } // enumeration for pipeline yaml template paths -- GitLab From e568274f4b74508d027cd316c7a851de1b7440fa Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Wed, 8 Sep 2021 02:18:37 -0600 Subject: [PATCH 37/55] successful bootstrap int test --- custom/p1/project_bootstrap.go | 8 ++- integration-tests/custom/p1/p1_main_test.go | 5 +- .../custom/p1/p1_projects_bootstrap_test.go | 72 ++++++++++++++++--- 3 files changed, 71 insertions(+), 14 deletions(-) diff --git a/custom/p1/project_bootstrap.go b/custom/p1/project_bootstrap.go index 5d46319..c9bab97 100644 --- a/custom/p1/project_bootstrap.go +++ b/custom/p1/project_bootstrap.go @@ -2,6 +2,7 @@ package p1 import ( "fmt" + "os" "strings" "github.com/romana/rlog" @@ -98,7 +99,7 @@ func BootstrapProject(gitlabCredentials GitlabCredentials, projectID int, source rlog.Errorf("Error - CreateTempDir %v", err) return err } - rlog.Debugf("TestGit_AddPath_Create_Branch - Created temp workDir %s", workDir) + rlog.Debugf("%s - CreateTempDir - Created temp workDir %s", logPrefix, workDir) client, err := git.NewClientOSFS( gitlabUsername, @@ -124,8 +125,6 @@ func BootstrapProject(gitlabCredentials GitlabCredentials, projectID int, source return err } - rlog.Errorf("sourcePath %s", sourcePath) - rlog.Errorf("tempDir %s", workDir) // add everything in working tree err = client.AddFile(".") if err != nil { @@ -150,6 +149,9 @@ func BootstrapProject(gitlabCredentials GitlabCredentials, projectID int, source return err } rlog.Debugf("Checkout and Push branch %s - success", branch) + + // cleanup + os.RemoveAll(workDir) return nil } diff --git a/integration-tests/custom/p1/p1_main_test.go b/integration-tests/custom/p1/p1_main_test.go index 7524bc4..e57933c 100644 --- a/integration-tests/custom/p1/p1_main_test.go +++ b/integration-tests/custom/p1/p1_main_test.go @@ -10,8 +10,7 @@ import ( "os" "strings" "testing" - - "github.com/romana/rlog" + gogitlab "github.com/xanzy/go-gitlab" gitlab "valkyrie.dso.mil/valkyrie-api/clients/gitlab" ) @@ -54,7 +53,7 @@ var p1Config P1Config // packageSetup - setup environment for integration testing func packageSetup() error { p1Config.WorkingDir, _ = os.Getwd() - rlog.Errorf("Working Dir %s", p1Config.WorkingDir) + var ok bool var err error diff --git a/integration-tests/custom/p1/p1_projects_bootstrap_test.go b/integration-tests/custom/p1/p1_projects_bootstrap_test.go index 47919e8..fffb30c 100644 --- a/integration-tests/custom/p1/p1_projects_bootstrap_test.go +++ b/integration-tests/custom/p1/p1_projects_bootstrap_test.go @@ -3,35 +3,37 @@ package integration import ( + "os" "strings" "testing" "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" "valkyrie.dso.mil/valkyrie-api/clients/utils" - custom_p1 "valkyrie.dso.mil/valkyrie-api/custom/p1" + customP1 "valkyrie.dso.mil/valkyrie-api/custom/p1" ) // go clean -testcache && go test -tags "integration" ./integration-tests/custom/p1/p1_main_test.go ./integration-tests/custom/p1/p1_projects_bootstrap_test.go const integrationTestProjectBootstrapPath = "int-test-bootstrap-project" +const integrationTestProjectDataFile = "angular-world.tar.gz" // Delete bootstrap test project if exists and re-create empty clean project -func Test_P1_ProjectBootstrap_DeleteAndAddProject(t *testing.T) { +func Test_P1_ProjectBootstrap_DataFile(t *testing.T) { logPrefix := "Test_P1_AddProject" t.Run("test", func(t *testing.T) { projectSpec := v1alpha1.ProjectSpec{ - Name: "My Project Bootstrap Test Project", + Name: "Int Test Bootstrap Project", FullPath: p1Config.GitlabIntTestRootGroupPath + "/" + integrationTestProjectBootstrapPath, } - creds := custom_p1.GitlabCredentials{ + creds := customP1.GitlabCredentials{ ServerURL: p1Config.GitlabAPIURL, ServerToken: p1Config.GitlabAPIToken, } var err error - err = custom_p1.DeleteProject(creds, projectSpec, nil) + err = customP1.DeleteProject(creds, projectSpec, nil) if err != nil && strings.Contains(err.Error(), "not found") { t.Logf("DeleteProject- project not found %s", projectSpec.FullPath) err = nil @@ -41,7 +43,7 @@ func Test_P1_ProjectBootstrap_DeleteAndAddProject(t *testing.T) { } t.Logf("%s deleted project %s", logPrefix, projectSpec.FullPath) - projectID, err := custom_p1.CreateProject(creds, projectSpec, nil) + projectID, err := customP1.CreateProject(creds, projectSpec, nil) if err != nil { t.Errorf("CreateProject() error = %v", err) return @@ -63,14 +65,68 @@ func Test_P1_ProjectBootstrap_DeleteAndAddProject(t *testing.T) { return } t.Logf("temp directory %s", tempDir) - err = custom_p1.BootstrapProject(creds, projectID, tempDir) + err = customP1.BootstrapProject(creds, projectID, tempDir, customP1.DefaultBootstrapBranch) if err != nil { t.Errorf("Error - BootstrapProject %v", err) return } + // cleanup + os.RemoveAll(tempDir) + t.Logf("Bootstrap completed") + }) +} + +func Test_P1_ProjectBootstrap_DataFile_Expanded(t *testing.T) { + logPrefix := "Test_P1_AddProject" + t.Run("test", func(t *testing.T) { + projectSpec := v1alpha1.ProjectSpec{ + Name: "Int Test Bootstrap Project 2", + FullPath: p1Config.GitlabIntTestRootGroupPath + "/" + integrationTestProjectBootstrapPath + "-2", + } + + creds := customP1.GitlabCredentials{ + ServerURL: p1Config.GitlabAPIURL, + ServerToken: p1Config.GitlabAPIToken, + } + + var err error + + err = customP1.DeleteProject(creds, projectSpec, nil) + if err != nil && strings.Contains(err.Error(), "not found") { + t.Logf("DeleteProject- project not found %s", projectSpec.FullPath) + err = nil + } + if err != nil { + t.Logf("DeleteProject() error = %v", err) + } + t.Logf("%s deleted project %s", logPrefix, projectSpec.FullPath) + + projectID, err := customP1.CreateProject(creds, projectSpec, nil) + if err != nil { + t.Errorf("CreateProject() error = %v", err) + return + } + + t.Logf("%s created project %v", logPrefix, projectSpec.FullPath) + + testDataPath := p1Config.WorkingDir + utils.PathSeparator + "data" + tempDir, err := utils.CreateTempDirWithFile(testDataPath+utils.PathSeparator+integrationTestProjectDataFile, "int-test-", true) + if err != nil { + t.Errorf("CreateTempDirWithFile() error = %v", err) + return + } - // os.RemoveAll(tempDir) + + t.Logf("temp directory %s", tempDir) + err = customP1.BootstrapProject(creds, projectID, tempDir, customP1.DefaultBootstrapBranch) + if err != nil { + t.Errorf("Error - BootstrapProject %v", err) + return + } + + // cleanup + os.RemoveAll(tempDir) t.Logf("Bootstrap completed") }) } -- GitLab From 2fe1fe07165fb8177b59d9044d1624b3ebddaae8 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Wed, 8 Sep 2021 11:24:19 -0600 Subject: [PATCH 38/55] update testing. --- clients/utils/file_utils.go | 79 +++++++++++++++++--------------- clients/utils/file_utils_test.go | 47 ++++++++++++++++++- custom/p1/project_bootstrap.go | 4 +- 3 files changed, 89 insertions(+), 41 deletions(-) diff --git a/clients/utils/file_utils.go b/clients/utils/file_utils.go index a79a776..93647e3 100644 --- a/clients/utils/file_utils.go +++ b/clients/utils/file_utils.go @@ -19,6 +19,7 @@ var PathSeparator = fmt.Sprintf("%c", os.PathSeparator) // Function pointers - allows for easy mocking of functions var osMkdirAll = os.MkdirAll +var osGetwd = os.Getwd // processError - helper func processError(logPrefix string, err error) { @@ -100,6 +101,7 @@ func CreateTempDirWithFile(filePath string, prefix string, decompress bool) (str if err != nil { return "", err } + stat, err := os.Stat(filePath) if err != nil { // try to cleanup @@ -107,44 +109,44 @@ func CreateTempDirWithFile(filePath string, prefix string, decompress bool) (str return "", err } - // if is file - if !stat.IsDir() { - if decompress { - if strings.HasSuffix(filePath, ".zip") { - err = UnZipFile(filePath, tempDir) - if err != nil { - // try to cleanup - DeleteDir(tempDir) - return "", err - } - } else { - if strings.HasSuffix(filePath, ".tar.gz") { - err = UnTarFile(filePath, tempDir) - if err != nil { - // try to cleanup - DeleteDir(tempDir) - return "", err - } - } else { - targetFullPath := tempDir + PathSeparator + stat.Name() - err = CopyFile(filePath, targetFullPath) - if err != nil { - // try to cleanup - DeleteDir(tempDir) - return "", err - } - } - } - } else { - targetFullPath := tempDir + PathSeparator + stat.Name() - err = CopyFile(filePath, targetFullPath) - if err != nil { - // try to cleanup - DeleteDir(tempDir) - return "", err - } + // flag if filepath already processed + var processed bool = false + + // if NOT directory, needs decompress and is a zip file + if !stat.IsDir() && decompress && strings.HasSuffix(filePath, ".zip") { + err = UnZipFile(filePath, tempDir) + if err != nil { + // try to cleanup + DeleteDir(tempDir) + return "", err } - } else { + processed = true + } + + // if NOT directory, needs decompress and is a tar gz file + if !stat.IsDir() && decompress && strings.HasSuffix(filePath, ".tar.gz") { + err = UnTarFile(filePath, tempDir) + if err != nil { + // try to cleanup + DeleteDir(tempDir) + return "", err + } + processed = true + } + + // if NOT directory, and not yet processed + if !stat.IsDir() && !processed { + targetFullPath := tempDir + PathSeparator + stat.Name() + err = CopyFile(filePath, targetFullPath) + if err != nil { + // try to cleanup + DeleteDir(tempDir) + return "", err + } + } + + // if IS a directory + if stat.IsDir() { err = CopyDir(filePath, tempDir) if err != nil { // try to cleanup @@ -152,6 +154,7 @@ func CreateTempDirWithFile(filePath string, prefix string, decompress bool) (str return "", err } } + return tempDir, nil } @@ -209,7 +212,7 @@ func IsDir(filePath string) bool { // CurrentDir - get current dir func CurrentDir() (string, error) { - path, err := os.Getwd() + path, err := osGetwd() if err != nil { return "", err } diff --git a/clients/utils/file_utils_test.go b/clients/utils/file_utils_test.go index 555d440..3117d98 100644 --- a/clients/utils/file_utils_test.go +++ b/clients/utils/file_utils_test.go @@ -50,7 +50,37 @@ func TestFileUtils_CreateTempDir(t *testing.T) { } } -// mock used to create an error in createTempDir +func TestCurrentDir(t *testing.T) { + tests := []struct { + name string + want string + wantErr bool + mockKey string + }{ + {name: "test", want: "test_osgetwd", wantErr: false, mockKey: "osGetwdGood"}, + } + for _, tt := range tests { + osGetwdOrig := osGetwd + t.Run(tt.name, func(t *testing.T) { + if tt.mockKey == "osGetwdGood" { + osGetwd = osGetwdGood + } + got, err := CurrentDir() + if (err != nil) != tt.wantErr { + t.Errorf("CurrentDir() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("CurrentDir() = %v, want %v", got, tt.want) + } + + osGetwd = osGetwdOrig + + }) + } +} + +// mocks used to create an error in createTempDir var testCounter = 1 func osMkdirAllBad(path string, mode os.FileMode) error { @@ -61,3 +91,18 @@ func osMkdirAllBad(path string, mode os.FileMode) error { testCounter = testCounter - 1 return os.MkdirAll(path, mode) } + +func osGetwdGood() (string, error) { + return "test_osgetwd", nil +} + +func osGetwdBad() (string, error) { + println(testCounter) + if testCounter == 1 { + return "", errors.New("test error") + } + testCounter = testCounter - 1 + return os.Getwd() +} + + diff --git a/custom/p1/project_bootstrap.go b/custom/p1/project_bootstrap.go index c9bab97..25a729e 100644 --- a/custom/p1/project_bootstrap.go +++ b/custom/p1/project_bootstrap.go @@ -35,14 +35,14 @@ func BootstrapProjectWithManifest(gitlabCredentials *gitlabAPIVer.GitlabCredenti RootDir, err := utils.CurrentDir() if err != nil { - processProjectBootstrapError(logPrefix+" gitlab.NewClient", err) + processProjectBootstrapError(logPrefix+" utils.CurrentDir", err) return err } var templatePath string = RootDir + "/resources/templates/manifests/mission-bootstrap/integrations" templateOutputDirectory, err := templateCustom.ProcessCookieCutterFile(templatePath, &templateConfigObj) if err != nil { - processProjectBootstrapError(logPrefix+" gitlab.NewClient", err) + processProjectBootstrapError(logPrefix+" templateCustom.ProcessCookieCutterFile", err) return err } -- GitLab From e045aa5086708d54779ddb24c5634791af46f92c Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Thu, 9 Sep 2021 09:52:36 -0600 Subject: [PATCH 39/55] update error logging --- custom/p1/project_bootstrap.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/custom/p1/project_bootstrap.go b/custom/p1/project_bootstrap.go index 25a729e..4d5f645 100644 --- a/custom/p1/project_bootstrap.go +++ b/custom/p1/project_bootstrap.go @@ -90,13 +90,14 @@ func BootstrapProject(gitlabCredentials GitlabCredentials, projectID int, source } if !repoIsEmpty(fileTree) { err = fmt.Errorf("repository %s not empty", project.PathWithNamespace) + processProjectBootstrapError(logPrefix + " repoIsEmpty", err) return err } // be sure to cleanup temp directory workDir, err := utils.CreateTempDir(directoryPrefix, utils.TempRoot) if err != nil { - rlog.Errorf("Error - CreateTempDir %v", err) + processProjectBootstrapError(logPrefix + " CreateTempDir", err) return err } rlog.Debugf("%s - CreateTempDir - Created temp workDir %s", logPrefix, workDir) @@ -108,32 +109,32 @@ func BootstrapProject(gitlabCredentials GitlabCredentials, projectID int, source workDir, ) if err != nil { - rlog.Errorf("Error - TestGit_AddPath_Create_Branch - NewClientOSFS %v", err) + processProjectBootstrapError(logPrefix + " git.NewClientOSFS", err) return err } // If remote does NOT already exist, then this is a LOCAL Branch only until pushed err = client.CheckoutOrCreateBranch(branch) if err != nil { - rlog.Errorf("Error - TestGit_AddPath_Create_Branch - CheckoutOrCreateBranch %v", err) + processProjectBootstrapError(logPrefix + " CheckoutOrCreateBranch", err) return err } // copy files from sourcePath to root of repository err = utils.CopyDir(sourcePath, workDir) if err != nil { - rlog.Errorf("Error - TestGit_AddPath_Create_Branch - CheckoutOrCreateBranch %v", err) + processProjectBootstrapError(logPrefix + " utils.CopyDir", err) return err } // add everything in working tree err = client.AddFile(".") if err != nil { - rlog.Errorf("Error - TestGit_AddPath_Create_Branch - CheckoutOrCreateBranch %v", err) + processProjectBootstrapError(logPrefix + " client.AddFile", err) return err } err = client.Commit("Valkyrie - Bootstrap") if err != nil { - rlog.Errorf("Error - TestGit_AddPath_Create_Branch - CheckoutOrCreateBranch %v", err) + processProjectBootstrapError(logPrefix + " client.Commit", err) return err } @@ -141,11 +142,11 @@ func BootstrapProject(gitlabCredentials GitlabCredentials, projectID int, source err = client.Push(branch) //if already up-to-date, then it's already deleted if err != nil && err.Error() == "already up-to-date" { - rlog.Debugf(logPrefix+" CheckoutOrCreateBranch %s - already exists", branch) + rlog.Debugf(logPrefix+" client.Push %s - already up-to-date", branch) err = nil } if err != nil { - rlog.Errorf("Push %v", err) + processProjectBootstrapError(logPrefix + " client.Push", err) return err } rlog.Debugf("Checkout and Push branch %s - success", branch) -- GitLab From 432a9f40d32d85e4b007d1acd155ca459fdc7e16 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Thu, 9 Sep 2021 14:19:25 -0600 Subject: [PATCH 40/55] bootstrap cookie cutter integration testing --- apis/gitlab/v1alpha1/common_types.go | 6 +- apis/gitlab/v1alpha1/project_types_test.go | 2 +- apis/gitlab/v1alpha1/zz_generated.deepcopy.go | 17 ++++- clients/utils/file_utils_test.go | 8 +-- custom/p1/project_bootstrap.go | 34 +++++---- integration-tests/custom/p1/p1_main_test.go | 4 +- .../custom/p1/p1_projects_bootstrap_test.go | 71 +++++++++++++++++-- 7 files changed, 109 insertions(+), 33 deletions(-) diff --git a/apis/gitlab/v1alpha1/common_types.go b/apis/gitlab/v1alpha1/common_types.go index efbbb60..44fe221 100755 --- a/apis/gitlab/v1alpha1/common_types.go +++ b/apis/gitlab/v1alpha1/common_types.go @@ -33,11 +33,11 @@ type BootstrapWithManifestRepo struct { // Language is a string key to an existing pre-built code stack // +kubebuilder:validation:Required - Services []services `json:"services"` + Services []Service `json:"services"` } -// services (private) manifest representation of a deployable container -type services struct { +// Service manifest representation of a deployable container +type Service struct { Name string `json:"name"` ContainerRegistry string `json:"containerRegistry"` Port int `json:"port"` diff --git a/apis/gitlab/v1alpha1/project_types_test.go b/apis/gitlab/v1alpha1/project_types_test.go index 86fb853..7f9014f 100644 --- a/apis/gitlab/v1alpha1/project_types_test.go +++ b/apis/gitlab/v1alpha1/project_types_test.go @@ -248,7 +248,7 @@ func TestDeepCopy_BoostrapManifest(t *testing.T) { registry := "test22" port := 9999 toCopy := BootstrapWithManifestRepo{ - Services: []services{ + Services: []Service{ { Name: name, ContainerRegistry: registry, diff --git a/apis/gitlab/v1alpha1/zz_generated.deepcopy.go b/apis/gitlab/v1alpha1/zz_generated.deepcopy.go index bf45adc..c9e0c75 100644 --- a/apis/gitlab/v1alpha1/zz_generated.deepcopy.go +++ b/apis/gitlab/v1alpha1/zz_generated.deepcopy.go @@ -31,7 +31,7 @@ func (in *BootstrapWithManifestRepo) DeepCopyInto(out *BootstrapWithManifestRepo *out = *in if in.Services != nil { in, out := &in.Services, &out.Services - *out = make([]services, len(*in)) + *out = make([]Service, len(*in)) copy(*out, *in) } } @@ -727,3 +727,18 @@ func (in *SdElementsPipelineConfigurationStatus) DeepCopy() *SdElementsPipelineC in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Service) DeepCopyInto(out *Service) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Service. +func (in *Service) DeepCopy() *Service { + if in == nil { + return nil + } + out := new(Service) + in.DeepCopyInto(out) + return out +} diff --git a/clients/utils/file_utils_test.go b/clients/utils/file_utils_test.go index 3117d98..025689f 100644 --- a/clients/utils/file_utils_test.go +++ b/clients/utils/file_utils_test.go @@ -55,7 +55,7 @@ func TestCurrentDir(t *testing.T) { name string want string wantErr bool - mockKey string + mockKey string }{ {name: "test", want: "test_osgetwd", wantErr: false, mockKey: "osGetwdGood"}, } @@ -73,9 +73,9 @@ func TestCurrentDir(t *testing.T) { if got != tt.want { t.Errorf("CurrentDir() = %v, want %v", got, tt.want) } - + osGetwd = osGetwdOrig - + }) } } @@ -104,5 +104,3 @@ func osGetwdBad() (string, error) { testCounter = testCounter - 1 return os.Getwd() } - - diff --git a/custom/p1/project_bootstrap.go b/custom/p1/project_bootstrap.go index 4d5f645..091ed4a 100644 --- a/custom/p1/project_bootstrap.go +++ b/custom/p1/project_bootstrap.go @@ -25,8 +25,17 @@ func processProjectBootstrapError(logPrefix string, err error) { rlog.Warnf("%s error: %v", logPrefix, err) } -// BootstrapProjectWithManifest - +//BootstrapProjectWithManifest - wrapper to be called from controller func BootstrapProjectWithManifest(gitlabCredentials *gitlabAPIVer.GitlabCredentials, projectID int, bootstrapConfig gitlabAPIVer.BootstrapWithManifestRepo) (err error) { + var gitlabCreds GitlabCredentials + gitlabCreds.ServerURL = gitlabCredentials.Spec.URL + gitlabCreds.ServerUsername = gitlabCredentials.Spec.Username + gitlabCreds.ServerToken = gitlabCredentials.Spec.AccessTokenPrivate + return BootstrapProjectWithManifestCreds(gitlabCreds, projectID, bootstrapConfig) +} + +// BootstrapProjectWithManifest - use simple gitlabCredentials object +func BootstrapProjectWithManifestCreds(gitlabCredentials GitlabCredentials, projectID int, bootstrapConfig gitlabAPIVer.BootstrapWithManifestRepo) (err error) { logPrefix := "BootstrapProjectWithManfiest" // create sourcePath with content templateConfigObj := templateConfig.Microservice{ @@ -46,12 +55,7 @@ func BootstrapProjectWithManifest(gitlabCredentials *gitlabAPIVer.GitlabCredenti return err } - // checkitall in - var gitlabCreds GitlabCredentials - gitlabCreds.ServerURL = gitlabCredentials.Spec.URL - gitlabCreds.ServerUsername = gitlabCredentials.Spec.Username - gitlabCreds.ServerToken = gitlabCredentials.Spec.AccessTokenPrivate - err = BootstrapProject(gitlabCreds, projectID, templateOutputDirectory, DefaultBootstrapBranch) + err = BootstrapProject(gitlabCredentials, projectID, templateOutputDirectory, DefaultBootstrapBranch) return } @@ -90,14 +94,14 @@ func BootstrapProject(gitlabCredentials GitlabCredentials, projectID int, source } if !repoIsEmpty(fileTree) { err = fmt.Errorf("repository %s not empty", project.PathWithNamespace) - processProjectBootstrapError(logPrefix + " repoIsEmpty", err) + processProjectBootstrapError(logPrefix+" repoIsEmpty", err) return err } // be sure to cleanup temp directory workDir, err := utils.CreateTempDir(directoryPrefix, utils.TempRoot) if err != nil { - processProjectBootstrapError(logPrefix + " CreateTempDir", err) + processProjectBootstrapError(logPrefix+" CreateTempDir", err) return err } rlog.Debugf("%s - CreateTempDir - Created temp workDir %s", logPrefix, workDir) @@ -109,32 +113,32 @@ func BootstrapProject(gitlabCredentials GitlabCredentials, projectID int, source workDir, ) if err != nil { - processProjectBootstrapError(logPrefix + " git.NewClientOSFS", err) + processProjectBootstrapError(logPrefix+" git.NewClientOSFS", err) return err } // If remote does NOT already exist, then this is a LOCAL Branch only until pushed err = client.CheckoutOrCreateBranch(branch) if err != nil { - processProjectBootstrapError(logPrefix + " CheckoutOrCreateBranch", err) + processProjectBootstrapError(logPrefix+" CheckoutOrCreateBranch", err) return err } // copy files from sourcePath to root of repository err = utils.CopyDir(sourcePath, workDir) if err != nil { - processProjectBootstrapError(logPrefix + " utils.CopyDir", err) + processProjectBootstrapError(logPrefix+" utils.CopyDir", err) return err } // add everything in working tree err = client.AddFile(".") if err != nil { - processProjectBootstrapError(logPrefix + " client.AddFile", err) + processProjectBootstrapError(logPrefix+" client.AddFile", err) return err } err = client.Commit("Valkyrie - Bootstrap") if err != nil { - processProjectBootstrapError(logPrefix + " client.Commit", err) + processProjectBootstrapError(logPrefix+" client.Commit", err) return err } @@ -146,7 +150,7 @@ func BootstrapProject(gitlabCredentials GitlabCredentials, projectID int, source err = nil } if err != nil { - processProjectBootstrapError(logPrefix + " client.Push", err) + processProjectBootstrapError(logPrefix+" client.Push", err) return err } rlog.Debugf("Checkout and Push branch %s - success", branch) diff --git a/integration-tests/custom/p1/p1_main_test.go b/integration-tests/custom/p1/p1_main_test.go index e57933c..613ce61 100644 --- a/integration-tests/custom/p1/p1_main_test.go +++ b/integration-tests/custom/p1/p1_main_test.go @@ -10,7 +10,7 @@ import ( "os" "strings" "testing" - + gogitlab "github.com/xanzy/go-gitlab" gitlab "valkyrie.dso.mil/valkyrie-api/clients/gitlab" ) @@ -53,7 +53,7 @@ var p1Config P1Config // packageSetup - setup environment for integration testing func packageSetup() error { p1Config.WorkingDir, _ = os.Getwd() - + var ok bool var err error diff --git a/integration-tests/custom/p1/p1_projects_bootstrap_test.go b/integration-tests/custom/p1/p1_projects_bootstrap_test.go index fffb30c..ba8ac2f 100644 --- a/integration-tests/custom/p1/p1_projects_bootstrap_test.go +++ b/integration-tests/custom/p1/p1_projects_bootstrap_test.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" + gitlabAPIVer "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" "valkyrie.dso.mil/valkyrie-api/clients/utils" customP1 "valkyrie.dso.mil/valkyrie-api/custom/p1" ) @@ -17,11 +17,21 @@ import ( const integrationTestProjectBootstrapPath = "int-test-bootstrap-project" const integrationTestProjectDataFile = "angular-world.tar.gz" +// force working directory to be root of the project folder +var testPath = "" +func init() { + wd, _ := os.Getwd() + // save current directory as TestPath + testPath = wd + if err := os.Chdir(wd + "/../../../"); err != nil { + panic(err) + } +} // Delete bootstrap test project if exists and re-create empty clean project func Test_P1_ProjectBootstrap_DataFile(t *testing.T) { logPrefix := "Test_P1_AddProject" t.Run("test", func(t *testing.T) { - projectSpec := v1alpha1.ProjectSpec{ + projectSpec := gitlabAPIVer.ProjectSpec{ Name: "Int Test Bootstrap Project", FullPath: p1Config.GitlabIntTestRootGroupPath + "/" + integrationTestProjectBootstrapPath, } @@ -58,7 +68,7 @@ func Test_P1_ProjectBootstrap_DataFile(t *testing.T) { return } - testDataPath := p1Config.WorkingDir + utils.PathSeparator + "data" + testDataPath := testPath + utils.PathSeparator + "data" err = utils.CopyDir(testDataPath, tempDir) if err != nil { t.Errorf("Error - CopyDir %v", err) @@ -80,7 +90,7 @@ func Test_P1_ProjectBootstrap_DataFile(t *testing.T) { func Test_P1_ProjectBootstrap_DataFile_Expanded(t *testing.T) { logPrefix := "Test_P1_AddProject" t.Run("test", func(t *testing.T) { - projectSpec := v1alpha1.ProjectSpec{ + projectSpec := gitlabAPIVer.ProjectSpec{ Name: "Int Test Bootstrap Project 2", FullPath: p1Config.GitlabIntTestRootGroupPath + "/" + integrationTestProjectBootstrapPath + "-2", } @@ -110,14 +120,13 @@ func Test_P1_ProjectBootstrap_DataFile_Expanded(t *testing.T) { t.Logf("%s created project %v", logPrefix, projectSpec.FullPath) - testDataPath := p1Config.WorkingDir + utils.PathSeparator + "data" + testDataPath := testPath + utils.PathSeparator + "data" tempDir, err := utils.CreateTempDirWithFile(testDataPath+utils.PathSeparator+integrationTestProjectDataFile, "int-test-", true) if err != nil { t.Errorf("CreateTempDirWithFile() error = %v", err) return } - t.Logf("temp directory %s", tempDir) err = customP1.BootstrapProject(creds, projectID, tempDir, customP1.DefaultBootstrapBranch) if err != nil { @@ -130,3 +139,53 @@ func Test_P1_ProjectBootstrap_DataFile_Expanded(t *testing.T) { t.Logf("Bootstrap completed") }) } + +func Test_P1_ProjectBootstrap_CookieCutter(t *testing.T) { + logPrefix := "Test_P1_AddProject" + t.Run("test", func(t *testing.T) { + projectSpec := gitlabAPIVer.ProjectSpec{ + Name: "Int Test Bootstrap Project CC", + FullPath: p1Config.GitlabIntTestRootGroupPath + "/" + integrationTestProjectBootstrapPath + "-cc", + } + + creds := customP1.GitlabCredentials{ + ServerURL: p1Config.GitlabAPIURL, + ServerToken: p1Config.GitlabAPIToken, + ServerUsername: "oauth2", + } + + var err error + + err = customP1.DeleteProject(creds, projectSpec, nil) + if err != nil && strings.Contains(err.Error(), "not found") { + t.Logf("DeleteProject- project not found %s", projectSpec.FullPath) + err = nil + } + if err != nil { + t.Logf("DeleteProject() error = %v", err) + } + t.Logf("%s deleted project %s", logPrefix, projectSpec.FullPath) + + projectID, err := customP1.CreateProject(creds, projectSpec, nil) + if err != nil { + t.Errorf("CreateProject() error = %v", err) + return + } + + t.Logf("%s created project %v", logPrefix, projectSpec.FullPath) + + // err = customP1.BootstrapProject(creds, projectID, tempDir, customP1.DefaultBootstrapBranch) + bootstrapConfig := gitlabAPIVer.BootstrapWithManifestRepo{ + Services: []gitlabAPIVer.Service{ + {Name: "name", ContainerRegistry: "registry.il2.dso.mil", Port: 8081}, + }, + } + err = customP1.BootstrapProjectWithManifestCreds(creds, projectID, bootstrapConfig) + if err != nil { + t.Errorf("Error - BootstrapProject %v", err) + return + } + + t.Logf("Bootstrap completed") + }) +} -- GitLab From f0fb748c5ce295101598e5b4d613e1127a521c89 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Thu, 9 Sep 2021 15:52:30 -0600 Subject: [PATCH 41/55] minor fixes --- custom/p1/project_bootstrap.go | 22 ++++++++++++--- integration-tests/custom/p1/p1_groups_test.go | 4 +-- .../custom/p1/p1_projects_bootstrap_test.go | 2 +- .../custom/p1/p1_projects_test.go | 27 +++++++++++++++++-- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/custom/p1/project_bootstrap.go b/custom/p1/project_bootstrap.go index 091ed4a..e0516b0 100644 --- a/custom/p1/project_bootstrap.go +++ b/custom/p1/project_bootstrap.go @@ -34,14 +34,18 @@ func BootstrapProjectWithManifest(gitlabCredentials *gitlabAPIVer.GitlabCredenti return BootstrapProjectWithManifestCreds(gitlabCreds, projectID, bootstrapConfig) } -// BootstrapProjectWithManifest - use simple gitlabCredentials object +// BootstrapProjectWithManifestCreds - use simple gitlabCredentials object for credentials func BootstrapProjectWithManifestCreds(gitlabCredentials GitlabCredentials, projectID int, bootstrapConfig gitlabAPIVer.BootstrapWithManifestRepo) (err error) { logPrefix := "BootstrapProjectWithManfiest" - // create sourcePath with content + + // TODO: figure out how to convert bootstrapConfig into templateConfigObj templateConfigObj := templateConfig.Microservice{ ProjectName: "PROJECT_NAME", + ImpactLevel: "IL2", + MetaData: "xx", } + // identify cookie cutter folder location RootDir, err := utils.CurrentDir() if err != nil { processProjectBootstrapError(logPrefix+" utils.CurrentDir", err) @@ -49,13 +53,25 @@ func BootstrapProjectWithManifestCreds(gitlabCredentials GitlabCredentials, proj } var templatePath string = RootDir + "/resources/templates/manifests/mission-bootstrap/integrations" - templateOutputDirectory, err := templateCustom.ProcessCookieCutterFile(templatePath, &templateConfigObj) + // create a temp copy of the templatePath + scratchTemplatePath, err := utils.CreateTempDirWithFile(templatePath, "bootstrap-manifest-", false) + if err != nil { + processProjectBootstrapError(logPrefix+" utils.CreateTempDirWithFile", err) + return err + } + + templateOutputDirectory, err := templateCustom.ProcessCookieCutterFile(scratchTemplatePath, &templateConfigObj) if err != nil { processProjectBootstrapError(logPrefix+" templateCustom.ProcessCookieCutterFile", err) return err } err = BootstrapProject(gitlabCredentials, projectID, templateOutputDirectory, DefaultBootstrapBranch) + // cleanup + rlog.Errorf("%s scratchDir %s", logPrefix,scratchTemplatePath) + rlog.Errorf("%s ccOutputDir %s", logPrefix,templateOutputDirectory) + // remove templateOutputDirectory + // remove scratchTemplatePath return } diff --git a/integration-tests/custom/p1/p1_groups_test.go b/integration-tests/custom/p1/p1_groups_test.go index 6a1f9a1..0b07ec6 100644 --- a/integration-tests/custom/p1/p1_groups_test.go +++ b/integration-tests/custom/p1/p1_groups_test.go @@ -15,7 +15,7 @@ func Test_P1_AddGroup(t *testing.T) { logPrefix := "Test_P1_AddGroup" t.Run("test", func(t *testing.T) { groupSpec := v1alpha1.GroupSpec{ - Name: "My Test Group", + Name: "Int Test Group", FullPath: p1Config.GitlabIntTestRootGroupPath + "/" + integrationTestGroupPath, } @@ -38,7 +38,7 @@ func Test_P1_UpdateGroup(t *testing.T) { logPrefix := "Test_P1_UpdateGroup" t.Run("test", func(t *testing.T) { groupSpec := v1alpha1.GroupSpec{ - Name: "My Test Updated Group", + Name: "Int Test Updated Group", FullPath: p1Config.GitlabIntTestRootGroupPath + "/" + integrationTestGroupPath, } diff --git a/integration-tests/custom/p1/p1_projects_bootstrap_test.go b/integration-tests/custom/p1/p1_projects_bootstrap_test.go index ba8ac2f..c599c6b 100644 --- a/integration-tests/custom/p1/p1_projects_bootstrap_test.go +++ b/integration-tests/custom/p1/p1_projects_bootstrap_test.go @@ -32,7 +32,7 @@ func Test_P1_ProjectBootstrap_DataFile(t *testing.T) { logPrefix := "Test_P1_AddProject" t.Run("test", func(t *testing.T) { projectSpec := gitlabAPIVer.ProjectSpec{ - Name: "Int Test Bootstrap Project", + Name: "Int Test Bootstrap Project 1", FullPath: p1Config.GitlabIntTestRootGroupPath + "/" + integrationTestProjectBootstrapPath, } diff --git a/integration-tests/custom/p1/p1_projects_test.go b/integration-tests/custom/p1/p1_projects_test.go index cf5e5c4..cc501b4 100644 --- a/integration-tests/custom/p1/p1_projects_test.go +++ b/integration-tests/custom/p1/p1_projects_test.go @@ -15,7 +15,7 @@ func Test_P1_AddProject(t *testing.T) { logPrefix := "Test_P1_AddProject" t.Run("test", func(t *testing.T) { projectSpec := v1alpha1.ProjectSpec{ - Name: "My Test Project", + Name: "Int Test Add Project", FullPath: p1Config.GitlabIntTestRootGroupPath + "/" + integrationTestProjectPath, } @@ -46,7 +46,7 @@ func Test_P1_UpdateProject(t *testing.T) { logPrefix := "Test_P1_UpdateProject" t.Run("test", func(t *testing.T) { projectSpec := v1alpha1.ProjectSpec{ - Name: "My Test Updated Project", + Name: "Int Test Updated Project", FullPath: p1Config.GitlabIntTestRootGroupPath + "/" + integrationTestProjectPath, } @@ -63,3 +63,26 @@ func Test_P1_UpdateProject(t *testing.T) { t.Logf("%s update project %v", logPrefix, projectSpec) }) } + +func Test_P1_DeleteProject(t *testing.T) { + logPrefix := "Test_P1_UpdateProject" + t.Run("test", func(t *testing.T) { + projectSpec := v1alpha1.ProjectSpec{ + Name: "Int Test Updated Project", + FullPath: p1Config.GitlabIntTestRootGroupPath + "/" + integrationTestProjectPath, + } + + creds := custom_p1.GitlabCredentials{ + ServerURL: p1Config.GitlabAPIURL, + ServerToken: p1Config.GitlabAPIToken, + } + + var err error + + err = custom_p1.DeleteProject(creds, projectSpec, nil) + if err != nil { + t.Logf("DeleteProject() error = %v", err) + } + t.Logf("%s deleted project with fullpath %v", logPrefix, projectSpec) + }) +} \ No newline at end of file -- GitLab From 713b96ed76aca2542466fdb02f68a5c8153b1471 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Thu, 9 Sep 2021 16:03:19 -0600 Subject: [PATCH 42/55] wire into project controller --- controllers/gitlab/project_controller.go | 8 +++++--- custom/p1/project_bootstrap.go | 8 ++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/controllers/gitlab/project_controller.go b/controllers/gitlab/project_controller.go index 7305f38..e749c7e 100644 --- a/controllers/gitlab/project_controller.go +++ b/controllers/gitlab/project_controller.go @@ -219,9 +219,11 @@ func (r *ProjectReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct // project should exists - check bootstrap manifest if project.Spec.BootstrapWithManifestRepo != nil { - // get token from gitlabCredentials - customImpl.BootstrapProjectWithManifest(r.gitlabCredentials, gitlabProject.ID, *project.Spec.BootstrapWithManifestRepo) - + // bootstrap with manifests + err = customImpl.BootstrapProjectWithManifest(r.gitlabCredentials, gitlabProject.ID, *project.Spec.BootstrapWithManifestRepo) + if err != nil { + log.Error(err, "Error bootstrapping manifest") + } } if err = r.updateCiVariables(*id, project, log); err != nil { diff --git a/custom/p1/project_bootstrap.go b/custom/p1/project_bootstrap.go index e0516b0..7565ddf 100644 --- a/custom/p1/project_bootstrap.go +++ b/custom/p1/project_bootstrap.go @@ -66,12 +66,16 @@ func BootstrapProjectWithManifestCreds(gitlabCredentials GitlabCredentials, proj return err } + // bootstrap project with contents of templateOutputDirectory err = BootstrapProject(gitlabCredentials, projectID, templateOutputDirectory, DefaultBootstrapBranch) + // cleanup - rlog.Errorf("%s scratchDir %s", logPrefix,scratchTemplatePath) - rlog.Errorf("%s ccOutputDir %s", logPrefix,templateOutputDirectory) + // rlog.Errorf("%s scratchDir %s", logPrefix,scratchTemplatePath) + // rlog.Errorf("%s ccOutputDir %s", logPrefix,templateOutputDirectory) // remove templateOutputDirectory + os.RemoveAll(templateOutputDirectory) // remove scratchTemplatePath + os.RemoveAll(scratchTemplatePath) return } -- GitLab From d642276228f3ea7b5080ea0578e69a4d9808a566 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Thu, 9 Sep 2021 16:28:32 -0600 Subject: [PATCH 43/55] update unit tests --- clients/utils/file_utils_test.go | 52 ++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/clients/utils/file_utils_test.go b/clients/utils/file_utils_test.go index 025689f..a3332f9 100644 --- a/clients/utils/file_utils_test.go +++ b/clients/utils/file_utils_test.go @@ -57,7 +57,8 @@ func TestCurrentDir(t *testing.T) { wantErr bool mockKey string }{ - {name: "test", want: "test_osgetwd", wantErr: false, mockKey: "osGetwdGood"}, + {name: "test good", want: "test_osgetwd", wantErr: false, mockKey: "osGetwdGood"}, + {name: "test bad", want: "test_osgetwd", wantErr: true, mockKey: "osGetwdBad"}, } for _, tt := range tests { osGetwdOrig := osGetwd @@ -65,21 +66,57 @@ func TestCurrentDir(t *testing.T) { if tt.mockKey == "osGetwdGood" { osGetwd = osGetwdGood } + if tt.mockKey == "osGetwdBad" { + osGetwd = osGetwdBad + } got, err := CurrentDir() - if (err != nil) != tt.wantErr { + if (err != nil) && !tt.wantErr { t.Errorf("CurrentDir() error = %v, wantErr %v", err, tt.wantErr) + osGetwd = osGetwdOrig + return + } + if (err != nil) && tt.wantErr { + t.Logf("CurrentDir() expected error occured. error = %v, wantErr %v", err, tt.wantErr) + osGetwd = osGetwdOrig return } + if got != tt.want { t.Errorf("CurrentDir() = %v, want %v", got, tt.want) } - osGetwd = osGetwdOrig }) } } +func TestIsDir(t *testing.T) { + type args struct { + filePath string + } + tests := []struct { + name string + args args + want bool + }{ + {name: "test good", args: args{filePath: "/tmp/bad/path"}, want: false}, + {name: "test good", args: args{filePath: "/tmp/testfile.txt"}, want: false}, + {name: "test good", args: args{filePath: "/tmp"}, want: true}, + } + // create a test file + _, err := os.Create("/tmp/testfile.txt") + if err != nil { + t.Errorf("Ios.Create failed %v", err) + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := IsDir(tt.args.filePath); got != tt.want { + t.Errorf("IsDir() = %v, want %v", got, tt.want) + } + }) + } +} + // mocks used to create an error in createTempDir var testCounter = 1 @@ -97,10 +134,7 @@ func osGetwdGood() (string, error) { } func osGetwdBad() (string, error) { - println(testCounter) - if testCounter == 1 { - return "", errors.New("test error") - } - testCounter = testCounter - 1 - return os.Getwd() + return "", errors.New("test error") } + + -- GitLab From 83a714663c23892ed3838d7b7bfcef62c9215a65 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Thu, 9 Sep 2021 19:12:43 -0600 Subject: [PATCH 44/55] coverage --- clients/utils/file_utils_test.go | 188 ++++++++++++++++++++++++++++++- 1 file changed, 184 insertions(+), 4 deletions(-) diff --git a/clients/utils/file_utils_test.go b/clients/utils/file_utils_test.go index a3332f9..41f4eac 100644 --- a/clients/utils/file_utils_test.go +++ b/clients/utils/file_utils_test.go @@ -99,8 +99,8 @@ func TestIsDir(t *testing.T) { args args want bool }{ - {name: "test good", args: args{filePath: "/tmp/bad/path"}, want: false}, - {name: "test good", args: args{filePath: "/tmp/testfile.txt"}, want: false}, + {name: "test bad path", args: args{filePath: "/tmp/bad/path"}, want: false}, + {name: "test bad type", args: args{filePath: "/tmp/testfile.txt"}, want: false}, {name: "test good", args: args{filePath: "/tmp"}, want: true}, } // create a test file @@ -117,6 +117,188 @@ func TestIsDir(t *testing.T) { } } +func TestIsFile(t *testing.T) { + type args struct { + filePath string + } + tests := []struct { + name string + args args + want bool + }{ + {name: "test bad", args: args{filePath: "/tmp/bad/path"}, want: false}, + {name: "test good", args: args{filePath: "/tmp/testfile.txt"}, want: true}, + {name: "test bad type", args: args{filePath: "/tmp"}, want: false}, + } + // create a test file + _, err := os.Create("/tmp/testfile.txt") + if err != nil { + t.Errorf("Ios.Create failed %v", err) + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := IsFile(tt.args.filePath); got != tt.want { + t.Errorf("IsFile() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestUnZipFile(t *testing.T) { + type args struct { + filePath string + dstPath string + } + tests := []struct { + name string + args args + wantErr bool + }{ + {name: "test bad file", args: args{filePath: "/tmp/notzipfile.zip", dstPath: "/tmp/out"}, wantErr: true}, + {name: "test bad path", args: args{filePath: "/tmp/filenotfound.zip", dstPath: "/tmp/out"}, wantErr: true}, + } + // create a test file + _, err := os.Create("/tmp/notzipfile.zip") + if err != nil { + t.Errorf("Ios.Create failed %v", err) + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := UnZipFile(tt.args.filePath, tt.args.dstPath); (err != nil) != tt.wantErr { + t.Errorf("UnZipFile() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestUnTarFile(t *testing.T) { + type args struct { + filePath string + dstPath string + } + tests := []struct { + name string + args args + wantErr bool + }{ + {name: "test bad file", args: args{filePath: "/tmp/nottarfile.tar.gz", dstPath: "/tmp/out"}, wantErr: true}, + {name: "test bad path", args: args{filePath: "/tmp/filenotfound.zip", dstPath: "/tmp/out"}, wantErr: true}, + } + // create a test file + _, err := os.Create("/tmp/nottarfile.tar.gz") + if err != nil { + t.Errorf("Ios.Create failed %v", err) + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := UnTarFile(tt.args.filePath, tt.args.dstPath); (err != nil) != tt.wantErr { + t.Errorf("UnTarFile() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestDeleteDir(t *testing.T) { + testDir := "/tmp/test-dir" + type args struct { + path string + } + tests := []struct { + name string + args args + wantErr bool + }{ + {name: "test good", args: args{path: testDir}, wantErr: false}, + {name: "test bad path", args: args{path: "/tmp/baddir"}, wantErr: false}, + {name: "test bad path", args: args{path: "/tmp"}, wantErr: true}, + } + // create a test dir + os.RemoveAll(testDir) + err := os.Mkdir(testDir, 0755) + if err != nil { + t.Errorf("os.Mkdir failed %v", err) + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := DeleteDir(tt.args.path); (err != nil) != tt.wantErr { + t.Errorf("DeleteDir() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } + os.RemoveAll(testDir) +} + +func TestCopyDir(t *testing.T) { + testDir := "/tmp/test-dir" + type args struct { + srcPath string + dstPath string + } + tests := []struct { + name string + args args + wantErr bool + }{ + {name: "test good", args: args{srcPath: testDir, dstPath: "/tmp/test-out-dir"}, wantErr: false}, + {name: "test bad path", args: args{srcPath: "/tmp/baddir", dstPath: "/tmp/test-out-dir"}, wantErr: true}, + } + // create a test dir and file + os.RemoveAll(testDir) + err := os.Mkdir(testDir, 0755) + if err != nil { + t.Errorf("os.Mkdir failed %v", err) + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := CopyDir(tt.args.srcPath, tt.args.dstPath); (err != nil) != tt.wantErr { + t.Errorf("CopyDir() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } + + os.RemoveAll(testDir) +} + +func TestCopyFile(t *testing.T) { + testDir := "/tmp/test-dir" + testFile := testDir + PathSeparator + "test-file.txt" + testDstFile := testDir + PathSeparator + "test-file.dst.txt" + + type args struct { + src string + dst string + } + tests := []struct { + name string + args args + wantErr bool + }{ + {name: "test good", args: args{src: testFile, dst: testDstFile}, wantErr: false}, + } + // create a test dir and file + os.RemoveAll(testDir) + err := os.Mkdir(testDir, 0755) + if err != nil { + t.Errorf("os.Mkdir failed %v", err) + } + // create a test file + _, err = os.Create(testFile) + if err != nil { + t.Errorf("Ios.Create failed %v", err) + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := CopyFile(tt.args.src, tt.args.dst); (err != nil) != tt.wantErr { + t.Errorf("CopyFile() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } + os.RemoveAll(testDir) +} + + // mocks used to create an error in createTempDir var testCounter = 1 @@ -136,5 +318,3 @@ func osGetwdGood() (string, error) { func osGetwdBad() (string, error) { return "", errors.New("test error") } - - -- GitLab From c65396d740b2237bf66c906a36c4381e50f0fa7d Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Thu, 9 Sep 2021 19:21:16 -0600 Subject: [PATCH 45/55] minor --- clients/utils/file_utils_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/clients/utils/file_utils_test.go b/clients/utils/file_utils_test.go index 41f4eac..d274496 100644 --- a/clients/utils/file_utils_test.go +++ b/clients/utils/file_utils_test.go @@ -298,7 +298,6 @@ func TestCopyFile(t *testing.T) { os.RemoveAll(testDir) } - // mocks used to create an error in createTempDir var testCounter = 1 -- GitLab From 86e109fbd5c9cd0417e2eb267219df549606a760 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Thu, 9 Sep 2021 19:25:30 -0600 Subject: [PATCH 46/55] remove destructive test --- clients/utils/file_utils_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/clients/utils/file_utils_test.go b/clients/utils/file_utils_test.go index d274496..910a473 100644 --- a/clients/utils/file_utils_test.go +++ b/clients/utils/file_utils_test.go @@ -210,7 +210,6 @@ func TestDeleteDir(t *testing.T) { }{ {name: "test good", args: args{path: testDir}, wantErr: false}, {name: "test bad path", args: args{path: "/tmp/baddir"}, wantErr: false}, - {name: "test bad path", args: args{path: "/tmp"}, wantErr: true}, } // create a test dir os.RemoveAll(testDir) -- GitLab From 7ae7eae37ab71dbd10cc6f99d4dc4bcf31f19633 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Thu, 9 Sep 2021 23:52:02 -0600 Subject: [PATCH 47/55] file utils test coverage --- clients/utils/file_utils_test.go | 75 +++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/clients/utils/file_utils_test.go b/clients/utils/file_utils_test.go index 910a473..8d99d8d 100644 --- a/clients/utils/file_utils_test.go +++ b/clients/utils/file_utils_test.go @@ -2,6 +2,7 @@ package utils import ( "errors" + "fmt" "os" "strings" "testing" @@ -37,6 +38,7 @@ func TestFileUtils_CreateTempDir(t *testing.T) { } else { t.Errorf("createTempDir() UNEXPECTED error = %v, wantErr %v", err, tt.wantErr) } + osMkdirAll = osMkdirAllOrig return } if !strings.HasPrefix(gotTempDir, tt.wantTempDir) { @@ -284,7 +286,7 @@ func TestCopyFile(t *testing.T) { // create a test file _, err = os.Create(testFile) if err != nil { - t.Errorf("Ios.Create failed %v", err) + t.Errorf("os.Create failed %v", err) } for _, tt := range tests { @@ -297,6 +299,77 @@ func TestCopyFile(t *testing.T) { os.RemoveAll(testDir) } +func TestCreateTempDirWithFile(t *testing.T) { + testDir := "/tmp/test-dir" + testFile := testDir + PathSeparator + "test-file.txt" + testZipFile := testDir + PathSeparator + "test-file.zip" + testTarFile := testDir + PathSeparator + "test-file.tar.gz" + + type args struct { + filePath string + prefix string + decompress bool + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + {name: "test good 1", args: args{filePath: testDir, prefix: "unit-test-", decompress: false}, want: "unit-test-", wantErr: false}, + {name: "test good 2", args: args{filePath: testFile, prefix: "unit-test-", decompress: false}, want: "unit-test-", wantErr: false}, + {name: "test bad zip", args: args{filePath: testZipFile, prefix: "unit-test-", decompress: true}, want: "unit-test-", wantErr: true}, + {name: "test bad tar", args: args{filePath: testTarFile, prefix: "unit-test-", decompress: true}, want: "unit-test-", wantErr: true}, + } + + // create a test dir and file + os.RemoveAll(testDir) + err := os.Mkdir(testDir, 0755) + if err != nil { + t.Errorf("os.Mkdir failed %v", err) + } + // create a test file + _, err = os.Create(testFile) + if err != nil { + t.Errorf("os.Create failed %v", err) + } + _, err = os.Create(testZipFile) + if err != nil { + t.Errorf("os.Create failed %v", err) + } + + // tar file needs some bad data in it to fail + tf, err := os.Create(testTarFile) + if err != nil { + t.Errorf("os.Create failed %v", err) + } + newLine := "invalid data" + DateTimeUTC() + fmt.Fprintln(tf, newLine) + tf.Close() + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := CreateTempDirWithFile(tt.args.filePath, tt.args.prefix, tt.args.decompress) + if (err != nil) && ! tt.wantErr { + t.Errorf("CreateTempDirWithFile() error = %v, wantErr %v", err, tt.wantErr) + return + } + if (err != nil) && tt.wantErr { + t.Logf("CreateTempDirWithFile() expected error = %v, wantErr %v", err, tt.wantErr) + return + } + if (err == nil) && tt.wantErr { + t.Errorf("CreateTempDirWithFile() expected error got = %v, wantErr %v", got, tt.wantErr) + return + } + if !strings.Contains(got,tt.want) { + t.Errorf("CreateTempDirWithFile() = %v, want %v", got, tt.want) + } + }) + } + os.RemoveAll(testDir) +} + // mocks used to create an error in createTempDir var testCounter = 1 -- GitLab From 52b2f96072428d8a2ecf5b2cc96c1e527f198f73 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Fri, 10 Sep 2021 09:10:42 -0600 Subject: [PATCH 48/55] bootstrap generic unit tests --- clients/utils/file_utils_test.go | 8 +- custom/p1/README.md | 6 + custom/p1/project_bootstrap_test.go | 145 ++++++++++++++++++ .../configurations/template_config.go | 2 + 4 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 custom/p1/README.md create mode 100644 custom/p1/project_bootstrap_test.go diff --git a/clients/utils/file_utils_test.go b/clients/utils/file_utils_test.go index 8d99d8d..4122417 100644 --- a/clients/utils/file_utils_test.go +++ b/clients/utils/file_utils_test.go @@ -350,19 +350,19 @@ func TestCreateTempDirWithFile(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := CreateTempDirWithFile(tt.args.filePath, tt.args.prefix, tt.args.decompress) - if (err != nil) && ! tt.wantErr { + if (err != nil) && !tt.wantErr { t.Errorf("CreateTempDirWithFile() error = %v, wantErr %v", err, tt.wantErr) return } - if (err != nil) && tt.wantErr { + if (err != nil) && tt.wantErr { t.Logf("CreateTempDirWithFile() expected error = %v, wantErr %v", err, tt.wantErr) return } - if (err == nil) && tt.wantErr { + if (err == nil) && tt.wantErr { t.Errorf("CreateTempDirWithFile() expected error got = %v, wantErr %v", got, tt.wantErr) return } - if !strings.Contains(got,tt.want) { + if !strings.Contains(got, tt.want) { t.Errorf("CreateTempDirWithFile() = %v, want %v", got, tt.want) } }) diff --git a/custom/p1/README.md b/custom/p1/README.md new file mode 100644 index 0000000..99a3c50 --- /dev/null +++ b/custom/p1/README.md @@ -0,0 +1,6 @@ +## P1 platform one interface to automation methods + +### Run tests +- go clean -testcache && go test -v ./custom/p1/... -coverprofile cover.out +- go tool cover -html=cover.out -o coverage.html +- open coverage.html diff --git a/custom/p1/project_bootstrap_test.go b/custom/p1/project_bootstrap_test.go new file mode 100644 index 0000000..67c02c6 --- /dev/null +++ b/custom/p1/project_bootstrap_test.go @@ -0,0 +1,145 @@ +package p1 + +import ( + "fmt" + "testing" + + gogitlab "github.com/xanzy/go-gitlab" + gitlabAPIVer "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" +) + +func Test_processProjectBootstrapError(t *testing.T) { + type args struct { + logPrefix string + err error + } + tests := []struct { + name string + args args + }{ + {name: "test", args: args{logPrefix: "prefix-", err: fmt.Errorf("test error")}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + processProjectBootstrapError(tt.args.logPrefix, tt.args.err) + }) + } +} + +func TestBootstrapProjectWithManifest(t *testing.T) { + // test objects + testAPIUrl := "https://test/api/v4/" + testToken := "token" + testUsername := "username" + testCreds := gitlabAPIVer.GitlabCredentials{ + Spec: gitlabAPIVer.GitlabCredentialsSpec{URL: testAPIUrl, Username: testUsername, AccessTokenPrivate: testToken}, + } + testBootstrapConfig := gitlabAPIVer.BootstrapWithManifestRepo{} + + type args struct { + gitlabCredentials *gitlabAPIVer.GitlabCredentials + projectID int + bootstrapConfig gitlabAPIVer.BootstrapWithManifestRepo + } + tests := []struct { + name string + args args + wantErr bool + }{ + {name: "test", args: args{gitlabCredentials: &testCreds, projectID: 11, bootstrapConfig: testBootstrapConfig}, wantErr: true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := BootstrapProjectWithManifest(tt.args.gitlabCredentials, tt.args.projectID, tt.args.bootstrapConfig); (err != nil) != tt.wantErr { + t.Errorf("BootstrapProjectWithManifest() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestBootstrapProjectWithManifestCreds(t *testing.T) { + // test objects + testAPIUrl := "https://test/api/v4/" + testToken := "token" + testUsername := "username" + testCreds := GitlabCredentials{ + ServerURL: testAPIUrl, + ServerUsername: testUsername, + ServerToken: testToken, + } + testBootstrapConfig := gitlabAPIVer.BootstrapWithManifestRepo{} + + type args struct { + gitlabCredentials GitlabCredentials + projectID int + bootstrapConfig gitlabAPIVer.BootstrapWithManifestRepo + } + tests := []struct { + name string + args args + wantErr bool + }{ + {name: "test", args: args{gitlabCredentials: testCreds, projectID: 11, bootstrapConfig: testBootstrapConfig}, wantErr: true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := BootstrapProjectWithManifestCreds(tt.args.gitlabCredentials, tt.args.projectID, tt.args.bootstrapConfig); (err != nil) != tt.wantErr { + t.Errorf("BootstrapProjectWithManifestCreds() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestBootstrapProject(t *testing.T) { + // test objects + testAPIUrl := "https://test/api/v4/" + testToken := "token" + testUsername := "username" + testCreds := GitlabCredentials{ + ServerURL: testAPIUrl, + ServerUsername: testUsername, + ServerToken: testToken, + } + testSourcePath := "/tmp/test-dir" + + type args struct { + gitlabCredentials GitlabCredentials + projectID int + sourcePath string + branch string + } + tests := []struct { + name string + args args + wantErr bool + }{ + {name: "test", args: args{gitlabCredentials: testCreds, projectID: 11, sourcePath: testSourcePath, branch: DefaultBootstrapBranch}, wantErr: true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := BootstrapProject(tt.args.gitlabCredentials, tt.args.projectID, tt.args.sourcePath, tt.args.branch); (err != nil) != tt.wantErr { + t.Errorf("BootstrapProject() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_repoIsEmpty(t *testing.T) { + type args struct { + fileTree []*gogitlab.TreeNode + } + tests := []struct { + name string + args args + want bool + }{ + {name: "test 1", args: args{fileTree: nil}, want: true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := repoIsEmpty(tt.args.fileTree); got != tt.want { + t.Errorf("repoIsEmpty() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/custom/template/configurations/template_config.go b/custom/template/configurations/template_config.go index 3d1483c..cf6e5c9 100644 --- a/custom/template/configurations/template_config.go +++ b/custom/template/configurations/template_config.go @@ -1,4 +1,6 @@ package templateconfiguration +// Common Cookie Cutter Template Objects +// These Structs are converted to JSON then used as inputs to Cookie Cutter Templates // Application - type Application struct { -- GitLab From f9e9d051598ca71e616e827afc24907da21ac7ec Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Fri, 10 Sep 2021 10:10:07 -0600 Subject: [PATCH 49/55] update unit tests for template --- custom/template/configurations/template_config.go | 1 + custom/template/template_test.go | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/custom/template/configurations/template_config.go b/custom/template/configurations/template_config.go index cf6e5c9..d312315 100644 --- a/custom/template/configurations/template_config.go +++ b/custom/template/configurations/template_config.go @@ -1,4 +1,5 @@ package templateconfiguration + // Common Cookie Cutter Template Objects // These Structs are converted to JSON then used as inputs to Cookie Cutter Templates diff --git a/custom/template/template_test.go b/custom/template/template_test.go index 913393b..db2200e 100644 --- a/custom/template/template_test.go +++ b/custom/template/template_test.go @@ -5,6 +5,8 @@ import ( "os" "strings" "testing" + + "valkyrie.dso.mil/valkyrie-api/clients/utils" ) func Test_createTempDir(t *testing.T) { @@ -27,6 +29,7 @@ func Test_createTempDir(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { osMkdirAllOrig := os.MkdirAll + // IF MOCK then MUST restore to original when exiting if tt.mockKey == "osMkdirAll" { osMkdirAll = osMkdirAllBad } @@ -37,15 +40,14 @@ func Test_createTempDir(t *testing.T) { } else { t.Errorf("createTempDir() UNEXPECTED error = %v, wantErr %v", err, tt.wantErr) } + osMkdirAll = osMkdirAllOrig return } if !strings.HasPrefix(gotTempDir, tt.wantTempDir) { t.Errorf("createTempDir() = %v, want %v", gotTempDir, tt.wantTempDir) } os.RemoveAll(gotTempDir) - if tt.mockKey == "osMkdirAll" { - osMkdirAll = osMkdirAllOrig - } + osMkdirAll = osMkdirAllOrig }) } } @@ -122,6 +124,7 @@ func TestReadCookieCutterFile(t *testing.T) { func TestProcessCookieCutterFile(t *testing.T) { testConfigPath := os.TempDir() + "test/" + testConfigPathExists, _ := utils.CreateTempDir("unit-test-", utils.TempRoot) type args struct { cookieCutterConfigPath string templateConfigObject interface{} @@ -134,9 +137,11 @@ func TestProcessCookieCutterFile(t *testing.T) { mockKey string testCounter int }{ + {name: "test pass 1", args: args{cookieCutterConfigPath: testConfigPathExists, templateConfigObject: struct{ Test string }{Test: "test"}}, wantOutputDirectory: "/tmp/cc", wantErr: true, mockKey: "", testCounter: 1}, {name: "test fail 1", args: args{cookieCutterConfigPath: testConfigPath, templateConfigObject: struct{ Test string }{Test: "test"}}, wantOutputDirectory: "/tmp/cc", wantErr: true, mockKey: "", testCounter: 1}, {name: "test fail 2", args: args{cookieCutterConfigPath: "/tmp", templateConfigObject: struct{ Test string }{Test: "test"}}, wantOutputDirectory: "/tmp/cc", wantErr: true, mockKey: "osMkdirAll", testCounter: 1}, {name: "test fail 3", args: args{cookieCutterConfigPath: "/tmp", templateConfigObject: struct{ Test string }{Test: "test"}}, wantOutputDirectory: "/tmp/cc", wantErr: true, mockKey: "osMkdirAll", testCounter: 2}, + {name: "test fail 4", args: args{cookieCutterConfigPath: "/tmp", templateConfigObject: struct{ Test string }{Test: "test"}}, wantOutputDirectory: "/tmp/cc", wantErr: true, mockKey: "osMkdirAll", testCounter: 3}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { -- GitLab From d080e44d27761595236cd2b4f6e658d211b4c59b Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Fri, 10 Sep 2021 10:40:42 -0600 Subject: [PATCH 50/55] bump unit test --- custom/p1/project_bootstrap_test.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/custom/p1/project_bootstrap_test.go b/custom/p1/project_bootstrap_test.go index 67c02c6..7527ba2 100644 --- a/custom/p1/project_bootstrap_test.go +++ b/custom/p1/project_bootstrap_test.go @@ -2,12 +2,24 @@ package p1 import ( "fmt" + "os" "testing" gogitlab "github.com/xanzy/go-gitlab" gitlabAPIVer "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1" ) +// force working directory to be root of the project folder +var testPath = "" + +func init() { + wd, _ := os.Getwd() + // save current directory as TestPath + testPath = wd + if err := os.Chdir(wd + "/../../"); err != nil { + panic(err) + } +} func Test_processProjectBootstrapError(t *testing.T) { type args struct { logPrefix string @@ -125,6 +137,8 @@ func TestBootstrapProject(t *testing.T) { } func Test_repoIsEmpty(t *testing.T) { + testTreeGood := []*gogitlab.TreeNode{{ID: "1", Name: newRepoInitializeFile}} + testTreeBad := []*gogitlab.TreeNode{{ID: "1", Name: "bad filename"}} type args struct { fileTree []*gogitlab.TreeNode } @@ -134,6 +148,8 @@ func Test_repoIsEmpty(t *testing.T) { want bool }{ {name: "test 1", args: args{fileTree: nil}, want: true}, + {name: "test 2", args: args{fileTree: testTreeGood}, want: true}, + {name: "test 3", args: args{fileTree: testTreeBad}, want: false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { -- GitLab From eb0bfea46061445bdd486bb517b9c020003797e0 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Fri, 10 Sep 2021 11:11:25 -0600 Subject: [PATCH 51/55] minor update --- custom/p1/project_bootstrap_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/custom/p1/project_bootstrap_test.go b/custom/p1/project_bootstrap_test.go index 7527ba2..33cc7f6 100644 --- a/custom/p1/project_bootstrap_test.go +++ b/custom/p1/project_bootstrap_test.go @@ -80,6 +80,11 @@ func TestBootstrapProjectWithManifestCreds(t *testing.T) { ServerToken: testToken, } testBootstrapConfig := gitlabAPIVer.BootstrapWithManifestRepo{} + testBootstrapConfig2 := gitlabAPIVer.BootstrapWithManifestRepo{ + Services: []gitlabAPIVer.Service{ + {Name: "name", ContainerRegistry: "registry.il2.dso.mil", Port: 8081}, + }, + } type args struct { gitlabCredentials GitlabCredentials @@ -92,6 +97,7 @@ func TestBootstrapProjectWithManifestCreds(t *testing.T) { wantErr bool }{ {name: "test", args: args{gitlabCredentials: testCreds, projectID: 11, bootstrapConfig: testBootstrapConfig}, wantErr: true}, + {name: "test", args: args{gitlabCredentials: testCreds, projectID: 11, bootstrapConfig: testBootstrapConfig2}, wantErr: true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { -- GitLab From 9b5742cc3b2b95e6a5e66d465b1d0f99c142f047 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Fri, 10 Sep 2021 11:27:41 -0600 Subject: [PATCH 52/55] unit test --- custom/p1/project_bootstrap.go | 5 ----- custom/template/template_test.go | 34 +++++++++++++++++++++++--------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/custom/p1/project_bootstrap.go b/custom/p1/project_bootstrap.go index 7565ddf..e9fedb6 100644 --- a/custom/p1/project_bootstrap.go +++ b/custom/p1/project_bootstrap.go @@ -82,11 +82,6 @@ func BootstrapProjectWithManifestCreds(gitlabCredentials GitlabCredentials, proj //BootstrapProject add filepath to an existing gitlab project ID repository func BootstrapProject(gitlabCredentials GitlabCredentials, projectID int, sourcePath string, branch string) error { logPrefix := "BootstrapProject" - // clone project - // copy filePath to clone root - // git add - // git commit - // git push // gitlab username token credentials to use for git ops gitlabUsername := "oauth2" diff --git a/custom/template/template_test.go b/custom/template/template_test.go index db2200e..18104b1 100644 --- a/custom/template/template_test.go +++ b/custom/template/template_test.go @@ -2,6 +2,7 @@ package template import ( "errors" + "fmt" "os" "strings" "testing" @@ -85,7 +86,26 @@ func TestWriteCookieCutterFile(t *testing.T) { } func TestReadCookieCutterFile(t *testing.T) { - testFilePath := os.TempDir() + "cc_test.json" + testFilePathGood := os.TempDir() + "cc_test_good.json" + testFilePathBad := os.TempDir() + "cc_test_missing.json" + testFilePathMarshallError := os.TempDir() + "cc_test_error.json" + + tf1, err := os.Create(testFilePathGood) + if err != nil { + t.Errorf("os.Create failed %v", err) + } + newLine1 := "{}" + fmt.Fprintln(tf1, newLine1) + tf1.Close() + + tf2, err := os.Create(testFilePathMarshallError) + if err != nil { + t.Errorf("os.Create failed %v", err) + } + newLine2 := "{invalid data}" + fmt.Fprintln(tf2, newLine2) + tf2.Close() + type args struct { filePath string obj interface{} @@ -95,16 +115,12 @@ func TestReadCookieCutterFile(t *testing.T) { args args wantErr bool }{ - {name: "test pass 1", args: args{filePath: testFilePath, obj: struct{ Test string }{Test: "test"}}, wantErr: false}, - {name: "test pass 2", args: args{filePath: "/xx/xx.json", obj: struct{ Test int }{Test: 7}}, wantErr: true}, + {name: "test pass 1", args: args{filePath: testFilePathGood, obj: struct{ Test string }{Test: "test"}}, wantErr: true}, + {name: "test fail 1", args: args{filePath: testFilePathBad, obj: struct{ Test string }{Test: "test"}}, wantErr: true}, + {name: "test fail 2", args: args{filePath: testFilePathMarshallError, obj: struct{ Test string }{Test: "test"}}, wantErr: true}, + {name: "test fail 3", args: args{filePath: "/xx/xx.json", obj: struct{ Test int }{Test: 7}}, wantErr: true}, } for _, tt := range tests { - // wrire a Cookiecutter file first so we can read it - err := WriteCookieCutterFile(testFilePath, tt.args.obj) - if err != nil { - t.Errorf("WriteCookieCutterFile() error = %v, wantErr %v", err, tt.wantErr) - return - } t.Run(tt.name, func(t *testing.T) { err := ReadCookieCutterFile(tt.args.filePath, tt.args.obj) if err != nil { -- GitLab From 115e7b53dfc027b67f3e5d10d598f93538749809 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Fri, 10 Sep 2021 12:05:54 -0600 Subject: [PATCH 53/55] test --- custom/template/template_test.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/custom/template/template_test.go b/custom/template/template_test.go index 18104b1..5a76194 100644 --- a/custom/template/template_test.go +++ b/custom/template/template_test.go @@ -3,6 +3,7 @@ package template import ( "errors" "fmt" + "math" "os" "strings" "testing" @@ -54,6 +55,13 @@ func Test_createTempDir(t *testing.T) { } func TestWriteCookieCutterFile(t *testing.T) { + + type badStruct struct { + Name string `json:"name"` + Age float64 `json:"age"` + } + testObjBad := badStruct{Name: "name", Age: math.Inf(1)} + testFilePath := os.TempDir() + "cc_test.json" type args struct { filePath string @@ -65,7 +73,8 @@ func TestWriteCookieCutterFile(t *testing.T) { wantErr bool }{ {name: "test pass 1", args: args{filePath: testFilePath, obj: struct{ Test string }{Test: "test"}}, wantErr: false}, - {name: "test pass 2", args: args{filePath: "/xx/xx.json", obj: struct{ Test int }{Test: 7}}, wantErr: true}, + {name: "test fail 1", args: args{filePath: testFilePath, obj: testObjBad}, wantErr: true}, + {name: "test fail 2", args: args{filePath: "/xx/xx.json", obj: struct{ Test int }{Test: 7}}, wantErr: true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { -- GitLab From 625e59e070956b548a0d2673583b80d63708c35b Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Fri, 10 Sep 2021 12:29:35 -0600 Subject: [PATCH 54/55] coverage .... --- clients/git/repo_client_test.go | 90 ++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/clients/git/repo_client_test.go b/clients/git/repo_client_test.go index 9a65a88..c90d72a 100644 --- a/clients/git/repo_client_test.go +++ b/clients/git/repo_client_test.go @@ -1,8 +1,7 @@ package git -// reference: https://github.com/src-d/go-git/blob/master/repository_test.go - import ( + "reflect" "testing" "github.com/go-git/go-billy/v5/memfs" @@ -125,3 +124,90 @@ func TestRepoClientImpl_DeleteRemoteBranch(t *testing.T) { t.Fatalf("expect an error but got %v", err) } } + +func Test_newClientFS(t *testing.T) { + type args struct { + username string + token string + repoURL string + memoryFs bool + osPath string + } + tests := []struct { + name string + args args + wantClient *RepoClientImpl + wantErr bool + }{ + {name: "test 1", args: args{username: "username", token: "token", repoURL: "http://site/path", memoryFs: true, osPath: ""}, wantClient: nil, wantErr: true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotClient, err := newClientFS(tt.args.username, tt.args.token, tt.args.repoURL, tt.args.memoryFs, tt.args.osPath) + if (err != nil) != tt.wantErr { + t.Errorf("newClientFS() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(gotClient, tt.wantClient) { + t.Errorf("newClientFS() = %v, want %v", gotClient, tt.wantClient) + } + }) + } +} + +func TestNewClient(t *testing.T) { + type args struct { + username string + token string + repoURL string + } + tests := []struct { + name string + args args + wantClient *RepoClientImpl + wantErr bool + }{ + {name: "test 1", args: args{username: "username", token: "token", repoURL: "http://site/path"}, wantClient: nil, wantErr: true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotClient, err := NewClient(tt.args.username, tt.args.token, tt.args.repoURL) + if (err != nil) != tt.wantErr { + t.Errorf("NewClient() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(gotClient, tt.wantClient) { + t.Errorf("NewClient() = %v, want %v", gotClient, tt.wantClient) + } + }) + } +} + +func TestNewClientOSFS(t *testing.T) { + type args struct { + username string + token string + repoURL string + osPath string + } + tests := []struct { + name string + args args + wantClient *RepoClientImpl + wantErr bool + }{ + {name: "test 1", args: args{username: "username", token: "token", repoURL: "http://site/path", osPath: "/tmp"}, wantClient: nil, wantErr: true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotClient, err := NewClientOSFS(tt.args.username, tt.args.token, tt.args.repoURL, tt.args.osPath) + if (err != nil) != tt.wantErr { + t.Errorf("NewClientOSFS() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(gotClient, tt.wantClient) { + t.Errorf("NewClientOSFS() = %v, want %v", gotClient, tt.wantClient) + } + }) + } +} -- GitLab From cf755a5176f1e4df63f42a8779eb3f693b4fcb65 Mon Sep 17 00:00:00 2001 From: "adam.richards" Date: Fri, 10 Sep 2021 12:40:45 -0600 Subject: [PATCH 55/55] test push --- clients/git/repo_client_test.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/clients/git/repo_client_test.go b/clients/git/repo_client_test.go index c90d72a..3682540 100644 --- a/clients/git/repo_client_test.go +++ b/clients/git/repo_client_test.go @@ -35,6 +35,30 @@ func TestRepoClientImpl_CheckoutOrCreateBranch(t *testing.T) { } } +func TestRepoClientImpl_Push(t *testing.T) { + fileSystem := memfs.New() + auth := &http.BasicAuth{ + Username: "username", + Password: "token", + } + memStorage := memory.NewStorage() + repo, err := git.Init(memStorage, fileSystem) + if err != nil { + panic(err) + } + client := RepoClientImpl{ + repo: repo, + fs: &fileSystem, + auth: auth, + } + + branchName := "test_branch" + err = client.Push(branchName) + if err == nil { + t.Fatal("expected an error when creating the branch") + } +} + func TestRepoClientImpl_AddFile(t *testing.T) { fileSystem := memfs.New() auth := &http.BasicAuth{ -- GitLab