diff --git a/pkg/k8s/cloud.go b/pkg/k8s/cloud.go new file mode 100644 index 0000000..910a0f6 --- /dev/null +++ b/pkg/k8s/cloud.go @@ -0,0 +1,247 @@ +package k8s + +import ( + "fmt" + "strings" + + unstructured "github.com/linuxsuren/unstructured/pkg" + v1 "k8s.io/api/core/v1" + "sigs.k8s.io/yaml" +) + +// JenkinsConfig represents a Jenkins configuration-as-code object +type JenkinsConfig struct { + Config []byte +} + +// GetConfigAsString returns the config data as string +func (c *JenkinsConfig) GetConfigAsString() string { + return string(c.Config) +} + +// ReplaceOrAddPodTemplate replace the existing PodTemplate, or add it if it's not exist +func (c *JenkinsConfig) ReplaceOrAddPodTemplate(podTemplate *v1.PodTemplate) (err error) { + if err = c.RemovePodTemplate(podTemplate.Name); err == nil { + err = c.AddPodTemplate(podTemplate) + } + return +} + +// AddPodTemplate adds a PodTemplate to the Jenkins cloud config +func (c *JenkinsConfig) AddPodTemplate(podTemplate *v1.PodTemplate) (err error) { + casc := map[string]interface{}{} + if err = yaml.Unmarshal(c.Config, &casc); err != nil { + err = fmt.Errorf("failed to unmarshal YAML to map structure, error: %v", err) + return + } + + var templatesObj interface{} + var ok bool + if templatesObj, ok, err = unstructured.NestedField(casc, "jenkins", "clouds[0]", "kubernetes", "templates"); !ok { + err = fmt.Errorf("failed to find jenkins.cloud[0]") + return + } else if err != nil { + return + } + + var targetPodTemplate JenkinsPodTemplate + if targetPodTemplate, err = ConvertToJenkinsPodTemplate(podTemplate); err != nil { + return + } + + var templates []interface{} + if templates, ok = templatesObj.([]interface{}); ok { + templates = append(templates, targetPodTemplate) + } + + if err = unstructured.SetNestedField(casc, templates, "jenkins", "clouds[0]", "kubernetes", "templates"); err == nil { + c.Config, err = yaml.Marshal(casc) + } + return +} + +// ConvertToJenkinsPodTemplate converts a k8s style PodTemplate to a Jenkins style PodTemplate +func ConvertToJenkinsPodTemplate(podTemplate *v1.PodTemplate) (target JenkinsPodTemplate, err error) { + target.Name = podTemplate.Name + target.Namespace = podTemplate.Namespace + target.Label = podTemplate.Name + target.NodeUsageMode = "EXCLUSIVE" + + // make sure the annotations are not empty + if podTemplate.Annotations == nil { + podTemplate.Annotations = map[string]string{} + } + annotations := podTemplate.Annotations + + // set the Jenkins agent labels + if val, ok := annotations["jenkins.agent.labels"]; ok && val != "" { + labels := strings.Split(val, " ") + labels = append(labels, podTemplate.Name) + target.Label = strings.Join(labels, " ") + } + + // set the template level fields + target.YAML = annotations["containers.yaml"] + target.InheritFrom = annotations["inherit.from"] + + // convert the containers + containers := podTemplate.Template.Spec.Containers + containersCount := len(containers) + if containersCount > 0 { + target.Containers = make([]Container, containersCount) + + for i, container := range containers { + name := container.Name + + jenkinsAgentContainer := Container{ + Name: name, + Image: container.Image, + Command: strings.Join(container.Command, " "), + Args: strings.Join(container.Args, " "), + TtyEnabled: true, + } + + if mem := container.Resources.Requests.Memory(); mem != nil && !mem.IsZero() { + jenkinsAgentContainer.ResourceRequestMemory = mem.String() + } + if mem := container.Resources.Limits.Memory(); mem != nil && !mem.IsZero() { + jenkinsAgentContainer.ResourceLimitMemory = mem.String() + } + if cpu := container.Resources.Requests.Cpu(); cpu != nil && !cpu.IsZero() { + jenkinsAgentContainer.ResourceRequestCPU = cpu.String() + } + if cpu := container.Resources.Limits.Cpu(); cpu != nil && !cpu.IsZero() { + jenkinsAgentContainer.ResourceLimitCPU = cpu.String() + } + + target.Containers[i] = jenkinsAgentContainer + } + + container := containers[0] + for _, volMount := range container.VolumeMounts { + for _, vol := range podTemplate.Template.Spec.Volumes { + if vol.Name == volMount.Name && vol.HostPath != nil { + target.Volumes = append(target.Volumes, Volume{ + HostPathVolume{ + HostPath: vol.HostPath.Path, + MountPath: volMount.MountPath, + }, + }) + break + } + } + } + } + return +} + +// RemovePodTemplate removes a PodTemplate from the Jenkins cloud config +func (c *JenkinsConfig) RemovePodTemplate(name string) (err error) { + casc := map[string]interface{}{} + if err = yaml.Unmarshal(c.Config, &casc); err != nil { + err = fmt.Errorf("failed to unmarshal YAML to map structure, error: %v", err) + return + } + + var templatesObj interface{} + var ok bool + if templatesObj, ok, err = unstructured.NestedField(casc, "jenkins", "clouds[0]", "kubernetes", "templates"); !ok { + err = fmt.Errorf("failed to find jenkins.cloud[0]") + return + } else if err != nil { + return + } + + var templateArray []interface{} + if templateArray, ok = templatesObj.([]interface{}); ok { + for i, templateObj := range templateArray { + var template map[string]interface{} + if template, ok = templateObj.(map[string]interface{}); ok { + if template["name"].(string) == name { + if i == len(template)-1 { + templateArray = templateArray[0:i] + } else { + templateArray = append(templateArray[0:i], templateArray[i+1:]...) + } + break + } + } + } + } + + if err = unstructured.SetNestedField(casc, templateArray, "jenkins", "clouds[0]", "kubernetes", "templates"); err == nil { + c.Config, err = yaml.Marshal(casc) + } + return +} + +// CloudAgent represents a Jenkins cloud agent +type CloudAgent struct { + Kubernetes KubernetesCloud `json:"kubernetes"` +} + +// KubernetesCloud represents a Kubernetes connection in Jenkins +type KubernetesCloud struct { + Name string `json:"name"` + ServerURL string `json:"serverUrl"` + SkipTLSVerify bool `json:"skipTlsVerify"` + Namespace string `json:"namespace"` + CredentialsID string `json:"credentialsId"` + JenkinsURL string `json:"jenkinsUrl"` + JenkinsTunnel string `json:"jenkinsTunnel"` + ContainerCapStr string `json:"containerCapStr"` + ConnectTimeout string `json:"connectTimeout"` + ReadTimeout string `json:"readTimeout"` + MaxRequestsPerhHostStr string `json:"maxRequestsPerhHostStr"` + Templates []JenkinsPodTemplate `json:"templates"` +} + +// JenkinsPodTemplate represents the PodTemplate that defined in Jenkins +type JenkinsPodTemplate struct { + Name string `json:"name"` + Namespace string `json:"namespace"` + Label string `json:"label"` + NodeUsageMode string `json:"nodeUsageMode"` + IdleMinutes int `json:"idleMinutes"` + Containers []Container `json:"containers"` + InheritFrom string `json:"inheritFrom,omitempty"` + Volumes []Volume `json:"volumes"` + // YAML is the YAML format for merging into the whole PodTemplate + YAML string `json:"yaml"` + WorkspaceVolume WorkspaceVolume `json:"workspaceVolume"` +} + +// Volume represents the volume in kubernetes +type Volume struct { + HostPathVolume HostPathVolume `json:"hostPathVolume"` +} + +// Container represents the container that defined in Jenkins +type Container struct { + Name string `json:"name"` + Image string `json:"image"` + Command string `json:"command"` + Args string `json:"args"` + TtyEnabled bool `json:"ttyEnabled"` + Privileged bool `json:"privileged"` + ResourceRequestCPU string `json:"resourceRequestCpu,omitempty"` + ResourceLimitCPU string `json:"resourceLimitCpu,omitempty"` + ResourceRequestMemory string `json:"resourceRequestMemory,omitempty"` + ResourceLimitMemory string `json:"resourceLimitMemory,omitempty"` +} + +// WorkspaceVolume is the volume of the Jenkins agent workspace +type WorkspaceVolume struct { + EmptyDirWorkspaceVolume EmptyDirWorkspaceVolume `json:"emptyDirWorkspaceVolume"` +} + +// EmptyDirWorkspaceVolume is an empty dir type of workspace volume +type EmptyDirWorkspaceVolume struct { + Memory bool `json:"memory"` +} + +// HostPathVolume represents a host path volume +type HostPathVolume struct { + HostPath string `json:"hostPath"` + MountPath string `json:"mountPath"` +} diff --git a/pkg/k8s/cloud_test.go b/pkg/k8s/cloud_test.go new file mode 100644 index 0000000..0f757ee --- /dev/null +++ b/pkg/k8s/cloud_test.go @@ -0,0 +1,190 @@ +package k8s + +import ( + "fmt" + "io/ioutil" + "testing" + + "github.com/stretchr/testify/assert" + v1 "k8s.io/api/core/v1" + "sigs.k8s.io/yaml" +) + +func TestJenkinsConfig_AddPodTemplate(t *testing.T) { + type fields struct { + Config []byte + } + type args struct { + podTemplate *v1.PodTemplate + } + tests := []struct { + name string + fields fields + args args + expectResult string + wantErr bool + }{{ + name: "normal", + fields: fields{Config: readFile("testdata/casc.yaml")}, + args: args{podTemplate: readPodTemplate("testdata/k8s-podtemplate.yaml")}, + expectResult: "testdata/result-casc.yaml", + wantErr: false, + }, { + name: "casc is not a valid YAMl", + fields: fields{Config: []byte(`fake`)}, + args: args{podTemplate: readPodTemplate("testdata/k8s-podtemplate.yaml")}, + wantErr: true, + }, { + name: "casc has not the expect structure", + fields: fields{Config: []byte(`name: rick`)}, + args: args{podTemplate: readPodTemplate("testdata/k8s-podtemplate.yaml")}, + wantErr: true, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &JenkinsConfig{ + Config: tt.fields.Config, + } + if err := c.AddPodTemplate(tt.args.podTemplate); (err != nil) != tt.wantErr { + t.Errorf("AddPodTemplate() error = %v, wantErr %v", err, tt.wantErr) + } + + if tt.expectResult != "" { + assert.Equal(t, readFileASString(tt.expectResult), c.GetConfigAsString()) + } + }) + } +} + +func TestJenkinsConfig_RemovePodTemplate(t *testing.T) { + type fields struct { + Config []byte + } + type args struct { + podTemplate string + } + tests := []struct { + name string + fields fields + args args + wantErr bool + expectResult string + }{{ + name: "normal", + fields: fields{Config: readFile("testdata/result-casc.yaml")}, + args: args{podTemplate: "base"}, + expectResult: "testdata/casc.yaml", + wantErr: false, + }, { + name: "casc is invalid", + fields: fields{Config: []byte("fake")}, + args: args{podTemplate: "base"}, + wantErr: true, + }, { + name: "casc has an unexpected structure", + fields: fields{Config: []byte(`name: rick`)}, + args: args{podTemplate: "base"}, + wantErr: true, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &JenkinsConfig{ + Config: tt.fields.Config, + } + if err := c.RemovePodTemplate(tt.args.podTemplate); (err != nil) != tt.wantErr { + t.Errorf("RemovePodTemplate() error = %v, wantErr %v", err, tt.wantErr) + } + if tt.expectResult != "" { + assert.Equal(t, readFileASString(tt.expectResult), c.GetConfigAsString()) + } + }) + } +} + +func readPodTemplate(file string) (result *v1.PodTemplate) { + result = &v1.PodTemplate{} + + data := readFile(file) + _ = yaml.Unmarshal(data, result) + return +} + +func readJenkinsPodTemplate(file string) (result JenkinsPodTemplate) { + data := readFile(file) + _ = yaml.Unmarshal(data, &result) + return +} + +func readFile(file string) (data []byte) { + data, _ = ioutil.ReadFile(file) + return +} + +func readFileASString(file string) string { + return string(readFile(file)) +} + +func TestJenkinsConfig_ReplaceOrAddPodTemplate(t *testing.T) { + type fields struct { + Config []byte + } + type args struct { + podTemplate *v1.PodTemplate + } + tests := []struct { + name string + fields fields + args args + expectResult string + wantErr assert.ErrorAssertionFunc + }{{ + name: "normal", + fields: fields{Config: readFile("testdata/result-casc.yaml")}, + args: args{podTemplate: readPodTemplate("testdata/k8s-podtemplate.yaml")}, + expectResult: "testdata/result-casc.yaml", + wantErr: func(t assert.TestingT, err error, i ...interface{}) bool { + assert.Nil(t, err) + return true + }, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &JenkinsConfig{ + Config: tt.fields.Config, + } + tt.wantErr(t, c.ReplaceOrAddPodTemplate(tt.args.podTemplate), fmt.Sprintf("ReplaceOrAddPodTemplate(%v)", tt.args.podTemplate)) + assert.Equal(t, readFileASString(tt.expectResult), c.GetConfigAsString()) + }) + } +} + +func TestConvertToJenkinsPodTemplate(t *testing.T) { + type args struct { + podTemplate *v1.PodTemplate + } + tests := []struct { + name string + args args + wantTarget JenkinsPodTemplate + wantErr assert.ErrorAssertionFunc + }{{ + name: "annotation is nil", + args: args{ + podTemplate: readPodTemplate("testdata/k8s-podtemplate-without-annotations.yaml"), + }, + wantTarget: readJenkinsPodTemplate("testdata/jenkins-pod-template.yaml"), + wantErr: func(t assert.TestingT, err error, i ...interface{}) bool { + assert.Nil(t, err) + return true + }, + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotTarget, err := ConvertToJenkinsPodTemplate(tt.args.podTemplate) + if !tt.wantErr(t, err, fmt.Sprintf("ConvertToJenkinsPodTemplate(%v)", tt.args.podTemplate)) { + return + } + assert.Equalf(t, tt.wantTarget, gotTarget, "ConvertToJenkinsPodTemplate(%v)", tt.args.podTemplate) + }) + } +} diff --git a/pkg/k8s/go.mod b/pkg/k8s/go.mod new file mode 100644 index 0000000..a5c5146 --- /dev/null +++ b/pkg/k8s/go.mod @@ -0,0 +1,27 @@ +module github.com/jenkins-zh/jenkins-client/pkg/k8s + +go 1.18 + +require ( + github.com/linuxsuren/unstructured v0.0.1 + github.com/stretchr/testify v1.4.0 + k8s.io/api v0.18.6 + sigs.k8s.io/yaml v1.2.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/gogo/protobuf v1.3.1 // indirect + github.com/google/gofuzz v1.1.0 // indirect + github.com/json-iterator/go v1.1.8 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 // indirect + golang.org/x/text v0.3.2 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.2.8 // indirect + k8s.io/apimachinery v0.18.6 // indirect + k8s.io/klog v1.0.0 // indirect + sigs.k8s.io/structured-merge-diff/v3 v3.0.0 // indirect +) diff --git a/pkg/k8s/go.sum b/pkg/k8s/go.sum new file mode 100644 index 0000000..bb179d5 --- /dev/null +++ b/pkg/k8s/go.sum @@ -0,0 +1,111 @@ +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= +github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= +github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= +github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= +github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/linuxsuren/unstructured v0.0.1 h1:ilUA8MUYbR6l9ebo/YPV2bKqlf62bzQursDSE+j00iU= +github.com/linuxsuren/unstructured v0.0.1/go.mod h1:KH6aTj+FegzGBzc1vS6mzZx3/duhTUTEVyW5sO7p4as= +github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI= +golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +k8s.io/api v0.18.6 h1:osqrAXbOQjkKIWDTjrqxWQ3w0GkKb1KA1XkUGHHYpeE= +k8s.io/api v0.18.6/go.mod h1:eeyxr+cwCjMdLAmr2W3RyDI0VvTawSg/3RFFBEnmZGI= +k8s.io/apimachinery v0.18.6 h1:RtFHnfGNfd1N0LeSrKCUznz5xtUP1elRGvHJbL3Ntag= +k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= +k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= +k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= +sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= +sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E= +sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/pkg/k8s/testdata/casc.yaml b/pkg/k8s/testdata/casc.yaml new file mode 100644 index 0000000..b84c394 --- /dev/null +++ b/pkg/k8s/testdata/casc.yaml @@ -0,0 +1,86 @@ +jenkins: + clouds: + - kubernetes: + connectTimeout: "60" + containerCapStr: "4" + credentialsId: k8s-service-account + jenkinsTunnel: devops-jenkins-agent.kubesphere-devops-system:50000 + jenkinsUrl: http://devops-jenkins.kubesphere-devops-system:80 + maxRequestsPerHostStr: "32" + name: kubernetes + namespace: kubesphere-devops-worker + readTimeout: "60" + serverUrl: https://kubernetes.default + skipTlsVerify: true + templates: + - containers: + - args: "" + command: cat + image: kubesphere/builder-go:v3.2.0 + name: go + privileged: false + resourceLimitCpu: 4000m + resourceLimitMemory: 8192Mi + resourceRequestCpu: 100m + resourceRequestMemory: 100Mi + ttyEnabled: true + - args: ^${computer.jnlpmac} ^${computer.name} + command: jenkins-slave + image: jenkins/jnlp-slave:3.27-1 + name: jnlp + resourceLimitCpu: 500m + resourceLimitMemory: 1536Mi + resourceRequestCpu: 50m + resourceRequestMemory: 400Mi + idleMinutes: 0 + label: go + name: go + namespace: kubesphere-devops-worker + nodeUsageMode: EXCLUSIVE + volumes: + - hostPathVolume: + hostPath: /var/run/docker.sock + mountPath: /var/run/docker.sock + - hostPathVolume: + hostPath: /var/data/jenkins_go_cache + mountPath: /home/jenkins/go/pkg + - hostPathVolume: + hostPath: /var/data/jenkins_sonar_cache + mountPath: /root/.sonar/cache + workspaceVolume: + emptyDirWorkspaceVolume: + memory: false + yaml: "" + disableRememberMe: true + mode: EXCLUSIVE + numExecutors: 0 + scmCheckoutRetryCount: 2 + securityRealm: + ldap: + configurations: + - displayNameAttributeName: uid + groupSearchBase: ou=Groups + groupSearchFilter: (&(objectClass=posixGroup)(cn={0})) + inhibitInferRootDN: false + mailAddressAttributeName: mail + managerDN: cn=admin,dc=kubesphere,dc=io + managerPasswordSecret: admin + rootDN: dc=kubesphere,dc=io + server: ldap://openldap.kubesphere-system.svc:389 + userSearch: (&(objectClass=inetOrgPerson)(|(uid={0})(mail={0}))) + userSearchBase: ou=Users + disableMailAddressResolver: false + disableRolePrefixing: true +unclassified: + gitLabServers: + servers: + - name: https://gitlab.com + serverUrl: https://gitlab.com + kubespheretokenauthglobalconfiguration: + cacheConfiguration: + size: 20 + ttl: 300 + enabled: true + server: http://devops-apiserver.kubesphere-devops-system:9090/ + location: + url: jenkins.devops.kubesphere.local diff --git a/pkg/k8s/testdata/cloud-k8s.yaml b/pkg/k8s/testdata/cloud-k8s.yaml new file mode 100644 index 0000000..6b707c6 --- /dev/null +++ b/pkg/k8s/testdata/cloud-k8s.yaml @@ -0,0 +1,47 @@ +name: "kubernetes" +serverUrl: "https://kubernetes.default" +skipTlsVerify: true +namespace: "kubesphere-devops-worker" +credentialsId: "k8s-service-account" +jenkinsUrl: "http://devops-jenkins.kubesphere-devops-system:80" +jenkinsTunnel: "devops-jenkins-agent.kubesphere-devops-system:50000" +containerCapStr: "4" +connectTimeout: "60" +readTimeout: "60" +maxRequestsPerHostStr: "32" +templates: + - name: "base" + namespace: "kubesphere-devops-worker" + label: "base" + nodeUsageMode: "NORMAL" + idleMinutes: 0 + containers: + - name: "base" + image: "kubesphere/builder-base:v3.2.0" + command: "cat" + args: "" + ttyEnabled: true + privileged: false + resourceRequestCpu: "100m" + resourceLimitCpu: "4000m" + resourceRequestMemory: "100Mi" + resourceLimitMemory: "8192Mi" + - name: "jnlp" + image: "jenkins/jnlp-slave:3.27-1" + command: "jenkins-slave" + args: "^${computer.jnlpmac} ^${computer.name}" + resourceRequestCpu: "50m" + resourceLimitCpu: "500m" + resourceRequestMemory: "400Mi" + resourceLimitMemory: "1536Mi" + workspaceVolume: + emptyDirWorkspaceVolume: + memory: false + volumes: + - hostPathVolume: + hostPath: "/var/run/docker.sock" + mountPath: "/var/run/docker.sock" + - hostPathVolume: + hostPath: "/var/data/jenkins_sonar_cache" + mountPath: "/root/.sonar/cache" + yaml: "spec:\r\n affinity:\r\n nodeAffinity:\r\n preferredDuringSchedulingIgnoredDuringExecution:\r\n - weight: 1\r\n preference:\r\n matchExpressions:\r\n - key: node-role.kubernetes.io/worker\r\n operator: In\r\n values:\r\n - ci\r\n tolerations:\r\n - key: \"node.kubernetes.io/ci\"\r\n operator: \"Exists\"\r\n effect: \"NoSchedule\"\r\n - key: \"node.kubernetes.io/ci\"\r\n operator: \"Exists\"\r\n effect: \"PreferNoSchedule\"\r\n containers:\r\n - name: \"base\"\r\n resources:\r\n requests:\r\n ephemeral-storage: \"1Gi\"\r\n limits:\r\n ephemeral-storage: \"10Gi\"\r\n securityContext:\r\n fsGroup: 1000\r\n " diff --git a/pkg/k8s/testdata/jenkins-pod-template.yaml b/pkg/k8s/testdata/jenkins-pod-template.yaml new file mode 100644 index 0000000..a06a5d3 --- /dev/null +++ b/pkg/k8s/testdata/jenkins-pod-template.yaml @@ -0,0 +1,26 @@ +name: base +namespace: default +label: base +idleMinutes: 0 +containers: +- args: "" + command: cat + image: kubesphere/builder-base:v3.2.0 + name: base + privileged: false + ttyEnabled: true +nodeUsageMode: EXCLUSIVE +volumes: + - hostPathVolume: + hostPath: /var/run/docker.sock + mountPath: /var/run/docker.sock + - hostPathVolume: + hostPath: /var/data/jenkins_go_cache + mountPath: /home/jenkins/go/pkg + - hostPathVolume: + hostPath: /var/data/jenkins_sonar_cache + mountPath: /root/.sonar/cache +yaml: "" +workspaceVolume: + emptyDirWorkspaceVolume: + memory: false diff --git a/pkg/k8s/testdata/k8s-podtemplate-without-annotations.yaml b/pkg/k8s/testdata/k8s-podtemplate-without-annotations.yaml new file mode 100644 index 0000000..6656dea --- /dev/null +++ b/pkg/k8s/testdata/k8s-podtemplate-without-annotations.yaml @@ -0,0 +1,31 @@ +apiVersion: v1 +kind: PodTemplate +metadata: + name: base + namespace: default +template: + metadata: + name: base + spec: + volumes: + - name: docker + hostPath: + path: /var/run/docker.sock + - name: gocache + hostPath: + path: /var/data/jenkins_go_cache + - name: sonarcache + hostPath: + path: /var/data/jenkins_sonar_cache + containers: + - name: base + image: kubesphere/builder-base:v3.2.0 + command: ["cat"] + args: [""] + volumeMounts: + - name: docker + mountPath: /var/run/docker.sock + - name: gocache + mountPath: /home/jenkins/go/pkg + - name: sonarcache + mountPath: /root/.sonar/cache diff --git a/pkg/k8s/testdata/k8s-podtemplate.yaml b/pkg/k8s/testdata/k8s-podtemplate.yaml new file mode 100644 index 0000000..80c511b --- /dev/null +++ b/pkg/k8s/testdata/k8s-podtemplate.yaml @@ -0,0 +1,42 @@ +apiVersion: v1 +kind: PodTemplate +metadata: + name: base + namespace: default + annotations: + jenkins.agent.labels: "go newbase" + inherit.from: "base" + containers.yaml: "fake" +template: + metadata: + name: base + spec: + volumes: + - name: docker + hostPath: + path: /var/run/docker.sock + - name: gocache + hostPath: + path: /var/data/jenkins_go_cache + - name: sonarcache + hostPath: + path: /var/data/jenkins_sonar_cache + containers: + - name: base + image: kubesphere/builder-base:v3.2.0 + command: ["cat"] + args: [""] + resources: + limits: + memory: 8192Mi + cpu: 4000m + requests: + memory: 100Mi + cpu: 100m + volumeMounts: + - name: docker + mountPath: /var/run/docker.sock + - name: gocache + mountPath: /home/jenkins/go/pkg + - name: sonarcache + mountPath: /root/.sonar/cache diff --git a/pkg/k8s/testdata/result-casc.yaml b/pkg/k8s/testdata/result-casc.yaml new file mode 100644 index 0000000..0aaf800 --- /dev/null +++ b/pkg/k8s/testdata/result-casc.yaml @@ -0,0 +1,117 @@ +jenkins: + clouds: + - kubernetes: + connectTimeout: "60" + containerCapStr: "4" + credentialsId: k8s-service-account + jenkinsTunnel: devops-jenkins-agent.kubesphere-devops-system:50000 + jenkinsUrl: http://devops-jenkins.kubesphere-devops-system:80 + maxRequestsPerHostStr: "32" + name: kubernetes + namespace: kubesphere-devops-worker + readTimeout: "60" + serverUrl: https://kubernetes.default + skipTlsVerify: true + templates: + - containers: + - args: "" + command: cat + image: kubesphere/builder-go:v3.2.0 + name: go + privileged: false + resourceLimitCpu: 4000m + resourceLimitMemory: 8192Mi + resourceRequestCpu: 100m + resourceRequestMemory: 100Mi + ttyEnabled: true + - args: ^${computer.jnlpmac} ^${computer.name} + command: jenkins-slave + image: jenkins/jnlp-slave:3.27-1 + name: jnlp + resourceLimitCpu: 500m + resourceLimitMemory: 1536Mi + resourceRequestCpu: 50m + resourceRequestMemory: 400Mi + idleMinutes: 0 + label: go + name: go + namespace: kubesphere-devops-worker + nodeUsageMode: EXCLUSIVE + volumes: + - hostPathVolume: + hostPath: /var/run/docker.sock + mountPath: /var/run/docker.sock + - hostPathVolume: + hostPath: /var/data/jenkins_go_cache + mountPath: /home/jenkins/go/pkg + - hostPathVolume: + hostPath: /var/data/jenkins_sonar_cache + mountPath: /root/.sonar/cache + workspaceVolume: + emptyDirWorkspaceVolume: + memory: false + yaml: "" + - containers: + - args: "" + command: cat + image: kubesphere/builder-base:v3.2.0 + name: base + privileged: false + resourceLimitCpu: "4" + resourceLimitMemory: 8Gi + resourceRequestCpu: 100m + resourceRequestMemory: 100Mi + ttyEnabled: true + idleMinutes: 0 + inheritFrom: base + label: go newbase base + name: base + namespace: default + nodeUsageMode: EXCLUSIVE + volumes: + - hostPathVolume: + hostPath: /var/run/docker.sock + mountPath: /var/run/docker.sock + - hostPathVolume: + hostPath: /var/data/jenkins_go_cache + mountPath: /home/jenkins/go/pkg + - hostPathVolume: + hostPath: /var/data/jenkins_sonar_cache + mountPath: /root/.sonar/cache + workspaceVolume: + emptyDirWorkspaceVolume: + memory: false + yaml: fake + disableRememberMe: true + mode: EXCLUSIVE + numExecutors: 0 + scmCheckoutRetryCount: 2 + securityRealm: + ldap: + configurations: + - displayNameAttributeName: uid + groupSearchBase: ou=Groups + groupSearchFilter: (&(objectClass=posixGroup)(cn={0})) + inhibitInferRootDN: false + mailAddressAttributeName: mail + managerDN: cn=admin,dc=kubesphere,dc=io + managerPasswordSecret: admin + rootDN: dc=kubesphere,dc=io + server: ldap://openldap.kubesphere-system.svc:389 + userSearch: (&(objectClass=inetOrgPerson)(|(uid={0})(mail={0}))) + userSearchBase: ou=Users + disableMailAddressResolver: false + disableRolePrefixing: true +unclassified: + gitLabServers: + servers: + - name: https://gitlab.com + serverUrl: https://gitlab.com + kubespheretokenauthglobalconfiguration: + cacheConfiguration: + size: 20 + ttl: 300 + enabled: true + server: http://devops-apiserver.kubesphere-devops-system:9090/ + location: + url: jenkins.devops.kubesphere.local