diff --git a/api/api-rules/violation_exceptions.list b/api/api-rules/violation_exceptions.list index b69e630afda2809bb4e720b0c2a3ebe024f236cc..3839cffa351e552970e3ad0864d93c028b67726d 100644 --- a/api/api-rules/violation_exceptions.list +++ b/api/api-rules/violation_exceptions.list @@ -40,15 +40,6 @@ API rule violation: names_match,./pkg/apis/devops/v1alpha3,BitbucketServerSource API rule violation: names_match,./pkg/apis/devops/v1alpha3,BitbucketServerSource,ScmId API rule violation: names_match,./pkg/apis/devops/v1alpha3,DiscarderProperty,DaysToKeep API rule violation: names_match,./pkg/apis/devops/v1alpha3,DiscarderProperty,NumToKeep -API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitProviderSource,ApiUri -API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitProviderSource,CloneOption -API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitProviderSource,CredentialId -API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitProviderSource,DiscoverBranches -API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitProviderSource,DiscoverPRFromForks -API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitProviderSource,DiscoverPRFromOrigin -API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitProviderSource,DiscoverTags -API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitProviderSource,RegexFilter -API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitProviderSource,ScmId API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitSource,CloneOption API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitSource,CredentialId API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitSource,DiscoverBranches @@ -64,11 +55,22 @@ API rule violation: names_match,./pkg/apis/devops/v1alpha3,GithubSource,Discover API rule violation: names_match,./pkg/apis/devops/v1alpha3,GithubSource,DiscoverTags API rule violation: names_match,./pkg/apis/devops/v1alpha3,GithubSource,RegexFilter API rule violation: names_match,./pkg/apis/devops/v1alpha3,GithubSource,ScmId +API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitlabSource,ApiUri +API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitlabSource,CloneOption +API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitlabSource,CredentialId +API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitlabSource,DiscoverBranches +API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitlabSource,DiscoverPRFromForks +API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitlabSource,DiscoverPRFromOrigin +API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitlabSource,DiscoverTags +API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitlabSource,RegexFilter +API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitlabSource,ScmId +API rule violation: names_match,./pkg/apis/devops/v1alpha3,GitlabSource,ServerName API rule violation: names_match,./pkg/apis/devops/v1alpha3,MultiBranchJobTrigger,CreateActionJobsToTrigger API rule violation: names_match,./pkg/apis/devops/v1alpha3,MultiBranchJobTrigger,DeleteActionJobsToTrigger API rule violation: names_match,./pkg/apis/devops/v1alpha3,MultiBranchPipeline,BitbucketServerSource API rule violation: names_match,./pkg/apis/devops/v1alpha3,MultiBranchPipeline,GitHubSource API rule violation: names_match,./pkg/apis/devops/v1alpha3,MultiBranchPipeline,GitSource +API rule violation: names_match,./pkg/apis/devops/v1alpha3,MultiBranchPipeline,GitlabSource API rule violation: names_match,./pkg/apis/devops/v1alpha3,MultiBranchPipeline,MultiBranchJobTrigger API rule violation: names_match,./pkg/apis/devops/v1alpha3,MultiBranchPipeline,ScriptPath API rule violation: names_match,./pkg/apis/devops/v1alpha3,MultiBranchPipeline,SingleSvnSource diff --git a/api/ks-openapi-spec/swagger.json b/api/ks-openapi-spec/swagger.json index 25c6e19e160ee2eca913039eb5ee4e94fab0db1e..a5d7b7b20ef49f5d5a893eaecf8aaeaedd31274d 100644 --- a/api/ks-openapi-spec/swagger.json +++ b/api/ks-openapi-spec/swagger.json @@ -3789,6 +3789,49 @@ } } }, + "/kapis/iam.kubesphere.io/v1alpha2/namespace/{namespace}/rolebindings/{rolebinding}": { + "delete": { + "produces": [ + "application/json" + ], + "tags": [ + "Group" + ], + "summary": "Delete rolebinding under namespace.", + "operationId": "DeleteRoleBinding", + "parameters": [ + { + "type": "string", + "description": "workspace name", + "name": "workspace", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "groupbinding name", + "name": "namespace", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "groupbinding name", + "name": "rolebinding", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "ok", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, "/kapis/iam.kubesphere.io/v1alpha2/namespaces/{namespace}/members": { "get": { "produces": [ @@ -4007,6 +4050,49 @@ } } }, + "/kapis/iam.kubesphere.io/v1alpha2/namespaces/{namespace}/rolebindings": { + "post": { + "produces": [ + "application/json" + ], + "tags": [ + "Namespace Role" + ], + "summary": "Create rolebinding in the specified namespace.", + "operationId": "CreateRoleBinding", + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/v1.RoleBinding" + } + } + }, + { + "type": "string", + "description": "namespace", + "name": "namespace", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "ok", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/v1.RoleBinding" + } + } + } + } + } + }, "/kapis/iam.kubesphere.io/v1alpha2/namespaces/{namespace}/roles": { "get": { "produces": [ @@ -4711,6 +4797,42 @@ } } }, + "/kapis/iam.kubesphere.io/v1alpha2/workspaces/{workspace}/groups/{group}/devopsrolebindings": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Group" + ], + "summary": "Retrieve group's rolebindings of all devops projects in the workspace.", + "operationId": "ListGroupDevOpsRoleBindings", + "parameters": [ + { + "type": "string", + "description": "workspace name", + "name": "workspace", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "group name", + "name": "group", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "ok", + "schema": { + "$ref": "#/definitions/api.ListResult" + } + } + } + } + }, "/kapis/iam.kubesphere.io/v1alpha2/workspaces/{workspace}/groups/{group}/groupbindings": { "get": { "produces": [ @@ -4756,7 +4878,7 @@ "Group" ], "summary": "Retrieve group's rolebindings of all projects in the workspace.", - "operationId": "ListGroupsRoleBinding", + "operationId": "ListGroupRoleBindings", "parameters": [ { "type": "string", @@ -4783,7 +4905,7 @@ } } }, - "/kapis/iam.kubesphere.io/v1alpha2/workspaces/{workspace}/groups/{group}/workspacerolebinding": { + "/kapis/iam.kubesphere.io/v1alpha2/workspaces/{workspace}/groups/{group}/workspacerolebindings": { "get": { "produces": [ "application/json" @@ -4792,7 +4914,7 @@ "Group" ], "summary": "Retrieve group's workspacerolebindings of the workspace.", - "operationId": "ListGroupsWorkspaceRoleBinding", + "operationId": "ListGroupWorkspaceRoleBindings", "parameters": [ { "type": "string", @@ -5037,6 +5159,85 @@ } } }, + "/kapis/iam.kubesphere.io/v1alpha2/workspaces/{workspace}/workspacerolebindings": { + "post": { + "produces": [ + "application/json" + ], + "tags": [ + "Group" + ], + "summary": "Create group's workspacerolebindings of the workspace.", + "operationId": "CreateWorkspaceRoleBinding", + "parameters": [ + { + "type": "string", + "description": "workspace name", + "name": "workspace", + "in": "path", + "required": true + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/v1alpha2.WorkspaceRoleBinding" + } + } + } + ], + "responses": { + "200": { + "description": "ok", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/v1alpha2.WorkspaceRoleBinding" + } + } + } + } + } + }, + "/kapis/iam.kubesphere.io/v1alpha2/workspaces/{workspace}/workspacerolebindings/{rolebinding}": { + "delete": { + "produces": [ + "application/json" + ], + "tags": [ + "Group" + ], + "summary": "Delete workspacerolebinding.", + "operationId": "DeleteWorkspaceRoleBinding", + "parameters": [ + { + "type": "string", + "description": "workspace name", + "name": "workspace", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "groupbinding name", + "name": "rolebinding", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "ok", + "schema": { + "$ref": "#/definitions/errors.Error" + } + } + } + } + }, "/kapis/iam.kubesphere.io/v1alpha2/workspaces/{workspace}/workspaceroles": { "get": { "produces": [ @@ -19700,6 +19901,59 @@ } } }, + "v1.RoleBinding": { + "description": "RoleBinding references a role, but does not contain it. It can reference a Role in the same namespace or a ClusterRole in the global namespace. It adds who information via Subjects and namespace information by which namespace it exists in. RoleBindings in a given namespace only have effect in that namespace.", + "required": [ + "roleRef" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "description": "Standard object's metadata.", + "$ref": "#/definitions/v1.ObjectMeta" + }, + "roleRef": { + "description": "RoleRef can reference a Role in the current namespace or a ClusterRole in the global namespace. If the RoleRef cannot be resolved, the Authorizer must return an error.", + "$ref": "#/definitions/v1.RoleRef" + }, + "subjects": { + "description": "Subjects holds references to the objects the role applies to.", + "type": "array", + "items": { + "$ref": "#/definitions/v1.Subject" + } + } + } + }, + "v1.RoleRef": { + "description": "RoleRef contains information that points to the role being used", + "required": [ + "apiGroup", + "kind", + "name" + ], + "properties": { + "apiGroup": { + "description": "APIGroup is the group for the resource being referenced", + "type": "string" + }, + "kind": { + "description": "Kind is the type of resource being referenced", + "type": "string" + }, + "name": { + "description": "Name is the name of resource being referenced", + "type": "string" + } + } + }, "v1.RollingUpdateDaemonSet": { "description": "Spec to control the desired behavior of daemon set rolling update.", "properties": { @@ -20342,6 +20596,31 @@ } } }, + "v1.Subject": { + "description": "Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, or a value for non-objects such as user and group names.", + "required": [ + "kind", + "name" + ], + "properties": { + "apiGroup": { + "description": "APIGroup holds the API group of the referenced subject. Defaults to \"\" for ServiceAccount subjects. Defaults to \"rbac.authorization.k8s.io\" for User and Group subjects.", + "type": "string" + }, + "kind": { + "description": "Kind of object being referenced. Values defined by this API group are \"User\", \"Group\", and \"ServiceAccount\". If the Authorizer does not recognized the kind value, the Authorizer should report an error.", + "type": "string" + }, + "name": { + "description": "Name of the object being referenced.", + "type": "string" + }, + "namespace": { + "description": "Namespace of the referenced object. If the object kind is non-namespace, such as \"User\" or \"Group\", and this value is not empty the Authorizer should report an error.", + "type": "string" + } + } + }, "v1.Sysctl": { "description": "Sysctl defines a kernel parameter to be set", "required": [ @@ -21266,10 +21545,10 @@ }, "v1alpha2.NodeSummary": { "required": [ - "id", - "label", "labelMinor", - "rank" + "rank", + "id", + "label" ], "properties": { "adjacency": { @@ -21567,6 +21846,33 @@ } } }, + "v1alpha2.WorkspaceRoleBinding": { + "required": [ + "roleRef" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "$ref": "#/definitions/v1.ObjectMeta" + }, + "roleRef": { + "$ref": "#/definitions/v1.RoleRef" + }, + "subjects": { + "type": "array", + "items": { + "$ref": "#/definitions/v1.Subject" + } + } + } + }, "v1alpha2.WorkspaceTemplate": { "properties": { "apiVersion": { @@ -21888,6 +22194,60 @@ } } }, + "v1alpha3.GitlabSource": { + "properties": { + "api_uri": { + "description": "The api url can specify the location of the gitlab apiserver.For private cloud configuration", + "type": "string" + }, + "credential_id": { + "description": "credential id to access gitlab source", + "type": "string" + }, + "discover_branches": { + "description": "Discover branch configuration", + "type": "integer", + "format": "int32" + }, + "discover_pr_from_forks": { + "description": "Discover fork PR configuration", + "$ref": "#/definitions/v1alpha3.DiscoverPRFromForks" + }, + "discover_pr_from_origin": { + "description": "Discover origin PR configuration", + "type": "integer", + "format": "int32" + }, + "discover_tags": { + "description": "Discover tags configuration", + "type": "boolean" + }, + "git_clone_option": { + "description": "advavced git clone options", + "$ref": "#/definitions/v1alpha3.GitCloneOption" + }, + "owner": { + "description": "owner of gitlab repo", + "type": "string" + }, + "regex_filter": { + "description": "Regex used to match the name of the branch that needs to be run", + "type": "string" + }, + "repo": { + "description": "repo name of gitlab repo", + "type": "string" + }, + "scm_id": { + "description": "uid of scm", + "type": "string" + }, + "server_name": { + "description": "the name of gitlab server which was configured in jenkins", + "type": "string" + } + } + }, "v1alpha3.MultiBranchJobTrigger": { "properties": { "create_action_job_to_trigger": { @@ -21927,6 +22287,10 @@ "description": "github scm define", "$ref": "#/definitions/v1alpha3.GithubSource" }, + "gitlab_source": { + "description": "gitlab scm define", + "$ref": "#/definitions/v1alpha3.GitlabSource" + }, "multibranch_job_trigger": { "description": "Pipeline tasks that need to be triggered when branch creation/deletion", "$ref": "#/definitions/v1alpha3.MultiBranchJobTrigger" diff --git a/config/crds/devops.kubesphere.io_pipelines.yaml b/config/crds/devops.kubesphere.io_pipelines.yaml index 830b656611e5c06571cc600d70f2a4faf2221fb9..4796f7a5f2497371a281a0b239ad7576a56dfbdd 100644 --- a/config/crds/devops.kubesphere.io_pipelines.yaml +++ b/config/crds/devops.kubesphere.io_pipelines.yaml @@ -145,6 +145,45 @@ spec: scm_id: type: string type: object + gitlab_source: + properties: + api_uri: + type: string + credential_id: + type: string + discover_branches: + type: integer + discover_pr_from_forks: + properties: + strategy: + type: integer + trust: + type: integer + type: object + discover_pr_from_origin: + type: integer + discover_tags: + type: boolean + git_clone_option: + properties: + depth: + type: integer + shallow: + type: boolean + timeout: + type: integer + type: object + owner: + type: string + regex_filter: + type: string + repo: + type: string + scm_id: + type: string + server_name: + type: string + type: object multibranch_job_trigger: properties: create_action_job_to_trigger: diff --git a/go.mod b/go.mod index 3da56712697047284f170e262ff063ad12a96f4a..6cb23d2f2f8fdd7874fe8ed613e4875dff34057e 100644 --- a/go.mod +++ b/go.mod @@ -51,6 +51,7 @@ require ( github.com/kubernetes-csi/external-snapshotter/v2 v2.1.0 github.com/kubesphere/sonargo v0.0.2 github.com/lib/pq v1.2.0 // indirect + github.com/mitchellh/mapstructure v1.2.2 github.com/onsi/ginkgo v1.12.0 github.com/onsi/gomega v1.9.0 github.com/open-policy-agent/opa v0.18.0 diff --git a/pkg/apis/devops/v1alpha3/pipeline_types.go b/pkg/apis/devops/v1alpha3/pipeline_types.go index ba3494a49d01c1f11aae6d261c92a969f69659a4..198a3d23d9f03337c255c3fed2a7964601c75b6b 100644 --- a/pkg/apis/devops/v1alpha3/pipeline_types.go +++ b/pkg/apis/devops/v1alpha3/pipeline_types.go @@ -81,6 +81,15 @@ const ( MultiBranchPipelineType = "multi-branch-pipeline" ) +const ( + SourceType_SVN = "svn" + SourceType_Git = "git" + SourceType_SingleSVN = "single_svn" + SourceType_Gitlab = "gitlab" + SourceType_Github = "github" + SourceType_Bitbucket = "bitbucket_server" +) + type NoScmPipeline struct { Name string `json:"name" description:"name of pipeline"` Description string `json:"description,omitempty" description:"description of pipeline"` @@ -100,6 +109,7 @@ type MultiBranchPipeline struct { SourceType string `json:"source_type" description:"type of scm, such as github/git/svn"` GitSource *GitSource `json:"git_source,omitempty" description:"git scm define"` GitHubSource *GithubSource `json:"github_source,omitempty" description:"github scm define"` + GitlabSource *GitlabSource `json:"gitlab_source,omitempty" description:"gitlab scm define"` SvnSource *SvnSource `json:"svn_source,omitempty" description:"multi branch svn scm define"` SingleSvnSource *SingleSvnSource `json:"single_svn_source,omitempty" description:"single branch svn scm define"` BitbucketServerSource *BitbucketServerSource `json:"bitbucket_server_source,omitempty" description:"bitbucket server scm defile"` @@ -132,6 +142,21 @@ type GithubSource struct { RegexFilter string `json:"regex_filter,omitempty" mapstructure:"regex_filter" description:"Regex used to match the name of the branch that needs to be run"` } +type GitlabSource struct { + ScmId string `json:"scm_id,omitempty" description:"uid of scm"` + Owner string `json:"owner,omitempty" mapstructure:"owner" description:"owner of gitlab repo"` + Repo string `json:"repo,omitempty" mapstructure:"repo" description:"repo name of gitlab repo"` + ServerName string `json:"server_name,omitempty" description:"the name of gitlab server which was configured in jenkins"` + CredentialId string `json:"credential_id,omitempty" mapstructure:"credential_id" description:"credential id to access gitlab source"` + ApiUri string `json:"api_uri,omitempty" mapstructure:"api_uri" description:"The api url can specify the location of the gitlab apiserver.For private cloud configuration"` + DiscoverBranches int `json:"discover_branches,omitempty" mapstructure:"discover_branches" description:"Discover branch configuration"` + DiscoverPRFromOrigin int `json:"discover_pr_from_origin,omitempty" mapstructure:"discover_pr_from_origin" description:"Discover origin PR configuration"` + DiscoverPRFromForks *DiscoverPRFromForks `json:"discover_pr_from_forks,omitempty" mapstructure:"discover_pr_from_forks" description:"Discover fork PR configuration"` + DiscoverTags bool `json:"discover_tags,omitempty" mapstructure:"discover_tags" description:"Discover tags configuration"` + CloneOption *GitCloneOption `json:"git_clone_option,omitempty" mapstructure:"git_clone_option" description:"advavced git clone options"` + RegexFilter string `json:"regex_filter,omitempty" mapstructure:"regex_filter" description:"Regex used to match the name of the branch that needs to be run"` +} + type BitbucketServerSource struct { ScmId string `json:"scm_id,omitempty" description:"uid of scm"` Owner string `json:"owner,omitempty" mapstructure:"owner" description:"owner of github repo"` diff --git a/pkg/apis/devops/v1alpha3/zz_generated.deepcopy.go b/pkg/apis/devops/v1alpha3/zz_generated.deepcopy.go index d82684e7faa1f1aa111ecfe07c93efa3f0a9da4d..09ea8add7ff6034d501c53b886c042b04a99f5c8 100644 --- a/pkg/apis/devops/v1alpha3/zz_generated.deepcopy.go +++ b/pkg/apis/devops/v1alpha3/zz_generated.deepcopy.go @@ -228,6 +228,31 @@ func (in *GithubSource) DeepCopy() *GithubSource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GitlabSource) DeepCopyInto(out *GitlabSource) { + *out = *in + if in.DiscoverPRFromForks != nil { + in, out := &in.DiscoverPRFromForks, &out.DiscoverPRFromForks + *out = new(DiscoverPRFromForks) + **out = **in + } + if in.CloneOption != nil { + in, out := &in.CloneOption, &out.CloneOption + *out = new(GitCloneOption) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitlabSource. +func (in *GitlabSource) DeepCopy() *GitlabSource { + if in == nil { + return nil + } + out := new(GitlabSource) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MultiBranchJobTrigger) DeepCopyInto(out *MultiBranchJobTrigger) { *out = *in @@ -266,6 +291,11 @@ func (in *MultiBranchPipeline) DeepCopyInto(out *MultiBranchPipeline) { *out = new(GithubSource) (*in).DeepCopyInto(*out) } + if in.GitlabSource != nil { + in, out := &in.GitlabSource, &out.GitlabSource + *out = new(GitlabSource) + (*in).DeepCopyInto(*out) + } if in.SvnSource != nil { in, out := &in.SvnSource, &out.SvnSource *out = new(SvnSource) diff --git a/pkg/kapis/devops/v1alpha3/handler.go b/pkg/kapis/devops/v1alpha3/handler.go index 060effc72976db0672e693083b32a0ab0ac93a1c..0de11e8e16bb9e3d57a52a7ecb29270a96441dd7 100644 --- a/pkg/kapis/devops/v1alpha3/handler.go +++ b/pkg/kapis/devops/v1alpha3/handler.go @@ -255,6 +255,7 @@ func (h *devopsHandler) DeletePipeline(request *restful.Request, response *restf devops := request.PathParameter("devops") pipeline := request.PathParameter("pipeline") + klog.V(7).Infof("ready to delete pipeline %s/%s", devops, pipeline) err := h.devops.DeletePipelineObj(devops, pipeline) if err != nil { diff --git a/pkg/simple/client/devops/jenkins/internal/gitlab.go b/pkg/simple/client/devops/jenkins/internal/gitlab.go new file mode 100644 index 0000000000000000000000000000000000000000..7ccebacaf902c7719f6666414b9a58cbabf4edf3 --- /dev/null +++ b/pkg/simple/client/devops/jenkins/internal/gitlab.go @@ -0,0 +1,161 @@ +package internal + +import ( + "github.com/beevik/etree" + devopsv1alpha3 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha3" + "strconv" + "strings" +) + +func AppendGitlabSourceToEtree(source *etree.Element, gitSource *devopsv1alpha3.GitlabSource) { + source.CreateAttr("class", "io.jenkins.plugins.gitlabbranchsource.GitLabSCMSource") + source.CreateAttr("plugin", "gitlab-branch-source") + source.CreateElement("id").SetText(gitSource.ScmId) + source.CreateElement("gitlab-7069").SetText(gitSource.ServerName) + source.CreateElement("credentialsId").SetText(gitSource.CredentialId) + source.CreateElement("projectOwner").SetText(gitSource.Owner) + source.CreateElement("projectPath").SetText(gitSource.Repo) + if gitSource.ApiUri != "" { + source.CreateElement("apiUri").SetText(gitSource.ApiUri) + } + traits := source.CreateElement("traits") + if gitSource.DiscoverBranches != 0 { + traits.CreateElement("io.jenkins.plugins.gitlabbranchsource.BranchDiscoveryTrait"). + CreateElement("strategyId").SetText(strconv.Itoa(gitSource.DiscoverBranches)) + } + if gitSource.DiscoverTags { + traits.CreateElement("io.jenkins.plugins.gitlabbranchsource.TagDiscoveryTrait") + } + if gitSource.DiscoverPRFromOrigin != 0 { + traits.CreateElement("io.jenkins.plugins.gitlabbranchsource.OriginMergeRequestDiscoveryTrait"). + CreateElement("strategyId").SetText(strconv.Itoa(gitSource.DiscoverPRFromOrigin)) + } + if gitSource.DiscoverPRFromForks != nil { + forkTrait := traits.CreateElement("io.jenkins.plugins.gitlabbranchsource.ForkMergeRequestDiscoveryTrait") + forkTrait.CreateElement("strategyId").SetText(strconv.Itoa(gitSource.DiscoverPRFromForks.Strategy)) + trustClass := "io.jenkins.plugins.gitlabbranchsource.ForkMergeRequestDiscoveryTrait$" + switch gitSource.DiscoverPRFromForks.Trust { + case 1: + trustClass += "TrustMembers" // it's difference with GitHub + case 2: + trustClass += "TrustEveryone" + case 3: + trustClass += "TrustPermission" + case 4: + trustClass += "TrustNobody" + default: + } + forkTrait.CreateElement("trust").CreateAttr("class", trustClass) + } + if gitSource.CloneOption != nil { + cloneExtension := traits.CreateElement("jenkins.plugins.git.traits.CloneOptionTrait").CreateElement("extension") + cloneExtension.CreateAttr("class", "hudson.plugins.git.extensions.impl.CloneOption") + cloneExtension.CreateElement("shallow").SetText(strconv.FormatBool(gitSource.CloneOption.Shallow)) + cloneExtension.CreateElement("noTags").SetText(strconv.FormatBool(false)) + cloneExtension.CreateElement("honorRefspec").SetText(strconv.FormatBool(true)) + cloneExtension.CreateElement("reference") + if gitSource.CloneOption.Timeout >= 0 { + cloneExtension.CreateElement("timeout").SetText(strconv.Itoa(gitSource.CloneOption.Timeout)) + } else { + cloneExtension.CreateElement("timeout").SetText(strconv.Itoa(10)) + } + + if gitSource.CloneOption.Depth >= 0 { + cloneExtension.CreateElement("depth").SetText(strconv.Itoa(gitSource.CloneOption.Depth)) + } else { + cloneExtension.CreateElement("depth").SetText(strconv.Itoa(1)) + } + } + if gitSource.RegexFilter != "" { + regexTraits := traits.CreateElement("jenkins.scm.impl.trait.RegexSCMHeadFilterTrait") + regexTraits.CreateAttr("plugin", "scm-api@2.4.0") + regexTraits.CreateElement("regex").SetText(gitSource.RegexFilter) + } + return +} + +func GetGitlabSourceFromEtree(source *etree.Element) (gitSource *devopsv1alpha3.GitlabSource) { + gitSource = &devopsv1alpha3.GitlabSource{} + if credential := source.SelectElement("credentialsId"); credential != nil { + gitSource.CredentialId = credential.Text() + } + if serverName := source.SelectElement("serverName"); serverName != nil { + gitSource.ServerName = serverName.Text() + } + if repoOwner := source.SelectElement("repoOwner"); repoOwner != nil { + gitSource.Owner = repoOwner.Text() + } + if repository := source.SelectElement("repository"); repository != nil { + gitSource.Repo = repository.Text() + } + if apiUri := source.SelectElement("apiUri"); apiUri != nil { + gitSource.ApiUri = apiUri.Text() + } + traits := source.SelectElement("traits") + if branchDiscoverTrait := traits.SelectElement( + "io.jenkins.plugins.gitlabbranchsource.BranchDiscoveryTrait"); branchDiscoverTrait != nil { + strategyId, _ := strconv.Atoi(branchDiscoverTrait.SelectElement("strategyId").Text()) + gitSource.DiscoverBranches = strategyId + } + if tagDiscoverTrait := traits.SelectElement( + "io.jenkins.plugins.gitlabbranchsource.TagDiscoveryTrait"); tagDiscoverTrait != nil { + gitSource.DiscoverTags = true + } + if originPRDiscoverTrait := traits.SelectElement( + "io.jenkins.plugins.gitlabbranchsource.OriginMergeRequestDiscoveryTrait"); originPRDiscoverTrait != nil { + strategyId, _ := strconv.Atoi(originPRDiscoverTrait.SelectElement("strategyId").Text()) + gitSource.DiscoverPRFromOrigin = strategyId + } + if forkPRDiscoverTrait := traits.SelectElement( + "io.jenkins.plugins.gitlabbranchsource.ForkMergeRequestDiscoveryTrait"); forkPRDiscoverTrait != nil { + strategyId, _ := strconv.Atoi(forkPRDiscoverTrait.SelectElement("strategyId").Text()) + trustClass := forkPRDiscoverTrait.SelectElement("trust").SelectAttr("class").Value + trust := strings.Split(trustClass, "$") + switch trust[1] { + case "TrustMembers": // it's difference with GitHub + gitSource.DiscoverPRFromForks = &devopsv1alpha3.DiscoverPRFromForks{ + Strategy: strategyId, + Trust: 1, + } + case "TrustEveryone": + gitSource.DiscoverPRFromForks = &devopsv1alpha3.DiscoverPRFromForks{ + Strategy: strategyId, + Trust: 2, + } + case "TrustPermission": + gitSource.DiscoverPRFromForks = &devopsv1alpha3.DiscoverPRFromForks{ + Strategy: strategyId, + Trust: 3, + } + case "TrustNobody": + gitSource.DiscoverPRFromForks = &devopsv1alpha3.DiscoverPRFromForks{ + Strategy: strategyId, + Trust: 4, + } + } + if cloneTrait := traits.SelectElement( + "jenkins.plugins.git.traits.CloneOptionTrait"); cloneTrait != nil { + if cloneExtension := cloneTrait.SelectElement( + "extension"); cloneExtension != nil { + gitSource.CloneOption = &devopsv1alpha3.GitCloneOption{} + if value, err := strconv.ParseBool(cloneExtension.SelectElement("shallow").Text()); err == nil { + gitSource.CloneOption.Shallow = value + } + if value, err := strconv.ParseInt(cloneExtension.SelectElement("timeout").Text(), 10, 32); err == nil { + gitSource.CloneOption.Timeout = int(value) + } + if value, err := strconv.ParseInt(cloneExtension.SelectElement("depth").Text(), 10, 32); err == nil { + gitSource.CloneOption.Depth = int(value) + } + } + } + + if regexTrait := traits.SelectElement( + "jenkins.scm.impl.trait.RegexSCMHeadFilterTrait"); regexTrait != nil { + if regex := regexTrait.SelectElement("regex"); regex != nil { + gitSource.RegexFilter = regex.Text() + } + } + } + return +} diff --git a/pkg/simple/client/devops/jenkins/pipeline_internal.go b/pkg/simple/client/devops/jenkins/pipeline_internal.go index 2719338a1540a821ca191bbac37a3232f08a0c19..30722324df0540a6ea4c5ba0856be30e7aa11e46 100644 --- a/pkg/simple/client/devops/jenkins/pipeline_internal.go +++ b/pkg/simple/client/devops/jenkins/pipeline_internal.go @@ -20,6 +20,7 @@ import ( "fmt" "github.com/beevik/etree" devopsv1alpha3 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha3" + "kubesphere.io/kubesphere/pkg/simple/client/devops/jenkins/internal" "strconv" "strings" "time" @@ -816,6 +817,8 @@ func createMultiBranchPipelineConfigXml(projectName string, pipeline *devopsv1al appendGitSourceToEtree(source, pipeline.GitSource) case "github": appendGithubSourceToEtree(source, pipeline.GitHubSource) + case "gitlab": + internal.AppendGitlabSourceToEtree(source, pipeline.GitlabSource) case "svn": appendSvnSourceToEtree(source, pipeline.SvnSource) case "single_svn": @@ -824,7 +827,7 @@ func createMultiBranchPipelineConfigXml(projectName string, pipeline *devopsv1al appendBitbucketServerSourceToEtree(source, pipeline.BitbucketServerSource) default: - return "", fmt.Errorf("unsupport source type") + return "", fmt.Errorf("unsupport source type: %s", pipeline.SourceType) } factory := project.CreateElement("factory") @@ -881,21 +884,24 @@ func parseMultiBranchPipelineConfigXml(config string) (*devopsv1alpha3.MultiBran switch source.SelectAttr("class").Value { case "org.jenkinsci.plugins.github_branch_source.GitHubSCMSource": pipeline.GitHubSource = getGithubSourcefromEtree(source) - pipeline.SourceType = "github" + pipeline.SourceType = devopsv1alpha3.SourceType_Github case "com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMSource": pipeline.BitbucketServerSource = getBitbucketServerSourceFromEtree(source) - pipeline.SourceType = "bitbucket_server" + pipeline.SourceType = devopsv1alpha3.SourceType_Bitbucket + case "io.jenkins.plugins.gitlabbranchsource.GitLabSCMSource": + pipeline.GitlabSource = internal.GetGitlabSourceFromEtree(source) + pipeline.SourceType = devopsv1alpha3.SourceType_Gitlab case "jenkins.plugins.git.GitSCMSource": - pipeline.SourceType = "git" + pipeline.SourceType = devopsv1alpha3.SourceType_Git pipeline.GitSource = getGitSourcefromEtree(source) case "jenkins.scm.impl.SingleSCMSource": - pipeline.SourceType = "single_svn" + pipeline.SourceType = devopsv1alpha3.SourceType_SingleSVN pipeline.SingleSvnSource = getSingleSvnSourceFromEtree(source) case "jenkins.scm.impl.subversion.SubversionSCMSource": - pipeline.SourceType = "svn" + pipeline.SourceType = devopsv1alpha3.SourceType_SVN pipeline.SvnSource = getSvnSourcefromEtree(source) } }