UNCLASSIFIED

Commit 85af0479 authored by abrichards's avatar abrichards
Browse files

Dev 12 project

parent f6db8714
......@@ -60,7 +60,7 @@ test: # manifests generate ## Run tests.
##@ Build
build: generate fmt vet ## Build manager binary.
build: generate fmt vet lint ## Build manager binary.
go build -o bin/manager main.go driver.go
run: manifests generate fmt vet ## Run a controller from your host.
......
......@@ -438,21 +438,9 @@ func (r ClientImpl) GetGroups(search *string) ([]*gogitlab.Group, error) {
// AddGroup -
func (r ClientImpl) AddGroup(createGroupOptions gogitlab.CreateGroupOptions) (*gogitlab.Group, int, error) {
// https://stackoverflow.com/questions/65081356/how-do-you-create-a-project-in-a-specific-group-via-gitlab-api
// SubGroup will be created if a parentID is supplied
logPrefix := "AddGroup"
// force visibility to private
var visibility = gogitlab.PrivateVisibility
var opts = gogitlab.CreateGroupOptions{
Name: createGroupOptions.Name,
Path: createGroupOptions.Path,
Description: createGroupOptions.Description,
ParentID: createGroupOptions.ParentID,
Visibility: &visibility,
}
newGroup, res, err := r.client.Groups.CreateGroup(&opts)
newGroup, res, err := r.client.Groups.CreateGroup(&createGroupOptions)
if err != nil {
processError(logPrefix, err)
......@@ -657,20 +645,8 @@ func (r ClientImpl) GetProjects(search *string) ([]*gogitlab.Project, error) {
// AddProject -
func (r ClientImpl) AddProject(createProjectOptions gogitlab.CreateProjectOptions) (*gogitlab.Project, int, error) {
logPrefix := "AddProject"
// force visibility to private
var visibility = gogitlab.PrivateVisibility
// copy customizable settings from argument, hard code other options as desired
var opts = gogitlab.CreateProjectOptions{
Name: createProjectOptions.Name,
Path: createProjectOptions.Path,
Description: createProjectOptions.Description,
CIConfigPath: createProjectOptions.CIConfigPath,
NamespaceID: createProjectOptions.NamespaceID,
// hard coded values
Visibility: &visibility,
}
newProject, res, err := r.client.Projects.CreateProject(&opts)
newProject, res, err := r.client.Projects.CreateProject(&createProjectOptions)
if err != nil {
processError(logPrefix, err)
......@@ -684,15 +660,9 @@ func (r ClientImpl) AddProject(createProjectOptions gogitlab.CreateProjectOption
// UpdateProject -
func (r ClientImpl) UpdateProject(projectID int, editProjectOptions gogitlab.EditProjectOptions) (*gogitlab.Project, int, error) {
logPrefix := "UpdateProject"
// copy customizable settings from argument, hard code other options as desired
var opts = gogitlab.EditProjectOptions{
Name: editProjectOptions.Name,
Path: editProjectOptions.Path,
Description: editProjectOptions.Description,
CIConfigPath: editProjectOptions.CIConfigPath,
}
project, res, err := r.client.Projects.EditProject(projectID, &opts)
project, res, err := r.client.Projects.EditProject(projectID, &editProjectOptions)
if err != nil {
processError(logPrefix, err)
return nil, 0, err
......
......@@ -54,6 +54,10 @@ func CreateGroup(gitlabCredentials GitlabCredentials, groupSpec apigitlab.GroupS
ParentID: &parentGroup.ID,
}
// TODO: add membership for team lead as maintainer or owner
// TODO: setup CICD vars
// MANIFEST_REPO_URL KUSTOMIZE_STAGING_PATH KUSTOMIZE_PRODUCTION_PATH
group, statusCode, err := client.AddGroup(groupOptions)
if err != nil {
return fmt.Errorf("failed to add group with name %s to group path %s. error: %v", *groupOptions.Name, groupParentFullPath, err)
......
package p1
import (
"net/http"
"testing"
"github.com/jarcoal/httpmock"
gogitlab "github.com/xanzy/go-gitlab"
apigitlab "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1"
)
func TestCreateGroup(t *testing.T) {
// setup a http client for use in mocking
testHTTPClient := &http.Client{}
httpmock.ActivateNonDefault(testHTTPClient)
defer httpmock.DeactivateAndReset()
testGroupID := 2
testGroupName := "test group name"
testGroupFullPath := "group-path/sub-group-path"
testGroup := gogitlab.Group{ID: testGroupID, Name: testGroupName, FullPath: "group-path"}
testGroupArray := []*gogitlab.Group{}
testGroupArray = append(testGroupArray, &testGroup)
httpmock.RegisterResponder("GET",
`=~^https://test/api/v4/groups.*`,
httpmock.NewJsonResponderOrPanic(http.StatusOK, testGroupArray),
)
httpmock.RegisterResponder("POST",
`=~^https://test/api/v4/groups.*`,
httpmock.NewJsonResponderOrPanic(http.StatusCreated, testGroup),
)
// test objects
testAPIUrl := "https://test/api/v4/"
testToken := "token"
testGroupSpec := apigitlab.GroupSpec{FullPath: testGroupFullPath, Name: "Group Name", Description: "Group Description"}
type args struct {
gitlabCredentials GitlabCredentials
groupSpec apigitlab.GroupSpec
httpClient *http.Client
}
tests := []struct {
name string
args args
wantErr bool
}{
{name: "test", args: args{gitlabCredentials: GitlabCredentials{testAPIUrl, testToken}, groupSpec: testGroupSpec, httpClient: testHTTPClient}, wantErr: false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := CreateGroup(tt.args.gitlabCredentials, tt.args.groupSpec, tt.args.httpClient); (err != nil) != tt.wantErr {
t.Errorf("CreateGroup() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestDeleteGroup(t *testing.T) {
// setup a http client for use in mocking
testHTTPClient := &http.Client{}
httpmock.ActivateNonDefault(testHTTPClient)
defer httpmock.DeactivateAndReset()
// testGroupID := 1
// testUserID := 1
testGroupID := 2
testGroupName := "test group name"
testGroupFullPath := "group-path/sub-group-path"
testGroup := gogitlab.Group{ID: testGroupID, Name: testGroupName, FullPath: testGroupFullPath}
testGroupArray := []*gogitlab.Group{}
testGroupArray = append(testGroupArray, &testGroup)
counter := 0
httpmock.RegisterResponder("DELETE",
`=~^https://test/api/v4/groups.*`,
func(req *http.Request) (*http.Response, error) {
return httpmock.NewJsonResponse(http.StatusAccepted, testGroup)
},
)
// setup a mock that will change response on every 4th call
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, testGroupArray)
}
return httpmock.NewJsonResponse(http.StatusOK, testGroupArray)
},
)
// test objects
testAPIUrl := "https://test/api/v4/"
testToken := "token"
testGroupSpec := apigitlab.GroupSpec{FullPath: testGroupFullPath, Name: "Group Name", Description: "Group Description"}
type args struct {
gitlabCredentials GitlabCredentials
groupSpec apigitlab.GroupSpec
httpClient *http.Client
}
tests := []struct {
name string
args args
wantErr bool
}{
{name: "test", args: args{gitlabCredentials: GitlabCredentials{testAPIUrl, testToken}, groupSpec: testGroupSpec, httpClient: testHTTPClient}, wantErr: false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := DeleteGroup(tt.args.gitlabCredentials, tt.args.groupSpec, tt.args.httpClient); (err != nil) != tt.wantErr {
t.Errorf("DeleteGroup() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestUpdateGroup(t *testing.T) {
// setup a http client for use in mocking
testHTTPClient := &http.Client{}
httpmock.ActivateNonDefault(testHTTPClient)
defer httpmock.DeactivateAndReset()
testGroupID := 2
testGroupName := "test group name"
testGroupFullPath := "group-path/sub-group-path"
testGroup := gogitlab.Group{ID: testGroupID, Name: testGroupName, FullPath: testGroupFullPath}
testGroupArray := []*gogitlab.Group{}
testGroupArray = append(testGroupArray, &testGroup)
httpmock.RegisterResponder("PUT",
`=~^https://test/api/v4/groups.*`,
func(req *http.Request) (*http.Response, error) {
return httpmock.NewJsonResponse(http.StatusAccepted, testGroup)
},
)
httpmock.RegisterResponder("GET",
`=~^https://test/api/v4/groups.*`,
func(req *http.Request) (*http.Response, error) {
return httpmock.NewJsonResponse(http.StatusOK, testGroupArray)
},
)
// test objects
testAPIUrl := "https://test/api/v4/"
testToken := "token"
testGroupSpec := apigitlab.GroupSpec{FullPath: testGroupFullPath, Name: "Group Name", Description: "Group Description"}
type args struct {
gitlabCredentials GitlabCredentials
groupSpec apigitlab.GroupSpec
httpClient *http.Client
}
tests := []struct {
name string
args args
wantErr bool
}{
{name: "test", args: args{gitlabCredentials: GitlabCredentials{testAPIUrl, testToken}, groupSpec: testGroupSpec, httpClient: testHTTPClient}, wantErr: false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := UpdateGroup(tt.args.gitlabCredentials, tt.args.groupSpec, tt.args.httpClient); (err != nil) != tt.wantErr {
t.Errorf("UpdateGroup() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
......@@ -10,6 +10,17 @@ import (
gitlab "valkyrie.dso.mil/valkyrie-api/clients/gitlab"
)
// P1 default values for a project
var defaultBranch = "master"
var enabledAccessControl = gogitlab.EnabledAccessControl
var privateAccessControl = gogitlab.PrivateAccessControl
var privateVisibility = gogitlab.PrivateVisibility
var boolTrue = bool(true)
// values for delete. wait for complete
const deleteWaitInterval = 500 // ms
const deleteWaitCount = 240
// processProjectError - helper
func processProjectError(logPrefix string, err error) {
rlog.Warnf("%s error: %v", logPrefix, err)
......@@ -25,11 +36,17 @@ func logProjectStart(logPrefix string, projectSpec apigitlab.ProjectSpec) {
}
// CreateProject -
func CreateProject(projectCredentials GitlabCredentials, projectSpec apigitlab.ProjectSpec, httpClient *http.Client) error {
func CreateProject(gitlabCredentials GitlabCredentials, projectSpec apigitlab.ProjectSpec, httpClient *http.Client) error {
logPrefix := "CreateProject"
logProjectStart(logPrefix, projectSpec)
client, err := gitlab.NewClient(projectCredentials.ServerURL, projectCredentials.ServerToken, httpClient)
err := ValidateGitlabPath(projectSpec.FullPath)
if err != nil {
processProjectError(logPrefix, err)
return err
}
client, err := gitlab.NewClient(gitlabCredentials.ServerURL, gitlabCredentials.ServerToken, httpClient)
if err != nil {
processProjectError(logPrefix, err)
return err
......@@ -55,12 +72,35 @@ func CreateProject(projectCredentials GitlabCredentials, projectSpec apigitlab.P
}
projectOptions := gogitlab.CreateProjectOptions{
Name: &projectSpec.Name,
Path: &projectPath,
NamespaceID: &parentGroup.ID,
CIConfigPath: &ciConfigPath,
}
Name: &projectSpec.Name,
Path: &projectPath,
NamespaceID: &parentGroup.ID,
Description: nil,
CIConfigPath: &ciConfigPath,
DefaultBranch: &defaultBranch,
Visibility: &privateVisibility,
SharedRunnersEnabled: &boolTrue,
LFSEnabled: &boolTrue,
RequestAccessEnabled: &boolTrue,
ContainerRegistryEnabled: &boolTrue,
PackagesEnabled: &boolTrue,
MergeRequestsEnabled: &boolTrue,
WikiEnabled: &boolTrue,
JobsEnabled: &boolTrue,
SnippetsEnabled: &boolTrue,
IssuesAccessLevel: &enabledAccessControl,
RepositoryAccessLevel: &enabledAccessControl,
MergeRequestsAccessLevel: &enabledAccessControl,
ForkingAccessLevel: &enabledAccessControl,
WikiAccessLevel: &enabledAccessControl,
BuildsAccessLevel: &enabledAccessControl,
SnippetsAccessLevel: &enabledAccessControl,
PagesAccessLevel: &privateAccessControl,
OperationsAccessLevel: &enabledAccessControl,
}
// TODO: add project level ci cd vars MANIFEST_IMAGE
// parentGroupPath + '/' + projectPath
// TODO: add or check branch with group name to pipeline-products
// TODO: add initial product yaml file on that branch based on language type
// TODO: add MR to pipeline product to create project-ci.yml file that POINTS to the branch
......@@ -78,43 +118,18 @@ func CreateProject(projectCredentials GitlabCredentials, projectSpec apigitlab.P
return nil
}
// DeleteProject -
func DeleteProject(projectCredentials GitlabCredentials, projectSpec apigitlab.ProjectSpec, httpClient *http.Client) error {
logPrefix := "DeleteProject"
// UpdateProject -
func UpdateProject(gitlabCredentials GitlabCredentials, projectSpec apigitlab.ProjectSpec, httpClient *http.Client) error {
logPrefix := "UpdateProject"
logProjectStart(logPrefix, projectSpec)
client, err := gitlab.NewClient(projectCredentials.ServerURL, projectCredentials.ServerToken, httpClient)
err := ValidateGitlabPath(projectSpec.FullPath)
if err != nil {
processProjectError(logPrefix, err)
return err
}
projectFullPath := projectSpec.FullPath
project, statusCode, err := client.GetProjectByFullPath(&projectFullPath)
if err != nil {
processProjectError(logPrefix, err)
return err
}
if statusCode != http.StatusFound {
return fmt.Errorf("failed to find project with fullPath %s", projectFullPath)
}
// delete and wait for delete to complete up to 500ms * 240 tries
_, err = client.DeleteProject(project.ID, 500, 240)
if err != nil {
return fmt.Errorf("failed to delete project with fullPath: %s", projectFullPath)
}
return nil
}
// UpdateProject -
func UpdateProject(projectCredentials GitlabCredentials, projectSpec apigitlab.ProjectSpec, httpClient *http.Client) error {
logPrefix := "UpdateProject"
logProjectStart(logPrefix, projectSpec)
client, err := gitlab.NewClient(projectCredentials.ServerURL, projectCredentials.ServerToken, httpClient)
client, err := gitlab.NewClient(gitlabCredentials.ServerURL, gitlabCredentials.ServerToken, httpClient)
if err != nil {
processProjectError(logPrefix, err)
return err
......@@ -163,6 +178,37 @@ func UpdateProject(projectCredentials GitlabCredentials, projectSpec apigitlab.P
return nil
}
// DeleteProject -
func DeleteProject(gitlabCredentials GitlabCredentials, projectSpec apigitlab.ProjectSpec, httpClient *http.Client) error {
logPrefix := "DeleteProject"
logProjectStart(logPrefix, projectSpec)
client, err := gitlab.NewClient(gitlabCredentials.ServerURL, gitlabCredentials.ServerToken, httpClient)
if err != nil {
processProjectError(logPrefix, err)
return err
}
projectFullPath := projectSpec.FullPath
project, statusCode, err := client.GetProjectByFullPath(&projectFullPath)
if err != nil {
processProjectError(logPrefix, err)
return err
}
if statusCode != http.StatusFound {
return fmt.Errorf("failed to find project with fullPath %s", projectFullPath)
}
// delete and wait for delete to complete up to 500ms * 240 tries
_, err = client.DeleteProject(project.ID, deleteWaitInterval, deleteWaitCount)
if err != nil {
return fmt.Errorf("failed to delete project with fullPath: %s", projectFullPath)
}
return nil
}
// generateCIConfigPath - helper function. create CI configuration path for P1
func generateCIConfigPath(projectName string, parentGroupFullPath string) (string, error) {
// scrub the project name
......
package p1
import (
"net/http"
"testing"
"github.com/jarcoal/httpmock"
gogitlab "github.com/xanzy/go-gitlab"
apigitlab "valkyrie.dso.mil/valkyrie-api/apis/gitlab/v1alpha1"
)
func TestCreateProject(t *testing.T) {
// setup a http client for use in mocking
testHTTPClient := &http.Client{}
httpmock.ActivateNonDefault(testHTTPClient)
defer httpmock.DeactivateAndReset()
testGroupID := 2
testGroupName := "test group name"
testGroupFullPath := "group-path/sub-group-path"
testGroup := gogitlab.Group{ID: testGroupID, Name: testGroupName, FullPath: testGroupFullPath}
testGroupArray := []*gogitlab.Group{}
testGroupArray = append(testGroupArray, &testGroup)
testProjectID := 2
testProjectName := "test Project name"
testProjectFullPath := testGroupFullPath + "/" + "test-project-name"
testProject := gogitlab.Project{ID: testProjectID, Name: testProjectName, PathWithNamespace: testProjectFullPath}
testProjectArray := []*gogitlab.Project{}
testProjectArray = append(testProjectArray, &testProject)
httpmock.RegisterResponder("GET",
`=~^https://test/api/v4/groups.*`,
httpmock.NewJsonResponderOrPanic(http.StatusOK, testGroupArray),
)
httpmock.RegisterResponder("GET",
`=~^https://test/api/v4/projects.*`,
httpmock.NewJsonResponderOrPanic(http.StatusOK, testProjectArray),
)
httpmock.RegisterResponder("POST",
`=~^https://test/api/v4/projects.*`,
httpmock.NewJsonResponderOrPanic(http.StatusCreated, testProject),
)
// test objects
testAPIUrl := "https://test/api/v4/"
testToken := "token"
testProjectSpec := apigitlab.ProjectSpec{FullPath: testProjectFullPath, Name: "Project Name", Language: LangTypeCpp}
type args struct {
gitlabCredentials GitlabCredentials
projectSpec apigitlab.ProjectSpec
httpClient *http.Client
}
tests := []struct {
name string
args args
wantErr bool
}{
{name: "test", args: args{gitlabCredentials: GitlabCredentials{testAPIUrl, testToken}, projectSpec: testProjectSpec, httpClient: testHTTPClient}, wantErr: false},
}
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 {
t.Errorf("CreateProject() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestDeleteProject(t *testing.T) {
// setup a http client for use in mocking
testHTTPClient := &http.Client{}
httpmock.ActivateNonDefault(testHTTPClient)
defer httpmock.DeactivateAndReset()
testGroupFullPath := "group-path/sub-group-path"
testProjectID := 2
testProjectName := "test Project name"
testProjectFullPath := testGroupFullPath + "/" + "test-project-name"
testProject := gogitlab.Project{ID: testProjectID, Name: testProjectName, PathWithNamespace: testProjectFullPath}
testProjectArray := []*gogitlab.Project{}
testProjectArray = append(testProjectArray, &testProject)
counter := 0
httpmock.RegisterResponder("DELETE",
`=~^https://test/api/v4/projects.*`,
func(req *http.Request) (*http.Response, error) {
return httpmock.NewJsonResponse(http.StatusAccepted, testProject)
},
)
// setup a mock that will change response on every 4th call
httpmock.RegisterResponder("GET",
`=~^https://test/api/v4/projects.*`,
func(req *http.Request) (*http.Response, error) {
counter = counter + 1
if counter%4 == 0 {
return httpmock.NewJsonResponse(http.StatusNotFound, testProjectArray)
}
return httpmock.NewJsonResponse(http.StatusOK, testProjectArray)
},
)
// test objects
testAPIUrl := "https://test/api/v4/"
testToken := "token"
testProjectSpec := apigitlab.ProjectSpec{FullPath: testProjectFullPath, Name: "Project Name", Language: LangTypeCpp}
type args struct {
gitlabCredentials GitlabCredentials
projectSpec apigitlab.ProjectSpec
httpClient *http.Client
}
tests := []struct {
name string
args args
wantErr bool
}{
{name: "test", args: args{gitlabCredentials: GitlabCredentials{testAPIUrl, testToken}, projectSpec: testProjectSpec, httpClient: testHTTPClient}, wantErr: false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := DeleteProject(tt.args.gitlabCredentials, tt.args.projectSpec, tt.args.httpClient); (err != nil) != tt.wantErr {
t.Errorf("DeleteProject() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestUpdateProject(t *testing.T) {
// setup a http client for use in mocking
testHTTPClient := &http.Client{}
httpmock.ActivateNonDefault(testHTTPClient)
defer httpmock.DeactivateAndReset()
testGroupID := 2
testGroupName := "test group name"
testGroupFullPath := "group-path/sub-group-path"
testGroup := gogitlab.Group{ID: testGroupID, Name: testGroupName, FullPath: testGroupFullPath}
testGroupArray := []*gogitlab.Group{}
testGroupArray = append(testGroupArray, &testGroup)
testProjectID := 2
testProjectName := "test Project name"
testProjectFullPath := testGroupFullPath + "/" + "test-project-name"
testProject := gogitlab.Project{ID: testProjectID, Name: testProjectName, PathWithNamespace: testProjectFullPath}
testProjectArray := []*gogitlab.Project{}
testProjectArray = append(testProjectArray, &testProject)
httpmock.RegisterResponder("GET",
`=~^https://test/api/v4/groups.*`,
httpmock.NewJsonResponderOrPanic(http.StatusOK, testGroupArray),
)
httpmock.RegisterResponder("GET",
`=~^https://test/api/v4/projects.*`,
httpmock.NewJsonResponderOrPanic(http.StatusOK, testProjectArray),
)
httpmock.RegisterResponder("PUT",
`=~^https://test/api/v4/projects.*`,
httpmock.NewJsonResponderOrPanic(http.StatusCreated, testProject),
)
// test objects
testAPIUrl := "https://test/api/v4/"
testToken := "token"
testProjectSpec := apigitlab.ProjectSpec{FullPath: testProjectFullPath, Name: "Project Name", Language: LangTypeCpp}
type args struct {
gitlabCredentials GitlabCredentials
projectSpec apigitlab.ProjectSpec
httpClient *http.Client
}
tests := []struct {
name string
args args
wantErr bool
}{
{name: "test", args: args{gitlabCredentials: GitlabCredentials{testAPIUrl, testToken}, projectSpec: testProjectSpec, httpClient: testHTTPClient}, wantErr: false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := UpdateProject(tt.args.gitlabCredentials, tt.args.projectSpec, tt.args.httpClient); (err != nil) != tt.wantErr {
t.Errorf("UpdateProject() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
package p1
import (
"fmt"
"path"
"regexp"
"strings"
......@@ -43,3 +44,19 @@ func StripLastChar(value string, char string) string {
newValue := re.ReplaceAllString(value, "")
return newValue
}
// ValidateGitlabPath - Insure gitlab path value is compliant with P1
func ValidateGitlabPath(value string) error {
if value == "" {
return fmt.Errorf("noncompliant gitlab path. path cannot an empty string")
}
var re *regexp.Regexp
pattern := `^[a-zA-Z0-9/-]+$`
re, _ = regexp.Compile(pattern)
byteValue := []byte(value)
found := re.Match(byteValue)
if !found {
return fmt.Errorf("noncompliant gitlab path %s. path must comply to pattern %s", value, pattern)
}
return nil
}
......@@ -68,3 +68,50 @@ func TestParseGitlabPath(t *testing.T) {
})
}
}
func TestValidateGitlabPath(t *testing.T) {
type args struct {
value string
}
tests := []struct {
name string
args args
wantErr bool
}{
{name: "test 1", args: args{value: ""}, wantErr: true},
{name: "test 1", args: args{value: "group-path/project-path-1234"}, wantErr: false},
{name: "test 1", args: args{value: "group-path\\project-path-1230"}, wantErr: true},
{name: "test 1", args: args{value: "group-path/project_path"}, wantErr: true},
{name: "test 1", args: args{value: "group-path/project path"}, wantErr: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := ValidateGitlabPath(tt.args.value); (err != nil) != tt.wantErr {
t.Errorf("ValidateGitlabPath() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestStripLastChar(t *testing.T) {
type args struct {
value string
char string
}
tests := []struct {
name string
args args
want string
}{
{name: "test 1", args: args{value: "group-path_project-path", char: "h"}, want: "group-path_project-pat"},
{name: "test 1", args: args{value: "group-path_project-path--", char: "-"}, want: "group-path_project-path-"},
{name: "test 1", args: args{value: "", char: "-"}, want: ""},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := StripLastChar(tt.args.value, tt.args.char); got != tt.want {
t.Errorf("StripLastChar() = %v, want %v", got, tt.want)
}
})
}
}
## Gitlab Projects
### Reference
- https://docs.gitlab.com/ee/api/projects.html
- API Access
GET $API/projects/:id
curl --header "Authorization: Bearer $GITLAB_TOKEN" "https://code.il2.dso.mil/api/v4/projects/351" | jq . > project_sample_1.json
{
"id": 351,
"description": null,
"name": "workshop-7-app-manifests",
"name_with_namespace": "Tron / Products / Workshops / workshop-manifests / workshop-7-app-manifests",
"path": "workshop-7-app-manifests",
"path_with_namespace": "tron/products/workshops/workshop-manifests/workshop-7-app-manifests",
"created_at": "2020-08-28T00:44:13.141Z",
"default_branch": "master",
"tag_list": [],
"ssh_url_to_repo": "git@code.il2.dso.mil:tron/products/workshops/workshop-manifests/workshop-7-app-manifests.git",
"http_url_to_repo": "https://code.il2.dso.mil/tron/products/workshops/workshop-manifests/workshop-7-app-manifests.git",
"web_url": "https://code.il2.dso.mil/tron/products/workshops/workshop-manifests/workshop-7-app-manifests",
"readme_url": "https://code.il2.dso.mil/tron/products/workshops/workshop-manifests/workshop-7-app-manifests/-/blob/master/README.md",
"avatar_url": null,
"forks_count": 0,
"star_count": 0,
"last_activity_at": "2020-09-16T02:02:51.544Z",
"namespace": {
"id": 530,
"name": "workshop-manifests",
"path": "workshop-manifests",
"kind": "group",
"full_path": "tron/products/workshops/workshop-manifests",
"parent_id": 368,
"avatar_url": null,
"web_url": "https://code.il2.dso.mil/groups/tron/products/workshops/workshop-manifests"
},
"container_registry_image_prefix": "registry.il2.dso.mil/tron/products/workshops/workshop-manifests/workshop-7-app-manifests",
"_links": {
"self": "https://code.il2.dso.mil/api/v4/projects/351",
"issues": "https://code.il2.dso.mil/api/v4/projects/351/issues",
"merge_requests": "https://code.il2.dso.mil/api/v4/projects/351/merge_requests",
"repo_branches": "https://code.il2.dso.mil/api/v4/projects/351/repository/branches",
"labels": "https://code.il2.dso.mil/api/v4/projects/351/labels",
"events": "https://code.il2.dso.mil/api/v4/projects/351/events",
"members": "https://code.il2.dso.mil/api/v4/projects/351/members"
},
"packages_enabled": true,
"empty_repo": false,
"archived": false,
"visibility": "private",
"resolve_outdated_diff_discussions": false,
"container_registry_enabled": true,
"container_expiration_policy": {
"cadence": "7d",
"enabled": true,
"keep_n": null,
"older_than": null,
"name_regex": null,
"name_regex_keep": null,
"next_run_at": "2020-11-13T05:50:21.793Z"
},
"issues_enabled": true,
"merge_requests_enabled": true,
"wiki_enabled": true,
"jobs_enabled": true,
"snippets_enabled": true,
"service_desk_enabled": false,
"service_desk_address": null,
"can_create_merge_request_in": true,
"issues_access_level": "enabled",
"repository_access_level": "enabled",
"merge_requests_access_level": "enabled",
"forking_access_level": "enabled",
"wiki_access_level": "enabled",
"builds_access_level": "enabled",
"snippets_access_level": "enabled",
"pages_access_level": "private",
"operations_access_level": "enabled",
"analytics_access_level": "enabled",
"emails_disabled": null,
"shared_runners_enabled": true,
"lfs_enabled": true,
"creator_id": 107,
"import_status": "none",
"import_error": null,
"open_issues_count": 0,
"runners_token": "orUXi_7uf7Ha8M1d61QV",
"ci_default_git_depth": 50,
"ci_forward_deployment_enabled": true,
"public_jobs": true,
"build_git_strategy": "fetch",
"build_timeout": 3600,
"auto_cancel_pending_pipelines": "enabled",
"build_coverage_regex": null,
"ci_config_path": "",
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
"allow_merge_on_skipped_pipeline": null,
"restrict_user_defined_variables": false,
"request_access_enabled": true,
"only_allow_merge_if_all_discussions_are_resolved": false,
"remove_source_branch_after_merge": true,
"printing_merge_request_link_enabled": true,
"merge_method": "merge",
"suggestion_commit_message": null,
"auto_devops_enabled": false,
"auto_devops_deploy_strategy": "continuous",
"autoclose_referenced_issues": true,
"repository_storage": "default",
"approvals_before_merge": 0,
"mirror": false,
"external_authorization_classification_label": null,
"marked_for_deletion_at": null,
"marked_for_deletion_on": null,
"requirements_enabled": false,
"security_and_compliance_enabled": true,
"compliance_frameworks": [],
"issues_template": null,
"merge_requests_template": null,
"permissions": {
"project_access": null,
"group_access": {
"access_level": 40,
"notification_level": 3
}
}
}
{
"id": 49,
"description": "",
"name": "python-world",
"name_with_namespace": "Platform One / DevOps / hello-pipeline / python-world",
"path": "python-world",
"path_with_namespace": "platform-one/devops/hello-pipeline/python-world",
"created_at": "2020-07-22T16:56:04.870Z",
"default_branch": "master",
"tag_list": [],
"ssh_url_to_repo": "git@code.il2.dso.mil:platform-one/devops/hello-pipeline/python-world.git",
"http_url_to_repo": "https://code.il2.dso.mil/platform-one/devops/hello-pipeline/python-world.git",
"web_url": "https://code.il2.dso.mil/platform-one/devops/hello-pipeline/python-world",
"readme_url": "https://code.il2.dso.mil/platform-one/devops/hello-pipeline/python-world/-/blob/master/README.md",
"avatar_url": "https://code.il2.dso.mil/uploads/-/system/project/avatar/49/logo_python.png",
"forks_count": 0,
"star_count": 2,
"last_activity_at": "2021-06-25T15:24:44.942Z",
"namespace": {
"id": 256,
"name": "hello-pipeline",
"path": "hello-pipeline",
"kind": "group",
"full_path": "platform-one/devops/hello-pipeline",
"parent_id": 255,
"avatar_url": null,
"web_url": "https://code.il2.dso.mil/groups/platform-one/devops/hello-pipeline"
},
"container_registry_image_prefix": "registry.il2.dso.mil/platform-one/devops/hello-pipeline/python-world",
"_links": {
"self": "https://code.il2.dso.mil/api/v4/projects/49",
"merge_requests": "https://code.il2.dso.mil/api/v4/projects/49/merge_requests",
"repo_branches": "https://code.il2.dso.mil/api/v4/projects/49/repository/branches",
"labels": "https://code.il2.dso.mil/api/v4/projects/49/labels",
"events": "https://code.il2.dso.mil/api/v4/projects/49/events",
"members": "https://code.il2.dso.mil/api/v4/projects/49/members"
},
"packages_enabled": true,
"empty_repo": false,
"archived": false,
"visibility": "internal",
"resolve_outdated_diff_discussions": false,
"container_registry_enabled": true,
"container_expiration_policy": {
"cadence": "7d",
"enabled": false,
"keep_n": null,
"older_than": null,
"name_regex": null,
"name_regex_keep": null,
"next_run_at": "2021-06-17T19:50:15.553Z"
},
"issues_enabled": false,
"merge_requests_enabled": true,
"wiki_enabled": false,
"jobs_enabled": true,
"snippets_enabled": false,
"service_desk_enabled": false,
"service_desk_address": null,
"can_create_merge_request_in": true,
"issues_access_level": "disabled",
"repository_access_level": "enabled",
"merge_requests_access_level": "private",
"forking_access_level": "disabled",
"wiki_access_level": "disabled",
"builds_access_level": "enabled",
"snippets_access_level": "disabled",
"pages_access_level": "private",
"operations_access_level": "enabled",
"analytics_access_level": "enabled",
"emails_disabled": false,
"shared_runners_enabled": true,
"lfs_enabled": true,
"creator_id": 18,
"import_status": "none",
"import_error": null,
"runners_token": "TxeYu7aZzGRbdz3iSxLh",
"ci_default_git_depth": 50,
"ci_forward_deployment_enabled": true,
"public_jobs": true,
"build_git_strategy": "fetch",
"build_timeout": 3600,
"auto_cancel_pending_pipelines": "enabled",
"build_coverage_regex": "",
"ci_config_path": "products/platformone/hello-pipeline/python-world-ci.yml@platform-one/devops/pipeline-products",
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
"allow_merge_on_skipped_pipeline": null,
"restrict_user_defined_variables": false,
"request_access_enabled": false,
"only_allow_merge_if_all_discussions_are_resolved": false,
"remove_source_branch_after_merge": true,
"printing_merge_request_link_enabled": true,
"merge_method": "merge",
"suggestion_commit_message": null,
"auto_devops_enabled": false,
"auto_devops_deploy_strategy": "continuous",
"autoclose_referenced_issues": true,
"repository_storage": "default",
"approvals_before_merge": 0,
"mirror": false,
"external_authorization_classification_label": null,
"marked_for_deletion_at": null,
"marked_for_deletion_on": null,
"requirements_enabled": false,
"security_and_compliance_enabled": true,
"compliance_frameworks": [],
"issues_template": null,
"merge_requests_template": null,
"permissions": {
"project_access": null,
"group_access": {
"access_level": 30,
"notification_level": 3
}
}
}
......@@ -30,7 +30,15 @@ func Test_P1_AddProject(t *testing.T) {
ServerToken: P1Config.gitlabAPIToken,
}
err := custom_p1.CreateProject(creds, projectSpec, nil)
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
......@@ -63,23 +71,23 @@ func Test_P1_UpdateProject(t *testing.T) {
})
}
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)
})
}
// 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)
// })
// }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment