devops refactor (#1739)
* add devops client interface Signed-off-by: runzexia <runzexia@yunify.com> * direct return jenkins Signed-off-by: runzexia <runzexia@yunify.com> * add some interface Signed-off-by: runzexia <runzexia@yunify.com> * update Signed-off-by: runzexia <runzexia@yunify.com> * update interface Signed-off-by: runzexia <runzexia@yunify.com> * update Signed-off-by: runzexia <runzexia@yunify.com> * credential op structs Signed-off-by: runzexia <runzexia@yunify.com> * status Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * update interface Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * credential handler Signed-off-by: runzexia <runzexia@yunify.com> * update devopsoperator func Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * get build sonar Signed-off-by: runzexia <runzexia@yunify.com> * sonar handler * mv code to cilent Signed-off-by: runzexia <runzexia@yunify.com> * update Signed-off-by: runzexia <runzexia@yunify.com> * project member handler Signed-off-by: runzexia <runzexia@yunify.com> * update pipeline operator interface Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add tenant devops handler Signed-off-by: runzexia <runzexia@yunify.com> * update merge Signed-off-by: runzexia <runzexia@yunify.com> * clean Signed-off-by: runzexia <runzexia@yunify.com> * fmt Signed-off-by: runzexia <runzexia@yunify.com> * update ListPipelineRuns Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * complate pipelineOperator interface Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * update HttpParameters Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add pipeline steps interface Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * update pipeline GetNodesDetail Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add s2i api Signed-off-by: runzexia <runzexia@yunify.com> * add branch pipeline interface and update handler Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add scan branch interface and update handler Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add common interface and update handler Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add SCM interface and update handler Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add handler Signed-off-by: runzexia <runzexia@yunify.com> * add fake s3 Signed-off-by: runzexia <runzexia@yunify.com> * add webhook&check interface and update handler Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * clean Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * clean Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * format Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add some func Signed-off-by: runzexia <runzexia@yunify.com> * clean code Signed-off-by: runzexia <runzexia@yunify.com> * implement interface Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * fix interface GetBranchArtifacts Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add s2ibinary upload test Signed-off-by: runzexia <runzexia@yunify.com> * tenant devops Signed-off-by: runzexia <runzexia@yunify.com> * update tenant Signed-off-by: runzexia <runzexia@yunify.com> * fake Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add some unit test Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * add devops tenant handler Signed-off-by: runzexia <runzexia@yunify.com> * status Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * status Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * status Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * update fake test Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * update unit test and fake data Signed-off-by: zhuxiaoyang <sunzhu@yunify.com> * update Co-authored-by: Xiaoyang Zhu <sunzhu@yunify.com>
This commit is contained in:
@@ -7,7 +7,7 @@ import (
|
|||||||
cliflag "k8s.io/component-base/cli/flag"
|
cliflag "k8s.io/component-base/cli/flag"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
kubesphereconfig "kubesphere.io/kubesphere/pkg/server/config"
|
kubesphereconfig "kubesphere.io/kubesphere/pkg/server/config"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
"kubesphere.io/kubesphere/pkg/simple/client/devops/jenkins"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
|
"kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/s3"
|
"kubesphere.io/kubesphere/pkg/simple/client/s3"
|
||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
|
|
||||||
type KubeSphereControllerManagerOptions struct {
|
type KubeSphereControllerManagerOptions struct {
|
||||||
KubernetesOptions *k8s.KubernetesOptions
|
KubernetesOptions *k8s.KubernetesOptions
|
||||||
DevopsOptions *devops.Options
|
DevopsOptions *jenkins.Options
|
||||||
S3Options *s3.Options
|
S3Options *s3.Options
|
||||||
OpenPitrixOptions *openpitrix.Options
|
OpenPitrixOptions *openpitrix.Options
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ type KubeSphereControllerManagerOptions struct {
|
|||||||
func NewKubeSphereControllerManagerOptions() *KubeSphereControllerManagerOptions {
|
func NewKubeSphereControllerManagerOptions() *KubeSphereControllerManagerOptions {
|
||||||
s := &KubeSphereControllerManagerOptions{
|
s := &KubeSphereControllerManagerOptions{
|
||||||
KubernetesOptions: k8s.NewKubernetesOptions(),
|
KubernetesOptions: k8s.NewKubernetesOptions(),
|
||||||
DevopsOptions: devops.NewDevopsOptions(),
|
DevopsOptions: jenkins.NewDevopsOptions(),
|
||||||
S3Options: s3.NewS3Options(),
|
S3Options: s3.NewS3Options(),
|
||||||
OpenPitrixOptions: openpitrix.NewOpenPitrixOptions(),
|
OpenPitrixOptions: openpitrix.NewOpenPitrixOptions(),
|
||||||
LeaderElection: &leaderelection.LeaderElectionConfig{
|
LeaderElection: &leaderelection.LeaderElectionConfig{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
cliflag "k8s.io/component-base/cli/flag"
|
cliflag "k8s.io/component-base/cli/flag"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
genericoptions "kubesphere.io/kubesphere/pkg/server/options"
|
genericoptions "kubesphere.io/kubesphere/pkg/server/options"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
"kubesphere.io/kubesphere/pkg/simple/client/devops/jenkins"
|
||||||
esclient "kubesphere.io/kubesphere/pkg/simple/client/elasticsearch"
|
esclient "kubesphere.io/kubesphere/pkg/simple/client/elasticsearch"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
|
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
|
||||||
@@ -21,7 +21,7 @@ type ServerRunOptions struct {
|
|||||||
ConfigFile string
|
ConfigFile string
|
||||||
GenericServerRunOptions *genericoptions.ServerRunOptions
|
GenericServerRunOptions *genericoptions.ServerRunOptions
|
||||||
KubernetesOptions *k8s.KubernetesOptions
|
KubernetesOptions *k8s.KubernetesOptions
|
||||||
DevopsOptions *devops.Options
|
DevopsOptions *jenkins.Options
|
||||||
SonarQubeOptions *sonarqube.Options
|
SonarQubeOptions *sonarqube.Options
|
||||||
ServiceMeshOptions *servicemesh.Options
|
ServiceMeshOptions *servicemesh.Options
|
||||||
MySQLOptions *mysql.Options
|
MySQLOptions *mysql.Options
|
||||||
@@ -36,7 +36,7 @@ func NewServerRunOptions() *ServerRunOptions {
|
|||||||
s := ServerRunOptions{
|
s := ServerRunOptions{
|
||||||
GenericServerRunOptions: genericoptions.NewServerRunOptions(),
|
GenericServerRunOptions: genericoptions.NewServerRunOptions(),
|
||||||
KubernetesOptions: k8s.NewKubernetesOptions(),
|
KubernetesOptions: k8s.NewKubernetesOptions(),
|
||||||
DevopsOptions: devops.NewDevopsOptions(),
|
DevopsOptions: jenkins.NewDevopsOptions(),
|
||||||
SonarQubeOptions: sonarqube.NewSonarQubeOptions(),
|
SonarQubeOptions: sonarqube.NewSonarQubeOptions(),
|
||||||
ServiceMeshOptions: servicemesh.NewServiceMeshOptions(),
|
ServiceMeshOptions: servicemesh.NewServiceMeshOptions(),
|
||||||
MySQLOptions: mysql.NewMySQLOptions(),
|
MySQLOptions: mysql.NewMySQLOptions(),
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -99,7 +99,7 @@ require (
|
|||||||
k8s.io/component-base v0.17.0
|
k8s.io/component-base v0.17.0
|
||||||
k8s.io/klog v1.0.0
|
k8s.io/klog v1.0.0
|
||||||
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a
|
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a
|
||||||
k8s.io/kubectl v0.17.0
|
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f // indirect
|
||||||
kubesphere.io/im v0.1.0 // indirect
|
kubesphere.io/im v0.1.0 // indirect
|
||||||
openpitrix.io/iam v0.1.0 // indirect
|
openpitrix.io/iam v0.1.0 // indirect
|
||||||
openpitrix.io/openpitrix v0.4.1-0.20190920134345-4d2be6e4965c
|
openpitrix.io/openpitrix v0.4.1-0.20190920134345-4d2be6e4965c
|
||||||
|
|||||||
25
go.sum
25
go.sum
@@ -18,8 +18,6 @@ github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VY
|
|||||||
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
|
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
|
||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU=
|
|
||||||
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
|
|
||||||
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||||
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||||
github.com/Microsoft/go-winio v0.4.12 h1:xAfWHN1IrQ0NJ9TBC0KBZoqLjzDTr1ML+4MywiUOryc=
|
github.com/Microsoft/go-winio v0.4.12 h1:xAfWHN1IrQ0NJ9TBC0KBZoqLjzDTr1ML+4MywiUOryc=
|
||||||
@@ -62,8 +60,6 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dR
|
|||||||
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
|
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
|
||||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8=
|
|
||||||
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
|
|
||||||
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
|
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
|
||||||
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
@@ -81,7 +77,6 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc
|
|||||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE=
|
|
||||||
github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
|
github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
|
||||||
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
|
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
|
||||||
github.com/denisenkom/go-mssqldb v0.0.0-20190204142019-df6d76eb9289/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc=
|
github.com/denisenkom/go-mssqldb v0.0.0-20190204142019-df6d76eb9289/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc=
|
||||||
@@ -120,8 +115,6 @@ github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3
|
|||||||
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
|
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
|
||||||
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
|
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
|
||||||
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM=
|
|
||||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
|
|
||||||
github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
|
github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
|
||||||
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
|
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
|
||||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||||
@@ -198,9 +191,6 @@ github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
|
|||||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho=
|
|
||||||
github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkYFkPcDKwRXegd+iM6E7matEszMG5HhwytU8=
|
|
||||||
github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk=
|
|
||||||
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
|
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||||
@@ -296,9 +286,6 @@ github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
|
|||||||
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
|
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
|
||||||
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
||||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
|
|
||||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
|
|
||||||
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
|
|
||||||
github.com/lucas-clemente/quic-go v0.11.1 h1:zasajC848Dqq/+WqfqBCkmPw+YHNe1MBts/z7y7nXf4=
|
github.com/lucas-clemente/quic-go v0.11.1 h1:zasajC848Dqq/+WqfqBCkmPw+YHNe1MBts/z7y7nXf4=
|
||||||
github.com/lucas-clemente/quic-go v0.11.1/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw=
|
github.com/lucas-clemente/quic-go v0.11.1/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw=
|
||||||
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
||||||
@@ -323,8 +310,6 @@ github.com/miekg/dns v1.1.9 h1:OIdC9wT96RzuZMf2PfKRhFgsStHUUBZLM/lo1LqiM9E=
|
|||||||
github.com/miekg/dns v1.1.9/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
github.com/miekg/dns v1.1.9/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
|
|
||||||
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
|
||||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
@@ -433,7 +418,6 @@ github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70
|
|||||||
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8=
|
|
||||||
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
|
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
|
||||||
@@ -535,8 +519,6 @@ k8s.io/apimachinery v0.0.0-20191028221656-72ed19daf4bb h1:ZUNsbuPdXWrj0rZziRfCWc
|
|||||||
k8s.io/apimachinery v0.0.0-20191028221656-72ed19daf4bb/go.mod h1:llRdnznGEAqC3DcNm6yEj472xaFVfLM7hnYofMb12tQ=
|
k8s.io/apimachinery v0.0.0-20191028221656-72ed19daf4bb/go.mod h1:llRdnznGEAqC3DcNm6yEj472xaFVfLM7hnYofMb12tQ=
|
||||||
k8s.io/apiserver v0.0.0-20191114103151-9ca1dc586682 h1:+FvAOv/4JyYgZanQI8h+UW9FCmLzyEz7EZunuET6p5g=
|
k8s.io/apiserver v0.0.0-20191114103151-9ca1dc586682 h1:+FvAOv/4JyYgZanQI8h+UW9FCmLzyEz7EZunuET6p5g=
|
||||||
k8s.io/apiserver v0.0.0-20191114103151-9ca1dc586682/go.mod h1:Idob8Va6/sMX5SmwPLsU0pdvFlkwxuJ5x+fXMG8NbKE=
|
k8s.io/apiserver v0.0.0-20191114103151-9ca1dc586682/go.mod h1:Idob8Va6/sMX5SmwPLsU0pdvFlkwxuJ5x+fXMG8NbKE=
|
||||||
k8s.io/cli-runtime v0.17.0 h1:XEuStbJBHCQlEKFyTQmceDKEWOSYHZkcYWKp3SsQ9Hk=
|
|
||||||
k8s.io/cli-runtime v0.17.0/go.mod h1:1E5iQpMODZq2lMWLUJELwRu2MLWIzwvMgDBpn3Y81Qo=
|
|
||||||
k8s.io/client-go v0.0.0-20191114101535-6c5935290e33 h1:07mhG/2oEoo3N+sHVOo0L9PJ/qvbk3N5n2dj8IWefnQ=
|
k8s.io/client-go v0.0.0-20191114101535-6c5935290e33 h1:07mhG/2oEoo3N+sHVOo0L9PJ/qvbk3N5n2dj8IWefnQ=
|
||||||
k8s.io/client-go v0.0.0-20191114101535-6c5935290e33/go.mod h1:4L/zQOBkEf4pArQJ+CMk1/5xjA30B5oyWv+Bzb44DOw=
|
k8s.io/client-go v0.0.0-20191114101535-6c5935290e33/go.mod h1:4L/zQOBkEf4pArQJ+CMk1/5xjA30B5oyWv+Bzb44DOw=
|
||||||
k8s.io/code-generator v0.0.0-20191004115455-8e001e5d1894 h1:NMYlxaF7rYQJk2E2IyrUhaX81zX24+dmoZdkPw0gJqI=
|
k8s.io/code-generator v0.0.0-20191004115455-8e001e5d1894 h1:NMYlxaF7rYQJk2E2IyrUhaX81zX24+dmoZdkPw0gJqI=
|
||||||
@@ -549,9 +531,6 @@ 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/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||||
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU=
|
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU=
|
||||||
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
|
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
|
||||||
k8s.io/kubectl v0.17.0 h1:xD4EWlL+epc/JTO1gvSjmV9yiYF0Z2wiHK2DIek6URY=
|
|
||||||
k8s.io/kubectl v0.17.0/go.mod h1:jIPrUAW656Vzn9wZCCe0PC+oTcu56u2HgFD21Xbfk1s=
|
|
||||||
k8s.io/metrics v0.17.0/go.mod h1:EH1D3YAwN6d7bMelrElnLhLg72l/ERStyv2SIQVt6Do=
|
|
||||||
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f h1:GiPwtSzdP43eI1hpPCbROQCCIgCuiMMNF8YUVLF3vJo=
|
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f h1:GiPwtSzdP43eI1hpPCbROQCCIgCuiMMNF8YUVLF3vJo=
|
||||||
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
kubesphere.io/application v0.0.0-20190404151855-67ae7f915d4e/go.mod h1:NhUQ0ZUdFz8NTQ+SvQG0JUKAn+q71v3TPExjsjRPIZI=
|
kubesphere.io/application v0.0.0-20190404151855-67ae7f915d4e/go.mod h1:NhUQ0ZUdFz8NTQ+SvQG0JUKAn+q71v3TPExjsjRPIZI=
|
||||||
@@ -572,13 +551,9 @@ sigs.k8s.io/controller-runtime v0.4.0 h1:wATM6/m+3w8lj8FXNaO6Fs/rq/vqoOjO1Q116Z9
|
|||||||
sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns=
|
sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns=
|
||||||
sigs.k8s.io/controller-tools v0.2.4 h1:la1h46EzElvWefWLqfsXrnsO3lZjpkI0asTpX6h8PLA=
|
sigs.k8s.io/controller-tools v0.2.4 h1:la1h46EzElvWefWLqfsXrnsO3lZjpkI0asTpX6h8PLA=
|
||||||
sigs.k8s.io/controller-tools v0.2.4/go.mod h1:m/ztfQNocGYBgTTCmFdnK94uVvgxeZeE3LtJvd/jIzA=
|
sigs.k8s.io/controller-tools v0.2.4/go.mod h1:m/ztfQNocGYBgTTCmFdnK94uVvgxeZeE3LtJvd/jIzA=
|
||||||
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
|
|
||||||
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
|
|
||||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca h1:6dsH6AYQWbyZmtttJNe8Gq1cXOeS1BdV3eW37zHilAQ=
|
sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca h1:6dsH6AYQWbyZmtttJNe8Gq1cXOeS1BdV3eW37zHilAQ=
|
||||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA=
|
sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA=
|
||||||
sigs.k8s.io/testing_frameworks v0.1.2 h1:vK0+tvjF0BZ/RYFeZ1E6BYBwHJJXhjuZ3TdsEKH+UQM=
|
sigs.k8s.io/testing_frameworks v0.1.2 h1:vK0+tvjF0BZ/RYFeZ1E6BYBwHJJXhjuZ3TdsEKH+UQM=
|
||||||
sigs.k8s.io/testing_frameworks v0.1.2/go.mod h1:ToQrwSC3s8Xf/lADdZp3Mktcql9CG0UAmdJG9th5i0w=
|
sigs.k8s.io/testing_frameworks v0.1.2/go.mod h1:ToQrwSC3s8Xf/lADdZp3Mktcql9CG0UAmdJG9th5i0w=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc h1:MksmcCZQWAQJCTA5T0jgI/0sJ51AVm4Z41MrmfczEoc=
|
|
||||||
vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI=
|
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ type FluentBitList struct {
|
|||||||
Items []FluentBit `json:"items"`
|
Items []FluentBit `json:"items"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type FluentbitOutputsResult struct {
|
type FluentbitOutputsResult struct {
|
||||||
Status int `json:"status" description:"response status"`
|
Status int `json:"status" description:"response status"`
|
||||||
Error string `json:"error,omitempty" description:"debug information"`
|
Error string `json:"error,omitempty" description:"debug information"`
|
||||||
|
|||||||
@@ -1,165 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2019 The KubeSphere Authors.
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package devops
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/emicklei/go-restful"
|
|
||||||
"k8s.io/klog"
|
|
||||||
"kubesphere.io/kubesphere/pkg/constants"
|
|
||||||
"kubesphere.io/kubesphere/pkg/models/devops"
|
|
||||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CreateDevOpsProjectCredentialHandler(request *restful.Request, resp *restful.Response) {
|
|
||||||
|
|
||||||
projectId := request.PathParameter("devops")
|
|
||||||
username := request.HeaderParameter(constants.UserNameHeader)
|
|
||||||
var credential *devops.JenkinsCredential
|
|
||||||
err := request.ReadEntity(&credential)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), resp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner, devops.ProjectMaintainer})
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
credentialId, err := devops.CreateProjectCredential(projectId, username, credential)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
errors.ParseSvcErr(err, resp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.WriteAsJson(struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
}{Name: credentialId})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func UpdateDevOpsProjectCredentialHandler(request *restful.Request, resp *restful.Response) {
|
|
||||||
|
|
||||||
projectId := request.PathParameter("devops")
|
|
||||||
username := request.HeaderParameter(constants.UserNameHeader)
|
|
||||||
credentialId := request.PathParameter("credential")
|
|
||||||
var credential *devops.JenkinsCredential
|
|
||||||
err := request.ReadEntity(&credential)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), resp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner, devops.ProjectMaintainer})
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
credentialId, err = devops.UpdateProjectCredential(projectId, credentialId, credential)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
errors.ParseSvcErr(err, resp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.WriteAsJson(struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
}{Name: credentialId})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteDevOpsProjectCredentialHandler(request *restful.Request, resp *restful.Response) {
|
|
||||||
|
|
||||||
projectId := request.PathParameter("devops")
|
|
||||||
username := request.HeaderParameter(constants.UserNameHeader)
|
|
||||||
credentialId := request.PathParameter("credential")
|
|
||||||
var credential *devops.JenkinsCredential
|
|
||||||
err := request.ReadEntity(&credential)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), resp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner, devops.ProjectMaintainer})
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
credentialId, err = devops.DeleteProjectCredential(projectId, credentialId, credential)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
errors.ParseSvcErr(err, resp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.WriteAsJson(struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
}{Name: credentialId})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetDevOpsProjectCredentialHandler(request *restful.Request, resp *restful.Response) {
|
|
||||||
|
|
||||||
projectId := request.PathParameter("devops")
|
|
||||||
username := request.HeaderParameter(constants.UserNameHeader)
|
|
||||||
credentialId := request.PathParameter("credential")
|
|
||||||
getContent := request.QueryParameter("content")
|
|
||||||
domain := request.QueryParameter("domain")
|
|
||||||
|
|
||||||
err := devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner, devops.ProjectMaintainer})
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
response, err := devops.GetProjectCredential(projectId, credentialId, domain, getContent)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
errors.ParseSvcErr(err, resp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.WriteAsJson(response)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetDevOpsProjectCredentialsHandler(request *restful.Request, resp *restful.Response) {
|
|
||||||
projectId := request.PathParameter("devops")
|
|
||||||
username := request.HeaderParameter(constants.UserNameHeader)
|
|
||||||
domain := request.QueryParameter("domain")
|
|
||||||
|
|
||||||
err := devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner, devops.ProjectMaintainer})
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
jenkinsCredentials, err := devops.GetProjectCredentials(projectId, domain)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
errors.ParseSvcErr(err, resp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp.WriteAsJson(jenkinsCredentials)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
54
pkg/apiserver/openpitrix/attachments.go
Normal file
54
pkg/apiserver/openpitrix/attachments.go
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright 2019 The KubeSphere Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* /
|
||||||
|
*/
|
||||||
|
|
||||||
|
package openpitrix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/emicklei/go-restful"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/openpitrix/attachment"
|
||||||
|
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DescribeAttachment(req *restful.Request, resp *restful.Response) {
|
||||||
|
attachmentId := req.PathParameter("attachment")
|
||||||
|
fileName := req.QueryParameter("filename")
|
||||||
|
result, err := attachment.DescribeAttachment(attachmentId)
|
||||||
|
// file raw
|
||||||
|
if fileName != "" {
|
||||||
|
data := result.AttachmentContent[fileName]
|
||||||
|
resp.Write(data)
|
||||||
|
resp.Header().Set("Content-Type", "text/plain")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, notEnabled := err.(client.ClientSetNotEnabledError); notEnabled {
|
||||||
|
resp.WriteHeaderAndEntity(http.StatusNotImplemented, errors.Wrap(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if status.Code(err) == codes.NotFound {
|
||||||
|
resp.WriteHeaderAndEntity(http.StatusNotFound, errors.Wrap(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.WriteEntity(result)
|
||||||
|
}
|
||||||
328
pkg/apiserver/tenant/tenant.go
Normal file
328
pkg/apiserver/tenant/tenant.go
Normal file
@@ -0,0 +1,328 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019 The KubeSphere Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
package tenant
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/emicklei/go-restful"
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
|
k8serr "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
"k8s.io/apimachinery/pkg/util/net"
|
||||||
|
"k8s.io/klog"
|
||||||
|
devopsv1alpha2 "kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
|
||||||
|
loggingv1alpha2 "kubesphere.io/kubesphere/pkg/api/logging/v1alpha2"
|
||||||
|
"kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
|
||||||
|
"kubesphere.io/kubesphere/pkg/apiserver/logging"
|
||||||
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/iam"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/metrics"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/tenant"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/workspaces"
|
||||||
|
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||||
|
"kubesphere.io/kubesphere/pkg/server/params"
|
||||||
|
|
||||||
|
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ListWorkspaceRules(req *restful.Request, resp *restful.Response) {
|
||||||
|
workspace := req.PathParameter("workspace")
|
||||||
|
username := req.HeaderParameter(constants.UserNameHeader)
|
||||||
|
|
||||||
|
rules, err := iam.GetUserWorkspaceSimpleRules(workspace, username)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.WriteAsJson(rules)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ListWorkspaces(req *restful.Request, resp *restful.Response) {
|
||||||
|
username := req.HeaderParameter(constants.UserNameHeader)
|
||||||
|
conditions, err := params.ParseConditions(req.QueryParameter(params.ConditionsParam))
|
||||||
|
orderBy := req.QueryParameter(params.OrderByParam)
|
||||||
|
limit, offset := params.ParsePaging(req.QueryParameter(params.PagingParam))
|
||||||
|
reverse := params.ParseReverse(req)
|
||||||
|
|
||||||
|
if orderBy == "" {
|
||||||
|
orderBy = v1alpha2.CreateTime
|
||||||
|
reverse = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := tenant.ListWorkspaces(username, conditions, orderBy, reverse, limit, offset)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.WriteAsJson(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DescribeWorkspace(req *restful.Request, resp *restful.Response) {
|
||||||
|
username := req.HeaderParameter(constants.UserNameHeader)
|
||||||
|
workspaceName := req.PathParameter("workspace")
|
||||||
|
|
||||||
|
result, err := tenant.DescribeWorkspace(username, workspaceName)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("describe workspace failed: %+v", err)
|
||||||
|
if k8serr.IsNotFound(err) {
|
||||||
|
resp.WriteHeaderAndEntity(http.StatusNotFound, errors.Wrap(err))
|
||||||
|
} else {
|
||||||
|
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.WriteAsJson(result)
|
||||||
|
}
|
||||||
|
func ListNamespacesByUsername(req *restful.Request, resp *restful.Response) {
|
||||||
|
ListNamespaces(req, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ListNamespaces(req *restful.Request, resp *restful.Response) {
|
||||||
|
workspace := req.PathParameter("workspace")
|
||||||
|
username := req.PathParameter("member")
|
||||||
|
// /workspaces/{workspace}/members/{username}/namespaces
|
||||||
|
if username == "" {
|
||||||
|
// /workspaces/{workspace}/namespaces
|
||||||
|
username = req.HeaderParameter(constants.UserNameHeader)
|
||||||
|
}
|
||||||
|
|
||||||
|
conditions, err := params.ParseConditions(req.QueryParameter(params.ConditionsParam))
|
||||||
|
orderBy := req.QueryParameter(params.OrderByParam)
|
||||||
|
limit, offset := params.ParsePaging(req.QueryParameter(params.PagingParam))
|
||||||
|
reverse := params.ParseReverse(req)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
conditions.Match[constants.WorkspaceLabelKey] = workspace
|
||||||
|
|
||||||
|
result, err := tenant.ListNamespaces(username, conditions, orderBy, reverse, limit, offset)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
namespaces := make([]*v1.Namespace, 0)
|
||||||
|
|
||||||
|
for _, item := range result.Items {
|
||||||
|
namespaces = append(namespaces, item.(*v1.Namespace).DeepCopy())
|
||||||
|
}
|
||||||
|
|
||||||
|
namespaces = metrics.GetNamespacesWithMetrics(namespaces)
|
||||||
|
|
||||||
|
items := make([]interface{}, 0)
|
||||||
|
|
||||||
|
for _, item := range namespaces {
|
||||||
|
items = append(items, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Items = items
|
||||||
|
|
||||||
|
resp.WriteAsJson(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateNamespace(req *restful.Request, resp *restful.Response) {
|
||||||
|
workspaceName := req.PathParameter("workspace")
|
||||||
|
username := req.HeaderParameter(constants.UserNameHeader)
|
||||||
|
var namespace v1.Namespace
|
||||||
|
err := req.ReadEntity(&namespace)
|
||||||
|
if err != nil {
|
||||||
|
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
workspace, err := tenant.GetWorkspace(workspaceName)
|
||||||
|
|
||||||
|
err = checkResourceQuotas(workspace)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
resp.WriteHeaderAndEntity(http.StatusForbidden, errors.Wrap(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if k8serr.IsNotFound(err) {
|
||||||
|
resp.WriteHeaderAndEntity(http.StatusForbidden, errors.Wrap(err))
|
||||||
|
} else {
|
||||||
|
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
created, err := tenant.CreateNamespace(workspaceName, &namespace, username)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if k8serr.IsAlreadyExists(err) {
|
||||||
|
resp.WriteHeaderAndEntity(http.StatusConflict, err)
|
||||||
|
} else {
|
||||||
|
resp.WriteHeaderAndEntity(http.StatusInternalServerError, err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp.WriteAsJson(created)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteNamespace(req *restful.Request, resp *restful.Response) {
|
||||||
|
workspaceName := req.PathParameter("workspace")
|
||||||
|
namespaceName := req.PathParameter("namespace")
|
||||||
|
|
||||||
|
err := workspaces.DeleteNamespace(workspaceName, namespaceName)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.WriteAsJson(errors.None)
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkResourceQuotas(wokrspace *v1alpha1.Workspace) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func ListNamespaceRules(req *restful.Request, resp *restful.Response) {
|
||||||
|
namespace := req.PathParameter("namespace")
|
||||||
|
username := req.HeaderParameter(constants.UserNameHeader)
|
||||||
|
|
||||||
|
rules, err := iam.GetUserNamespaceSimpleRules(namespace, username)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
resp.WriteError(http.StatusInternalServerError, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.WriteAsJson(rules)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LogQuery(req *restful.Request, resp *restful.Response) {
|
||||||
|
operation := req.QueryParameter("operation")
|
||||||
|
req, err := regenerateLoggingRequest(req)
|
||||||
|
switch {
|
||||||
|
case err != nil:
|
||||||
|
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
|
||||||
|
case req != nil:
|
||||||
|
logging.LoggingQueryCluster(req, resp)
|
||||||
|
default:
|
||||||
|
if operation == "export" {
|
||||||
|
resp.Header().Set(restful.HEADER_ContentType, "text/plain")
|
||||||
|
resp.Header().Set("Content-Disposition", "attachment")
|
||||||
|
resp.Write(nil)
|
||||||
|
} else {
|
||||||
|
resp.WriteAsJson(loggingv1alpha2.QueryResult{Read: new(loggingv1alpha2.ReadResult)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// override namespace query conditions
|
||||||
|
func regenerateLoggingRequest(req *restful.Request) (*restful.Request, error) {
|
||||||
|
|
||||||
|
username := req.HeaderParameter(constants.UserNameHeader)
|
||||||
|
|
||||||
|
// regenerate the request for log query
|
||||||
|
newUrl := net.FormatURL("http", "127.0.0.1", 80, "/kapis/logging.kubesphere.io/v1alpha2/cluster")
|
||||||
|
values := req.Request.URL.Query()
|
||||||
|
|
||||||
|
clusterRules, err := iam.GetUserClusterRules(username)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorln(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
hasClusterLogAccess := iam.RulesMatchesRequired(clusterRules, rbacv1.PolicyRule{Verbs: []string{"get"}, Resources: []string{"*"}, APIGroups: []string{"logging.kubesphere.io"}})
|
||||||
|
// if the user is not a cluster admin
|
||||||
|
if !hasClusterLogAccess {
|
||||||
|
queryNamespaces := strings.Split(req.QueryParameter("namespaces"), ",")
|
||||||
|
// then the user can only view logs of namespaces he belongs to
|
||||||
|
namespaces := make([]string, 0)
|
||||||
|
roles, err := iam.GetUserRoles("", username)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorln(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, role := range roles {
|
||||||
|
if !sliceutil.HasString(namespaces, role.Namespace) && iam.RulesMatchesRequired(role.Rules, rbacv1.PolicyRule{Verbs: []string{"get"}, Resources: []string{"*"}, APIGroups: []string{"logging.kubesphere.io"}}) {
|
||||||
|
namespaces = append(namespaces, role.Namespace)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the user belongs to no namespace
|
||||||
|
// then no log visible
|
||||||
|
if len(namespaces) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
} else if len(queryNamespaces) == 1 && queryNamespaces[0] == "" {
|
||||||
|
values.Set("namespaces", strings.Join(namespaces, ","))
|
||||||
|
} else {
|
||||||
|
inter := intersection(queryNamespaces, namespaces)
|
||||||
|
if len(inter) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
values.Set("namespaces", strings.Join(inter, ","))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newUrl.RawQuery = values.Encode()
|
||||||
|
|
||||||
|
// forward the request to logging model
|
||||||
|
newHttpRequest, _ := http.NewRequest(http.MethodGet, newUrl.String(), nil)
|
||||||
|
return restful.NewRequest(newHttpRequest), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func intersection(s1, s2 []string) (inter []string) {
|
||||||
|
hash := make(map[string]bool)
|
||||||
|
for _, e := range s1 {
|
||||||
|
hash[e] = true
|
||||||
|
}
|
||||||
|
for _, e := range s2 {
|
||||||
|
// If elements present in the hashmap then append intersection list.
|
||||||
|
if hash[e] {
|
||||||
|
inter = append(inter, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Remove dups from slice.
|
||||||
|
inter = removeDups(inter)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Remove dups from slice.
|
||||||
|
func removeDups(elements []string) (nodups []string) {
|
||||||
|
encountered := make(map[string]bool)
|
||||||
|
for _, element := range elements {
|
||||||
|
if !encountered[element] {
|
||||||
|
nodups = append(nodups, element)
|
||||||
|
encountered[element] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<table page-has-up="false" page-has-down="false" page-entry-newest="-9223372036854775805" page-entry-oldest="-9223372036854775807" class="pane hasPageData"><tr page-entry-id="-9223372036854775805" class="build-row single-line"><td class="build-row-cell"><div class="pane build-name"><div class="build-icon"><a href="/jenkins/job/j1/3/console" class="build-status-link"><img src="/jenkins/images/16x16/blue.png" alt="Success > Console Output" tooltip="Success > Console Output" style="width: 16px; height: 16px; " class="icon-blue icon-sm" /></a></div><a update-parent-class=".build-row" href="/jenkins/job/j1/3/" class="tip model-link inside build-link display-name">#3</a></div><div time="1484327939346" class="pane build-details"><a update-parent-class=".build-row" href="/jenkins/job/j1/3/" class="tip model-link inside build-link">Jan 13, 2017 9:18 AM</a></div><div class="pane build-controls"><div class="middle-align build-badge"></div></div><div class="left-bar"></div></td></tr><tr page-entry-id="-9223372036854775806" class="build-row single-line"><td class="build-row-cell"><div class="pane build-name"><div class="build-icon"><a href="/jenkins/job/j1/2/console" class="build-status-link"><img src="/jenkins/images/16x16/blue.png" alt="Success > Console Output" tooltip="Success > Console Output" style="width: 16px; height: 16px; " class="icon-blue icon-sm" /></a></div><a update-parent-class=".build-row" href="/jenkins/job/j1/2/" class="tip model-link inside build-link display-name">#2</a></div><div time="1484327935341" class="pane build-details"><a update-parent-class=".build-row" href="/jenkins/job/j1/2/" class="tip model-link inside build-link">Jan 13, 2017 9:18 AM</a></div><div class="pane build-controls"><div class="middle-align build-badge"></div></div><div class="left-bar"></div></td></tr><tr page-entry-id="-9223372036854775807" class="build-row single-line"><td class="build-row-cell"><div class="pane build-name"><div class="build-icon"><a href="/jenkins/job/j1/1/console" class="build-status-link"><img src="/jenkins/images/16x16/blue.png" alt="Success > Console Output" tooltip="Success > Console Output" style="width: 16px; height: 16px; " class="icon-blue icon-sm" /></a></div><a update-parent-class=".build-row" href="/jenkins/job/j1/1/" class="tip model-link inside build-link display-name">#1</a></div><div time="1484327924442" class="pane build-details"><a update-parent-class=".build-row" href="/jenkins/job/j1/1/" class="tip model-link inside build-link">Jan 13, 2017 9:18 AM</a></div><div class="pane build-controls"><div class="middle-align build-badge"></div></div><div class="left-bar"></div></td></tr></table>
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
<?xml version='1.0' encoding='UTF-8'?>
|
|
||||||
<project>
|
|
||||||
<actions/>
|
|
||||||
<description>Some Job Description</description>
|
|
||||||
<keepDependencies>false</keepDependencies>
|
|
||||||
<properties>
|
|
||||||
<hudson.model.ParametersDefinitionProperty>
|
|
||||||
<parameterDefinitions>
|
|
||||||
<hudson.model.StringParameterDefinition>
|
|
||||||
<name>params1</name>
|
|
||||||
<description>description</description>
|
|
||||||
<defaultValue>defaultVal</defaultValue>
|
|
||||||
</hudson.model.StringParameterDefinition>
|
|
||||||
</parameterDefinitions>
|
|
||||||
</hudson.model.ParametersDefinitionProperty>
|
|
||||||
</properties>
|
|
||||||
<scm class="hudson.scm.NullSCM"/>
|
|
||||||
<canRoam>true</canRoam>
|
|
||||||
<disabled>false</disabled>
|
|
||||||
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
|
|
||||||
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
|
|
||||||
<triggers class="vector"/>
|
|
||||||
<concurrentBuild>false</concurrentBuild>
|
|
||||||
<builders/>
|
|
||||||
<publishers/>
|
|
||||||
<buildWrappers/>
|
|
||||||
</project>
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
// Copyright 2015 Vadim Kravcenko
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
|
||||||
// not use this file except in compliance with the License. You may obtain
|
|
||||||
// a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
// License for the specific language governing permissions and limitations
|
|
||||||
// under the License.
|
|
||||||
|
|
||||||
package gojenkins
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/md5"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Represents an Artifact
|
|
||||||
type Artifact struct {
|
|
||||||
Jenkins *Jenkins
|
|
||||||
Build *Build
|
|
||||||
FileName string
|
|
||||||
Path string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get raw byte data of Artifact
|
|
||||||
func (a Artifact) GetData() ([]byte, error) {
|
|
||||||
var data string
|
|
||||||
response, err := a.Jenkins.Requester.Get(a.Path, &data, nil)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
code := response.StatusCode
|
|
||||||
if code != 200 {
|
|
||||||
Error.Printf("Jenkins responded with StatusCode: %d", code)
|
|
||||||
return nil, errors.New("Could not get File Contents")
|
|
||||||
}
|
|
||||||
return []byte(data), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save artifact to a specific path, using your own filename.
|
|
||||||
func (a Artifact) Save(path string) (bool, error) {
|
|
||||||
data, err := a.GetData()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return false, errors.New("No Data received, not saving file.")
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err = os.Stat(path); err == nil {
|
|
||||||
Warning.Println("Local Copy already exists, Overwriting...")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ioutil.WriteFile(path, data, 0644)
|
|
||||||
a.validateDownload(path)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save Artifact to directory using Artifact filename.
|
|
||||||
func (a Artifact) SaveToDir(dir string) (bool, error) {
|
|
||||||
if _, err := os.Stat(dir); err != nil {
|
|
||||||
Error.Printf("can't save artifact: directory %s does not exist", dir)
|
|
||||||
return false, fmt.Errorf("can't save artifact: directory %s does not exist", dir)
|
|
||||||
}
|
|
||||||
saved, err := a.Save(path.Join(dir, a.FileName))
|
|
||||||
if err != nil {
|
|
||||||
return saved, nil
|
|
||||||
}
|
|
||||||
return saved, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare Remote and local MD5
|
|
||||||
func (a Artifact) validateDownload(path string) (bool, error) {
|
|
||||||
localHash := a.getMD5local(path)
|
|
||||||
|
|
||||||
fp := FingerPrint{Jenkins: a.Jenkins, Base: "/fingerprint/", Id: localHash, Raw: new(FingerPrintResponse)}
|
|
||||||
|
|
||||||
valid, err := fp.ValidateForBuild(a.FileName, a.Build)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if !valid {
|
|
||||||
return false, errors.New("FingerPrint of the downloaded artifact could not be verified")
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Local MD5
|
|
||||||
func (a Artifact) getMD5local(path string) string {
|
|
||||||
h := md5.New()
|
|
||||||
localFile, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
buffer := make([]byte, 2^20)
|
|
||||||
n, err := localFile.Read(buffer)
|
|
||||||
defer localFile.Close()
|
|
||||||
for err == nil {
|
|
||||||
io.WriteString(h, string(buffer[0:n]))
|
|
||||||
n, err = localFile.Read(buffer)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%x", h.Sum(nil))
|
|
||||||
}
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
package gojenkins
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"golang.org/x/net/html"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Parse jenkins ajax response in order find the current jenkins build history
|
|
||||||
func parseBuildHistory(d io.Reader) []*History {
|
|
||||||
z := html.NewTokenizer(d)
|
|
||||||
depth := 0
|
|
||||||
buildRowCellDepth := -1
|
|
||||||
builds := make([]*History, 0)
|
|
||||||
var curBuild *History
|
|
||||||
for {
|
|
||||||
tt := z.Next()
|
|
||||||
switch tt {
|
|
||||||
case html.ErrorToken:
|
|
||||||
if z.Err() == io.EOF {
|
|
||||||
return builds
|
|
||||||
}
|
|
||||||
case html.SelfClosingTagToken:
|
|
||||||
tn, hasAttr := z.TagName()
|
|
||||||
// fmt.Println("START__", string(tn), hasAttr)
|
|
||||||
if hasAttr {
|
|
||||||
a := attr(z)
|
|
||||||
// <img src="/static/f2881562/images/16x16/red.png" alt="Failed > Console Output" tooltip="Failed > Console Output" style="width: 16px; height: 16px; " class="icon-red icon-sm" />
|
|
||||||
if string(tn) == "img" {
|
|
||||||
if hasCSSClass(a, "icon-sm") && buildRowCellDepth > -1 {
|
|
||||||
if alt, found := a["alt"]; found {
|
|
||||||
curBuild.BuildStatus = strings.Fields(alt)[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case html.StartTagToken:
|
|
||||||
depth++
|
|
||||||
tn, hasAttr := z.TagName()
|
|
||||||
// fmt.Println("START__", string(tn), hasAttr)
|
|
||||||
if hasAttr {
|
|
||||||
a := attr(z)
|
|
||||||
// <td class="build-row-cell">
|
|
||||||
if string(tn) == "td" {
|
|
||||||
if hasCSSClass(a, "build-row-cell") {
|
|
||||||
buildRowCellDepth = depth
|
|
||||||
curBuild = &History{}
|
|
||||||
builds = append(builds, curBuild)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// <a update-parent-class=".build-row" href="/job/appscode/job/43/job/build-binary/227/" class="tip model-link inside build-link display-name">#227</a>
|
|
||||||
if string(tn) == "a" {
|
|
||||||
if hasCSSClass(a, "build-link") && buildRowCellDepth > -1 {
|
|
||||||
if href, found := a["href"]; found {
|
|
||||||
parts := strings.Split(href, "/")
|
|
||||||
if num, err := strconv.Atoi(parts[len(parts)-2]); err == nil {
|
|
||||||
curBuild.BuildNumber = num
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// <div time="1469024602546" class="pane build-details"> ... </div>
|
|
||||||
if string(tn) == "div" {
|
|
||||||
if hasCSSClass(a, "build-details") && buildRowCellDepth > -1 {
|
|
||||||
if t, found := a["time"]; found {
|
|
||||||
if msec, err := strconv.ParseInt(t, 10, 0); err == nil {
|
|
||||||
curBuild.BuildTimestamp = msec / 1000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case html.EndTagToken:
|
|
||||||
tn, _ := z.TagName()
|
|
||||||
if string(tn) == "td" && depth == buildRowCellDepth {
|
|
||||||
buildRowCellDepth = -1
|
|
||||||
curBuild = nil
|
|
||||||
}
|
|
||||||
depth--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func attr(z *html.Tokenizer) map[string]string {
|
|
||||||
a := make(map[string]string)
|
|
||||||
for {
|
|
||||||
k, v, more := z.TagAttr()
|
|
||||||
if k != nil && v != nil {
|
|
||||||
a[string(k)] = string(v)
|
|
||||||
}
|
|
||||||
if !more {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasCSSClass(a map[string]string, className string) bool {
|
|
||||||
if classes, found := a["class"]; found {
|
|
||||||
for _, class := range strings.Fields(classes) {
|
|
||||||
if class == className {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
@@ -1,225 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 The KubeSphere Authors.
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package gojenkins
|
|
||||||
|
|
||||||
const SSHCrenditalStaplerClass = "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
|
|
||||||
const DirectSSHCrenditalStaplerClass = "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource"
|
|
||||||
const UsernamePassswordCredentialStaplerClass = "com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl"
|
|
||||||
const SecretTextCredentialStaplerClass = "org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl"
|
|
||||||
const KubeconfigCredentialStaplerClass = "com.microsoft.jenkins.kubernetes.credentials.KubeconfigCredentials"
|
|
||||||
const DirectKubeconfigCredentialStaperClass = "com.microsoft.jenkins.kubernetes.credentials.KubeconfigCredentials$DirectEntryKubeconfigSource"
|
|
||||||
const GLOBALScope = "GLOBAL"
|
|
||||||
|
|
||||||
type CreateSshCredentialRequest struct {
|
|
||||||
Credentials SshCredential `json:"credentials"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateUsernamePasswordCredentialRequest struct {
|
|
||||||
Credentials UsernamePasswordCredential `json:"credentials"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateSecretTextCredentialRequest struct {
|
|
||||||
Credentials SecretTextCredential `json:"credentials"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateKubeconfigCredentialRequest struct {
|
|
||||||
Credentials KubeconfigCredential `json:"credentials"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UsernamePasswordCredential struct {
|
|
||||||
Scope string `json:"scope"`
|
|
||||||
Id string `json:"id"`
|
|
||||||
Username string `json:"username"`
|
|
||||||
Password string `json:"password"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
StaplerClass string `json:"stapler-class"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SshCredential struct {
|
|
||||||
Scope string `json:"scope"`
|
|
||||||
Id string `json:"id"`
|
|
||||||
Username string `json:"username"`
|
|
||||||
Passphrase string `json:"passphrase"`
|
|
||||||
KeySource PrivateKeySource `json:"privateKeySource"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
StaplerClass string `json:"stapler-class"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SecretTextCredential struct {
|
|
||||||
Scope string `json:"scope"`
|
|
||||||
Id string `json:"id"`
|
|
||||||
Secret string `json:"secret"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
StaplerClass string `json:"stapler-class"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type KubeconfigCredential struct {
|
|
||||||
Scope string `json:"scope"`
|
|
||||||
Id string `json:"id"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
KubeconfigSource KubeconfigSource `json:"kubeconfigSource"`
|
|
||||||
StaplerClass string `json:"stapler-class"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type PrivateKeySource struct {
|
|
||||||
StaplerClass string `json:"stapler-class"`
|
|
||||||
PrivateKey string `json:"privateKey"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type KubeconfigSource struct {
|
|
||||||
StaplerClass string `json:"stapler-class"`
|
|
||||||
Content string `json:"content"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CredentialResponse struct {
|
|
||||||
Id string `json:"id"`
|
|
||||||
TypeName string `json:"typeName"`
|
|
||||||
DisplayName string `json:"displayName"`
|
|
||||||
Fingerprint *struct {
|
|
||||||
FileName string `json:"file_name,omitempty" description:"Credential's display name and description"`
|
|
||||||
Hash string `json:"hash,omitempty" description:"Credential's hash"`
|
|
||||||
Usage []*struct {
|
|
||||||
Name string `json:"name,omitempty" description:"Jenkins pipeline full name"`
|
|
||||||
Ranges struct {
|
|
||||||
Ranges []*struct {
|
|
||||||
Start int `json:"start,omitempty" description:"Start build number"`
|
|
||||||
End int `json:"end,omitempty" description:"End build number"`
|
|
||||||
} `json:"ranges,omitempty"`
|
|
||||||
} `json:"ranges,omitempty" description:"The build number of all pipelines that use this credential"`
|
|
||||||
} `json:"usage,omitempty" description:"all usage of Credential"`
|
|
||||||
} `json:"fingerprint,omitempty" description:"usage of the Credential"`
|
|
||||||
Description string `json:"description,omitempty"`
|
|
||||||
Domain string `json:"domain"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewCreateSshCredentialRequest(id, username, passphrase, privateKey, description string) *CreateSshCredentialRequest {
|
|
||||||
|
|
||||||
keySource := PrivateKeySource{
|
|
||||||
StaplerClass: DirectSSHCrenditalStaplerClass,
|
|
||||||
PrivateKey: privateKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
sshCredential := SshCredential{
|
|
||||||
Scope: GLOBALScope,
|
|
||||||
Id: id,
|
|
||||||
Username: username,
|
|
||||||
Passphrase: passphrase,
|
|
||||||
KeySource: keySource,
|
|
||||||
Description: description,
|
|
||||||
StaplerClass: SSHCrenditalStaplerClass,
|
|
||||||
}
|
|
||||||
return &CreateSshCredentialRequest{
|
|
||||||
Credentials: sshCredential,
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewCreateUsernamePasswordRequest(id, username, password, description string) *CreateUsernamePasswordCredentialRequest {
|
|
||||||
credential := UsernamePasswordCredential{
|
|
||||||
Scope: GLOBALScope,
|
|
||||||
Id: id,
|
|
||||||
Username: username,
|
|
||||||
Password: password,
|
|
||||||
Description: description,
|
|
||||||
StaplerClass: UsernamePassswordCredentialStaplerClass,
|
|
||||||
}
|
|
||||||
return &CreateUsernamePasswordCredentialRequest{
|
|
||||||
Credentials: credential,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewCreateSecretTextCredentialRequest(id, secret, description string) *CreateSecretTextCredentialRequest {
|
|
||||||
credential := SecretTextCredential{
|
|
||||||
Scope: GLOBALScope,
|
|
||||||
Id: id,
|
|
||||||
Secret: secret,
|
|
||||||
Description: description,
|
|
||||||
StaplerClass: SecretTextCredentialStaplerClass,
|
|
||||||
}
|
|
||||||
return &CreateSecretTextCredentialRequest{
|
|
||||||
Credentials: credential,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewCreateKubeconfigCredentialRequest(id, content, description string) *CreateKubeconfigCredentialRequest {
|
|
||||||
|
|
||||||
credentialSource := KubeconfigSource{
|
|
||||||
StaplerClass: DirectKubeconfigCredentialStaperClass,
|
|
||||||
Content: content,
|
|
||||||
}
|
|
||||||
|
|
||||||
credential := KubeconfigCredential{
|
|
||||||
Scope: GLOBALScope,
|
|
||||||
Id: id,
|
|
||||||
Description: description,
|
|
||||||
KubeconfigSource: credentialSource,
|
|
||||||
StaplerClass: KubeconfigCredentialStaplerClass,
|
|
||||||
}
|
|
||||||
return &CreateKubeconfigCredentialRequest{
|
|
||||||
credential,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewSshCredential(id, username, passphrase, privateKey, description string) *SshCredential {
|
|
||||||
keySource := PrivateKeySource{
|
|
||||||
StaplerClass: DirectSSHCrenditalStaplerClass,
|
|
||||||
PrivateKey: privateKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
return &SshCredential{
|
|
||||||
Scope: GLOBALScope,
|
|
||||||
Id: id,
|
|
||||||
Username: username,
|
|
||||||
Passphrase: passphrase,
|
|
||||||
KeySource: keySource,
|
|
||||||
Description: description,
|
|
||||||
StaplerClass: SSHCrenditalStaplerClass,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewUsernamePasswordCredential(id, username, password, description string) *UsernamePasswordCredential {
|
|
||||||
return &UsernamePasswordCredential{
|
|
||||||
Scope: GLOBALScope,
|
|
||||||
Id: id,
|
|
||||||
Username: username,
|
|
||||||
Password: password,
|
|
||||||
Description: description,
|
|
||||||
StaplerClass: UsernamePassswordCredentialStaplerClass,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewSecretTextCredential(id, secret, description string) *SecretTextCredential {
|
|
||||||
return &SecretTextCredential{
|
|
||||||
Scope: GLOBALScope,
|
|
||||||
Id: id,
|
|
||||||
Secret: secret,
|
|
||||||
Description: description,
|
|
||||||
StaplerClass: SecretTextCredentialStaplerClass,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewKubeconfigCredential(id, content, description string) *KubeconfigCredential {
|
|
||||||
credentialSource := KubeconfigSource{
|
|
||||||
StaplerClass: DirectKubeconfigCredentialStaperClass,
|
|
||||||
Content: content,
|
|
||||||
}
|
|
||||||
|
|
||||||
return &KubeconfigCredential{
|
|
||||||
Scope: GLOBALScope,
|
|
||||||
Id: id,
|
|
||||||
Description: description,
|
|
||||||
KubeconfigSource: credentialSource,
|
|
||||||
StaplerClass: KubeconfigCredentialStaplerClass,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
// Copyright 2015 Vadim Kravcenko
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
|
||||||
// not use this file except in compliance with the License. You may obtain
|
|
||||||
// a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
// License for the specific language governing permissions and limitations
|
|
||||||
// under the License.
|
|
||||||
|
|
||||||
package gojenkins
|
|
||||||
|
|
||||||
type Executor struct {
|
|
||||||
Raw *ExecutorResponse
|
|
||||||
Jenkins *Jenkins
|
|
||||||
}
|
|
||||||
type ViewData struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
}
|
|
||||||
type ExecutorResponse struct {
|
|
||||||
AssignedLabels []struct{} `json:"assignedLabels"`
|
|
||||||
Description interface{} `json:"description"`
|
|
||||||
Jobs []InnerJob `json:"jobs"`
|
|
||||||
Mode string `json:"mode"`
|
|
||||||
NodeDescription string `json:"nodeDescription"`
|
|
||||||
NodeName string `json:"nodeName"`
|
|
||||||
NumExecutors int64 `json:"numExecutors"`
|
|
||||||
OverallLoad struct{} `json:"overallLoad"`
|
|
||||||
PrimaryView struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
} `json:"primaryView"`
|
|
||||||
QuietingDown bool `json:"quietingDown"`
|
|
||||||
SlaveAgentPort int64 `json:"slaveAgentPort"`
|
|
||||||
UnlabeledLoad struct{} `json:"unlabeledLoad"`
|
|
||||||
UseCrumbs bool `json:"useCrumbs"`
|
|
||||||
UseSecurity bool `json:"useSecurity"`
|
|
||||||
Views []ViewData `json:"views"`
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
// Copyright 2015 Vadim Kravcenko
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
|
||||||
// not use this file except in compliance with the License. You may obtain
|
|
||||||
// a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
// License for the specific language governing permissions and limitations
|
|
||||||
// under the License.
|
|
||||||
|
|
||||||
package gojenkins
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
type FingerPrint struct {
|
|
||||||
Jenkins *Jenkins
|
|
||||||
Base string
|
|
||||||
Id string
|
|
||||||
Raw *FingerPrintResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
type FingerPrintResponse struct {
|
|
||||||
FileName string `json:"fileName"`
|
|
||||||
Hash string `json:"hash"`
|
|
||||||
Original struct {
|
|
||||||
Name string
|
|
||||||
Number int64
|
|
||||||
} `json:"original"`
|
|
||||||
Timestamp int64 `json:"timestamp"`
|
|
||||||
Usage []struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Ranges struct {
|
|
||||||
Ranges []struct {
|
|
||||||
End int64 `json:"end"`
|
|
||||||
Start int64 `json:"start"`
|
|
||||||
} `json:"ranges"`
|
|
||||||
} `json:"ranges"`
|
|
||||||
} `json:"usage"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f FingerPrint) Valid() (bool, error) {
|
|
||||||
status, err := f.Poll()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if status != 200 || f.Raw.Hash != f.Id {
|
|
||||||
return false, fmt.Errorf("Jenkins says %s is Invalid or the Status is unknown", f.Id)
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f FingerPrint) ValidateForBuild(filename string, build *Build) (bool, error) {
|
|
||||||
valid, err := f.Valid()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if valid {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if f.Raw.FileName != filename {
|
|
||||||
return false, errors.New("Filename does not Match")
|
|
||||||
}
|
|
||||||
if build != nil && f.Raw.Original.Name == build.Job.GetName() &&
|
|
||||||
f.Raw.Original.Number == build.GetBuildNumber() {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f FingerPrint) GetInfo() (*FingerPrintResponse, error) {
|
|
||||||
_, err := f.Poll()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return f.Raw, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f FingerPrint) Poll() (int, error) {
|
|
||||||
response, err := f.Jenkins.Requester.GetJSON(f.Base+f.Id, f.Raw, nil)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return response.StatusCode, nil
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,62 +0,0 @@
|
|||||||
// Copyright 2015 Vadim Kravcenko
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
|
||||||
// not use this file except in compliance with the License. You may obtain
|
|
||||||
// a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
// License for the specific language governing permissions and limitations
|
|
||||||
// under the License.
|
|
||||||
|
|
||||||
package gojenkins
|
|
||||||
|
|
||||||
type Label struct {
|
|
||||||
Raw *LabelResponse
|
|
||||||
Jenkins *Jenkins
|
|
||||||
Base string
|
|
||||||
}
|
|
||||||
|
|
||||||
type MODE string
|
|
||||||
|
|
||||||
const (
|
|
||||||
NORMAL MODE = "NORMAL"
|
|
||||||
EXCLUSIVE = "EXCLUSIVE"
|
|
||||||
)
|
|
||||||
|
|
||||||
type LabelNode struct {
|
|
||||||
NodeName string `json:"nodeName"`
|
|
||||||
NodeDescription string `json:"nodeDescription"`
|
|
||||||
NumExecutors int64 `json:"numExecutors"`
|
|
||||||
Mode string `json:"mode"`
|
|
||||||
Class string `json:"_class"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type LabelResponse struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
Nodes []LabelNode `json:"nodes"`
|
|
||||||
Offline bool `json:"offline"`
|
|
||||||
IdleExecutors int64 `json:"idleExecutors"`
|
|
||||||
BusyExecutors int64 `json:"busyExecutors"`
|
|
||||||
TotalExecutors int64 `json:"totalExecutors"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *Label) GetName() string {
|
|
||||||
return l.Raw.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *Label) GetNodes() []LabelNode {
|
|
||||||
return l.Raw.Nodes
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *Label) Poll() (int, error) {
|
|
||||||
response, err := l.Jenkins.Requester.GetJSON(l.Base, l.Raw, nil)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return response.StatusCode, nil
|
|
||||||
}
|
|
||||||
@@ -1,230 +0,0 @@
|
|||||||
// Copyright 2015 Vadim Kravcenko
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
|
||||||
// not use this file except in compliance with the License. You may obtain
|
|
||||||
// a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
// License for the specific language governing permissions and limitations
|
|
||||||
// under the License.
|
|
||||||
|
|
||||||
package gojenkins
|
|
||||||
|
|
||||||
import "errors"
|
|
||||||
|
|
||||||
// Nodes
|
|
||||||
|
|
||||||
type Computers struct {
|
|
||||||
BusyExecutors int `json:"busyExecutors"`
|
|
||||||
Computers []*NodeResponse `json:"computer"`
|
|
||||||
DisplayName string `json:"displayName"`
|
|
||||||
TotalExecutors int `json:"totalExecutors"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Node struct {
|
|
||||||
Raw *NodeResponse
|
|
||||||
Jenkins *Jenkins
|
|
||||||
Base string
|
|
||||||
}
|
|
||||||
|
|
||||||
type NodeResponse struct {
|
|
||||||
Actions []interface{} `json:"actions"`
|
|
||||||
DisplayName string `json:"displayName"`
|
|
||||||
Executors []struct {
|
|
||||||
CurrentExecutable struct {
|
|
||||||
Number int `json:"number"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
SubBuilds []struct {
|
|
||||||
Abort bool `json:"abort"`
|
|
||||||
Build interface{} `json:"build"`
|
|
||||||
BuildNumber int `json:"buildNumber"`
|
|
||||||
Duration string `json:"duration"`
|
|
||||||
Icon string `json:"icon"`
|
|
||||||
JobName string `json:"jobName"`
|
|
||||||
ParentBuildNumber int `json:"parentBuildNumber"`
|
|
||||||
ParentJobName string `json:"parentJobName"`
|
|
||||||
PhaseName string `json:"phaseName"`
|
|
||||||
Result string `json:"result"`
|
|
||||||
Retry bool `json:"retry"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
} `json:"subBuilds"`
|
|
||||||
} `json:"currentExecutable"`
|
|
||||||
} `json:"executors"`
|
|
||||||
Icon string `json:"icon"`
|
|
||||||
IconClassName string `json:"iconClassName"`
|
|
||||||
Idle bool `json:"idle"`
|
|
||||||
JnlpAgent bool `json:"jnlpAgent"`
|
|
||||||
LaunchSupported bool `json:"launchSupported"`
|
|
||||||
LoadStatistics struct{} `json:"loadStatistics"`
|
|
||||||
ManualLaunchAllowed bool `json:"manualLaunchAllowed"`
|
|
||||||
MonitorData struct {
|
|
||||||
Hudson_NodeMonitors_ArchitectureMonitor interface{} `json:"hudson.node_monitors.ArchitectureMonitor"`
|
|
||||||
Hudson_NodeMonitors_ClockMonitor interface{} `json:"hudson.node_monitors.ClockMonitor"`
|
|
||||||
Hudson_NodeMonitors_DiskSpaceMonitor interface{} `json:"hudson.node_monitors.DiskSpaceMonitor"`
|
|
||||||
Hudson_NodeMonitors_ResponseTimeMonitor struct {
|
|
||||||
Average int64 `json:"average"`
|
|
||||||
} `json:"hudson.node_monitors.ResponseTimeMonitor"`
|
|
||||||
Hudson_NodeMonitors_SwapSpaceMonitor interface{} `json:"hudson.node_monitors.SwapSpaceMonitor"`
|
|
||||||
Hudson_NodeMonitors_TemporarySpaceMonitor interface{} `json:"hudson.node_monitors.TemporarySpaceMonitor"`
|
|
||||||
} `json:"monitorData"`
|
|
||||||
NumExecutors int64 `json:"numExecutors"`
|
|
||||||
Offline bool `json:"offline"`
|
|
||||||
OfflineCause struct{} `json:"offlineCause"`
|
|
||||||
OfflineCauseReason string `json:"offlineCauseReason"`
|
|
||||||
OneOffExecutors []interface{} `json:"oneOffExecutors"`
|
|
||||||
TemporarilyOffline bool `json:"temporarilyOffline"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) Info() (*NodeResponse, error) {
|
|
||||||
_, err := n.Poll()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return n.Raw, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) GetName() string {
|
|
||||||
return n.Raw.DisplayName
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) Delete() (bool, error) {
|
|
||||||
resp, err := n.Jenkins.Requester.Post(n.Base+"/doDelete", nil, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return resp.StatusCode == 200, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) IsOnline() (bool, error) {
|
|
||||||
_, err := n.Poll()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return !n.Raw.Offline, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) IsTemporarilyOffline() (bool, error) {
|
|
||||||
_, err := n.Poll()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return n.Raw.TemporarilyOffline, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) IsIdle() (bool, error) {
|
|
||||||
_, err := n.Poll()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return n.Raw.Idle, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) IsJnlpAgent() (bool, error) {
|
|
||||||
_, err := n.Poll()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return n.Raw.JnlpAgent, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) SetOnline() (bool, error) {
|
|
||||||
_, err := n.Poll()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.Raw.Offline && !n.Raw.TemporarilyOffline {
|
|
||||||
return false, errors.New("Node is Permanently offline, can't bring it up")
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.Raw.Offline && n.Raw.TemporarilyOffline {
|
|
||||||
return n.ToggleTemporarilyOffline()
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) SetOffline(options ...interface{}) (bool, error) {
|
|
||||||
if !n.Raw.Offline {
|
|
||||||
return n.ToggleTemporarilyOffline(options...)
|
|
||||||
}
|
|
||||||
return false, errors.New("Node already Offline")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) ToggleTemporarilyOffline(options ...interface{}) (bool, error) {
|
|
||||||
state_before, err := n.IsTemporarilyOffline()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
qr := map[string]string{"offlineMessage": "requested from gojenkins"}
|
|
||||||
if len(options) > 0 {
|
|
||||||
qr["offlineMessage"] = options[0].(string)
|
|
||||||
}
|
|
||||||
_, err = n.Jenkins.Requester.Post(n.Base+"/toggleOffline", nil, nil, qr)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
new_state, err := n.IsTemporarilyOffline()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if state_before == new_state {
|
|
||||||
return false, errors.New("Node state not changed")
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) Poll() (int, error) {
|
|
||||||
response, err := n.Jenkins.Requester.GetJSON(n.Base, n.Raw, nil)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return response.StatusCode, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) LaunchNodeBySSH() (int, error) {
|
|
||||||
qr := map[string]string{
|
|
||||||
"json": "",
|
|
||||||
"Submit": "Launch slave agent",
|
|
||||||
}
|
|
||||||
response, err := n.Jenkins.Requester.Post(n.Base+"/launchSlaveAgent", nil, nil, qr)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return response.StatusCode, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) Disconnect() (int, error) {
|
|
||||||
qr := map[string]string{
|
|
||||||
"offlineMessage": "",
|
|
||||||
"json": makeJson(map[string]string{"offlineMessage": ""}),
|
|
||||||
"Submit": "Yes",
|
|
||||||
}
|
|
||||||
response, err := n.Jenkins.Requester.Post(n.Base+"/doDisconnect", nil, nil, qr)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return response.StatusCode, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Node) GetLogText() (string, error) {
|
|
||||||
var log string
|
|
||||||
|
|
||||||
_, err := n.Jenkins.Requester.Post(n.Base+"/log", nil, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
qr := map[string]string{"start": "0"}
|
|
||||||
_, err = n.Jenkins.Requester.GetJSON(n.Base+"/logText/progressiveHtml/", &log, qr)
|
|
||||||
if err != nil {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return log, nil
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
// Copyright 2015 Vadim Kravcenko
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
|
||||||
// not use this file except in compliance with the License. You may obtain
|
|
||||||
// a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
// License for the specific language governing permissions and limitations
|
|
||||||
// under the License.
|
|
||||||
|
|
||||||
package gojenkins
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Plugins struct {
|
|
||||||
Jenkins *Jenkins
|
|
||||||
Raw *PluginResponse
|
|
||||||
Base string
|
|
||||||
Depth int
|
|
||||||
}
|
|
||||||
|
|
||||||
type PluginResponse struct {
|
|
||||||
Plugins []Plugin `json:"plugins"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Plugin struct {
|
|
||||||
Active bool `json:"active"`
|
|
||||||
BackupVersion interface{} `json:"backupVersion"`
|
|
||||||
Bundled bool `json:"bundled"`
|
|
||||||
Deleted bool `json:"deleted"`
|
|
||||||
Dependencies []struct {
|
|
||||||
Optional string `json:"optional"`
|
|
||||||
ShortName string `json:"shortname"`
|
|
||||||
Version string `json:"version"`
|
|
||||||
} `json:"dependencies"`
|
|
||||||
Downgradable bool `json:"downgradable"`
|
|
||||||
Enabled bool `json:"enabled"`
|
|
||||||
HasUpdate bool `json:"hasUpdate"`
|
|
||||||
LongName string `json:"longName"`
|
|
||||||
Pinned bool `json:"pinned"`
|
|
||||||
ShortName string `json:"shortName"`
|
|
||||||
SupportsDynamicLoad string `json:"supportsDynamicLoad"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
Version string `json:"version"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Plugins) Count() int {
|
|
||||||
return len(p.Raw.Plugins)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Plugins) Contains(name string) *Plugin {
|
|
||||||
for _, p := range p.Raw.Plugins {
|
|
||||||
if p.LongName == name || p.ShortName == name {
|
|
||||||
return &p
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Plugins) Poll() (int, error) {
|
|
||||||
qr := map[string]string{
|
|
||||||
"depth": strconv.Itoa(p.Depth),
|
|
||||||
}
|
|
||||||
response, err := p.Jenkins.Requester.GetJSON(p.Base, p.Raw, qr)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return response.StatusCode, nil
|
|
||||||
}
|
|
||||||
@@ -1,158 +0,0 @@
|
|||||||
// Copyright 2015 Vadim Kravcenko
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
|
||||||
// not use this file except in compliance with the License. You may obtain
|
|
||||||
// a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
// License for the specific language governing permissions and limitations
|
|
||||||
// under the License.
|
|
||||||
|
|
||||||
package gojenkins
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Queue struct {
|
|
||||||
Jenkins *Jenkins
|
|
||||||
Raw *queueResponse
|
|
||||||
Base string
|
|
||||||
}
|
|
||||||
|
|
||||||
type queueResponse struct {
|
|
||||||
Items []taskResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
type Task struct {
|
|
||||||
Raw *taskResponse
|
|
||||||
Jenkins *Jenkins
|
|
||||||
Queue *Queue
|
|
||||||
}
|
|
||||||
|
|
||||||
type taskResponse struct {
|
|
||||||
Actions []generalAction `json:"actions"`
|
|
||||||
Blocked bool `json:"blocked"`
|
|
||||||
Buildable bool `json:"buildable"`
|
|
||||||
BuildableStartMilliseconds int64 `json:"buildableStartMilliseconds"`
|
|
||||||
ID int64 `json:"id"`
|
|
||||||
InQueueSince int64 `json:"inQueueSince"`
|
|
||||||
Params string `json:"params"`
|
|
||||||
Pending bool `json:"pending"`
|
|
||||||
Stuck bool `json:"stuck"`
|
|
||||||
Task struct {
|
|
||||||
Color string `json:"color"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
} `json:"task"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
Why string `json:"why"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type generalAction struct {
|
|
||||||
Causes []map[string]interface{}
|
|
||||||
Parameters []parameter
|
|
||||||
}
|
|
||||||
|
|
||||||
type QueueItemResponse struct {
|
|
||||||
Actions []generalAction `json:"actions"`
|
|
||||||
Blocked bool `json:"blocked"`
|
|
||||||
Buildable bool `json:"buildable"`
|
|
||||||
ID int64 `json:"id"`
|
|
||||||
InQueueSince int64 `json:"inQueueSince"`
|
|
||||||
Params string `json:"params"`
|
|
||||||
Stuck bool `json:"stuck"`
|
|
||||||
Task struct {
|
|
||||||
Color string `json:"color"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
} `json:"task"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
Cancelled bool `json:"cancelled"`
|
|
||||||
Why string `json:"why"`
|
|
||||||
Executable struct {
|
|
||||||
Number int64 `json:"number"`
|
|
||||||
Url string `json:"url"`
|
|
||||||
} `json:"executable"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *Queue) Tasks() []*Task {
|
|
||||||
tasks := make([]*Task, len(q.Raw.Items))
|
|
||||||
for i, t := range q.Raw.Items {
|
|
||||||
tasks[i] = &Task{Jenkins: q.Jenkins, Queue: q, Raw: &t}
|
|
||||||
}
|
|
||||||
return tasks
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *Queue) GetTaskById(id int64) *Task {
|
|
||||||
for _, t := range q.Raw.Items {
|
|
||||||
if t.ID == id {
|
|
||||||
return &Task{Jenkins: q.Jenkins, Queue: q, Raw: &t}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *Queue) GetTasksForJob(name string) []*Task {
|
|
||||||
tasks := make([]*Task, 0)
|
|
||||||
for _, t := range q.Raw.Items {
|
|
||||||
if t.Task.Name == name {
|
|
||||||
tasks = append(tasks, &Task{Jenkins: q.Jenkins, Queue: q, Raw: &t})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tasks
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *Queue) CancelTask(id int64) (bool, error) {
|
|
||||||
task := q.GetTaskById(id)
|
|
||||||
return task.Cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Task) Cancel() (bool, error) {
|
|
||||||
qr := map[string]string{
|
|
||||||
"id": strconv.FormatInt(t.Raw.ID, 10),
|
|
||||||
}
|
|
||||||
response, err := t.Jenkins.Requester.Post(t.Jenkins.GetQueueUrl()+"/cancelItem", nil, t.Raw, qr)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return response.StatusCode == 200, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Task) GetJob() (*Job, error) {
|
|
||||||
return t.Jenkins.GetJob(t.Raw.Task.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Task) GetWhy() string {
|
|
||||||
return t.Raw.Why
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Task) GetParameters() []parameter {
|
|
||||||
for _, a := range t.Raw.Actions {
|
|
||||||
if a.Parameters != nil {
|
|
||||||
return a.Parameters
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Task) GetCauses() []map[string]interface{} {
|
|
||||||
for _, a := range t.Raw.Actions {
|
|
||||||
if a.Causes != nil {
|
|
||||||
return a.Causes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *Queue) Poll() (int, error) {
|
|
||||||
response, err := q.Jenkins.Requester.GetJSON(q.Base, q.Raw, nil)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return response.StatusCode, nil
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
// Copyright 2015 Vadim Kravcenko
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
|
||||||
// not use this file except in compliance with the License. You may obtain
|
|
||||||
// a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
// License for the specific language governing permissions and limitations
|
|
||||||
// under the License.
|
|
||||||
|
|
||||||
package gojenkins
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
func makeJson(data interface{}) string {
|
|
||||||
str, err := json.Marshal(data)
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return string(json.RawMessage(str))
|
|
||||||
}
|
|
||||||
|
|
||||||
func Reverse(s string) string {
|
|
||||||
size := len(s)
|
|
||||||
buf := make([]byte, size)
|
|
||||||
for start := 0; start < size; {
|
|
||||||
r, n := utf8.DecodeRuneInString(s[start:])
|
|
||||||
start += n
|
|
||||||
utf8.EncodeRune(buf[size-start:], r)
|
|
||||||
}
|
|
||||||
return string(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
type JenkinsBlueTime time.Time
|
|
||||||
|
|
||||||
func (t *JenkinsBlueTime) UnmarshalJSON(b []byte) error {
|
|
||||||
if b == nil || strings.Trim(string(b), "\"") == "null" {
|
|
||||||
*t = JenkinsBlueTime(time.Time{})
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
j, err := time.Parse("2006-01-02T15:04:05.000-0700", strings.Trim(string(b), "\""))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*t = JenkinsBlueTime(j)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t JenkinsBlueTime) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(time.Time(t))
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package utils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/asaskevich/govalidator"
|
|
||||||
"kubesphere.io/kubesphere/pkg/gojenkins"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetJenkinsStatusCode(jenkinsErr error) int {
|
|
||||||
if code, err := strconv.Atoi(jenkinsErr.Error()); err == nil {
|
|
||||||
message := http.StatusText(code)
|
|
||||||
if !govalidator.IsNull(message) {
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if jErr, ok := jenkinsErr.(*gojenkins.ErrorResponse); ok {
|
|
||||||
return jErr.Response.StatusCode
|
|
||||||
}
|
|
||||||
return http.StatusInternalServerError
|
|
||||||
}
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
// Copyright 2015 Vadim Kravcenko
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
|
||||||
// not use this file except in compliance with the License. You may obtain
|
|
||||||
// a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
// License for the specific language governing permissions and limitations
|
|
||||||
// under the License.
|
|
||||||
|
|
||||||
package gojenkins
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
type View struct {
|
|
||||||
Raw *ViewResponse
|
|
||||||
Jenkins *Jenkins
|
|
||||||
Base string
|
|
||||||
}
|
|
||||||
|
|
||||||
type ViewResponse struct {
|
|
||||||
Description string `json:"description"`
|
|
||||||
Jobs []InnerJob `json:"jobs"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Property []interface{} `json:"property"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
LIST_VIEW = "hudson.model.ListView"
|
|
||||||
NESTED_VIEW = "hudson.plugins.nested_view.NestedView"
|
|
||||||
MY_VIEW = "hudson.model.MyView"
|
|
||||||
DASHBOARD_VIEW = "hudson.plugins.view.dashboard.Dashboard"
|
|
||||||
PIPELINE_VIEW = "au.com.centrumsystems.hudson.plugin.buildpipeline.BuildPipelineView"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Returns True if successfully added Job, otherwise false
|
|
||||||
func (v *View) AddJob(name string) (bool, error) {
|
|
||||||
url := "/addJobToView"
|
|
||||||
qr := map[string]string{"name": name}
|
|
||||||
resp, err := v.Jenkins.Requester.Post(v.Base+url, nil, nil, qr)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if resp.StatusCode == 200 {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
return false, errors.New(strconv.Itoa(resp.StatusCode))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns True if successfully deleted Job, otherwise false
|
|
||||||
func (v *View) DeleteJob(name string) (bool, error) {
|
|
||||||
url := "/removeJobFromView"
|
|
||||||
qr := map[string]string{"name": name}
|
|
||||||
resp, err := v.Jenkins.Requester.Post(v.Base+url, nil, nil, qr)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if resp.StatusCode == 200 {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
return false, errors.New(strconv.Itoa(resp.StatusCode))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) GetDescription() string {
|
|
||||||
return v.Raw.Description
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) GetJobs() []InnerJob {
|
|
||||||
return v.Raw.Jobs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) GetName() string {
|
|
||||||
return v.Raw.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) GetUrl() string {
|
|
||||||
return v.Raw.URL
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *View) Poll() (int, error) {
|
|
||||||
response, err := v.Jenkins.Requester.GetJSON(v.Base, v.Raw, nil)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return response.StatusCode, nil
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1 +1,43 @@
|
|||||||
package v1alpha2
|
package v1alpha2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||||
|
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/devops"
|
||||||
|
devopsClient "kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/s3"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/sonarqube"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProjectPipelineHandler struct {
|
||||||
|
projectCredentialOperator devops.ProjectCredentialOperator
|
||||||
|
projectMemberOperator devops.ProjectMemberOperator
|
||||||
|
projectPipelineOperator devops.ProjectPipelineOperator
|
||||||
|
devopsOperator devops.DevopsOperator
|
||||||
|
projectOperator devops.ProjectOperator
|
||||||
|
}
|
||||||
|
|
||||||
|
type PipelineSonarHandler struct {
|
||||||
|
pipelineSonarGetter devops.PipelineSonarGetter
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewProjectPipelineHandler(devopsClient devopsClient.Interface, dbClient *mysql.Database) ProjectPipelineHandler {
|
||||||
|
return ProjectPipelineHandler{
|
||||||
|
projectCredentialOperator: devops.NewProjectCredentialOperator(devopsClient, dbClient),
|
||||||
|
projectMemberOperator: devops.NewProjectMemberOperator(devopsClient, dbClient),
|
||||||
|
projectPipelineOperator: devops.NewProjectPipelineOperator(devopsClient),
|
||||||
|
devopsOperator: devops.NewDevopsOperator(devopsClient),
|
||||||
|
projectOperator: devops.NewProjectOperator(dbClient),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPipelineSonarHandler(devopsClient devopsClient.Interface, sonarClient sonarqube.SonarInterface) PipelineSonarHandler {
|
||||||
|
return PipelineSonarHandler{
|
||||||
|
pipelineSonarGetter: devops.NewPipelineSonarGetter(devopsClient, sonarClient),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewS2iBinaryHandler(client versioned.Interface, informers externalversions.SharedInformerFactory, s3Client s3.Interface) S2iBinaryHandler {
|
||||||
|
return S2iBinaryHandler{devops.NewS2iBinaryUploader(client, informers, s3Client)}
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package devops
|
package v1alpha2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -19,19 +19,19 @@ import (
|
|||||||
"github.com/emicklei/go-restful"
|
"github.com/emicklei/go-restful"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
"kubesphere.io/kubesphere/pkg/constants"
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
"kubesphere.io/kubesphere/pkg/models/devops"
|
|
||||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||||
"kubesphere.io/kubesphere/pkg/server/params"
|
"kubesphere.io/kubesphere/pkg/server/params"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
"kubesphere.io/kubesphere/pkg/utils/reflectutils"
|
"kubesphere.io/kubesphere/pkg/utils/reflectutils"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetDevOpsProjectMembersHandler(request *restful.Request, resp *restful.Response) {
|
func (h ProjectPipelineHandler) GetDevOpsProjectMembersHandler(request *restful.Request, resp *restful.Response) {
|
||||||
|
|
||||||
projectId := request.PathParameter("devops")
|
projectId := request.PathParameter("devops")
|
||||||
username := request.HeaderParameter(constants.UserNameHeader)
|
username := request.HeaderParameter(constants.UserNameHeader)
|
||||||
|
|
||||||
err := devops.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
|
err := h.projectOperator.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||||
@@ -42,7 +42,7 @@ func GetDevOpsProjectMembersHandler(request *restful.Request, resp *restful.Resp
|
|||||||
limit, offset := params.ParsePaging(request.QueryParameter(params.PagingParam))
|
limit, offset := params.ParsePaging(request.QueryParameter(params.PagingParam))
|
||||||
conditions, err := params.ParseConditions(request.QueryParameter(params.ConditionsParam))
|
conditions, err := params.ParseConditions(request.QueryParameter(params.ConditionsParam))
|
||||||
|
|
||||||
project, err := devops.GetProjectMembers(projectId, conditions, orderBy, reverse, limit, offset)
|
project, err := h.projectMemberOperator.GetProjectMembers(projectId, conditions, orderBy, reverse, limit, offset)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
@@ -54,19 +54,19 @@ func GetDevOpsProjectMembersHandler(request *restful.Request, resp *restful.Resp
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Response) {
|
func (h ProjectPipelineHandler) GetDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Response) {
|
||||||
|
|
||||||
projectId := request.PathParameter("devops")
|
projectId := request.PathParameter("devops")
|
||||||
username := request.HeaderParameter(constants.UserNameHeader)
|
username := request.HeaderParameter(constants.UserNameHeader)
|
||||||
member := request.PathParameter("member")
|
member := request.PathParameter("member")
|
||||||
|
|
||||||
err := devops.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
|
err := h.projectOperator.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
project, err := devops.GetProjectMember(projectId, member)
|
project, err := h.projectMemberOperator.GetProjectMember(projectId, member)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
@@ -78,11 +78,11 @@ func GetDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Respo
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Response) {
|
func (h ProjectPipelineHandler) AddDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Response) {
|
||||||
|
|
||||||
projectId := request.PathParameter("devops")
|
projectId := request.PathParameter("devops")
|
||||||
username := request.HeaderParameter(constants.UserNameHeader)
|
username := request.HeaderParameter(constants.UserNameHeader)
|
||||||
member := &devops.DevOpsProjectMembership{}
|
member := &devops.ProjectMembership{}
|
||||||
err := request.ReadEntity(&member)
|
err := request.ReadEntity(&member)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
@@ -102,14 +102,15 @@ func AddDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Respo
|
|||||||
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), resp)
|
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), resp)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
err = h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
|
||||||
err = devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
project, err := devops.AddProjectMember(projectId, username, member)
|
|
||||||
|
member.GrantBy = username
|
||||||
|
project, err := h.projectMemberOperator.AddProjectMember(projectId, member)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
@@ -121,11 +122,11 @@ func AddDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Respo
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Response) {
|
func (h ProjectPipelineHandler) UpdateDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Response) {
|
||||||
|
|
||||||
projectId := request.PathParameter("devops")
|
projectId := request.PathParameter("devops")
|
||||||
username := request.HeaderParameter(constants.UserNameHeader)
|
username := request.HeaderParameter(constants.UserNameHeader)
|
||||||
member := &devops.DevOpsProjectMembership{}
|
member := &devops.ProjectMembership{}
|
||||||
err := request.ReadEntity(&member)
|
err := request.ReadEntity(&member)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
@@ -153,13 +154,13 @@ func UpdateDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Re
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
|
err = h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
project, err := devops.UpdateProjectMember(projectId, username, member)
|
project, err := h.projectMemberOperator.UpdateProjectMember(projectId, member)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
@@ -171,19 +172,19 @@ func UpdateDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Re
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Response) {
|
func (h ProjectPipelineHandler) DeleteDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Response) {
|
||||||
|
|
||||||
projectId := request.PathParameter("devops")
|
projectId := request.PathParameter("devops")
|
||||||
username := request.HeaderParameter(constants.UserNameHeader)
|
username := request.HeaderParameter(constants.UserNameHeader)
|
||||||
member := request.PathParameter("member")
|
member := request.PathParameter("member")
|
||||||
|
|
||||||
err := devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
|
err := h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
username, err = devops.DeleteProjectMember(projectId, member)
|
username, err = h.projectMemberOperator.DeleteProjectMember(projectId, member)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
errors.ParseSvcErr(err, resp)
|
errors.ParseSvcErr(err, resp)
|
||||||
49
pkg/kapis/devops/v1alpha2/pipeline_sonar.go
Normal file
49
pkg/kapis/devops/v1alpha2/pipeline_sonar.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package v1alpha2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/emicklei/go-restful"
|
||||||
|
"k8s.io/klog"
|
||||||
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/devops"
|
||||||
|
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h PipelineSonarHandler) GetPipelineSonarStatusHandler(request *restful.Request, resp *restful.Response) {
|
||||||
|
projectId := request.PathParameter("devops")
|
||||||
|
username := request.HeaderParameter(constants.UserNameHeader)
|
||||||
|
pipelineId := request.PathParameter("pipeline")
|
||||||
|
err := devops.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sonarStatus, err := h.pipelineSonarGetter.GetPipelineSonar(projectId, pipelineId)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
errors.ParseSvcErr(err, resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp.WriteAsJson(sonarStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h PipelineSonarHandler) GetMultiBranchesPipelineSonarStatusHandler(request *restful.Request, resp *restful.Response) {
|
||||||
|
projectId := request.PathParameter("devops")
|
||||||
|
username := request.HeaderParameter(constants.UserNameHeader)
|
||||||
|
pipelineId := request.PathParameter("pipeline")
|
||||||
|
branchId := request.PathParameter("branch")
|
||||||
|
err := devops.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sonarStatus, err := h.pipelineSonarGetter.GetMultiBranchPipelineSonar(projectId, pipelineId, branchId)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
errors.ParseSvcErr(err, resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp.WriteAsJson(sonarStatus)
|
||||||
|
}
|
||||||
@@ -11,30 +11,30 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package devops
|
package v1alpha2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/emicklei/go-restful"
|
"github.com/emicklei/go-restful"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
"kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
|
"kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
|
||||||
"kubesphere.io/kubesphere/pkg/constants"
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
"kubesphere.io/kubesphere/pkg/models/devops"
|
|
||||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetDevOpsProjectHandler(request *restful.Request, resp *restful.Response) {
|
func (h ProjectPipelineHandler) GetDevOpsProjectHandler(request *restful.Request, resp *restful.Response) {
|
||||||
|
|
||||||
projectId := request.PathParameter("devops")
|
projectId := request.PathParameter("devops")
|
||||||
username := request.HeaderParameter(constants.UserNameHeader)
|
username := request.HeaderParameter(constants.UserNameHeader)
|
||||||
|
|
||||||
err := devops.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
|
err := h.projectOperator.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
project, err := devops.GetProject(projectId)
|
project, err := h.projectOperator.GetProject(projectId)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
@@ -46,7 +46,7 @@ func GetDevOpsProjectHandler(request *restful.Request, resp *restful.Response) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateProjectHandler(request *restful.Request, resp *restful.Response) {
|
func (h ProjectPipelineHandler) UpdateProjectHandler(request *restful.Request, resp *restful.Response) {
|
||||||
|
|
||||||
projectId := request.PathParameter("devops")
|
projectId := request.PathParameter("devops")
|
||||||
username := request.HeaderParameter(constants.UserNameHeader)
|
username := request.HeaderParameter(constants.UserNameHeader)
|
||||||
@@ -58,13 +58,13 @@ func UpdateProjectHandler(request *restful.Request, resp *restful.Response) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
project.ProjectId = projectId
|
project.ProjectId = projectId
|
||||||
err = devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
|
err = h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
project, err = devops.UpdateProject(project)
|
project, err = h.projectOperator.UpdateProject(project)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
122
pkg/kapis/devops/v1alpha2/project_credential.go
Normal file
122
pkg/kapis/devops/v1alpha2/project_credential.go
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2019 The KubeSphere Authors.
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1alpha2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/emicklei/go-restful"
|
||||||
|
"k8s.io/klog"
|
||||||
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
|
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h ProjectPipelineHandler) CreateDevOpsProjectCredentialHandler(request *restful.Request, resp *restful.Response) {
|
||||||
|
|
||||||
|
projectId := request.PathParameter("devops")
|
||||||
|
username := request.HeaderParameter(constants.UserNameHeader)
|
||||||
|
var credential *devops.Credential
|
||||||
|
err := request.ReadEntity(&credential)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
credentialId, err := h.projectCredentialOperator.CreateProjectCredential(projectId, username, credential)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
errors.ParseSvcErr(err, resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.WriteAsJson(struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}{Name: credentialId})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h ProjectPipelineHandler) UpdateDevOpsProjectCredentialHandler(request *restful.Request, resp *restful.Response) {
|
||||||
|
|
||||||
|
projectId := request.PathParameter("devops")
|
||||||
|
credentialId := request.PathParameter("credential")
|
||||||
|
var credential *devops.Credential
|
||||||
|
err := request.ReadEntity(&credential)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
credentialId, err = h.projectCredentialOperator.UpdateProjectCredential(projectId, credentialId, credential)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
errors.ParseSvcErr(err, resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.WriteAsJson(struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}{Name: credentialId})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h ProjectPipelineHandler) DeleteDevOpsProjectCredentialHandler(request *restful.Request, resp *restful.Response) {
|
||||||
|
|
||||||
|
projectId := request.PathParameter("devops")
|
||||||
|
credentialId := request.PathParameter("credential")
|
||||||
|
|
||||||
|
credentialId, err := h.projectCredentialOperator.DeleteProjectCredential(projectId, credentialId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
errors.ParseSvcErr(err, resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.WriteAsJson(struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}{Name: credentialId})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h ProjectPipelineHandler) GetDevOpsProjectCredentialHandler(request *restful.Request, resp *restful.Response) {
|
||||||
|
|
||||||
|
projectId := request.PathParameter("devops")
|
||||||
|
credentialId := request.PathParameter("credential")
|
||||||
|
getContent := request.QueryParameter("content")
|
||||||
|
response, err := h.projectCredentialOperator.GetProjectCredential(projectId, credentialId, getContent)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
errors.ParseSvcErr(err, resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.WriteAsJson(response)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h ProjectPipelineHandler) GetDevOpsProjectCredentialsHandler(request *restful.Request, resp *restful.Response) {
|
||||||
|
projectId := request.PathParameter("devops")
|
||||||
|
|
||||||
|
jenkinsCredentials, err := h.projectCredentialOperator.GetProjectCredentials(projectId)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
errors.ParseSvcErr(err, resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp.WriteAsJson(jenkinsCredentials)
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -11,18 +11,18 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package devops
|
package v1alpha2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/emicklei/go-restful"
|
"github.com/emicklei/go-restful"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
"kubesphere.io/kubesphere/pkg/constants"
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
"kubesphere.io/kubesphere/pkg/models/devops"
|
|
||||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CreateDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.Response) {
|
func (h ProjectPipelineHandler) CreateDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.Response) {
|
||||||
|
|
||||||
projectId := request.PathParameter("devops")
|
projectId := request.PathParameter("devops")
|
||||||
username := request.HeaderParameter(constants.UserNameHeader)
|
username := request.HeaderParameter(constants.UserNameHeader)
|
||||||
@@ -33,13 +33,13 @@ func CreateDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.
|
|||||||
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), resp)
|
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), resp)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner, devops.ProjectMaintainer})
|
err = h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner, devops.ProjectMaintainer})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pipelineName, err := devops.CreateProjectPipeline(projectId, pipeline)
|
pipelineName, err := h.projectPipelineOperator.CreateProjectPipeline(projectId, pipeline)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
@@ -53,18 +53,18 @@ func CreateDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.Response) {
|
func (h ProjectPipelineHandler) DeleteDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.Response) {
|
||||||
projectId := request.PathParameter("devops")
|
projectId := request.PathParameter("devops")
|
||||||
username := request.HeaderParameter(constants.UserNameHeader)
|
username := request.HeaderParameter(constants.UserNameHeader)
|
||||||
pipelineId := request.PathParameter("pipeline")
|
pipelineId := request.PathParameter("pipeline")
|
||||||
|
|
||||||
err := devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner, devops.ProjectMaintainer})
|
err := h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner, devops.ProjectMaintainer})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pipelineName, err := devops.DeleteProjectPipeline(projectId, pipelineId)
|
pipelineName, err := h.projectPipelineOperator.DeleteProjectPipeline(projectId, pipelineId)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
@@ -78,7 +78,7 @@ func DeleteDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.Response) {
|
func (h ProjectPipelineHandler) UpdateDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.Response) {
|
||||||
|
|
||||||
projectId := request.PathParameter("devops")
|
projectId := request.PathParameter("devops")
|
||||||
username := request.HeaderParameter(constants.UserNameHeader)
|
username := request.HeaderParameter(constants.UserNameHeader)
|
||||||
@@ -90,13 +90,13 @@ func UpdateDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.
|
|||||||
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), resp)
|
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), resp)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner, devops.ProjectMaintainer})
|
err = h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner, devops.ProjectMaintainer})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pipelineName, err := devops.UpdateProjectPipeline(projectId, pipelineId, pipeline)
|
pipelineName, err := h.projectPipelineOperator.UpdateProjectPipeline(projectId, pipelineId, pipeline)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
@@ -110,19 +110,19 @@ func UpdateDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.Response) {
|
func (h ProjectPipelineHandler) GetDevOpsProjectPipelineConfigHandler(request *restful.Request, resp *restful.Response) {
|
||||||
|
|
||||||
projectId := request.PathParameter("devops")
|
projectId := request.PathParameter("devops")
|
||||||
username := request.HeaderParameter(constants.UserNameHeader)
|
username := request.HeaderParameter(constants.UserNameHeader)
|
||||||
pipelineId := request.PathParameter("pipeline")
|
pipelineId := request.PathParameter("pipeline")
|
||||||
|
|
||||||
err := devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner, devops.ProjectMaintainer})
|
err := h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner, devops.ProjectMaintainer})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pipeline, err := devops.GetProjectPipeline(projectId, pipelineId)
|
pipeline, err := h.projectPipelineOperator.GetProjectPipelineConfig(projectId, pipelineId)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
@@ -133,42 +133,3 @@ func GetDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.Res
|
|||||||
resp.WriteAsJson(pipeline)
|
resp.WriteAsJson(pipeline)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPipelineSonarStatusHandler(request *restful.Request, resp *restful.Response) {
|
|
||||||
projectId := request.PathParameter("devops")
|
|
||||||
username := request.HeaderParameter(constants.UserNameHeader)
|
|
||||||
pipelineId := request.PathParameter("pipeline")
|
|
||||||
err := devops.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sonarStatus, err := devops.GetPipelineSonar(projectId, pipelineId)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
errors.ParseSvcErr(err, resp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp.WriteAsJson(sonarStatus)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetMultiBranchesPipelineSonarStatusHandler(request *restful.Request, resp *restful.Response) {
|
|
||||||
projectId := request.PathParameter("devops")
|
|
||||||
username := request.HeaderParameter(constants.UserNameHeader)
|
|
||||||
pipelineId := request.PathParameter("pipeline")
|
|
||||||
branchId := request.PathParameter("branch")
|
|
||||||
err := devops.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sonarStatus, err := devops.GetMultiBranchPipelineSonar(projectId, pipelineId, branchId)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
errors.ParseSvcErr(err, resp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp.WriteAsJson(sonarStatus)
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
|||||||
package devops
|
package v1alpha2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"code.cloudfoundry.org/bytefmt"
|
"code.cloudfoundry.org/bytefmt"
|
||||||
@@ -11,7 +11,11 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func UploadS2iBinary(req *restful.Request, resp *restful.Response) {
|
type S2iBinaryHandler struct {
|
||||||
|
s2iUploader devops.S2iBinaryUploader
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h S2iBinaryHandler) UploadS2iBinaryHandler(req *restful.Request, resp *restful.Response) {
|
||||||
ns := req.PathParameter("namespace")
|
ns := req.PathParameter("namespace")
|
||||||
name := req.PathParameter("s2ibinary")
|
name := req.PathParameter("s2ibinary")
|
||||||
|
|
||||||
@@ -62,7 +66,7 @@ func UploadS2iBinary(req *restful.Request, resp *restful.Response) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s2ibin, err := devops.UploadS2iBinary(ns, name, filemd5, req.Request.MultipartForm.File["s2ibinary"][0])
|
s2ibin, err := h.s2iUploader.UploadS2iBinary(ns, name, filemd5, req.Request.MultipartForm.File["s2ibinary"][0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
errors.ParseSvcErr(err, resp)
|
errors.ParseSvcErr(err, resp)
|
||||||
@@ -72,11 +76,11 @@ func UploadS2iBinary(req *restful.Request, resp *restful.Response) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func DownloadS2iBinary(req *restful.Request, resp *restful.Response) {
|
func (h S2iBinaryHandler) DownloadS2iBinaryHandler(req *restful.Request, resp *restful.Response) {
|
||||||
ns := req.PathParameter("namespace")
|
ns := req.PathParameter("namespace")
|
||||||
name := req.PathParameter("s2ibinary")
|
name := req.PathParameter("s2ibinary")
|
||||||
fileName := req.PathParameter("file")
|
fileName := req.PathParameter("file")
|
||||||
url, err := devops.DownloadS2iBinary(ns, name, fileName)
|
url, err := h.s2iUploader.DownloadS2iBinary(ns, name, fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
errors.ParseSvcErr(err, resp)
|
errors.ParseSvcErr(err, resp)
|
||||||
154
pkg/kapis/tenant/v1alpha2/devops.go
Normal file
154
pkg/kapis/tenant/v1alpha2/devops.go
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019 The KubeSphere Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
package v1alpha2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/emicklei/go-restful"
|
||||||
|
"k8s.io/klog"
|
||||||
|
"kubesphere.io/kubesphere/pkg/api"
|
||||||
|
devopsv1alpha2 "kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
|
||||||
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
|
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||||
|
"kubesphere.io/kubesphere/pkg/server/params"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h *tenantHandler) DeleteDevOpsProjectHandler(req *restful.Request, resp *restful.Response) {
|
||||||
|
projectId := req.PathParameter("devops")
|
||||||
|
workspaceName := req.PathParameter("workspace")
|
||||||
|
username := req.HeaderParameter(constants.UserNameHeader)
|
||||||
|
|
||||||
|
_, err := h.tenant.GetWorkspace(workspaceName)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = h.tenant.DeleteDevOpsProject(projectId, username)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
errors.ParseSvcErr(err, resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.WriteAsJson(errors.None)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *tenantHandler) CreateDevOpsProjectHandler(req *restful.Request, resp *restful.Response) {
|
||||||
|
|
||||||
|
workspaceName := req.PathParameter("workspace")
|
||||||
|
username := req.HeaderParameter(constants.UserNameHeader)
|
||||||
|
|
||||||
|
var devops devopsv1alpha2.DevOpsProject
|
||||||
|
|
||||||
|
err := req.ReadEntity(&devops)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
klog.Infof("%+v", err)
|
||||||
|
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
klog.Infoln("create workspace", username, workspaceName, devops)
|
||||||
|
project, err := h.tenant.CreateDevOpsProject(username, workspaceName, &devops)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
errors.ParseSvcErr(err, resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.WriteAsJson(project)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *tenantHandler) GetDevOpsProjectsCountHandler(req *restful.Request, resp *restful.Response) {
|
||||||
|
username := req.HeaderParameter(constants.UserNameHeader)
|
||||||
|
|
||||||
|
result, err := h.tenant.GetDevOpsProjectsCount(username)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
errors.ParseSvcErr(err, resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp.WriteAsJson(struct {
|
||||||
|
Count uint32 `json:"count"`
|
||||||
|
}{Count: result})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *tenantHandler) ListDevOpsProjectsHandler(req *restful.Request, resp *restful.Response) {
|
||||||
|
|
||||||
|
workspace := req.PathParameter("workspace")
|
||||||
|
username := req.PathParameter("member")
|
||||||
|
if username == "" {
|
||||||
|
username = req.HeaderParameter(constants.UserNameHeader)
|
||||||
|
}
|
||||||
|
orderBy := req.QueryParameter(params.OrderByParam)
|
||||||
|
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
|
||||||
|
limit, offset := params.ParsePaging(req)
|
||||||
|
conditions, err := params.ParseConditions(req)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := h.tenant.ListDevOpsProjects(workspace, username, conditions, orderBy, reverse, limit, offset)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
errors.ParseSvcErr(err, resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.WriteAsJson(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *tenantHandler) ListDevOpsRules(req *restful.Request, resp *restful.Response) {
|
||||||
|
|
||||||
|
devops := req.PathParameter("devops")
|
||||||
|
username := req.HeaderParameter(constants.UserNameHeader)
|
||||||
|
|
||||||
|
rules, err := h.tenant.GetUserDevOpsSimpleRules(username, devops)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
errors.ParseSvcErr(err, resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.WriteAsJson(rules)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *tenantHandler) ListDevopsRules(req *restful.Request, resp *restful.Response) {
|
||||||
|
|
||||||
|
devops := req.PathParameter("devops")
|
||||||
|
username := req.HeaderParameter(constants.UserNameHeader)
|
||||||
|
|
||||||
|
rules, err := h.tenant.GetUserDevOpsSimpleRules(username, devops)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
api.HandleInternalError(resp, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.WriteAsJson(rules)
|
||||||
|
}
|
||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/net"
|
"k8s.io/apimachinery/pkg/util/net"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
"kubesphere.io/kubesphere/pkg/api"
|
"kubesphere.io/kubesphere/pkg/api"
|
||||||
devopsv1alpha2 "kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
|
|
||||||
loggingv1alpha2 "kubesphere.io/kubesphere/pkg/api/logging/v1alpha2"
|
loggingv1alpha2 "kubesphere.io/kubesphere/pkg/api/logging/v1alpha2"
|
||||||
"kubesphere.io/kubesphere/pkg/apiserver/logging"
|
"kubesphere.io/kubesphere/pkg/apiserver/logging"
|
||||||
"kubesphere.io/kubesphere/pkg/constants"
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
@@ -184,45 +183,6 @@ func (h *tenantHandler) DeleteNamespace(req *restful.Request, resp *restful.Resp
|
|||||||
resp.WriteAsJson(errors.None)
|
resp.WriteAsJson(errors.None)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *tenantHandler) ListDevopsProjects(req *restful.Request, resp *restful.Response) {
|
|
||||||
|
|
||||||
workspace := req.PathParameter("workspace")
|
|
||||||
username := req.PathParameter("member")
|
|
||||||
if username == "" {
|
|
||||||
username = req.HeaderParameter(constants.UserNameHeader)
|
|
||||||
}
|
|
||||||
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, v1alpha2.CreateTime)
|
|
||||||
limit, offset := params.ParsePaging(req)
|
|
||||||
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, true)
|
|
||||||
conditions, err := params.ParseConditions(req)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
api.HandleBadRequest(resp, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := tenant.ListDevopsProjects(workspace, username, conditions, orderBy, reverse, limit, offset)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
api.HandleInternalError(resp, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.WriteAsJson(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *tenantHandler) GetDevOpsProjectsCount(req *restful.Request, resp *restful.Response) {
|
|
||||||
username := req.HeaderParameter(constants.UserNameHeader)
|
|
||||||
|
|
||||||
result, err := tenant.GetDevOpsProjectsCount(username)
|
|
||||||
if err != nil {
|
|
||||||
api.HandleInternalError(resp, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp.WriteAsJson(struct {
|
|
||||||
Count uint32 `json:"count"`
|
|
||||||
}{Count: result})
|
|
||||||
}
|
|
||||||
func (h *tenantHandler) DeleteDevopsProject(req *restful.Request, resp *restful.Response) {
|
func (h *tenantHandler) DeleteDevopsProject(req *restful.Request, resp *restful.Response) {
|
||||||
projectId := req.PathParameter("devops")
|
projectId := req.PathParameter("devops")
|
||||||
workspace := req.PathParameter("workspace")
|
workspace := req.PathParameter("workspace")
|
||||||
@@ -235,7 +195,7 @@ func (h *tenantHandler) DeleteDevopsProject(req *restful.Request, resp *restful.
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = tenant.DeleteDevOpsProject(projectId, username)
|
err = h.tenant.DeleteDevOpsProject(projectId, username)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.HandleInternalError(resp, err)
|
api.HandleInternalError(resp, err)
|
||||||
@@ -245,30 +205,6 @@ func (h *tenantHandler) DeleteDevopsProject(req *restful.Request, resp *restful.
|
|||||||
resp.WriteAsJson(errors.None)
|
resp.WriteAsJson(errors.None)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *tenantHandler) CreateDevopsProject(req *restful.Request, resp *restful.Response) {
|
|
||||||
|
|
||||||
workspaceName := req.PathParameter("workspace")
|
|
||||||
username := req.HeaderParameter(constants.UserNameHeader)
|
|
||||||
|
|
||||||
var devops devopsv1alpha2.DevOpsProject
|
|
||||||
|
|
||||||
err := req.ReadEntity(&devops)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
api.HandleInternalError(resp, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
project, err := tenant.CreateDevopsProject(username, workspaceName, &devops)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
api.HandleInternalError(resp, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.WriteAsJson(project)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *tenantHandler) ListNamespaceRules(req *restful.Request, resp *restful.Response) {
|
func (h *tenantHandler) ListNamespaceRules(req *restful.Request, resp *restful.Response) {
|
||||||
namespace := req.PathParameter("namespace")
|
namespace := req.PathParameter("namespace")
|
||||||
username := req.HeaderParameter(constants.UserNameHeader)
|
username := req.HeaderParameter(constants.UserNameHeader)
|
||||||
@@ -283,21 +219,6 @@ func (h *tenantHandler) ListNamespaceRules(req *restful.Request, resp *restful.R
|
|||||||
resp.WriteAsJson(rules)
|
resp.WriteAsJson(rules)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *tenantHandler) ListDevopsRules(req *restful.Request, resp *restful.Response) {
|
|
||||||
|
|
||||||
devops := req.PathParameter("devops")
|
|
||||||
username := req.HeaderParameter(constants.UserNameHeader)
|
|
||||||
|
|
||||||
rules, err := tenant.GetUserDevopsSimpleRules(username, devops)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
api.HandleInternalError(resp, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.WriteAsJson(rules)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *tenantHandler) LogQuery(req *restful.Request, resp *restful.Response) {
|
func (h *tenantHandler) LogQuery(req *restful.Request, resp *restful.Response) {
|
||||||
operation := req.QueryParameter("operation")
|
operation := req.QueryParameter("operation")
|
||||||
req, err := h.regenerateLoggingRequest(req)
|
req, err := h.regenerateLoggingRequest(req)
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ func AddToContainer(c *restful.Container) error {
|
|||||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
|
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
|
||||||
|
|
||||||
ws.Route(ws.GET("/workspaces/{workspace}/devops").
|
ws.Route(ws.GET("/workspaces/{workspace}/devops").
|
||||||
To(handler.ListDevopsProjects).
|
To(handler.ListDevOpsProjectsHandler).
|
||||||
Param(ws.PathParameter("workspace", "workspace name")).
|
Param(ws.PathParameter("workspace", "workspace name")).
|
||||||
Param(ws.QueryParameter(params.PagingParam, "page").
|
Param(ws.QueryParameter(params.PagingParam, "page").
|
||||||
Required(false).
|
Required(false).
|
||||||
@@ -115,7 +115,7 @@ func AddToContainer(c *restful.Container) error {
|
|||||||
Doc("List devops projects for the current user").
|
Doc("List devops projects for the current user").
|
||||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
|
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
|
||||||
ws.Route(ws.GET("/workspaces/{workspace}/members/{member}/devops").
|
ws.Route(ws.GET("/workspaces/{workspace}/members/{member}/devops").
|
||||||
To(handler.ListDevopsProjects).
|
To(handler.ListDevOpsProjectsHandler).
|
||||||
Param(ws.PathParameter("workspace", "workspace name")).
|
Param(ws.PathParameter("workspace", "workspace name")).
|
||||||
Param(ws.PathParameter("member", "workspace member's username")).
|
Param(ws.PathParameter("member", "workspace member's username")).
|
||||||
Param(ws.QueryParameter(params.PagingParam, "page").
|
Param(ws.QueryParameter(params.PagingParam, "page").
|
||||||
@@ -129,14 +129,14 @@ func AddToContainer(c *restful.Container) error {
|
|||||||
Doc("List the devops projects for the workspace member").
|
Doc("List the devops projects for the workspace member").
|
||||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
|
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
|
||||||
ws.Route(ws.GET("/devopscount").
|
ws.Route(ws.GET("/devopscount").
|
||||||
To(handler.GetDevOpsProjectsCount).
|
To(handler.GetDevOpsProjectsCountHandler).
|
||||||
Returns(http.StatusOK, api.StatusOK, struct {
|
Returns(http.StatusOK, api.StatusOK, struct {
|
||||||
Count uint32 `json:"count"`
|
Count uint32 `json:"count"`
|
||||||
}{}).
|
}{}).
|
||||||
Doc("Get the devops projects count for the member").
|
Doc("Get the devops projects count for the member").
|
||||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
|
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
|
||||||
ws.Route(ws.POST("/workspaces/{workspace}/devops").
|
ws.Route(ws.POST("/workspaces/{workspace}/devops").
|
||||||
To(handler.CreateDevopsProject).
|
To(handler.CreateDevOpsProjectHandler).
|
||||||
Param(ws.PathParameter("workspace", "workspace name")).
|
Param(ws.PathParameter("workspace", "workspace name")).
|
||||||
Doc("Create a devops project in the specified workspace").
|
Doc("Create a devops project in the specified workspace").
|
||||||
Reads(devopsv1alpha2.DevOpsProject{}).
|
Reads(devopsv1alpha2.DevOpsProject{}).
|
||||||
|
|||||||
@@ -14,13 +14,7 @@ limitations under the License.
|
|||||||
package devops
|
package devops
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/fatih/structs"
|
"github.com/fatih/structs"
|
||||||
"k8s.io/klog"
|
|
||||||
"kubesphere.io/kubesphere/pkg/db"
|
|
||||||
"kubesphere.io/kubesphere/pkg/gojenkins"
|
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client"
|
|
||||||
"kubesphere.io/kubesphere/pkg/utils/reflectutils"
|
|
||||||
"kubesphere.io/kubesphere/pkg/utils/stringutils"
|
"kubesphere.io/kubesphere/pkg/utils/stringutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -67,298 +61,3 @@ const (
|
|||||||
const (
|
const (
|
||||||
KS_ADMIN = "admin"
|
KS_ADMIN = "admin"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
ProjectOwner = "owner"
|
|
||||||
ProjectMaintainer = "maintainer"
|
|
||||||
ProjectDeveloper = "developer"
|
|
||||||
ProjectReporter = "reporter"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
JenkinsAllUserRoleName = "kubesphere-user"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Role struct {
|
|
||||||
Name string `json:"name" description:"role's name e.g. owner'"`
|
|
||||||
Description string `json:"description" description:"role 's description'"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var DefaultRoles = []*Role{
|
|
||||||
{
|
|
||||||
Name: ProjectOwner,
|
|
||||||
Description: "Owner have access to do all the operations of a DevOps project and own the highest permissions as well.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: ProjectMaintainer,
|
|
||||||
Description: "Maintainer have access to manage pipeline and credential configuration in a DevOps project.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: ProjectDeveloper,
|
|
||||||
Description: "Developer is able to view and trigger the pipeline.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: ProjectReporter,
|
|
||||||
Description: "Reporter is only allowed to view the status of the pipeline.",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var AllRoleSlice = []string{ProjectDeveloper, ProjectReporter, ProjectMaintainer, ProjectOwner}
|
|
||||||
|
|
||||||
var JenkinsOwnerProjectPermissionIds = &gojenkins.ProjectPermissionIds{
|
|
||||||
CredentialCreate: true,
|
|
||||||
CredentialDelete: true,
|
|
||||||
CredentialManageDomains: true,
|
|
||||||
CredentialUpdate: true,
|
|
||||||
CredentialView: true,
|
|
||||||
ItemBuild: true,
|
|
||||||
ItemCancel: true,
|
|
||||||
ItemConfigure: true,
|
|
||||||
ItemCreate: true,
|
|
||||||
ItemDelete: true,
|
|
||||||
ItemDiscover: true,
|
|
||||||
ItemMove: true,
|
|
||||||
ItemRead: true,
|
|
||||||
ItemWorkspace: true,
|
|
||||||
RunDelete: true,
|
|
||||||
RunReplay: true,
|
|
||||||
RunUpdate: true,
|
|
||||||
SCMTag: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
var JenkinsProjectPermissionMap = map[string]gojenkins.ProjectPermissionIds{
|
|
||||||
ProjectOwner: {
|
|
||||||
CredentialCreate: true,
|
|
||||||
CredentialDelete: true,
|
|
||||||
CredentialManageDomains: true,
|
|
||||||
CredentialUpdate: true,
|
|
||||||
CredentialView: true,
|
|
||||||
ItemBuild: true,
|
|
||||||
ItemCancel: true,
|
|
||||||
ItemConfigure: true,
|
|
||||||
ItemCreate: true,
|
|
||||||
ItemDelete: true,
|
|
||||||
ItemDiscover: true,
|
|
||||||
ItemMove: true,
|
|
||||||
ItemRead: true,
|
|
||||||
ItemWorkspace: true,
|
|
||||||
RunDelete: true,
|
|
||||||
RunReplay: true,
|
|
||||||
RunUpdate: true,
|
|
||||||
SCMTag: true,
|
|
||||||
},
|
|
||||||
ProjectMaintainer: {
|
|
||||||
CredentialCreate: true,
|
|
||||||
CredentialDelete: true,
|
|
||||||
CredentialManageDomains: true,
|
|
||||||
CredentialUpdate: true,
|
|
||||||
CredentialView: true,
|
|
||||||
ItemBuild: true,
|
|
||||||
ItemCancel: true,
|
|
||||||
ItemConfigure: false,
|
|
||||||
ItemCreate: true,
|
|
||||||
ItemDelete: false,
|
|
||||||
ItemDiscover: true,
|
|
||||||
ItemMove: false,
|
|
||||||
ItemRead: true,
|
|
||||||
ItemWorkspace: true,
|
|
||||||
RunDelete: true,
|
|
||||||
RunReplay: true,
|
|
||||||
RunUpdate: true,
|
|
||||||
SCMTag: true,
|
|
||||||
},
|
|
||||||
ProjectDeveloper: {
|
|
||||||
CredentialCreate: false,
|
|
||||||
CredentialDelete: false,
|
|
||||||
CredentialManageDomains: false,
|
|
||||||
CredentialUpdate: false,
|
|
||||||
CredentialView: false,
|
|
||||||
ItemBuild: true,
|
|
||||||
ItemCancel: true,
|
|
||||||
ItemConfigure: false,
|
|
||||||
ItemCreate: false,
|
|
||||||
ItemDelete: false,
|
|
||||||
ItemDiscover: true,
|
|
||||||
ItemMove: false,
|
|
||||||
ItemRead: true,
|
|
||||||
ItemWorkspace: true,
|
|
||||||
RunDelete: true,
|
|
||||||
RunReplay: true,
|
|
||||||
RunUpdate: true,
|
|
||||||
SCMTag: false,
|
|
||||||
},
|
|
||||||
ProjectReporter: {
|
|
||||||
CredentialCreate: false,
|
|
||||||
CredentialDelete: false,
|
|
||||||
CredentialManageDomains: false,
|
|
||||||
CredentialUpdate: false,
|
|
||||||
CredentialView: false,
|
|
||||||
ItemBuild: false,
|
|
||||||
ItemCancel: false,
|
|
||||||
ItemConfigure: false,
|
|
||||||
ItemCreate: false,
|
|
||||||
ItemDelete: false,
|
|
||||||
ItemDiscover: true,
|
|
||||||
ItemMove: false,
|
|
||||||
ItemRead: true,
|
|
||||||
ItemWorkspace: false,
|
|
||||||
RunDelete: false,
|
|
||||||
RunReplay: false,
|
|
||||||
RunUpdate: false,
|
|
||||||
SCMTag: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var JenkinsPipelinePermissionMap = map[string]gojenkins.ProjectPermissionIds{
|
|
||||||
ProjectOwner: {
|
|
||||||
CredentialCreate: true,
|
|
||||||
CredentialDelete: true,
|
|
||||||
CredentialManageDomains: true,
|
|
||||||
CredentialUpdate: true,
|
|
||||||
CredentialView: true,
|
|
||||||
ItemBuild: true,
|
|
||||||
ItemCancel: true,
|
|
||||||
ItemConfigure: true,
|
|
||||||
ItemCreate: true,
|
|
||||||
ItemDelete: true,
|
|
||||||
ItemDiscover: true,
|
|
||||||
ItemMove: true,
|
|
||||||
ItemRead: true,
|
|
||||||
ItemWorkspace: true,
|
|
||||||
RunDelete: true,
|
|
||||||
RunReplay: true,
|
|
||||||
RunUpdate: true,
|
|
||||||
SCMTag: true,
|
|
||||||
},
|
|
||||||
ProjectMaintainer: {
|
|
||||||
CredentialCreate: true,
|
|
||||||
CredentialDelete: true,
|
|
||||||
CredentialManageDomains: true,
|
|
||||||
CredentialUpdate: true,
|
|
||||||
CredentialView: true,
|
|
||||||
ItemBuild: true,
|
|
||||||
ItemCancel: true,
|
|
||||||
ItemConfigure: true,
|
|
||||||
ItemCreate: true,
|
|
||||||
ItemDelete: true,
|
|
||||||
ItemDiscover: true,
|
|
||||||
ItemMove: true,
|
|
||||||
ItemRead: true,
|
|
||||||
ItemWorkspace: true,
|
|
||||||
RunDelete: true,
|
|
||||||
RunReplay: true,
|
|
||||||
RunUpdate: true,
|
|
||||||
SCMTag: true,
|
|
||||||
},
|
|
||||||
ProjectDeveloper: {
|
|
||||||
CredentialCreate: false,
|
|
||||||
CredentialDelete: false,
|
|
||||||
CredentialManageDomains: false,
|
|
||||||
CredentialUpdate: false,
|
|
||||||
CredentialView: false,
|
|
||||||
ItemBuild: true,
|
|
||||||
ItemCancel: true,
|
|
||||||
ItemConfigure: false,
|
|
||||||
ItemCreate: false,
|
|
||||||
ItemDelete: false,
|
|
||||||
ItemDiscover: true,
|
|
||||||
ItemMove: false,
|
|
||||||
ItemRead: true,
|
|
||||||
ItemWorkspace: true,
|
|
||||||
RunDelete: true,
|
|
||||||
RunReplay: true,
|
|
||||||
RunUpdate: true,
|
|
||||||
SCMTag: false,
|
|
||||||
},
|
|
||||||
ProjectReporter: {
|
|
||||||
CredentialCreate: false,
|
|
||||||
CredentialDelete: false,
|
|
||||||
CredentialManageDomains: false,
|
|
||||||
CredentialUpdate: false,
|
|
||||||
CredentialView: false,
|
|
||||||
ItemBuild: false,
|
|
||||||
ItemCancel: false,
|
|
||||||
ItemConfigure: false,
|
|
||||||
ItemCreate: false,
|
|
||||||
ItemDelete: false,
|
|
||||||
ItemDiscover: true,
|
|
||||||
ItemMove: false,
|
|
||||||
ItemRead: true,
|
|
||||||
ItemWorkspace: false,
|
|
||||||
RunDelete: false,
|
|
||||||
RunReplay: false,
|
|
||||||
RunUpdate: false,
|
|
||||||
SCMTag: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetProjectRoleName(projectId, role string) string {
|
|
||||||
return fmt.Sprintf("%s-%s-project", projectId, role)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetPipelineRoleName(projectId, role string) string {
|
|
||||||
return fmt.Sprintf("%s-%s-pipeline", projectId, role)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetProjectRolePattern(projectId string) string {
|
|
||||||
return fmt.Sprintf("^%s$", projectId)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetPipelineRolePattern(projectId string) string {
|
|
||||||
return fmt.Sprintf("^%s/.*", projectId)
|
|
||||||
}
|
|
||||||
|
|
||||||
func CheckProjectUserInRole(username, projectId string, roles []string) error {
|
|
||||||
if username == KS_ADMIN {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
dbconn, err := client.ClientSets().MySQL()
|
|
||||||
if err != nil {
|
|
||||||
if _, ok := err.(client.ClientSetNotEnabledError); ok {
|
|
||||||
klog.Error("mysql is not enabled")
|
|
||||||
} else {
|
|
||||||
klog.Error("error creating mysql client", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
membership := &DevOpsProjectMembership{}
|
|
||||||
err = dbconn.Select(DevOpsProjectMembershipColumns...).
|
|
||||||
From(DevOpsProjectMembershipTableName).
|
|
||||||
Where(db.And(
|
|
||||||
db.Eq(DevOpsProjectMembershipUsernameColumn, username),
|
|
||||||
db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId))).LoadOne(membership)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !reflectutils.In(membership.Role, roles) {
|
|
||||||
return fmt.Errorf("user [%s] in project [%s] role is not in %s", username, projectId, roles)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetProjectUserRole(username, projectId string) (string, error) {
|
|
||||||
if username == KS_ADMIN {
|
|
||||||
return ProjectOwner, nil
|
|
||||||
}
|
|
||||||
dbconn, err := client.ClientSets().MySQL()
|
|
||||||
if err != nil {
|
|
||||||
if _, ok := err.(client.ClientSetNotEnabledError); ok {
|
|
||||||
klog.Error("mysql is not enabled")
|
|
||||||
} else {
|
|
||||||
klog.Error("error creating mysql client", err)
|
|
||||||
}
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
membership := &DevOpsProjectMembership{}
|
|
||||||
err = dbconn.Select(DevOpsProjectMembershipColumns...).
|
|
||||||
From(DevOpsProjectMembershipTableName).
|
|
||||||
Where(db.And(
|
|
||||||
db.Eq(DevOpsProjectMembershipUsernameColumn, username),
|
|
||||||
db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId))).LoadOne(membership)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return membership.Role, nil
|
|
||||||
}
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,40 +1,113 @@
|
|||||||
package devops
|
package devops
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops/fake"
|
||||||
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_parseCronJobTime(t *testing.T) {
|
const baseUrl = "http://127.0.0.1/kapis/devops.kubesphere.io/v1alpha2/"
|
||||||
type Except struct {
|
|
||||||
Last string
|
func TestGetNodesDetail(t *testing.T) {
|
||||||
Next string
|
fakeData := make(map[string]interface{})
|
||||||
|
PipelineRunNodes := []devops.PipelineRunNodes{
|
||||||
|
{
|
||||||
|
DisplayName: "Deploy to Kubernetes",
|
||||||
|
ID: "1",
|
||||||
|
Result: "SUCCESS",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
DisplayName: "Deploy to Kubernetes",
|
||||||
|
ID: "2",
|
||||||
|
Result: "SUCCESS",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
DisplayName: "Deploy to Kubernetes",
|
||||||
|
ID: "3",
|
||||||
|
Result: "SUCCESS",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
Items := []struct {
|
NodeSteps := []devops.NodeSteps{
|
||||||
Input string
|
{
|
||||||
Expected Except
|
DisplayName: "Deploy to Kubernetes",
|
||||||
}{
|
ID: "1",
|
||||||
{"上次运行的时间 Tuesday, September 10, 2019 8:59:09 AM UTC; 下次运行的时间 Tuesday, September 10, 2019 9:14:09 AM UTC.", Except{Last: "2019-09-10T08:59:09Z", Next: "2019-09-10T09:14:09Z"}},
|
Result: "SUCCESS",
|
||||||
{"上次运行的时间 Thursday, January 3, 2019 11:56:30 PM UTC; 下次运行的时间 Friday, January 3, 2020 12:11:30 AM UTC.", Except{Last: "2019-01-03T23:56:30Z", Next: "2020-01-03T00:11:30Z"}},
|
},
|
||||||
{"上次运行的时间 Tuesday, September 10, 2019 8:41:34 AM UTC; 下次运行的时间 Tuesday, September 10, 2019 9:41:34 AM UTC.", Except{Last: "2019-09-10T08:41:34Z", Next: "2019-09-10T09:41:34Z"}},
|
|
||||||
{"上次运行的时间 Tuesday, September 10, 2019 9:15:26 AM UTC; 下次运行的时间 Tuesday, September 10, 2019 10:03:26 AM UTC.", Except{Last: "2019-09-10T09:15:26Z", Next: "2019-09-10T10:03:26Z"}},
|
|
||||||
{"Would last have run at Tuesday, September 10, 2019 9:15:26 AM UTC; would next run at Tuesday, September 10, 2019 10:03:26 AM UTC.", Except{Last: "2019-09-10T09:15:26Z", Next: "2019-09-10T10:03:26Z"}},
|
|
||||||
{"Would last have run at Tuesday, September 10, 2019 8:41:34 AM UTC; would next run at Tuesday, September 10, 2019 9:41:34 AM UTC.", Except{Last: "2019-09-10T08:41:34Z", Next: "2019-09-10T09:41:34Z"}},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, item := range Items {
|
fakeData["project1-pipeline1-run1"] = PipelineRunNodes
|
||||||
last, next, err := parseCronJobTime(item.Input)
|
fakeData["project1-pipeline1-run1-1"] = NodeSteps
|
||||||
if err != nil {
|
fakeData["project1-pipeline1-run1-2"] = NodeSteps
|
||||||
|
fakeData["project1-pipeline1-run1-3"] = NodeSteps
|
||||||
|
|
||||||
|
devopsClient := fake.NewFakeDevops(fakeData)
|
||||||
|
|
||||||
|
devopsOperator := NewDevopsOperator(devopsClient)
|
||||||
|
|
||||||
|
httpReq, _ := http.NewRequest(http.MethodGet, baseUrl+"devops/project1/pipelines/pipeline1/runs/run1/nodesdetail/?limit=10000", nil)
|
||||||
|
|
||||||
|
nodesDetails, err := devopsOperator.GetNodesDetail("project1", "pipeline1", "run1", httpReq)
|
||||||
|
if err != nil || nodesDetails == nil {
|
||||||
t.Fatalf("should not get error %+v", err)
|
t.Fatalf("should not get error %+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if last != item.Expected.Last {
|
for _, v := range nodesDetails {
|
||||||
t.Errorf("got %#v, expected %#v", last, item.Expected.Last)
|
if v.Steps[0].ID == "" {
|
||||||
|
t.Fatalf("Can not get any step.")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if next != item.Expected.Next {
|
func TestGetBranchNodesDetail(t *testing.T) {
|
||||||
t.Errorf("got %#v, expected %#v", next, item.Expected.Next)
|
fakeData := make(map[string]interface{})
|
||||||
|
|
||||||
|
BranchPipelineRunNodes := []devops.BranchPipelineRunNodes{
|
||||||
|
{
|
||||||
|
DisplayName: "Deploy to Kubernetes",
|
||||||
|
ID: "1",
|
||||||
|
Result: "SUCCESS",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
DisplayName: "Deploy to Kubernetes",
|
||||||
|
ID: "2",
|
||||||
|
Result: "SUCCESS",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
DisplayName: "Deploy to Kubernetes",
|
||||||
|
ID: "3",
|
||||||
|
Result: "SUCCESS",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BranchNodeSteps := []devops.NodeSteps{
|
||||||
|
{
|
||||||
|
DisplayName: "Deploy to Kubernetes",
|
||||||
|
ID: "1",
|
||||||
|
Result: "SUCCESS",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fakeData["project1-pipeline1-branch1-run1"] = BranchPipelineRunNodes
|
||||||
|
fakeData["project1-pipeline1-branch1-run1-1"] = BranchNodeSteps
|
||||||
|
fakeData["project1-pipeline1-branch1-run1-2"] = BranchNodeSteps
|
||||||
|
fakeData["project1-pipeline1-branch1-run1-3"] = BranchNodeSteps
|
||||||
|
|
||||||
|
devopsClient := fake.NewFakeDevops(fakeData)
|
||||||
|
|
||||||
|
devopsOperator := NewDevopsOperator(devopsClient)
|
||||||
|
|
||||||
|
httpReq, _ := http.NewRequest(http.MethodGet, baseUrl+"devops/project1/pipelines/pipeline1/branchs/branch1/runs/run1/nodesdetail/?limit=10000", nil)
|
||||||
|
|
||||||
|
nodesDetails, err := devopsOperator.GetBranchNodesDetail("project1", "pipeline1", "branch1", "run1", httpReq)
|
||||||
|
if err != nil || nodesDetails == nil {
|
||||||
|
t.Fatalf("should not get error %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range nodesDetails {
|
||||||
|
if v.Steps[0].ID == "" {
|
||||||
|
t.Fatalf("Can not get any step.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,25 +13,19 @@ limitations under the License.
|
|||||||
|
|
||||||
package devops
|
package devops
|
||||||
|
|
||||||
|
import "kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DevOpsProjectMembershipTableName = "project_membership"
|
ProjectMembershipTableName = "project_membership"
|
||||||
DevOpsProjectMembershipUsernameColumn = "project_membership.username"
|
ProjectMembershipUsernameColumn = "project_membership.username"
|
||||||
DevOpsProjectMembershipProjectIdColumn = "project_membership.project_id"
|
ProjectMembershipProjectIdColumn = "project_membership.project_id"
|
||||||
DevOpsProjectMembershipRoleColumn = "project_membership.role"
|
ProjectMembershipRoleColumn = "project_membership.role"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DevOpsProjectMembership struct {
|
var ProjectMembershipColumns = GetColumnsFromStruct(&devops.ProjectMembership{})
|
||||||
Username string `json:"username" description:"Member's username,username can uniquely identify a user"`
|
|
||||||
ProjectId string `json:"project_id" db:"project_id" description:"the DevOps Projects which project membership belongs to"`
|
|
||||||
Role string `json:"role" description:"DevOps Project membership's role type. e.g. owner '"`
|
|
||||||
Status string `json:"status" description:"Deprecated, Status of project membership. e.g. active "`
|
|
||||||
GrantBy string `json:"grand_by,omitempty" description:"Username of the user who assigned the role"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var DevOpsProjectMembershipColumns = GetColumnsFromStruct(&DevOpsProjectMembership{})
|
func NewDevOpsProjectMemberShip(username, projectId, role, grantBy string) *devops.ProjectMembership {
|
||||||
|
return &devops.ProjectMembership{
|
||||||
func NewDevOpsProjectMemberShip(username, projectId, role, grantBy string) *DevOpsProjectMembership {
|
|
||||||
return &DevOpsProjectMembership{
|
|
||||||
Username: username,
|
Username: username,
|
||||||
ProjectId: projectId,
|
ProjectId: projectId,
|
||||||
Role: role,
|
Role: role,
|
||||||
|
|||||||
@@ -18,59 +18,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
CredentialTypeUsernamePassword = "username_password"
|
|
||||||
CredentialTypeSsh = "ssh"
|
|
||||||
CredentialTypeSecretText = "secret_text"
|
|
||||||
CredentialTypeKubeConfig = "kubeconfig"
|
|
||||||
)
|
|
||||||
|
|
||||||
type JenkinsCredential struct {
|
|
||||||
Id string `json:"id" description:"Id of Credential, e.g. dockerhub-id"`
|
|
||||||
Type string `json:"type" description:"Type of Credential, e.g. ssh/kubeconfig"`
|
|
||||||
DisplayName string `json:"display_name,omitempty" description:"Credential's display name"`
|
|
||||||
Fingerprint *struct {
|
|
||||||
FileName string `json:"file_name,omitempty" description:"Credential's display name and description"`
|
|
||||||
Hash string `json:"hash,omitempty" description:"Credential's hash"`
|
|
||||||
Usage []*struct {
|
|
||||||
Name string `json:"name,omitempty" description:"Jenkins pipeline full name"`
|
|
||||||
Ranges struct {
|
|
||||||
Ranges []*struct {
|
|
||||||
Start int `json:"start,omitempty" description:"Start build number"`
|
|
||||||
End int `json:"end,omitempty" description:"End build number"`
|
|
||||||
} `json:"ranges,omitempty"`
|
|
||||||
} `json:"ranges,omitempty" description:"The build number of all pipelines that use this credential"`
|
|
||||||
} `json:"usage,omitempty" description:"all usage of Credential"`
|
|
||||||
} `json:"fingerprint,omitempty" description:"usage of the Credential"`
|
|
||||||
Description string `json:"description,omitempty" description:"Credential's description'"`
|
|
||||||
Domain string `json:"domain,omitempty" description:"Credential's domain,In ks we only use the default domain, default '_''"`
|
|
||||||
CreateTime *time.Time `json:"create_time,omitempty" description:"Credential's create_time'"`
|
|
||||||
Creator string `json:"creator,omitempty" description:"Creator's username"`
|
|
||||||
UsernamePasswordCredential *UsernamePasswordCredential `json:"username_password,omitempty" description:"username password Credential struct"`
|
|
||||||
SshCredential *SshCredential `json:"ssh,omitempty" description:"ssh Credential struct"`
|
|
||||||
SecretTextCredential *SecretTextCredential `json:"secret_text,omitempty" description:"secret_text Credential struct"`
|
|
||||||
KubeconfigCredential *KubeconfigCredential `json:"kubeconfig,omitempty" description:"kubeconfig Credential struct"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type UsernamePasswordCredential struct {
|
|
||||||
Username string `json:"username,omitempty" description:"username of username_password credential"`
|
|
||||||
Password string `json:"password,omitempty" description:"password of username_password credential"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SshCredential struct {
|
|
||||||
Username string `json:"username,omitempty" description:"username of ssh credential"`
|
|
||||||
Passphrase string `json:"passphrase,omitempty" description:"passphrase of ssh credential, password of ssh credential"`
|
|
||||||
PrivateKey string `json:"private_key,omitempty" mapstructure:"private_key" description:"private key of ssh credential"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SecretTextCredential struct {
|
|
||||||
Secret string `json:"secret,omitempty" description:"secret content of credential"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type KubeconfigCredential struct {
|
|
||||||
Content string `json:"content,omitempty" description:"content of kubeconfig"`
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ProjectCredentialTableName = "project_credential"
|
ProjectCredentialTableName = "project_credential"
|
||||||
ProjectCredentialIdColumn = "credential_id"
|
ProjectCredentialIdColumn = "credential_id"
|
||||||
@@ -78,13 +25,6 @@ const (
|
|||||||
ProjectCredentialProjectIdColumn = "project_id"
|
ProjectCredentialProjectIdColumn = "project_id"
|
||||||
)
|
)
|
||||||
|
|
||||||
var CredentialTypeMap = map[string]string{
|
|
||||||
"SSH Username with private key": CredentialTypeSsh,
|
|
||||||
"Username with password": CredentialTypeUsernamePassword,
|
|
||||||
"Secret text": CredentialTypeSecretText,
|
|
||||||
"Kubernetes configuration (kubeconfig)": CredentialTypeKubeConfig,
|
|
||||||
}
|
|
||||||
|
|
||||||
type ProjectCredential struct {
|
type ProjectCredential struct {
|
||||||
ProjectId string `json:"project_id"`
|
ProjectId string `json:"project_id"`
|
||||||
CredentialId string `json:"credential_id"`
|
CredentialId string `json:"credential_id"`
|
||||||
|
|||||||
@@ -15,389 +15,209 @@ package devops
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/PuerkitoBio/goquery"
|
|
||||||
"github.com/asaskevich/govalidator"
|
|
||||||
"github.com/emicklei/go-restful"
|
"github.com/emicklei/go-restful"
|
||||||
"github.com/gocraft/dbr"
|
"github.com/gocraft/dbr"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
|
||||||
|
|
||||||
"kubesphere.io/kubesphere/pkg/db"
|
"kubesphere.io/kubesphere/pkg/db"
|
||||||
"kubesphere.io/kubesphere/pkg/gojenkins"
|
|
||||||
"kubesphere.io/kubesphere/pkg/gojenkins/utils"
|
|
||||||
cs "kubesphere.io/kubesphere/pkg/simple/client"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func CreateProjectCredential(projectId, username string, credentialRequest *JenkinsCredential) (string, error) {
|
type ProjectCredentialOperator interface {
|
||||||
devops, err := cs.ClientSets().Devops()
|
CreateProjectCredential(projectId, username string, credentialRequest *devops.Credential) (string, error)
|
||||||
if err != nil {
|
UpdateProjectCredential(projectId, credentialId string, credentialRequest *devops.Credential) (string, error)
|
||||||
return "", restful.NewError(http.StatusServiceUnavailable, err.Error())
|
DeleteProjectCredential(projectId, credentialId string) (string, error)
|
||||||
|
GetProjectCredential(projectId, credentialId, getContent string) (*devops.Credential, error)
|
||||||
|
GetProjectCredentials(projectId string) ([]*devops.Credential, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
jenkinsClient := devops.Jenkins()
|
type projectCredentialOperator struct {
|
||||||
|
devopsClient devops.Interface
|
||||||
err = checkJenkinsCredentialExists(projectId, credentialRequest.Domain, credentialRequest.Id)
|
db *mysql.Database
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewProjectCredentialOperator(devopsClient devops.Interface, dbClient *mysql.Database) ProjectCredentialOperator {
|
||||||
|
return &projectCredentialOperator{devopsClient: devopsClient, db: dbClient}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *projectCredentialOperator) CreateProjectCredential(projectId, username string, credentialRequest *devops.Credential) (string, error) {
|
||||||
switch credentialRequest.Type {
|
switch credentialRequest.Type {
|
||||||
case CredentialTypeUsernamePassword:
|
case devops.CredentialTypeUsernamePassword:
|
||||||
if credentialRequest.UsernamePasswordCredential == nil {
|
if credentialRequest.UsernamePasswordCredential == nil {
|
||||||
err := fmt.Errorf("usename_password should not be nil")
|
err := fmt.Errorf("usename_password should not be nil")
|
||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
credentialId, err := jenkinsClient.CreateUsernamePasswordCredentialInFolder(credentialRequest.Domain,
|
case devops.CredentialTypeSsh:
|
||||||
credentialRequest.Id,
|
if credentialRequest.SshCredential == nil {
|
||||||
credentialRequest.UsernamePasswordCredential.Username,
|
err := fmt.Errorf("ssh should not be nil")
|
||||||
credentialRequest.UsernamePasswordCredential.Password,
|
klog.Error(err)
|
||||||
credentialRequest.Description,
|
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
projectId)
|
}
|
||||||
|
case devops.CredentialTypeSecretText:
|
||||||
|
if credentialRequest.SecretTextCredential == nil {
|
||||||
|
err := fmt.Errorf("secret_text should not be nil")
|
||||||
|
klog.Error(err)
|
||||||
|
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
case devops.CredentialTypeKubeConfig:
|
||||||
|
if credentialRequest.KubeconfigCredential == nil {
|
||||||
|
err := fmt.Errorf("kubeconfig should not be nil")
|
||||||
|
klog.Error(err)
|
||||||
|
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
err := fmt.Errorf("error unsupport credential type")
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
|
|
||||||
|
}
|
||||||
|
credentialId, err := o.devopsClient.CreateCredentialInProject(projectId, credentialRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
return "", err
|
||||||
}
|
}
|
||||||
err = insertCredentialToDb(projectId, *credentialId, credentialRequest.Domain, username)
|
err = o.insertCredentialToDb(projectId, *credentialId, credentialRequest.Domain, username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return *credentialId, nil
|
return *credentialId, nil
|
||||||
case CredentialTypeSsh:
|
|
||||||
if credentialRequest.SshCredential == nil {
|
|
||||||
err := fmt.Errorf("ssh should not be nil")
|
|
||||||
klog.Error(err)
|
|
||||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
|
||||||
}
|
|
||||||
credentialId, err := jenkinsClient.CreateSshCredentialInFolder(credentialRequest.Domain,
|
|
||||||
credentialRequest.Id,
|
|
||||||
credentialRequest.SshCredential.Username,
|
|
||||||
credentialRequest.SshCredential.Passphrase,
|
|
||||||
credentialRequest.SshCredential.PrivateKey,
|
|
||||||
credentialRequest.Description,
|
|
||||||
projectId)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
err = insertCredentialToDb(projectId, *credentialId, credentialRequest.Domain, username)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(http.StatusInternalServerError, err.Error())
|
|
||||||
}
|
|
||||||
return *credentialId, nil
|
|
||||||
case CredentialTypeSecretText:
|
|
||||||
if credentialRequest.SecretTextCredential == nil {
|
|
||||||
err := fmt.Errorf("secret_text should not be nil")
|
|
||||||
klog.Error(err)
|
|
||||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
credentialId, err := jenkinsClient.CreateSecretTextCredentialInFolder(credentialRequest.Domain,
|
|
||||||
credentialRequest.Id,
|
|
||||||
credentialRequest.SecretTextCredential.Secret,
|
|
||||||
credentialRequest.Description,
|
|
||||||
projectId)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
err = insertCredentialToDb(projectId, *credentialId, credentialRequest.Domain, username)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(http.StatusInternalServerError, err.Error())
|
|
||||||
}
|
|
||||||
return *credentialId, nil
|
|
||||||
case CredentialTypeKubeConfig:
|
|
||||||
if credentialRequest.KubeconfigCredential == nil {
|
|
||||||
err := fmt.Errorf("kubeconfig should not be nil")
|
|
||||||
klog.Error(err)
|
|
||||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
|
||||||
}
|
|
||||||
credentialId, err := jenkinsClient.CreateKubeconfigCredentialInFolder(credentialRequest.Domain,
|
|
||||||
credentialRequest.Id,
|
|
||||||
credentialRequest.KubeconfigCredential.Content,
|
|
||||||
credentialRequest.Description,
|
|
||||||
projectId)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
err = insertCredentialToDb(projectId, *credentialId, credentialRequest.Domain, username)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(http.StatusInternalServerError, err.Error())
|
|
||||||
}
|
|
||||||
return *credentialId, nil
|
|
||||||
default:
|
|
||||||
err := fmt.Errorf("error unsupport credential type")
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
func (o *projectCredentialOperator) UpdateProjectCredential(projectId, credentialId string, credentialRequest *devops.Credential) (string, error) {
|
||||||
|
|
||||||
func UpdateProjectCredential(projectId, credentialId string, credentialRequest *JenkinsCredential) (string, error) {
|
credential, err := o.devopsClient.GetCredentialInProject(projectId,
|
||||||
devops, err := cs.ClientSets().Devops()
|
credentialId, false)
|
||||||
if err != nil {
|
|
||||||
return "", restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
}
|
|
||||||
jenkinsClient := devops.Jenkins()
|
|
||||||
|
|
||||||
jenkinsCredential, err := jenkinsClient.GetCredentialInFolder(credentialRequest.Domain,
|
|
||||||
credentialId,
|
|
||||||
projectId)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
return "", err
|
||||||
}
|
}
|
||||||
credentialType := CredentialTypeMap[jenkinsCredential.TypeName]
|
switch credential.Type {
|
||||||
switch credentialType {
|
case devops.CredentialTypeUsernamePassword:
|
||||||
case CredentialTypeUsernamePassword:
|
|
||||||
if credentialRequest.UsernamePasswordCredential == nil {
|
if credentialRequest.UsernamePasswordCredential == nil {
|
||||||
err := fmt.Errorf("usename_password should not be nil")
|
err := fmt.Errorf("usename_password should not be nil")
|
||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
credentialId, err := jenkinsClient.UpdateUsernamePasswordCredentialInFolder(credentialRequest.Domain,
|
case devops.CredentialTypeSsh:
|
||||||
credentialId,
|
|
||||||
credentialRequest.UsernamePasswordCredential.Username,
|
|
||||||
credentialRequest.UsernamePasswordCredential.Password,
|
|
||||||
credentialRequest.Description,
|
|
||||||
projectId)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return *credentialId, nil
|
|
||||||
case CredentialTypeSsh:
|
|
||||||
if credentialRequest.SshCredential == nil {
|
if credentialRequest.SshCredential == nil {
|
||||||
err := fmt.Errorf("ssh should not be nil")
|
err := fmt.Errorf("ssh should not be nil")
|
||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
credentialId, err := jenkinsClient.UpdateSshCredentialInFolder(credentialRequest.Domain,
|
case devops.CredentialTypeSecretText:
|
||||||
credentialId,
|
|
||||||
credentialRequest.SshCredential.Username,
|
|
||||||
credentialRequest.SshCredential.Passphrase,
|
|
||||||
credentialRequest.SshCredential.PrivateKey,
|
|
||||||
credentialRequest.Description,
|
|
||||||
projectId)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return *credentialId, nil
|
|
||||||
case CredentialTypeSecretText:
|
|
||||||
if credentialRequest.SecretTextCredential == nil {
|
if credentialRequest.SecretTextCredential == nil {
|
||||||
err := fmt.Errorf("secret_text should not be nil")
|
err := fmt.Errorf("secret_text should not be nil")
|
||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
credentialId, err := jenkinsClient.UpdateSecretTextCredentialInFolder(credentialRequest.Domain,
|
case devops.CredentialTypeKubeConfig:
|
||||||
credentialId,
|
|
||||||
credentialRequest.SecretTextCredential.Secret,
|
|
||||||
credentialRequest.Description,
|
|
||||||
projectId)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
return *credentialId, nil
|
|
||||||
case CredentialTypeKubeConfig:
|
|
||||||
if credentialRequest.KubeconfigCredential == nil {
|
if credentialRequest.KubeconfigCredential == nil {
|
||||||
err := fmt.Errorf("kubeconfig should not be nil")
|
err := fmt.Errorf("kubeconfig should not be nil")
|
||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
credentialId, err := jenkinsClient.UpdateKubeconfigCredentialInFolder(credentialRequest.Domain,
|
|
||||||
credentialId,
|
|
||||||
credentialRequest.KubeconfigCredential.Content,
|
|
||||||
credentialRequest.Description,
|
|
||||||
projectId)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
return *credentialId, nil
|
|
||||||
default:
|
default:
|
||||||
err := fmt.Errorf("error unsupport credential type")
|
err := fmt.Errorf("error unsupport credential type")
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
credentialRequest.Id = credentialId
|
||||||
}
|
_, err = o.devopsClient.UpdateCredentialInProject(projectId, credentialRequest)
|
||||||
|
|
||||||
func DeleteProjectCredential(projectId, credentialId string, credentialRequest *JenkinsCredential) (string, error) {
|
|
||||||
devops, err := cs.ClientSets().Devops()
|
|
||||||
if err != nil {
|
|
||||||
return "", restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
}
|
|
||||||
jenkinsClient := devops.Jenkins()
|
|
||||||
|
|
||||||
dbClient, err := cs.ClientSets().MySQL()
|
|
||||||
if err != nil {
|
|
||||||
return "", restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = jenkinsClient.GetCredentialInFolder(credentialRequest.Domain,
|
|
||||||
credentialId,
|
|
||||||
projectId)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
return credentialId, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := jenkinsClient.DeleteCredentialInFolder(credentialRequest.Domain, credentialId, projectId)
|
func (o *projectCredentialOperator) DeleteProjectCredential(projectId, credentialId string) (string, error) {
|
||||||
|
|
||||||
|
_, err := o.devopsClient.GetCredentialInProject(projectId,
|
||||||
|
credentialId, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := o.devopsClient.DeleteCredentialInProject(projectId, credentialId)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteConditions := append(make([]dbr.Builder, 0), db.Eq(ProjectCredentialProjectIdColumn, projectId))
|
deleteConditions := append(make([]dbr.Builder, 0), db.Eq(ProjectCredentialProjectIdColumn, projectId))
|
||||||
deleteConditions = append(deleteConditions, db.Eq(ProjectCredentialIdColumn, credentialId))
|
deleteConditions = append(deleteConditions, db.Eq(ProjectCredentialIdColumn, credentialId))
|
||||||
if !govalidator.IsNull(credentialRequest.Domain) {
|
|
||||||
deleteConditions = append(deleteConditions, db.Eq(ProjectCredentialDomainColumn, credentialRequest.Domain))
|
|
||||||
} else {
|
|
||||||
deleteConditions = append(deleteConditions, db.Eq(ProjectCredentialDomainColumn, "_"))
|
deleteConditions = append(deleteConditions, db.Eq(ProjectCredentialDomainColumn, "_"))
|
||||||
}
|
|
||||||
|
|
||||||
_, err = dbClient.DeleteFrom(ProjectCredentialTableName).
|
_, err = o.db.DeleteFrom(ProjectCredentialTableName).
|
||||||
Where(db.And(deleteConditions...)).Exec()
|
Where(db.And(deleteConditions...)).Exec()
|
||||||
if err != nil && err != db.ErrNotFound {
|
if err != nil && err != db.ErrNotFound {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return "", restful.NewError(http.StatusInternalServerError, err.Error())
|
return "", err
|
||||||
}
|
}
|
||||||
return *id, nil
|
return *id, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetProjectCredential(projectId, credentialId, domain, getContent string) (*JenkinsCredential, error) {
|
func (o *projectCredentialOperator) GetProjectCredential(projectId, credentialId, getContent string) (*devops.Credential, error) {
|
||||||
devops, err := cs.ClientSets().Devops()
|
|
||||||
if err != nil {
|
|
||||||
return nil, restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
}
|
|
||||||
jenkinsClient := devops.Jenkins()
|
|
||||||
|
|
||||||
dbClient, err := cs.ClientSets().MySQL()
|
content := false
|
||||||
if err != nil {
|
if getContent != "" {
|
||||||
return nil, restful.NewError(http.StatusServiceUnavailable, err.Error())
|
content = true
|
||||||
}
|
}
|
||||||
jenkinsResponse, err := jenkinsClient.GetCredentialInFolder(domain,
|
credential, err := o.devopsClient.GetCredentialInProject(projectId,
|
||||||
credentialId,
|
credentialId,
|
||||||
projectId)
|
content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
projectCredential := &ProjectCredential{}
|
projectCredential := &ProjectCredential{}
|
||||||
err = dbClient.Select(ProjectCredentialColumns...).
|
err = o.db.Select(ProjectCredentialColumns...).
|
||||||
From(ProjectCredentialTableName).Where(
|
From(ProjectCredentialTableName).Where(
|
||||||
db.And(db.Eq(ProjectCredentialProjectIdColumn, projectId),
|
db.And(db.Eq(ProjectCredentialProjectIdColumn, projectId),
|
||||||
db.Eq(ProjectCredentialIdColumn, credentialId),
|
db.Eq(ProjectCredentialIdColumn, credentialId),
|
||||||
db.Eq(ProjectCredentialDomainColumn, jenkinsResponse.Domain))).LoadOne(projectCredential)
|
db.Eq(ProjectCredentialDomainColumn, credential.Domain))).LoadOne(projectCredential)
|
||||||
|
|
||||||
if err != nil && err != db.ErrNotFound {
|
if err != nil && err != db.ErrNotFound {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
response := formatCredentialResponse(jenkinsResponse, projectCredential)
|
response := formatCredentialResponse(credential, projectCredential)
|
||||||
if getContent != "" {
|
|
||||||
stringBody, err := jenkinsClient.GetCredentialContentInFolder(jenkinsResponse.Domain, credentialId, projectId)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
stringReader := strings.NewReader(stringBody)
|
|
||||||
doc, err := goquery.NewDocumentFromReader(stringReader)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
|
||||||
}
|
|
||||||
switch response.Type {
|
|
||||||
case CredentialTypeKubeConfig:
|
|
||||||
content := &KubeconfigCredential{}
|
|
||||||
doc.Find("textarea[name*=content]").Each(func(i int, selection *goquery.Selection) {
|
|
||||||
value := selection.Text()
|
|
||||||
content.Content = value
|
|
||||||
})
|
|
||||||
response.KubeconfigCredential = content
|
|
||||||
case CredentialTypeUsernamePassword:
|
|
||||||
content := &UsernamePasswordCredential{}
|
|
||||||
doc.Find("input[name*=username]").Each(func(i int, selection *goquery.Selection) {
|
|
||||||
value, _ := selection.Attr("value")
|
|
||||||
content.Username = value
|
|
||||||
})
|
|
||||||
|
|
||||||
response.UsernamePasswordCredential = content
|
|
||||||
case CredentialTypeSsh:
|
|
||||||
content := &SshCredential{}
|
|
||||||
doc.Find("input[name*=username]").Each(func(i int, selection *goquery.Selection) {
|
|
||||||
value, _ := selection.Attr("value")
|
|
||||||
content.Username = value
|
|
||||||
})
|
|
||||||
|
|
||||||
doc.Find("textarea[name*=privateKey]").Each(func(i int, selection *goquery.Selection) {
|
|
||||||
value := selection.Text()
|
|
||||||
content.PrivateKey = value
|
|
||||||
})
|
|
||||||
response.SshCredential = content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return response, nil
|
return response, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetProjectCredentials(projectId, domain string) ([]*JenkinsCredential, error) {
|
func (o *projectCredentialOperator) GetProjectCredentials(projectId string) ([]*devops.Credential, error) {
|
||||||
devops, err := cs.ClientSets().Devops()
|
|
||||||
if err != nil {
|
|
||||||
return nil, restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
}
|
|
||||||
jenkinsClient := devops.Jenkins()
|
|
||||||
|
|
||||||
dbClient, err := cs.ClientSets().MySQL()
|
credentialResponses, err := o.devopsClient.GetCredentialsInProject(projectId)
|
||||||
if err != nil {
|
|
||||||
return nil, restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
}
|
|
||||||
jenkinsCredentialResponses, err := jenkinsClient.GetCredentialsInFolder(domain, projectId)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
return nil, err
|
||||||
}
|
}
|
||||||
selectCondition := db.Eq(ProjectCredentialProjectIdColumn, projectId)
|
selectCondition := db.Eq(ProjectCredentialProjectIdColumn, projectId)
|
||||||
if !govalidator.IsNull(domain) {
|
|
||||||
selectCondition = db.And(selectCondition, db.Eq(ProjectCredentialDomainColumn, domain))
|
|
||||||
}
|
|
||||||
projectCredentials := make([]*ProjectCredential, 0)
|
projectCredentials := make([]*ProjectCredential, 0)
|
||||||
_, err = dbClient.Select(ProjectCredentialColumns...).
|
_, err = o.db.Select(ProjectCredentialColumns...).
|
||||||
From(ProjectCredentialTableName).Where(selectCondition).Load(&projectCredentials)
|
From(ProjectCredentialTableName).Where(selectCondition).Load(&projectCredentials)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
response := formatCredentialsResponse(jenkinsCredentialResponses, projectCredentials)
|
response := formatCredentialsResponse(credentialResponses, projectCredentials)
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func insertCredentialToDb(projectId, credentialId, domain, username string) error {
|
func (o *projectCredentialOperator) insertCredentialToDb(projectId, credentialId, domain, username string) error {
|
||||||
dbClient, err := cs.ClientSets().MySQL()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
projectCredential := NewProjectCredential(projectId, credentialId, domain, username)
|
projectCredential := NewProjectCredential(projectId, credentialId, domain, username)
|
||||||
_, err = dbClient.InsertInto(ProjectCredentialTableName).Columns(ProjectCredentialColumns...).
|
_, err := o.db.InsertInto(ProjectCredentialTableName).Columns(ProjectCredentialColumns...).
|
||||||
Record(projectCredential).Exec()
|
Record(projectCredential).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
@@ -406,41 +226,19 @@ func insertCredentialToDb(projectId, credentialId, domain, username string) erro
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkJenkinsCredentialExists(projectId, domain, credentialId string) error {
|
|
||||||
devops, err := cs.ClientSets().Devops()
|
|
||||||
if err != nil {
|
|
||||||
return restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
jenkinsClient := devops.Jenkins()
|
|
||||||
|
|
||||||
credential, err := jenkinsClient.GetCredentialInFolder(domain, credentialId, projectId)
|
|
||||||
if credential != nil {
|
|
||||||
err := fmt.Errorf("credential id [%s] has been used", credential.Id)
|
|
||||||
klog.Warning(err.Error())
|
|
||||||
return restful.NewError(http.StatusConflict, err.Error())
|
|
||||||
}
|
|
||||||
if err != nil && utils.GetJenkinsStatusCode(err) != http.StatusNotFound {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
|
|
||||||
return restful.NewError(http.StatusBadRequest, err.Error())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func formatCredentialResponse(
|
func formatCredentialResponse(
|
||||||
jenkinsCredentialResponse *gojenkins.CredentialResponse,
|
credentialResponse *devops.Credential,
|
||||||
dbCredentialResponse *ProjectCredential) *JenkinsCredential {
|
dbCredentialResponse *ProjectCredential) *devops.Credential {
|
||||||
response := &JenkinsCredential{}
|
response := &devops.Credential{}
|
||||||
response.Id = jenkinsCredentialResponse.Id
|
response.Id = credentialResponse.Id
|
||||||
response.Description = jenkinsCredentialResponse.Description
|
response.Description = credentialResponse.Description
|
||||||
response.DisplayName = jenkinsCredentialResponse.DisplayName
|
response.DisplayName = credentialResponse.DisplayName
|
||||||
if jenkinsCredentialResponse.Fingerprint != nil && jenkinsCredentialResponse.Fingerprint.Hash != "" {
|
if credentialResponse.Fingerprint != nil && credentialResponse.Fingerprint.Hash != "" {
|
||||||
response.Fingerprint = &struct {
|
response.Fingerprint = &struct {
|
||||||
FileName string `json:"file_name,omitempty" description:"Credential's display name and description"`
|
FileName string `json:"file_name,omitempty" description:"Credential's display name and description"`
|
||||||
Hash string `json:"hash,omitempty" description:"Credential's hash"`
|
Hash string `json:"hash,omitempty" description:"Credential's hash"`
|
||||||
Usage []*struct {
|
Usage []*struct {
|
||||||
Name string `json:"name,omitempty" description:"Jenkins pipeline full name"`
|
Name string `json:"name,omitempty" description:"pipeline full name"`
|
||||||
Ranges struct {
|
Ranges struct {
|
||||||
Ranges []*struct {
|
Ranges []*struct {
|
||||||
Start int `json:"start,omitempty" description:"Start build number"`
|
Start int `json:"start,omitempty" description:"Start build number"`
|
||||||
@@ -449,40 +247,40 @@ func formatCredentialResponse(
|
|||||||
} `json:"ranges,omitempty" description:"The build number of all pipelines that use this credential"`
|
} `json:"ranges,omitempty" description:"The build number of all pipelines that use this credential"`
|
||||||
} `json:"usage,omitempty" description:"all usage of Credential"`
|
} `json:"usage,omitempty" description:"all usage of Credential"`
|
||||||
}{}
|
}{}
|
||||||
response.Fingerprint.FileName = jenkinsCredentialResponse.Fingerprint.FileName
|
response.Fingerprint.FileName = credentialResponse.Fingerprint.FileName
|
||||||
response.Fingerprint.Hash = jenkinsCredentialResponse.Fingerprint.Hash
|
response.Fingerprint.Hash = credentialResponse.Fingerprint.Hash
|
||||||
for _, usage := range jenkinsCredentialResponse.Fingerprint.Usage {
|
for _, usage := range credentialResponse.Fingerprint.Usage {
|
||||||
response.Fingerprint.Usage = append(response.Fingerprint.Usage, usage)
|
response.Fingerprint.Usage = append(response.Fingerprint.Usage, usage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
response.Domain = jenkinsCredentialResponse.Domain
|
response.Domain = credentialResponse.Domain
|
||||||
|
|
||||||
if dbCredentialResponse != nil {
|
if dbCredentialResponse != nil {
|
||||||
response.CreateTime = &dbCredentialResponse.CreateTime
|
response.CreateTime = &dbCredentialResponse.CreateTime
|
||||||
response.Creator = dbCredentialResponse.Creator
|
response.Creator = dbCredentialResponse.Creator
|
||||||
}
|
}
|
||||||
|
|
||||||
credentialType, ok := CredentialTypeMap[jenkinsCredentialResponse.TypeName]
|
credentialType, ok := devops.CredentialTypeMap[credentialResponse.Type]
|
||||||
if ok {
|
if ok {
|
||||||
response.Type = credentialType
|
response.Type = credentialType
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
response.Type = jenkinsCredentialResponse.TypeName
|
response.Type = credentialResponse.Type
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatCredentialsResponse(jenkinsCredentialsResponse []*gojenkins.CredentialResponse,
|
func formatCredentialsResponse(credentialsResponse []*devops.Credential,
|
||||||
projectCredentials []*ProjectCredential) []*JenkinsCredential {
|
projectCredentials []*ProjectCredential) []*devops.Credential {
|
||||||
responseSlice := make([]*JenkinsCredential, 0)
|
responseSlice := make([]*devops.Credential, 0)
|
||||||
for _, jenkinsCredential := range jenkinsCredentialsResponse {
|
for _, credential := range credentialsResponse {
|
||||||
var dbCredential *ProjectCredential = nil
|
var dbCredential *ProjectCredential = nil
|
||||||
for _, projectCredential := range projectCredentials {
|
for _, projectCredential := range projectCredentials {
|
||||||
if projectCredential.CredentialId == jenkinsCredential.Id &&
|
if projectCredential.CredentialId == credential.Id &&
|
||||||
projectCredential.Domain == jenkinsCredential.Domain {
|
projectCredential.Domain == credential.Domain {
|
||||||
dbCredential = projectCredential
|
dbCredential = projectCredential
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
responseSlice = append(responseSlice, formatCredentialResponse(jenkinsCredential, dbCredential))
|
responseSlice = append(responseSlice, formatCredentialResponse(credential, dbCredential))
|
||||||
}
|
}
|
||||||
return responseSlice
|
return responseSlice
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,23 +14,37 @@ limitations under the License.
|
|||||||
package devops
|
package devops
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/asaskevich/govalidator"
|
"github.com/asaskevich/govalidator"
|
||||||
"github.com/emicklei/go-restful"
|
"github.com/emicklei/go-restful"
|
||||||
"github.com/gocraft/dbr"
|
"github.com/gocraft/dbr"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
"kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
|
"kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
|
||||||
"kubesphere.io/kubesphere/pkg/db"
|
"kubesphere.io/kubesphere/pkg/db"
|
||||||
cs "kubesphere.io/kubesphere/pkg/simple/client"
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
|
||||||
|
"kubesphere.io/kubesphere/pkg/utils/reflectutils"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetProject(projectId string) (*v1alpha2.DevOpsProject, error) {
|
type ProjectOperator interface {
|
||||||
dbconn, err := cs.ClientSets().MySQL()
|
GetProject(projectId string) (*v1alpha2.DevOpsProject, error)
|
||||||
if err != nil {
|
UpdateProject(project *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, error)
|
||||||
return nil, err
|
CheckProjectUserInRole(username, projectId string, roles []string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type projectOperator struct {
|
||||||
|
db *mysql.Database
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewProjectOperator(dbClient *mysql.Database) ProjectOperator {
|
||||||
|
return &projectOperator{db: dbClient}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *projectOperator) GetProject(projectId string) (*v1alpha2.DevOpsProject, error) {
|
||||||
|
|
||||||
project := &v1alpha2.DevOpsProject{}
|
project := &v1alpha2.DevOpsProject{}
|
||||||
err = dbconn.Select(DevOpsProjectColumns...).
|
err := o.db.Select(DevOpsProjectColumns...).
|
||||||
From(DevOpsProjectTableName).
|
From(DevOpsProjectTableName).
|
||||||
Where(db.Eq(DevOpsProjectIdColumn, projectId)).
|
Where(db.Eq(DevOpsProjectIdColumn, projectId)).
|
||||||
LoadOne(project)
|
LoadOne(project)
|
||||||
@@ -46,13 +60,9 @@ func GetProject(projectId string) (*v1alpha2.DevOpsProject, error) {
|
|||||||
return project, nil
|
return project, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateProject(project *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, error) {
|
func (o *projectOperator) UpdateProject(project *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, error) {
|
||||||
dbconn, err := cs.ClientSets().MySQL()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
query := dbconn.Update(DevOpsProjectTableName)
|
query := o.db.Update(DevOpsProjectTableName)
|
||||||
if !govalidator.IsNull(project.Description) {
|
if !govalidator.IsNull(project.Description) {
|
||||||
query.Set(DevOpsProjectDescriptionColumn, project.Description)
|
query.Set(DevOpsProjectDescriptionColumn, project.Description)
|
||||||
}
|
}
|
||||||
@@ -73,7 +83,7 @@ func UpdateProject(project *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, er
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
newProject := &v1alpha2.DevOpsProject{}
|
newProject := &v1alpha2.DevOpsProject{}
|
||||||
err = dbconn.Select(DevOpsProjectColumns...).
|
err := o.db.Select(DevOpsProjectColumns...).
|
||||||
From(DevOpsProjectTableName).
|
From(DevOpsProjectTableName).
|
||||||
Where(db.Eq(DevOpsProjectIdColumn, project.ProjectId)).
|
Where(db.Eq(DevOpsProjectIdColumn, project.ProjectId)).
|
||||||
LoadOne(newProject)
|
LoadOne(newProject)
|
||||||
@@ -83,3 +93,22 @@ func UpdateProject(project *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, er
|
|||||||
}
|
}
|
||||||
return newProject, nil
|
return newProject, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *projectOperator) CheckProjectUserInRole(username, projectId string, roles []string) error {
|
||||||
|
if username == KS_ADMIN {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
membership := &devops.ProjectMembership{}
|
||||||
|
err := o.db.Select(ProjectMembershipColumns...).
|
||||||
|
From(ProjectMembershipTableName).
|
||||||
|
Where(db.And(
|
||||||
|
db.Eq(ProjectMembershipUsernameColumn, username),
|
||||||
|
db.Eq(ProjectMembershipProjectIdColumn, projectId))).LoadOne(membership)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !reflectutils.In(membership.Role, roles) {
|
||||||
|
return fmt.Errorf("user [%s] in project [%s] role is not in %s", username, projectId, roles)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,43 +15,58 @@ package devops
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/emicklei/go-restful"
|
"github.com/emicklei/go-restful"
|
||||||
"github.com/gocraft/dbr"
|
"github.com/gocraft/dbr"
|
||||||
"kubesphere.io/kubesphere/pkg/db"
|
"kubesphere.io/kubesphere/pkg/db"
|
||||||
"kubesphere.io/kubesphere/pkg/gojenkins"
|
|
||||||
"kubesphere.io/kubesphere/pkg/gojenkins/utils"
|
|
||||||
"kubesphere.io/kubesphere/pkg/models"
|
"kubesphere.io/kubesphere/pkg/models"
|
||||||
"kubesphere.io/kubesphere/pkg/server/params"
|
"kubesphere.io/kubesphere/pkg/server/params"
|
||||||
cs "kubesphere.io/kubesphere/pkg/simple/client"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetProjectMembers(projectId string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error) {
|
type ProjectMemberOperator interface {
|
||||||
dbconn, err := cs.ClientSets().MySQL()
|
GetProjectMembers(projectId string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error)
|
||||||
if err != nil {
|
GetProjectMember(projectId, username string) (*devops.ProjectMembership, error)
|
||||||
return nil, err
|
AddProjectMember(projectId string, membership *devops.ProjectMembership) (*devops.ProjectMembership, error)
|
||||||
|
UpdateProjectMember(projectId string, membership *devops.ProjectMembership) (*devops.ProjectMembership, error)
|
||||||
|
DeleteProjectMember(projectId, username string) (string, error)
|
||||||
}
|
}
|
||||||
memberships := make([]*DevOpsProjectMembership, 0)
|
type projectMemberOperator struct {
|
||||||
|
db *mysql.Database
|
||||||
|
projectMemberOperator devops.ProjectMemberOperator
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewProjectMemberOperator(devopsClient devops.ProjectMemberOperator, dbClient *mysql.Database) ProjectMemberOperator {
|
||||||
|
return &projectMemberOperator{
|
||||||
|
db: dbClient,
|
||||||
|
projectMemberOperator: devopsClient,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *projectMemberOperator) GetProjectMembers(projectId string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error) {
|
||||||
|
|
||||||
|
memberships := make([]*devops.ProjectMembership, 0)
|
||||||
var sqconditions []dbr.Builder
|
var sqconditions []dbr.Builder
|
||||||
sqconditions = append(sqconditions, db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId))
|
sqconditions = append(sqconditions, db.Eq(ProjectMembershipProjectIdColumn, projectId))
|
||||||
if keyword := conditions.Match["keyword"]; keyword != "" {
|
if keyword := conditions.Match["keyword"]; keyword != "" {
|
||||||
sqconditions = append(sqconditions, db.Like(DevOpsProjectMembershipUsernameColumn, keyword))
|
sqconditions = append(sqconditions, db.Like(ProjectMembershipUsernameColumn, keyword))
|
||||||
}
|
}
|
||||||
query := dbconn.Select(DevOpsProjectMembershipColumns...).
|
query := *o.db.Select(ProjectMembershipColumns...).
|
||||||
From(DevOpsProjectMembershipTableName)
|
From(ProjectMembershipTableName)
|
||||||
switch orderBy {
|
switch orderBy {
|
||||||
case "name":
|
case "name":
|
||||||
if reverse {
|
if reverse {
|
||||||
query.OrderDesc(DevOpsProjectMembershipUsernameColumn)
|
query.OrderDesc(ProjectMembershipUsernameColumn)
|
||||||
} else {
|
} else {
|
||||||
query.OrderAsc(DevOpsProjectMembershipUsernameColumn)
|
query.OrderAsc(ProjectMembershipUsernameColumn)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
if reverse {
|
if reverse {
|
||||||
query.OrderDesc(DevOpsProjectMembershipRoleColumn)
|
query.OrderDesc(ProjectMembershipRoleColumn)
|
||||||
} else {
|
} else {
|
||||||
query.OrderAsc(DevOpsProjectMembershipRoleColumn)
|
query.OrderAsc(ProjectMembershipRoleColumn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
query.Limit(uint64(limit))
|
query.Limit(uint64(limit))
|
||||||
@@ -61,7 +76,7 @@ func GetProjectMembers(projectId string, conditions *params.Conditions, orderBy
|
|||||||
} else {
|
} else {
|
||||||
query.Where(sqconditions[0])
|
query.Where(sqconditions[0])
|
||||||
}
|
}
|
||||||
_, err = query.Load(&memberships)
|
_, err := query.Load(&memberships)
|
||||||
if err != nil && err != dbr.ErrNotFound {
|
if err != nil && err != dbr.ErrNotFound {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||||
@@ -79,17 +94,13 @@ func GetProjectMembers(projectId string, conditions *params.Conditions, orderBy
|
|||||||
return &models.PageableResponse{Items: result, TotalCount: int(count)}, nil
|
return &models.PageableResponse{Items: result, TotalCount: int(count)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetProjectMember(projectId, username string) (*DevOpsProjectMembership, error) {
|
func (o *projectMemberOperator) GetProjectMember(projectId, username string) (*devops.ProjectMembership, error) {
|
||||||
dbconn, err := cs.ClientSets().MySQL()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
member := &DevOpsProjectMembership{}
|
member := &devops.ProjectMembership{}
|
||||||
err = dbconn.Select(DevOpsProjectMembershipColumns...).
|
err := o.db.Select(ProjectMembershipColumns...).
|
||||||
From(DevOpsProjectMembershipTableName).
|
From(ProjectMembershipTableName).
|
||||||
Where(db.And(db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId),
|
Where(db.And(db.Eq(ProjectMembershipProjectIdColumn, projectId),
|
||||||
db.Eq(DevOpsProjectMembershipUsernameColumn, username))).
|
db.Eq(ProjectMembershipUsernameColumn, username))).
|
||||||
LoadOne(&member)
|
LoadOne(&member)
|
||||||
if err != nil && err != dbr.ErrNotFound {
|
if err != nil && err != dbr.ErrNotFound {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
@@ -102,31 +113,17 @@ func GetProjectMember(projectId, username string) (*DevOpsProjectMembership, err
|
|||||||
return member, nil
|
return member, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddProjectMember(projectId, operator string, member *DevOpsProjectMembership) (*DevOpsProjectMembership, error) {
|
func (o *projectMemberOperator) AddProjectMember(projectId string, membership *devops.ProjectMembership) (*devops.ProjectMembership, error) {
|
||||||
dbconn, err := cs.ClientSets().MySQL()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
devops, err := cs.ClientSets().Devops()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
jenkinsClient := devops.Jenkins()
|
|
||||||
if jenkinsClient == nil {
|
|
||||||
err := fmt.Errorf("could not connect to jenkins")
|
|
||||||
klog.Error(err)
|
|
||||||
return nil, restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
membership := &DevOpsProjectMembership{}
|
dbmembership := &devops.ProjectMembership{}
|
||||||
err = dbconn.Select(DevOpsProjectMembershipColumns...).
|
err := o.db.Select(ProjectMembershipColumns...).
|
||||||
From(DevOpsProjectMembershipTableName).
|
From(ProjectMembershipTableName).
|
||||||
Where(db.And(
|
Where(db.And(
|
||||||
db.Eq(DevOpsProjectMembershipUsernameColumn, member.Username),
|
db.Eq(ProjectMembershipUsernameColumn, membership.Username),
|
||||||
db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId))).LoadOne(membership)
|
db.Eq(ProjectMembershipProjectIdColumn, projectId))).LoadOne(dbmembership)
|
||||||
// if user could be founded in db, user have been added to project
|
// if user could be founded in db, user have been added to project
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = fmt.Errorf("user [%s] have been added to project", member.Username)
|
err = fmt.Errorf("user [%s] have been added to project", membership.Username)
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return nil, restful.NewError(http.StatusBadRequest, err.Error())
|
return nil, restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
@@ -136,161 +133,65 @@ func AddProjectMember(projectId, operator string, member *DevOpsProjectMembershi
|
|||||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
globalRole, err := jenkinsClient.GetGlobalRole(JenkinsAllUserRoleName)
|
_, err = o.projectMemberOperator.AddProjectMember(membership)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
return nil, err
|
||||||
}
|
}
|
||||||
if globalRole == nil {
|
projectMembership := NewDevOpsProjectMemberShip(membership.Username, projectId, membership.Role, membership.GrantBy)
|
||||||
_, err := jenkinsClient.AddGlobalRole(JenkinsAllUserRoleName, gojenkins.GlobalPermissionIds{
|
_, err = o.db.
|
||||||
GlobalRead: true,
|
InsertInto(ProjectMembershipTableName).
|
||||||
}, true)
|
Columns(ProjectMembershipColumns...).
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("failed to create jenkins global role %+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err = globalRole.AssignRole(member.Username)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
projectRole, err := jenkinsClient.GetProjectRole(GetProjectRoleName(projectId, member.Role))
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
err = projectRole.AssignRole(member.Username)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
pipelineRole, err := jenkinsClient.GetProjectRole(GetPipelineRoleName(projectId, member.Role))
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
err = pipelineRole.AssignRole(member.Username)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
projectMembership := NewDevOpsProjectMemberShip(member.Username, projectId, member.Role, operator)
|
|
||||||
_, err = dbconn.
|
|
||||||
InsertInto(DevOpsProjectMembershipTableName).
|
|
||||||
Columns(DevOpsProjectMembershipColumns...).
|
|
||||||
Record(projectMembership).Exec()
|
Record(projectMembership).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
err = projectRole.UnAssignRole(member.Username)
|
_, err = o.projectMemberOperator.DeleteProjectMember(membership)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
return nil, err
|
||||||
}
|
|
||||||
err = pipelineRole.UnAssignRole(member.Username)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
}
|
||||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
return projectMembership, nil
|
return projectMembership, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateProjectMember(projectId, operator string, member *DevOpsProjectMembership) (*DevOpsProjectMembership, error) {
|
func (o *projectMemberOperator) UpdateProjectMember(projectId string, membership *devops.ProjectMembership) (*devops.ProjectMembership, error) {
|
||||||
dbconn, err := cs.ClientSets().MySQL()
|
|
||||||
if err != nil {
|
|
||||||
return nil, restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
}
|
|
||||||
devops, err := cs.ClientSets().Devops()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
jenkinsClient := devops.Jenkins()
|
oldMembership := &devops.ProjectMembership{}
|
||||||
if jenkinsClient == nil {
|
err := o.db.Select(ProjectMembershipColumns...).
|
||||||
err := fmt.Errorf("could not connect to jenkins")
|
From(ProjectMembershipTableName).
|
||||||
klog.Error(err)
|
|
||||||
return nil, restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
oldMembership := &DevOpsProjectMembership{}
|
|
||||||
err = dbconn.Select(DevOpsProjectMembershipColumns...).
|
|
||||||
From(DevOpsProjectMembershipTableName).
|
|
||||||
Where(db.And(
|
Where(db.And(
|
||||||
db.Eq(DevOpsProjectMembershipUsernameColumn, member.Username),
|
db.Eq(ProjectMembershipUsernameColumn, membership.Username),
|
||||||
db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId),
|
db.Eq(ProjectMembershipProjectIdColumn, projectId),
|
||||||
)).LoadOne(oldMembership)
|
)).LoadOne(oldMembership)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return nil, restful.NewError(http.StatusBadRequest, err.Error())
|
return nil, restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
oldProjectRole, err := jenkinsClient.GetProjectRole(GetProjectRoleName(projectId, oldMembership.Role))
|
_, err = o.projectMemberOperator.UpdateProjectMember(oldMembership, membership)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
return nil, err
|
||||||
}
|
}
|
||||||
|
_, err = o.db.Update(ProjectMembershipTableName).
|
||||||
err = oldProjectRole.UnAssignRole(member.Username)
|
Set(ProjectMembershipRoleColumn, membership.Role).
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
oldPipelineRole, err := jenkinsClient.GetProjectRole(GetPipelineRoleName(projectId, oldMembership.Role))
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
err = oldPipelineRole.UnAssignRole(member.Username)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
projectRole, err := jenkinsClient.GetProjectRole(GetProjectRoleName(projectId, member.Role))
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
err = projectRole.AssignRole(member.Username)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
pipelineRole, err := jenkinsClient.GetProjectRole(GetPipelineRoleName(projectId, member.Role))
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
err = pipelineRole.AssignRole(member.Username)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = dbconn.Update(DevOpsProjectMembershipTableName).
|
|
||||||
Set(DevOpsProjectMembershipRoleColumn, member.Role).
|
|
||||||
Where(db.And(
|
Where(db.And(
|
||||||
db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId),
|
db.Eq(ProjectMembershipProjectIdColumn, projectId),
|
||||||
db.Eq(DevOpsProjectMembershipUsernameColumn, member.Username),
|
db.Eq(ProjectMembershipUsernameColumn, membership.Username),
|
||||||
)).Exec()
|
)).Exec()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
responseMembership := &DevOpsProjectMembership{}
|
responseMembership := &devops.ProjectMembership{}
|
||||||
err = dbconn.Select(DevOpsProjectMembershipColumns...).
|
err = o.db.Select(ProjectMembershipColumns...).
|
||||||
From(DevOpsProjectMembershipTableName).
|
From(ProjectMembershipTableName).
|
||||||
Where(db.And(
|
Where(db.And(
|
||||||
db.Eq(DevOpsProjectMembershipUsernameColumn, member.Username),
|
db.Eq(ProjectMembershipUsernameColumn, membership.Username),
|
||||||
db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId),
|
db.Eq(ProjectMembershipProjectIdColumn, projectId),
|
||||||
)).LoadOne(responseMembership)
|
)).LoadOne(responseMembership)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
@@ -299,25 +200,14 @@ func UpdateProjectMember(projectId, operator string, member *DevOpsProjectMember
|
|||||||
return responseMembership, nil
|
return responseMembership, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteProjectMember(projectId, username string) (string, error) {
|
func (o *projectMemberOperator) DeleteProjectMember(projectId, username string) (string, error) {
|
||||||
dbconn, err := cs.ClientSets().MySQL()
|
|
||||||
if err != nil {
|
|
||||||
return "", restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
devops, err := cs.ClientSets().Devops()
|
oldMembership := &devops.ProjectMembership{}
|
||||||
if err != nil {
|
err := o.db.Select(ProjectMembershipColumns...).
|
||||||
return "", restful.NewError(http.StatusServiceUnavailable, err.Error())
|
From(ProjectMembershipTableName).
|
||||||
}
|
|
||||||
|
|
||||||
jenkinsClient := devops.Jenkins()
|
|
||||||
|
|
||||||
oldMembership := &DevOpsProjectMembership{}
|
|
||||||
err = dbconn.Select(DevOpsProjectMembershipColumns...).
|
|
||||||
From(DevOpsProjectMembershipTableName).
|
|
||||||
Where(db.And(
|
Where(db.And(
|
||||||
db.Eq(DevOpsProjectMembershipUsernameColumn, username),
|
db.Eq(ProjectMembershipUsernameColumn, username),
|
||||||
db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId),
|
db.Eq(ProjectMembershipProjectIdColumn, projectId),
|
||||||
)).LoadOne(oldMembership)
|
)).LoadOne(oldMembership)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != db.ErrNotFound {
|
if err != db.ErrNotFound {
|
||||||
@@ -329,12 +219,12 @@ func DeleteProjectMember(projectId, username string) (string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if oldMembership.Role == ProjectOwner {
|
if oldMembership.Role == devops.ProjectOwner {
|
||||||
count, err := dbconn.Select(DevOpsProjectMembershipProjectIdColumn).
|
count, err := o.db.Select(ProjectMembershipProjectIdColumn).
|
||||||
From(DevOpsProjectMembershipTableName).
|
From(ProjectMembershipTableName).
|
||||||
Where(db.And(
|
Where(db.And(
|
||||||
db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId),
|
db.Eq(ProjectMembershipProjectIdColumn, projectId),
|
||||||
db.Eq(DevOpsProjectMembershipRoleColumn, ProjectOwner))).Count()
|
db.Eq(ProjectMembershipRoleColumn, devops.ProjectOwner))).Count()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return "", restful.NewError(http.StatusInternalServerError, err.Error())
|
return "", restful.NewError(http.StatusInternalServerError, err.Error())
|
||||||
@@ -346,32 +236,16 @@ func DeleteProjectMember(projectId, username string) (string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
oldProjectRole, err := jenkinsClient.GetProjectRole(GetProjectRoleName(projectId, oldMembership.Role))
|
_, err = o.projectMemberOperator.DeleteProjectMember(oldMembership)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Error(err)
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
return "", err
|
||||||
}
|
|
||||||
err = oldProjectRole.UnAssignRole(username)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
oldPipelineRole, err := jenkinsClient.GetProjectRole(GetPipelineRoleName(projectId, oldMembership.Role))
|
_, err = o.db.DeleteFrom(ProjectMembershipTableName).
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
err = oldPipelineRole.UnAssignRole(username)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = dbconn.DeleteFrom(DevOpsProjectMembershipTableName).
|
|
||||||
Where(db.And(
|
Where(db.And(
|
||||||
db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId),
|
db.Eq(ProjectMembershipProjectIdColumn, projectId),
|
||||||
db.Eq(DevOpsProjectMembershipUsernameColumn, username),
|
db.Eq(ProjectMembershipUsernameColumn, username),
|
||||||
)).Exec()
|
)).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
|
|||||||
@@ -17,295 +17,49 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/emicklei/go-restful"
|
"github.com/emicklei/go-restful"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
"kubesphere.io/kubesphere/pkg/gojenkins/utils"
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
cs "kubesphere.io/kubesphere/pkg/simple/client"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CreateProjectPipeline(projectId string, pipeline *ProjectPipeline) (string, error) {
|
type ProjectPipelineOperator interface {
|
||||||
devops, err := cs.ClientSets().Devops()
|
CreateProjectPipeline(projectId string, pipeline *devops.ProjectPipeline) (string, error)
|
||||||
if err != nil {
|
DeleteProjectPipeline(projectId string, pipelineId string) (string, error)
|
||||||
return "", restful.NewError(http.StatusServiceUnavailable, err.Error())
|
UpdateProjectPipeline(projectId, pipelineId string, pipeline *devops.ProjectPipeline) (string, error)
|
||||||
|
GetProjectPipelineConfig(projectId, pipelineId string) (*devops.ProjectPipeline, error)
|
||||||
}
|
}
|
||||||
jenkinsClient := devops.Jenkins()
|
type projectPipelineOperator struct {
|
||||||
|
pipelineOperator devops.ProjectPipelineOperator
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewProjectPipelineOperator(devopsClient devops.ProjectPipelineOperator) ProjectPipelineOperator {
|
||||||
|
return &projectPipelineOperator{
|
||||||
|
pipelineOperator: devopsClient,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *projectPipelineOperator) CreateProjectPipeline(projectId string, pipeline *devops.ProjectPipeline) (string, error) {
|
||||||
|
return o.pipelineOperator.CreateProjectPipeline(projectId, pipeline)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *projectPipelineOperator) DeleteProjectPipeline(projectId string, pipelineId string) (string, error) {
|
||||||
|
return o.pipelineOperator.DeleteProjectPipeline(projectId, pipelineId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *projectPipelineOperator) UpdateProjectPipeline(projectId, pipelineId string, pipeline *devops.ProjectPipeline) (string, error) {
|
||||||
|
|
||||||
switch pipeline.Type {
|
switch pipeline.Type {
|
||||||
case NoScmPipelineType:
|
case devops.NoScmPipelineType:
|
||||||
|
pipeline.Pipeline.Name = pipelineId
|
||||||
config, err := createPipelineConfigXml(pipeline.Pipeline)
|
case devops.MultiBranchPipelineType:
|
||||||
if err != nil {
|
pipeline.MultiBranchPipeline.Name = pipelineId
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(http.StatusInternalServerError, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
job, err := jenkinsClient.GetJob(pipeline.Pipeline.Name, projectId)
|
|
||||||
if job != nil {
|
|
||||||
err := fmt.Errorf("job name [%s] has been used", job.GetName())
|
|
||||||
klog.Warning(err.Error())
|
|
||||||
return "", restful.NewError(http.StatusConflict, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil && utils.GetJenkinsStatusCode(err) != http.StatusNotFound {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = jenkinsClient.CreateJobInFolder(config, pipeline.Pipeline.Name, projectId)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return pipeline.Pipeline.Name, nil
|
|
||||||
case MultiBranchPipelineType:
|
|
||||||
config, err := createMultiBranchPipelineConfigXml(projectId, pipeline.MultiBranchPipeline)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
|
|
||||||
return "", restful.NewError(http.StatusInternalServerError, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
job, err := jenkinsClient.GetJob(pipeline.MultiBranchPipeline.Name, projectId)
|
|
||||||
if job != nil {
|
|
||||||
err := fmt.Errorf("job name [%s] has been used", job.GetName())
|
|
||||||
klog.Warning(err.Error())
|
|
||||||
return "", restful.NewError(http.StatusConflict, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil && utils.GetJenkinsStatusCode(err) != http.StatusNotFound {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = jenkinsClient.CreateJobInFolder(config, pipeline.MultiBranchPipeline.Name, projectId)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return pipeline.MultiBranchPipeline.Name, nil
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
err := fmt.Errorf("error unsupport job type")
|
err := fmt.Errorf("error unsupport pipeline type")
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
|
return o.pipelineOperator.UpdateProjectPipeline(projectId, pipeline)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteProjectPipeline(projectId string, pipelineId string) (string, error) {
|
func (o *projectPipelineOperator) GetProjectPipelineConfig(projectId, pipelineId string) (*devops.ProjectPipeline, error) {
|
||||||
devops, err := cs.ClientSets().Devops()
|
return o.pipelineOperator.GetProjectPipelineConfig(projectId, pipelineId)
|
||||||
if err != nil {
|
|
||||||
return "", restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
}
|
|
||||||
jenkinsClient := devops.Jenkins()
|
|
||||||
|
|
||||||
_, err = jenkinsClient.DeleteJob(pipelineId, projectId)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
return pipelineId, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func UpdateProjectPipeline(projectId, pipelineId string, pipeline *ProjectPipeline) (string, error) {
|
|
||||||
devops, err := cs.ClientSets().Devops()
|
|
||||||
if err != nil {
|
|
||||||
return "", restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
}
|
|
||||||
jenkinsClient := devops.Jenkins()
|
|
||||||
|
|
||||||
switch pipeline.Type {
|
|
||||||
case NoScmPipelineType:
|
|
||||||
|
|
||||||
config, err := createPipelineConfigXml(pipeline.Pipeline)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(http.StatusInternalServerError, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
job, err := jenkinsClient.GetJob(pipelineId, projectId)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
err = job.UpdateConfig(config)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return pipeline.Pipeline.Name, nil
|
|
||||||
case MultiBranchPipelineType:
|
|
||||||
|
|
||||||
config, err := createMultiBranchPipelineConfigXml(projectId, pipeline.MultiBranchPipeline)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
|
|
||||||
return "", restful.NewError(http.StatusInternalServerError, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
job, err := jenkinsClient.GetJob(pipelineId, projectId)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
err = job.UpdateConfig(config)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return pipeline.MultiBranchPipeline.Name, nil
|
|
||||||
|
|
||||||
default:
|
|
||||||
err := fmt.Errorf("error unsupport job type")
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetProjectPipeline(projectId, pipelineId string) (*ProjectPipeline, error) {
|
|
||||||
devops, err := cs.ClientSets().Devops()
|
|
||||||
if err != nil {
|
|
||||||
return nil, restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
}
|
|
||||||
jenkinsClient := devops.Jenkins()
|
|
||||||
|
|
||||||
job, err := jenkinsClient.GetJob(pipelineId, projectId)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
switch job.Raw.Class {
|
|
||||||
case "org.jenkinsci.plugins.workflow.job.WorkflowJob":
|
|
||||||
config, err := job.GetConfig()
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
pipeline, err := parsePipelineConfigXml(config)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
pipeline.Name = pipelineId
|
|
||||||
return &ProjectPipeline{
|
|
||||||
Type: NoScmPipelineType,
|
|
||||||
Pipeline: pipeline,
|
|
||||||
}, nil
|
|
||||||
|
|
||||||
case "org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject":
|
|
||||||
config, err := job.GetConfig()
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
pipeline, err := parseMultiBranchPipelineConfigXml(config)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
pipeline.Name = pipelineId
|
|
||||||
return &ProjectPipeline{
|
|
||||||
Type: MultiBranchPipelineType,
|
|
||||||
MultiBranchPipeline: pipeline,
|
|
||||||
}, nil
|
|
||||||
default:
|
|
||||||
err := fmt.Errorf("error unsupport job type")
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(http.StatusBadRequest, err.Error())
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetPipelineSonar(projectId, pipelineId string) ([]*SonarStatus, error) {
|
|
||||||
devops, err := cs.ClientSets().Devops()
|
|
||||||
if err != nil {
|
|
||||||
return nil, restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
}
|
|
||||||
jenkinsClient := devops.Jenkins()
|
|
||||||
|
|
||||||
job, err := jenkinsClient.GetJob(pipelineId, projectId)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
build, err := job.GetLastBuild()
|
|
||||||
if err != nil && utils.GetJenkinsStatusCode(err) != http.StatusNotFound {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
} else if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
sonarStatus, err := getBuildSonarResults(build)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(http.StatusBadRequest, err.Error())
|
|
||||||
}
|
|
||||||
if len(sonarStatus) == 0 {
|
|
||||||
build, err := job.GetLastCompletedBuild()
|
|
||||||
if err != nil && utils.GetJenkinsStatusCode(err) != http.StatusNotFound {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
} else if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
sonarStatus, err = getBuildSonarResults(build)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(http.StatusBadRequest, err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sonarStatus, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetMultiBranchPipelineSonar(projectId, pipelineId, branchId string) ([]*SonarStatus, error) {
|
|
||||||
devops, err := cs.ClientSets().Devops()
|
|
||||||
if err != nil {
|
|
||||||
return nil, restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
}
|
|
||||||
jenkinsClient := devops.Jenkins()
|
|
||||||
|
|
||||||
job, err := jenkinsClient.GetJob(branchId, projectId, pipelineId)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
build, err := job.GetLastBuild()
|
|
||||||
if err != nil && utils.GetJenkinsStatusCode(err) != http.StatusNotFound {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
} else if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
sonarStatus, err := getBuildSonarResults(build)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(http.StatusBadRequest, err.Error())
|
|
||||||
}
|
|
||||||
if len(sonarStatus) == 0 {
|
|
||||||
build, err := job.GetLastCompletedBuild()
|
|
||||||
if err != nil && utils.GetJenkinsStatusCode(err) != http.StatusNotFound {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
} else if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
sonarStatus, err = getBuildSonarResults(build)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(http.StatusBadRequest, err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sonarStatus, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
122
pkg/models/devops/project_pipeline_sonar_handler.go
Normal file
122
pkg/models/devops/project_pipeline_sonar_handler.go
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
package devops
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/emicklei/go-restful"
|
||||||
|
"k8s.io/klog"
|
||||||
|
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/sonarqube"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PipelineSonarGetter interface {
|
||||||
|
GetPipelineSonar(projectId, pipelineId string) ([]*sonarqube.SonarStatus, error)
|
||||||
|
GetMultiBranchPipelineSonar(projectId, pipelineId, branchId string) ([]*sonarqube.SonarStatus, error)
|
||||||
|
}
|
||||||
|
type pipelineSonarGetter struct {
|
||||||
|
devops.BuildGetter
|
||||||
|
sonarqube.SonarInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPipelineSonarGetter(devopClient devops.BuildGetter, sonarClient sonarqube.SonarInterface) PipelineSonarGetter {
|
||||||
|
return &pipelineSonarGetter{
|
||||||
|
BuildGetter: devopClient,
|
||||||
|
SonarInterface: sonarClient,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *pipelineSonarGetter) GetPipelineSonar(projectId, pipelineId string) ([]*sonarqube.SonarStatus, error) {
|
||||||
|
|
||||||
|
build, err := g.GetProjectPipelineBuildByType(projectId, pipelineId, devops.LastBuild)
|
||||||
|
if err != nil && errors.GetServiceErrorCode(err) != http.StatusNotFound {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, err
|
||||||
|
} else if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
var taskIds []string
|
||||||
|
for _, action := range build.Actions {
|
||||||
|
if action.ClassName == sonarqube.SonarAnalysisActionClass {
|
||||||
|
taskIds = append(taskIds, action.SonarTaskId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var sonarStatus []*sonarqube.SonarStatus
|
||||||
|
|
||||||
|
if len(taskIds) != 0 {
|
||||||
|
sonarStatus, err = g.GetSonarResultsByTaskIds(taskIds...)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
} else if len(taskIds) == 0 {
|
||||||
|
build, err := g.GetProjectPipelineBuildByType(projectId, pipelineId, devops.LastCompletedBuild)
|
||||||
|
if err != nil && errors.GetServiceErrorCode(err) != http.StatusNotFound {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, restful.NewError(errors.GetServiceErrorCode(err), err.Error())
|
||||||
|
} else if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
for _, action := range build.Actions {
|
||||||
|
if action.ClassName == sonarqube.SonarAnalysisActionClass {
|
||||||
|
taskIds = append(taskIds, action.SonarTaskId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sonarStatus, err = g.GetSonarResultsByTaskIds(taskIds...)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return sonarStatus, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *pipelineSonarGetter) GetMultiBranchPipelineSonar(projectId, pipelineId, branchId string) ([]*sonarqube.SonarStatus, error) {
|
||||||
|
|
||||||
|
build, err := g.GetMultiBranchPipelineBuildByType(projectId, pipelineId, branchId, devops.LastBuild)
|
||||||
|
if err != nil && errors.GetServiceErrorCode(err) != http.StatusNotFound {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, restful.NewError(errors.GetServiceErrorCode(err), err.Error())
|
||||||
|
} else if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
var taskIds []string
|
||||||
|
for _, action := range build.Actions {
|
||||||
|
if action.ClassName == sonarqube.SonarAnalysisActionClass {
|
||||||
|
taskIds = append(taskIds, action.SonarTaskId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var sonarStatus []*sonarqube.SonarStatus
|
||||||
|
|
||||||
|
if len(taskIds) != 0 {
|
||||||
|
sonarStatus, err = g.GetSonarResultsByTaskIds(taskIds...)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
} else if len(taskIds) == 0 {
|
||||||
|
build, err := g.GetMultiBranchPipelineBuildByType(projectId, pipelineId, branchId, devops.LastCompletedBuild)
|
||||||
|
if err != nil && errors.GetServiceErrorCode(err) != http.StatusNotFound {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, restful.NewError(errors.GetServiceErrorCode(err), err.Error())
|
||||||
|
} else if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
for _, action := range build.Actions {
|
||||||
|
if action.ClassName == sonarqube.SonarAnalysisActionClass {
|
||||||
|
taskIds = append(taskIds, action.SonarTaskId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sonarStatus, err = g.GetSonarResultsByTaskIds(taskIds...)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return sonarStatus, nil
|
||||||
|
}
|
||||||
@@ -3,6 +3,8 @@ package devops
|
|||||||
import (
|
import (
|
||||||
"code.cloudfoundry.org/bytefmt"
|
"code.cloudfoundry.org/bytefmt"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
awsS3 "github.com/aws/aws-sdk-go/service/s3"
|
||||||
"github.com/emicklei/go-restful"
|
"github.com/emicklei/go-restful"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/util/retry"
|
"k8s.io/client-go/util/retry"
|
||||||
@@ -10,7 +12,6 @@ import (
|
|||||||
"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||||
"kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
"kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||||
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
|
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client"
|
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/s3"
|
"kubesphere.io/kubesphere/pkg/simple/client/s3"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -22,9 +23,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type S2iBinaryUploader interface {
|
type S2iBinaryUploader interface {
|
||||||
UploadBinary(name, namespace, md5 string, header *multipart.FileHeader) (*v1alpha1.S2iBinary, error)
|
UploadS2iBinary(namespace, name, md5 string, header *multipart.FileHeader) (*v1alpha1.S2iBinary, error)
|
||||||
|
|
||||||
DownloadBinary(name, namespace, fileName string) (string, error)
|
DownloadS2iBinary(namespace, name, fileName string) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type s2iBinaryUploader struct {
|
type s2iBinaryUploader struct {
|
||||||
@@ -33,6 +34,14 @@ type s2iBinaryUploader struct {
|
|||||||
s3Client s3.Interface
|
s3Client s3.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewS2iBinaryUploader(client versioned.Interface, informers externalversions.SharedInformerFactory, s3Client s3.Interface) S2iBinaryUploader {
|
||||||
|
return &s2iBinaryUploader{
|
||||||
|
client: client,
|
||||||
|
informers: informers,
|
||||||
|
s3Client: s3Client,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *s2iBinaryUploader) UploadS2iBinary(namespace, name, md5 string, fileHeader *multipart.FileHeader) (*v1alpha1.S2iBinary, error) {
|
func (s *s2iBinaryUploader) UploadS2iBinary(namespace, name, md5 string, fileHeader *multipart.FileHeader) (*v1alpha1.S2iBinary, error) {
|
||||||
binFile, err := fileHeader.Open()
|
binFile, err := fileHeader.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -75,43 +84,20 @@ func (s *s2iBinaryUploader) UploadS2iBinary(namespace, name, md5 string, fileHea
|
|||||||
copy.Spec.FileName = fileHeader.Filename
|
copy.Spec.FileName = fileHeader.Filename
|
||||||
copy.Spec.DownloadURL = fmt.Sprintf(GetS2iBinaryURL, namespace, name, copy.Spec.FileName)
|
copy.Spec.DownloadURL = fmt.Sprintf(GetS2iBinaryURL, namespace, name, copy.Spec.FileName)
|
||||||
|
|
||||||
/*
|
err = s.s3Client.Upload(fmt.Sprintf("%s-%s", namespace, name), copy.Spec.FileName, binFile)
|
||||||
TODO: upload binary file use s3.Interface
|
|
||||||
s3session := s3Client.Session()
|
|
||||||
if s3session == nil {
|
|
||||||
err := fmt.Errorf("could not connect to s2i s3")
|
|
||||||
klog.Error(err)
|
|
||||||
_, serr := SetS2iBinaryStatusWithRetry(copy, origin.Status.Phase)
|
|
||||||
if serr != nil {
|
|
||||||
klog.Error(serr)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
uploader := s3manager.NewUploader(s3session, func(uploader *s3manager.Uploader) {
|
|
||||||
uploader.PartSize = 5 * bytefmt.MEGABYTE
|
|
||||||
uploader.LeavePartsOnError = true
|
|
||||||
})
|
|
||||||
_, err = uploader.Upload(&s3manager.UploadInput{
|
|
||||||
Bucket: s3Client.Bucket(),
|
|
||||||
Key: aws.String(fmt.Sprintf("%s-%s", namespace, name)),
|
|
||||||
Body: binFile,
|
|
||||||
ContentDisposition: aws.String(fmt.Sprintf("attachment; filename=\"%s\"", copy.Spec.FileName)),
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if aerr, ok := err.(awserr.Error); ok {
|
if aerr, ok := err.(awserr.Error); ok {
|
||||||
switch aerr.Code() {
|
switch aerr.Code() {
|
||||||
case s3.ErrCodeNoSuchBucket:
|
case awsS3.ErrCodeNoSuchBucket:
|
||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
_, serr := SetS2iBinaryStatusWithRetry(copy, origin.Status.Phase)
|
_, serr := s.SetS2iBinaryStatusWithRetry(copy, origin.Status.Phase)
|
||||||
if serr != nil {
|
if serr != nil {
|
||||||
klog.Error(serr)
|
klog.Error(serr)
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
default:
|
default:
|
||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
_, serr := SetS2iBinaryStatusWithRetry(copy, v1alpha1.StatusUploadFailed)
|
_, serr := s.SetS2iBinaryStatusWithRetry(copy, v1alpha1.StatusUploadFailed)
|
||||||
if serr != nil {
|
if serr != nil {
|
||||||
klog.Error(serr)
|
klog.Error(serr)
|
||||||
}
|
}
|
||||||
@@ -121,12 +107,12 @@ func (s *s2iBinaryUploader) UploadS2iBinary(namespace, name, md5 string, fileHea
|
|||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
if copy.Spec.UploadTimeStamp == nil {
|
if copy.Spec.UploadTimeStamp == nil {
|
||||||
copy.Spec.UploadTimeStamp = new(metav1.Time)
|
copy.Spec.UploadTimeStamp = new(metav1.Time)
|
||||||
}
|
}
|
||||||
*copy.Spec.UploadTimeStamp = metav1.Now()
|
*copy.Spec.UploadTimeStamp = metav1.Now()
|
||||||
copy, err = client.ClientSets().K8s().KubeSphere().DevopsV1alpha1().S2iBinaries(namespace).Update(copy)
|
copy, err = s.client.DevopsV1alpha1().S2iBinaries(namespace).Update(copy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -159,22 +145,7 @@ func (s *s2iBinaryUploader) DownloadS2iBinary(namespace, name, fileName string)
|
|||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
return s.s3Client.GetDownloadURL(fmt.Sprintf("%s-%s", namespace, name), fileName)
|
||||||
/*
|
|
||||||
TODO: get download url of requested binary
|
|
||||||
req, _ := s.s3Client.Client().GetObjectRequest(&s3.GetObjectInput{
|
|
||||||
Bucket: s3Client.Bucket(),
|
|
||||||
Key: aws.String(fmt.Sprintf("%s-%s", namespace, name)),
|
|
||||||
ResponseContentDisposition: aws.String(fmt.Sprintf("attachment; filename=\"%s\"", origin.Spec.FileName)),
|
|
||||||
})
|
|
||||||
url, err := req.Presign(5 * time.Minute)
|
|
||||||
if err != nil {
|
|
||||||
klog.Error(err)
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return "", nil
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *s2iBinaryUploader) SetS2iBinaryStatus(s2ibin *v1alpha1.S2iBinary, status string) (*v1alpha1.S2iBinary, error) {
|
func (s *s2iBinaryUploader) SetS2iBinaryStatus(s2ibin *v1alpha1.S2iBinary, status string) (*v1alpha1.S2iBinary, error) {
|
||||||
@@ -193,7 +164,7 @@ func (s *s2iBinaryUploader) SetS2iBinaryStatusWithRetry(s2ibin *v1alpha1.S2iBina
|
|||||||
var bin *v1alpha1.S2iBinary
|
var bin *v1alpha1.S2iBinary
|
||||||
var err error
|
var err error
|
||||||
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||||
bin, err = s.informers.Devops().V1alpha1().S2iBinaries().Lister().S2iBinaries(s2ibin.Namespace).Get(s2ibin.Name)
|
bin, err = s.client.DevopsV1alpha1().S2iBinaries(s2ibin.Namespace).Get(s2ibin.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
return err
|
return err
|
||||||
|
|||||||
114
pkg/models/devops/s2ibinary_handler_test.go
Normal file
114
pkg/models/devops/s2ibinary_handler_test.go
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
package devops
|
||||||
|
|
||||||
|
import (
|
||||||
|
"code.cloudfoundry.org/bytefmt"
|
||||||
|
"fmt"
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
clientgotesting "k8s.io/client-go/testing"
|
||||||
|
"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||||
|
"kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
|
||||||
|
ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
|
||||||
|
fakeS3 "kubesphere.io/kubesphere/pkg/simple/client/s3/fake"
|
||||||
|
"kubesphere.io/kubesphere/pkg/utils/hashutil"
|
||||||
|
"mime/multipart"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
fileaContents = "This is a test file."
|
||||||
|
fileaKey = "binary"
|
||||||
|
fileaName = "filea.txt"
|
||||||
|
boundary = `MyBoundary`
|
||||||
|
ns = "testns"
|
||||||
|
s2ibname = "test"
|
||||||
|
)
|
||||||
|
|
||||||
|
const message = `
|
||||||
|
--MyBoundary
|
||||||
|
Content-Disposition: form-data; name="binary"; filename="filea.txt"
|
||||||
|
Content-Type: text/plain
|
||||||
|
|
||||||
|
` + fileaContents + `
|
||||||
|
--MyBoundary--
|
||||||
|
`
|
||||||
|
|
||||||
|
func TestS2iBinaryUploader(t *testing.T) {
|
||||||
|
s2ib := s2ibinary(ns, s2ibname)
|
||||||
|
fakeKubeClient := fake.NewSimpleClientset(s2ib)
|
||||||
|
fakeWatch := watch.NewFake()
|
||||||
|
fakeKubeClient.AddWatchReactor("*", clientgotesting.DefaultWatchReactor(fakeWatch, nil))
|
||||||
|
informerFactory := ksinformers.NewSharedInformerFactory(fakeKubeClient, 0)
|
||||||
|
stopCh := make(chan struct{})
|
||||||
|
s2iInformer := informerFactory.Devops().V1alpha1().S2iBinaries()
|
||||||
|
err := s2iInformer.Informer().GetIndexer().Add(s2ib)
|
||||||
|
defer close(stopCh)
|
||||||
|
informerFactory.Start(stopCh)
|
||||||
|
informerFactory.WaitForCacheSync(stopCh)
|
||||||
|
|
||||||
|
s3 := fakeS3.NewFakeS3()
|
||||||
|
uploader := NewS2iBinaryUploader(fakeKubeClient, informerFactory, s3)
|
||||||
|
header := prepareFileHeader()
|
||||||
|
file, err := header.Open()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
md5, err := hashutil.GetMD5(file)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
wantSpec := v1alpha1.S2iBinarySpec{
|
||||||
|
FileName: fileaName,
|
||||||
|
MD5: md5,
|
||||||
|
Size: bytefmt.ByteSize(uint64(header.Size)),
|
||||||
|
}
|
||||||
|
|
||||||
|
binary, err := uploader.UploadS2iBinary(ns, s2ibname, md5, header)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
wantSpec.UploadTimeStamp = binary.Spec.UploadTimeStamp
|
||||||
|
wantSpec.DownloadURL = binary.Spec.DownloadURL
|
||||||
|
if !reflect.DeepEqual(binary.Spec, wantSpec) {
|
||||||
|
t.Fatalf("s2ibinary spec is not same with expected, get: %+v, expected: %+v", binary, wantSpec)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := s3.Storage[fmt.Sprintf("%s-%s", ns, s2ibname)]
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("should get file in s3")
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
url, err := uploader.DownloadS2iBinary(ns, s2ibname, fileaName)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if url != fmt.Sprintf("http://%s-%s/%s", ns, s2ibname, fileaName) {
|
||||||
|
t.Fatalf("download url is not equal with expected, get: %+v, expected: %+v", url, fmt.Sprintf("http://%s-%s/%s", ns, s2ibname, fileaName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func prepareFileHeader() *multipart.FileHeader {
|
||||||
|
reader := strings.NewReader(message)
|
||||||
|
multipartReader := multipart.NewReader(reader, boundary)
|
||||||
|
form, err := multipartReader.ReadForm(25)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return form.File["binary"][0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func s2ibinary(namespace, name string) *v1alpha1.S2iBinary {
|
||||||
|
return &v1alpha1.S2iBinary{
|
||||||
|
ObjectMeta: v1.ObjectMeta{
|
||||||
|
Name: name,
|
||||||
|
Namespace: namespace,
|
||||||
|
},
|
||||||
|
Spec: v1alpha1.S2iBinarySpec{},
|
||||||
|
Status: v1alpha1.S2iBinaryStatus{},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright 2019 The KubeSphere Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
*/
|
|
||||||
package devops
|
|
||||||
|
|
||||||
// Some apis for Jenkins.
|
|
||||||
const (
|
|
||||||
GetPipeBranchUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/?"
|
|
||||||
GetBranchPipeUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/"
|
|
||||||
GetPipelineUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/"
|
|
||||||
SearchPipelineUrl = "/blue/rest/search/?"
|
|
||||||
RunBranchPipelineUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/"
|
|
||||||
RunPipelineUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/"
|
|
||||||
GetPipelineRunUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/%s/"
|
|
||||||
GetPipeBranchRunUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/%s/"
|
|
||||||
SearchPipelineRunUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/?"
|
|
||||||
GetBranchPipeRunNodesUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/%s/nodes/?"
|
|
||||||
GetPipeRunNodesUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/%s/nodes/?"
|
|
||||||
GetBranchRunLogUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/%s/log/?"
|
|
||||||
GetRunLogUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/%s/log/?"
|
|
||||||
GetBranchStepLogUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/%s/nodes/%s/steps/%s/log/?"
|
|
||||||
GetStepLogUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/%s/nodes/%s/steps/%s/log/?"
|
|
||||||
StopBranchPipelineUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/%s/stop/?"
|
|
||||||
StopPipelineUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/%s/stop/?"
|
|
||||||
ReplayBranchPipelineUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/%s/replay/"
|
|
||||||
ReplayPipelineUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/%s/replay/"
|
|
||||||
GetBranchArtifactsUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/%s/artifacts/?"
|
|
||||||
GetArtifactsUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/%s/artifacts/?"
|
|
||||||
CheckBranchPipelineUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/%s/nodes/%s/steps/%s/"
|
|
||||||
CheckPipelineUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/%s/nodes/%s/steps/%s/"
|
|
||||||
GetBranchNodeStepsUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/%s/nodes/%s/steps/?"
|
|
||||||
GetNodeStepsUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/%s/nodes/%s/steps/?"
|
|
||||||
GetSCMServersUrl = "/blue/rest/organizations/jenkins/scm/%s/servers/"
|
|
||||||
CreateSCMServersUrl = "/blue/rest/organizations/jenkins/scm/%s/servers/"
|
|
||||||
ValidateUrl = "/blue/rest/organizations/jenkins/scm/%s/validate"
|
|
||||||
GetSCMOrgUrl = "/blue/rest/organizations/jenkins/scm/%s/organizations/?"
|
|
||||||
GetOrgRepoUrl = "/blue/rest/organizations/jenkins/scm/%s/organizations/%s/repositories/?"
|
|
||||||
GetConsoleLogUrl = "/job/%s/job/%s/indexing/consoleText"
|
|
||||||
ScanBranchUrl = "/job/%s/job/%s/build?"
|
|
||||||
GetCrumbUrl = "/crumbIssuer/api/json/"
|
|
||||||
ToJenkinsfileUrl = "/pipeline-model-converter/toJenkinsfile"
|
|
||||||
ToJsonUrl = "/pipeline-model-converter/toJson"
|
|
||||||
GetNotifyCommitUrl = "/git/notifyCommit/?"
|
|
||||||
GithubWebhookUrl = "/github-webhook/"
|
|
||||||
CheckScriptCompileUrl = "/job/%s/job/%s/descriptorByName/org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition/checkScriptCompile"
|
|
||||||
CheckPipelienCronUrl = "/job/%s/job/%s/descriptorByName/hudson.triggers.TimerTrigger/checkSpec?value=%s"
|
|
||||||
CheckCronUrl = "/job/%s/descriptorByName/hudson.triggers.TimerTrigger/checkSpec?value=%s"
|
|
||||||
)
|
|
||||||
@@ -566,9 +566,9 @@ func (im *imOperator) deleteUserInDevOps(username string) error {
|
|||||||
|
|
||||||
jenkinsClient := dp.Jenkins()
|
jenkinsClient := dp.Jenkins()
|
||||||
|
|
||||||
_, err = devopsDb.DeleteFrom(devops.DevOpsProjectMembershipTableName).
|
_, err = devopsDb.DeleteFrom(devops.ProjectMembershipTableName).
|
||||||
Where(db.And(
|
Where(db.And(
|
||||||
db.Eq(devops.DevOpsProjectMembershipUsernameColumn, username),
|
db.Eq(devops.ProjectMembershipUsernameColumn, username),
|
||||||
)).Exec()
|
)).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
|
|||||||
@@ -24,35 +24,40 @@ import (
|
|||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
"kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
|
"kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
|
||||||
"kubesphere.io/kubesphere/pkg/db"
|
"kubesphere.io/kubesphere/pkg/db"
|
||||||
"kubesphere.io/kubesphere/pkg/gojenkins"
|
|
||||||
"kubesphere.io/kubesphere/pkg/gojenkins/utils"
|
|
||||||
"kubesphere.io/kubesphere/pkg/models"
|
"kubesphere.io/kubesphere/pkg/models"
|
||||||
"kubesphere.io/kubesphere/pkg/models/devops"
|
"kubesphere.io/kubesphere/pkg/models/devops"
|
||||||
"kubesphere.io/kubesphere/pkg/models/iam"
|
"kubesphere.io/kubesphere/pkg/models/iam"
|
||||||
"kubesphere.io/kubesphere/pkg/server/params"
|
"kubesphere.io/kubesphere/pkg/server/params"
|
||||||
cs "kubesphere.io/kubesphere/pkg/simple/client"
|
dsClient "kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type DevOpsProjectRoleResponse struct {
|
type DevOpsProjectOperator interface {
|
||||||
ProjectRole *gojenkins.ProjectRole
|
ListDevOpsProjects(workspace, username string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error)
|
||||||
Err error
|
CreateDevOpsProject(username string, workspace string, req *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, error)
|
||||||
|
GetDevOpsProjectsCount(username string) (uint32, error)
|
||||||
|
DeleteDevOpsProject(projectId, username string) error
|
||||||
|
GetUserDevOpsSimpleRules(username, projectId string) ([]iam.SimpleRule, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListDevopsProjects(workspace, username string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error) {
|
type devopsProjectOperator struct {
|
||||||
|
ksProjectOperator devops.ProjectOperator
|
||||||
dbconn, err := cs.ClientSets().MySQL()
|
db *mysql.Database
|
||||||
if err != nil {
|
dsProject dsClient.ProjectOperator
|
||||||
if _, ok := err.(cs.ClientSetNotEnabledError); ok {
|
|
||||||
klog.V(4).Info("devops client is not enable")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
klog.Error(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
query := dbconn.Select(devops.GetColumnsFromStructWithPrefix(devops.DevOpsProjectTableName, v1alpha2.DevOpsProject{})...).
|
func newProjectOperator(operator devops.ProjectOperator, db *mysql.Database, client dsClient.ProjectOperator) DevOpsProjectOperator {
|
||||||
|
return &devopsProjectOperator{
|
||||||
|
ksProjectOperator: operator,
|
||||||
|
db: db,
|
||||||
|
dsProject: client,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *devopsProjectOperator) ListDevOpsProjects(workspace, username string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error) {
|
||||||
|
|
||||||
|
query := o.db.Select(devops.GetColumnsFromStructWithPrefix(devops.DevOpsProjectTableName, v1alpha2.DevOpsProject{})...).
|
||||||
From(devops.DevOpsProjectTableName)
|
From(devops.DevOpsProjectTableName)
|
||||||
var sqconditions []dbr.Builder
|
var sqconditions []dbr.Builder
|
||||||
|
|
||||||
@@ -61,11 +66,11 @@ func ListDevopsProjects(workspace, username string, conditions *params.Condition
|
|||||||
switch username {
|
switch username {
|
||||||
case devops.KS_ADMIN:
|
case devops.KS_ADMIN:
|
||||||
default:
|
default:
|
||||||
onCondition := fmt.Sprintf("%s = %s", devops.DevOpsProjectMembershipProjectIdColumn, devops.DevOpsProjectIdColumn)
|
onCondition := fmt.Sprintf("%s = %s", devops.ProjectMembershipProjectIdColumn, devops.DevOpsProjectIdColumn)
|
||||||
query.Join(devops.DevOpsProjectMembershipTableName, onCondition)
|
query.Join(devops.ProjectMembershipTableName, onCondition)
|
||||||
sqconditions = append(sqconditions, db.Eq(devops.DevOpsProjectMembershipUsernameColumn, username))
|
sqconditions = append(sqconditions, db.Eq(devops.ProjectMembershipUsernameColumn, username))
|
||||||
sqconditions = append(sqconditions, db.Eq(
|
sqconditions = append(sqconditions, db.Eq(
|
||||||
devops.DevOpsProjectMembershipTableName+"."+devops.StatusColumn, devops.StatusActive))
|
devops.ProjectMembershipTableName+"."+devops.StatusColumn, devops.StatusActive))
|
||||||
}
|
}
|
||||||
|
|
||||||
sqconditions = append(sqconditions, db.Eq(
|
sqconditions = append(sqconditions, db.Eq(
|
||||||
@@ -95,7 +100,7 @@ func ListDevopsProjects(workspace, username string, conditions *params.Condition
|
|||||||
}
|
}
|
||||||
query.Limit(uint64(limit))
|
query.Limit(uint64(limit))
|
||||||
query.Offset(uint64(offset))
|
query.Offset(uint64(offset))
|
||||||
_, err = query.Load(&projects)
|
_, err := query.Load(&projects)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||||
@@ -114,23 +119,18 @@ func ListDevopsProjects(workspace, username string, conditions *params.Condition
|
|||||||
return &models.PageableResponse{Items: result, TotalCount: int(count)}, nil
|
return &models.PageableResponse{Items: result, TotalCount: int(count)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDevOpsProjectsCount(username string) (uint32, error) {
|
func (o *devopsProjectOperator) GetDevOpsProjectsCount(username string) (uint32, error) {
|
||||||
dbconn, err := cs.ClientSets().MySQL()
|
|
||||||
if err != nil {
|
|
||||||
klog.Error(err)
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
query := dbconn.Select(devops.GetColumnsFromStructWithPrefix(devops.DevOpsProjectTableName, v1alpha2.DevOpsProject{})...).
|
query := o.db.Select(devops.GetColumnsFromStructWithPrefix(devops.DevOpsProjectTableName, v1alpha2.DevOpsProject{})...).
|
||||||
From(devops.DevOpsProjectTableName)
|
From(devops.DevOpsProjectTableName)
|
||||||
var sqconditions []dbr.Builder
|
var sqconditions []dbr.Builder
|
||||||
|
|
||||||
if username != devops.KS_ADMIN {
|
if username != devops.KS_ADMIN {
|
||||||
onCondition := fmt.Sprintf("%s = %s", devops.DevOpsProjectMembershipProjectIdColumn, devops.DevOpsProjectIdColumn)
|
onCondition := fmt.Sprintf("%s = %s", devops.ProjectMembershipProjectIdColumn, devops.DevOpsProjectIdColumn)
|
||||||
query.Join(devops.DevOpsProjectMembershipTableName, onCondition)
|
query.Join(devops.ProjectMembershipTableName, onCondition)
|
||||||
sqconditions = append(sqconditions, db.Eq(devops.DevOpsProjectMembershipUsernameColumn, username))
|
sqconditions = append(sqconditions, db.Eq(devops.ProjectMembershipUsernameColumn, username))
|
||||||
sqconditions = append(sqconditions, db.Eq(
|
sqconditions = append(sqconditions, db.Eq(
|
||||||
devops.DevOpsProjectMembershipTableName+"."+devops.StatusColumn, devops.StatusActive))
|
devops.ProjectMembershipTableName+"."+devops.StatusColumn, devops.StatusActive))
|
||||||
}
|
}
|
||||||
|
|
||||||
sqconditions = append(sqconditions, db.Eq(
|
sqconditions = append(sqconditions, db.Eq(
|
||||||
@@ -146,171 +146,61 @@ func GetDevOpsProjectsCount(username string) (uint32, error) {
|
|||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteDevOpsProject(projectId, username string) error {
|
func (o *devopsProjectOperator) DeleteDevOpsProject(projectId, username string) error {
|
||||||
err := devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
|
err := o.ksProjectOperator.CheckProjectUserInRole(username, projectId, []string{dsClient.ProjectOwner})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return restful.NewError(http.StatusForbidden, err.Error())
|
return restful.NewError(http.StatusForbidden, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
dp, err := cs.ClientSets().Devops()
|
err = o.dsProject.DeleteDevOpsProject(projectId)
|
||||||
if err != nil {
|
|
||||||
klog.Error(err)
|
|
||||||
return restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
}
|
|
||||||
jenkins := dp.Jenkins()
|
|
||||||
|
|
||||||
devopsdb, err := cs.ClientSets().MySQL()
|
|
||||||
if err != nil {
|
|
||||||
klog.Error(err)
|
|
||||||
return restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = jenkins.DeleteJob(projectId)
|
|
||||||
|
|
||||||
if err != nil && utils.GetJenkinsStatusCode(err) != http.StatusNotFound {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
roleNames := make([]string, 0)
|
|
||||||
for role := range devops.JenkinsProjectPermissionMap {
|
|
||||||
roleNames = append(roleNames, devops.GetProjectRoleName(projectId, role))
|
|
||||||
roleNames = append(roleNames, devops.GetPipelineRoleName(projectId, role))
|
|
||||||
}
|
|
||||||
err = jenkins.DeleteProjectRoles(roleNames...)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
return err
|
||||||
}
|
}
|
||||||
_, err = devopsdb.DeleteFrom(devops.DevOpsProjectMembershipTableName).
|
_, err = o.db.DeleteFrom(devops.ProjectMembershipTableName).
|
||||||
Where(db.Eq(devops.DevOpsProjectMembershipProjectIdColumn, projectId)).Exec()
|
Where(db.Eq(devops.ProjectMembershipProjectIdColumn, projectId)).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
return err
|
||||||
}
|
}
|
||||||
_, err = devopsdb.Update(devops.DevOpsProjectTableName).
|
_, err = o.db.Update(devops.DevOpsProjectTableName).
|
||||||
Set(devops.StatusColumn, devops.StatusDeleted).
|
Set(devops.StatusColumn, devops.StatusDeleted).
|
||||||
Where(db.Eq(devops.DevOpsProjectIdColumn, projectId)).Exec()
|
Where(db.Eq(devops.DevOpsProjectIdColumn, projectId)).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
return err
|
||||||
}
|
}
|
||||||
project := &v1alpha2.DevOpsProject{}
|
project := &v1alpha2.DevOpsProject{}
|
||||||
err = devopsdb.Select(devops.DevOpsProjectColumns...).
|
err = o.db.Select(devops.DevOpsProjectColumns...).
|
||||||
From(devops.DevOpsProjectTableName).
|
From(devops.DevOpsProjectTableName).
|
||||||
Where(db.Eq(devops.DevOpsProjectIdColumn, projectId)).
|
Where(db.Eq(devops.DevOpsProjectIdColumn, projectId)).
|
||||||
LoadOne(project)
|
LoadOne(project)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateDevopsProject(username string, workspace string, req *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, error) {
|
func (o *devopsProjectOperator) CreateDevOpsProject(username string, workspace string, req *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, error) {
|
||||||
|
|
||||||
dp, err := cs.ClientSets().Devops()
|
|
||||||
if err != nil {
|
|
||||||
klog.Error(err)
|
|
||||||
return nil, restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
|
|
||||||
}
|
|
||||||
jenkinsClient := dp.Jenkins()
|
|
||||||
|
|
||||||
devopsdb, err := cs.ClientSets().MySQL()
|
|
||||||
if err != nil {
|
|
||||||
klog.Error(err)
|
|
||||||
return nil, restful.NewError(http.StatusServiceUnavailable, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
project := devops.NewDevOpsProject(req.Name, req.Description, username, req.Extra, workspace)
|
project := devops.NewDevOpsProject(req.Name, req.Description, username, req.Extra, workspace)
|
||||||
_, err = jenkinsClient.CreateFolder(project.ProjectId, project.Description)
|
_, err := o.dsProject.CreateDevOpsProject(username, project)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Error(err)
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
return nil, err
|
||||||
}
|
}
|
||||||
|
_, err = o.db.InsertInto(devops.DevOpsProjectTableName).
|
||||||
var addRoleCh = make(chan *DevOpsProjectRoleResponse, 8)
|
|
||||||
var addRoleWg sync.WaitGroup
|
|
||||||
for role, permission := range devops.JenkinsProjectPermissionMap {
|
|
||||||
addRoleWg.Add(1)
|
|
||||||
go func(role string, permission gojenkins.ProjectPermissionIds) {
|
|
||||||
_, err := jenkinsClient.AddProjectRole(devops.GetProjectRoleName(project.ProjectId, role),
|
|
||||||
devops.GetProjectRolePattern(project.ProjectId), permission, true)
|
|
||||||
addRoleCh <- &DevOpsProjectRoleResponse{nil, err}
|
|
||||||
addRoleWg.Done()
|
|
||||||
}(role, permission)
|
|
||||||
}
|
|
||||||
for role, permission := range devops.JenkinsPipelinePermissionMap {
|
|
||||||
addRoleWg.Add(1)
|
|
||||||
go func(role string, permission gojenkins.ProjectPermissionIds) {
|
|
||||||
_, err := jenkinsClient.AddProjectRole(devops.GetPipelineRoleName(project.ProjectId, role),
|
|
||||||
devops.GetPipelineRolePattern(project.ProjectId), permission, true)
|
|
||||||
addRoleCh <- &DevOpsProjectRoleResponse{nil, err}
|
|
||||||
addRoleWg.Done()
|
|
||||||
}(role, permission)
|
|
||||||
}
|
|
||||||
addRoleWg.Wait()
|
|
||||||
close(addRoleCh)
|
|
||||||
for addRoleResponse := range addRoleCh {
|
|
||||||
if addRoleResponse.Err != nil {
|
|
||||||
klog.Errorf("%+v", addRoleResponse.Err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(addRoleResponse.Err), addRoleResponse.Err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
globalRole, err := jenkinsClient.GetGlobalRole(devops.JenkinsAllUserRoleName)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
if globalRole == nil {
|
|
||||||
_, err := jenkinsClient.AddGlobalRole(devops.JenkinsAllUserRoleName, gojenkins.GlobalPermissionIds{
|
|
||||||
GlobalRead: true,
|
|
||||||
}, true)
|
|
||||||
if err != nil {
|
|
||||||
klog.Error("failed to create jenkins global role")
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err = globalRole.AssignRole(username)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
projectRole, err := jenkinsClient.GetProjectRole(devops.GetProjectRoleName(project.ProjectId, devops.ProjectOwner))
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
err = projectRole.AssignRole(username)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
pipelineRole, err := jenkinsClient.GetProjectRole(devops.GetPipelineRoleName(project.ProjectId, devops.ProjectOwner))
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
err = pipelineRole.AssignRole(username)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%+v", err)
|
|
||||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
|
||||||
}
|
|
||||||
_, err = devopsdb.InsertInto(devops.DevOpsProjectTableName).
|
|
||||||
Columns(devops.DevOpsProjectColumns...).Record(project).Exec()
|
Columns(devops.DevOpsProjectColumns...).Record(project).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
projectMembership := devops.NewDevOpsProjectMemberShip(username, project.ProjectId, devops.ProjectOwner, username)
|
projectMembership := devops.NewDevOpsProjectMemberShip(username, project.ProjectId, dsClient.ProjectOwner, username)
|
||||||
_, err = devopsdb.InsertInto(devops.DevOpsProjectMembershipTableName).
|
_, err = o.db.InsertInto(devops.ProjectMembershipTableName).
|
||||||
Columns(devops.DevOpsProjectMembershipColumns...).Record(projectMembership).Exec()
|
Columns(devops.ProjectMembershipColumns...).Record(projectMembership).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||||
@@ -318,8 +208,9 @@ func CreateDevopsProject(username string, workspace string, req *v1alpha2.DevOps
|
|||||||
return project, nil
|
return project, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUserDevopsSimpleRules(username, projectId string) ([]iam.SimpleRule, error) {
|
func (o *devopsProjectOperator) GetUserDevOpsSimpleRules(username, projectId string) ([]iam.SimpleRule, error) {
|
||||||
role, err := devops.GetProjectUserRole(username, projectId)
|
|
||||||
|
role, err := o.getProjectUserRole(username, projectId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("%+v", err)
|
klog.Errorf("%+v", err)
|
||||||
return nil, restful.NewError(http.StatusForbidden, err.Error())
|
return nil, restful.NewError(http.StatusForbidden, err.Error())
|
||||||
@@ -327,6 +218,24 @@ func GetUserDevopsSimpleRules(username, projectId string) ([]iam.SimpleRule, err
|
|||||||
return GetDevopsRoleSimpleRules(role), nil
|
return GetDevopsRoleSimpleRules(role), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *devopsProjectOperator) getProjectUserRole(username, projectId string) (string, error) {
|
||||||
|
if username == devops.KS_ADMIN {
|
||||||
|
return dsClient.ProjectOwner, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
membership := &dsClient.ProjectMembership{}
|
||||||
|
err := o.db.Select(devops.ProjectMembershipColumns...).
|
||||||
|
From(devops.ProjectMembershipTableName).
|
||||||
|
Where(db.And(
|
||||||
|
db.Eq(devops.ProjectMembershipUsernameColumn, username),
|
||||||
|
db.Eq(devops.ProjectMembershipProjectIdColumn, projectId))).LoadOne(membership)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return membership.Role, nil
|
||||||
|
}
|
||||||
|
|
||||||
func GetDevopsRoleSimpleRules(role string) []iam.SimpleRule {
|
func GetDevopsRoleSimpleRules(role string) []iam.SimpleRule {
|
||||||
var rules []iam.SimpleRule
|
var rules []iam.SimpleRule
|
||||||
|
|
||||||
|
|||||||
@@ -36,11 +36,14 @@ type Interface interface {
|
|||||||
DescribeWorkspace(username, workspace string) (*v1alpha1.Workspace, error)
|
DescribeWorkspace(username, workspace string) (*v1alpha1.Workspace, error)
|
||||||
ListWorkspaces(username string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error)
|
ListWorkspaces(username string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error)
|
||||||
ListNamespaces(username string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error)
|
ListNamespaces(username string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error)
|
||||||
|
GetWorkspace(workspace string) (*v1alpha1.Workspace, error)
|
||||||
|
DevOpsProjectOperator
|
||||||
}
|
}
|
||||||
|
|
||||||
type tenantOperator struct {
|
type tenantOperator struct {
|
||||||
workspaces WorkspaceInterface
|
workspaces WorkspaceInterface
|
||||||
namespaces NamespaceInterface
|
namespaces NamespaceInterface
|
||||||
|
DevOpsProjectOperator
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tenantOperator) DeleteNamespace(workspace, namespace string) error {
|
func (t *tenantOperator) DeleteNamespace(workspace, namespace string) error {
|
||||||
@@ -101,7 +104,7 @@ func (t *tenantOperator) appendAnnotations(username string, workspace *v1alpha1.
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
workspace.Annotations["kubesphere.io/namespace-count"] = strconv.Itoa(ns.TotalCount)
|
workspace.Annotations["kubesphere.io/namespace-count"] = strconv.Itoa(ns.TotalCount)
|
||||||
}
|
}
|
||||||
devops, err := ListDevopsProjects(workspace.Name, username, ¶ms.Conditions{}, "", false, 1, 0)
|
devops, err := t.ListDevOpsProjects(workspace.Name, username, ¶ms.Conditions{}, "", false, 1, 0)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
workspace.Annotations["kubesphere.io/devops-count"] = strconv.Itoa(devops.TotalCount)
|
workspace.Annotations["kubesphere.io/devops-count"] = strconv.Itoa(devops.TotalCount)
|
||||||
}
|
}
|
||||||
@@ -132,3 +135,7 @@ func (t *tenantOperator) ListNamespaces(username string, conditions *params.Cond
|
|||||||
|
|
||||||
return &models.PageableResponse{Items: result, TotalCount: len(namespaces)}, nil
|
return &models.PageableResponse{Items: result, TotalCount: len(namespaces)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *tenantOperator) GetWorkspace(workspace string) (*v1alpha1.Workspace, error) {
|
||||||
|
return t.workspaces.GetWorkspace(workspace)
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/alerting"
|
"kubesphere.io/kubesphere/pkg/simple/client/alerting"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/cache"
|
"kubesphere.io/kubesphere/pkg/simple/client/cache"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
"kubesphere.io/kubesphere/pkg/simple/client/devops/jenkins"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/elasticsearch"
|
"kubesphere.io/kubesphere/pkg/simple/client/elasticsearch"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/kubesphere"
|
"kubesphere.io/kubesphere/pkg/simple/client/kubesphere"
|
||||||
@@ -159,7 +159,7 @@ var (
|
|||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
MySQLOptions *mysql.Options `json:"mysql,omitempty" yaml:"mysql,omitempty" mapstructure:"mysql"`
|
MySQLOptions *mysql.Options `json:"mysql,omitempty" yaml:"mysql,omitempty" mapstructure:"mysql"`
|
||||||
DevopsOptions *devops.Options `json:"devops,omitempty" yaml:"devops,omitempty" mapstructure:"devops"`
|
DevopsOptions *jenkins.Options `json:"devops,omitempty" yaml:"devops,omitempty" mapstructure:"devops"`
|
||||||
SonarQubeOptions *sonarqube.Options `json:"sonarqube,omitempty" yaml:"sonarQube,omitempty" mapstructure:"sonarqube"`
|
SonarQubeOptions *sonarqube.Options `json:"sonarqube,omitempty" yaml:"sonarQube,omitempty" mapstructure:"sonarqube"`
|
||||||
KubernetesOptions *k8s.KubernetesOptions `json:"kubernetes,omitempty" yaml:"kubernetes,omitempty" mapstructure:"kubernetes"`
|
KubernetesOptions *k8s.KubernetesOptions `json:"kubernetes,omitempty" yaml:"kubernetes,omitempty" mapstructure:"kubernetes"`
|
||||||
ServiceMeshOptions *servicemesh.Options `json:"servicemesh,omitempty" yaml:"servicemesh,omitempty" mapstructure:"servicemesh"`
|
ServiceMeshOptions *servicemesh.Options `json:"servicemesh,omitempty" yaml:"servicemesh,omitempty" mapstructure:"servicemesh"`
|
||||||
@@ -182,7 +182,7 @@ type Config struct {
|
|||||||
func newConfig() *Config {
|
func newConfig() *Config {
|
||||||
return &Config{
|
return &Config{
|
||||||
MySQLOptions: mysql.NewMySQLOptions(),
|
MySQLOptions: mysql.NewMySQLOptions(),
|
||||||
DevopsOptions: devops.NewDevopsOptions(),
|
DevopsOptions: jenkins.NewDevopsOptions(),
|
||||||
SonarQubeOptions: sonarqube.NewSonarQubeOptions(),
|
SonarQubeOptions: sonarqube.NewSonarQubeOptions(),
|
||||||
KubernetesOptions: k8s.NewKubernetesOptions(),
|
KubernetesOptions: k8s.NewKubernetesOptions(),
|
||||||
ServiceMeshOptions: servicemesh.NewServiceMeshOptions(),
|
ServiceMeshOptions: servicemesh.NewServiceMeshOptions(),
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/alerting"
|
"kubesphere.io/kubesphere/pkg/simple/client/alerting"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/cache"
|
"kubesphere.io/kubesphere/pkg/simple/client/cache"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
"kubesphere.io/kubesphere/pkg/simple/client/devops/jenkins"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/elasticsearch"
|
"kubesphere.io/kubesphere/pkg/simple/client/elasticsearch"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/kubesphere"
|
"kubesphere.io/kubesphere/pkg/simple/client/kubesphere"
|
||||||
@@ -34,7 +34,7 @@ func newTestConfig() *Config {
|
|||||||
MaxOpenConnections: 20,
|
MaxOpenConnections: 20,
|
||||||
MaxConnectionLifeTime: time.Duration(10) * time.Second,
|
MaxConnectionLifeTime: time.Duration(10) * time.Second,
|
||||||
},
|
},
|
||||||
DevopsOptions: &devops.Options{
|
DevopsOptions: &jenkins.Options{
|
||||||
Host: "http://ks-devops.kubesphere-devops-system.svc",
|
Host: "http://ks-devops.kubesphere-devops-system.svc",
|
||||||
Username: "jenkins",
|
Username: "jenkins",
|
||||||
Password: "kubesphere",
|
Password: "kubesphere",
|
||||||
|
|||||||
@@ -47,3 +47,11 @@ func ParseSvcErr(err error, resp *restful.Response) {
|
|||||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, Wrap(err))
|
resp.WriteHeaderAndEntity(http.StatusInternalServerError, Wrap(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetServiceErrorCode(err error) int {
|
||||||
|
if svcErr, ok := err.(restful.ServiceError); ok {
|
||||||
|
return svcErr.Code
|
||||||
|
} else {
|
||||||
|
return http.StatusInternalServerError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
115
pkg/simple/client/devops/build.go
Normal file
115
pkg/simple/client/devops/build.go
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
package devops
|
||||||
|
|
||||||
|
const (
|
||||||
|
LastBuild = "lastBuild"
|
||||||
|
LastCompletedBuild = "lastCompletedBuild"
|
||||||
|
LastFailedBuild = "lastFailedBuild"
|
||||||
|
LastStableBuild = "lastStableBuild"
|
||||||
|
LastSuccessfulBuild = "lastSuccessfulBuild"
|
||||||
|
LastUnstableBuild = "lastUnstableBuild"
|
||||||
|
LastUnsuccessfulBuild = "lastUnsuccessfulBuild"
|
||||||
|
FirstBuild = "firstBuild"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GeneralParameter struct {
|
||||||
|
Name string
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Branch struct {
|
||||||
|
SHA1 string `json:",omitempty"`
|
||||||
|
Name string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BuildRevision struct {
|
||||||
|
SHA1 string `json:"SHA1,omitempty"`
|
||||||
|
Branch []Branch `json:"Branch,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Builds struct {
|
||||||
|
BuildNumber int64 `json:"buildNumber"`
|
||||||
|
BuildResult interface{} `json:"buildResult"`
|
||||||
|
Marked BuildRevision `json:"marked"`
|
||||||
|
Revision BuildRevision `json:"revision"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Culprit struct {
|
||||||
|
AbsoluteUrl string
|
||||||
|
FullName string
|
||||||
|
}
|
||||||
|
|
||||||
|
type GeneralAction struct {
|
||||||
|
Parameters []GeneralParameter `json:"parameters,omitempty"`
|
||||||
|
Causes []map[string]interface{} `json:"causes,omitempty"`
|
||||||
|
BuildsByBranchName map[string]Builds `json:"buildsByBranchName,omitempty"`
|
||||||
|
LastBuiltRevision *BuildRevision `json:"lastBuiltRevision,omitempty"`
|
||||||
|
RemoteUrls []string `json:"remoteUrls,omitempty"`
|
||||||
|
ScmName string `json:"scmName,omitempty"`
|
||||||
|
Subdir interface{} `json:"subdir,omitempty"`
|
||||||
|
ClassName string `json:"_class,omitempty"`
|
||||||
|
SonarTaskId string `json:"ceTaskId,omitempty"`
|
||||||
|
SonarServerUrl string `json:"serverUrl,omitempty"`
|
||||||
|
SonarDashboardUrl string `json:"sonarqubeDashboardUrl,omitempty"`
|
||||||
|
TotalCount int64 `json:",omitempty"`
|
||||||
|
UrlName string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Build struct {
|
||||||
|
Actions []GeneralAction
|
||||||
|
Artifacts []struct {
|
||||||
|
DisplayPath string `json:"displayPath"`
|
||||||
|
FileName string `json:"fileName"`
|
||||||
|
RelativePath string `json:"relativePath"`
|
||||||
|
} `json:"artifacts"`
|
||||||
|
Building bool `json:"building"`
|
||||||
|
BuiltOn string `json:"builtOn"`
|
||||||
|
ChangeSet struct {
|
||||||
|
Items []struct {
|
||||||
|
AffectedPaths []string `json:"affectedPaths"`
|
||||||
|
Author struct {
|
||||||
|
AbsoluteUrl string `json:"absoluteUrl"`
|
||||||
|
FullName string `json:"fullName"`
|
||||||
|
} `json:"author"`
|
||||||
|
Comment string `json:"comment"`
|
||||||
|
CommitID string `json:"commitId"`
|
||||||
|
Date string `json:"date"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
Msg string `json:"msg"`
|
||||||
|
Paths []struct {
|
||||||
|
EditType string `json:"editType"`
|
||||||
|
File string `json:"file"`
|
||||||
|
} `json:"paths"`
|
||||||
|
Timestamp int64 `json:"timestamp"`
|
||||||
|
} `json:"items"`
|
||||||
|
Kind string `json:"kind"`
|
||||||
|
Revisions []struct {
|
||||||
|
Module string
|
||||||
|
Revision int
|
||||||
|
} `json:"revision"`
|
||||||
|
} `json:"changeSet"`
|
||||||
|
Culprits []Culprit `json:"culprits"`
|
||||||
|
Description interface{} `json:"description"`
|
||||||
|
Duration int64 `json:"duration"`
|
||||||
|
EstimatedDuration int64 `json:"estimatedDuration"`
|
||||||
|
Executor interface{} `json:"executor"`
|
||||||
|
FullDisplayName string `json:"fullDisplayName"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
KeepLog bool `json:"keepLog"`
|
||||||
|
Number int64 `json:"number"`
|
||||||
|
QueueID int64 `json:"queueId"`
|
||||||
|
Result string `json:"result"`
|
||||||
|
Timestamp int64 `json:"timestamp"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
Runs []struct {
|
||||||
|
Number int64
|
||||||
|
URL string
|
||||||
|
} `json:"runs"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BuildGetter interface {
|
||||||
|
// GetProjectPipelineBuildByType get the last build of the pipeline, status can specify the status of the last build.
|
||||||
|
GetProjectPipelineBuildByType(projectId, pipelineId string, status string) (*Build, error)
|
||||||
|
|
||||||
|
// GetMultiBranchPipelineBuildByType get the last build of the pipeline, status can specify the status of the last build.
|
||||||
|
GetMultiBranchPipelineBuildByType(projectId, pipelineId, branch string, status string) (*Build, error)
|
||||||
|
}
|
||||||
77
pkg/simple/client/devops/credential.go
Normal file
77
pkg/simple/client/devops/credential.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
package devops
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Credential struct {
|
||||||
|
Id string `json:"id" description:"Id of Credential, e.g. dockerhub-id"`
|
||||||
|
Type string `json:"type" description:"Type of Credential, e.g. ssh/kubeconfig"`
|
||||||
|
DisplayName string `json:"display_name,omitempty" description:"Credential's display name"`
|
||||||
|
Fingerprint *struct {
|
||||||
|
FileName string `json:"file_name,omitempty" description:"Credential's display name and description"`
|
||||||
|
Hash string `json:"hash,omitempty" description:"Credential's hash"`
|
||||||
|
Usage []*struct {
|
||||||
|
Name string `json:"name,omitempty" description:"pipeline full name"`
|
||||||
|
Ranges struct {
|
||||||
|
Ranges []*struct {
|
||||||
|
Start int `json:"start,omitempty" description:"Start build number"`
|
||||||
|
End int `json:"end,omitempty" description:"End build number"`
|
||||||
|
} `json:"ranges,omitempty"`
|
||||||
|
} `json:"ranges,omitempty" description:"The build number of all pipelines that use this credential"`
|
||||||
|
} `json:"usage,omitempty" description:"all usage of Credential"`
|
||||||
|
} `json:"fingerprint,omitempty" description:"usage of the Credential"`
|
||||||
|
Description string `json:"description,omitempty" description:"Credential's description'"`
|
||||||
|
Domain string `json:"domain,omitempty" description:"Credential's domain,In ks we only use the default domain, default '_''"`
|
||||||
|
CreateTime *time.Time `json:"create_time,omitempty" description:"Credential's create_time'"`
|
||||||
|
Creator string `json:"creator,omitempty" description:"Creator's username"`
|
||||||
|
UsernamePasswordCredential *UsernamePasswordCredential `json:"username_password,omitempty" description:"username password Credential struct"`
|
||||||
|
SshCredential *SshCredential `json:"ssh,omitempty" description:"ssh Credential struct"`
|
||||||
|
SecretTextCredential *SecretTextCredential `json:"secret_text,omitempty" description:"secret_text Credential struct"`
|
||||||
|
KubeconfigCredential *KubeconfigCredential `json:"kubeconfig,omitempty" description:"kubeconfig Credential struct"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UsernamePasswordCredential struct {
|
||||||
|
Username string `json:"username,omitempty" description:"username of username_password credential"`
|
||||||
|
Password string `json:"password,omitempty" description:"password of username_password credential"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SshCredential struct {
|
||||||
|
Username string `json:"username,omitempty" description:"username of ssh credential"`
|
||||||
|
Passphrase string `json:"passphrase,omitempty" description:"passphrase of ssh credential, password of ssh credential"`
|
||||||
|
PrivateKey string `json:"private_key,omitempty" mapstructure:"private_key" description:"private key of ssh credential"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SecretTextCredential struct {
|
||||||
|
Secret string `json:"secret,omitempty" description:"secret content of credential"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type KubeconfigCredential struct {
|
||||||
|
Content string `json:"content,omitempty" description:"content of kubeconfig"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
CredentialTypeUsernamePassword = "username_password"
|
||||||
|
CredentialTypeSsh = "ssh"
|
||||||
|
CredentialTypeSecretText = "secret_text"
|
||||||
|
CredentialTypeKubeConfig = "kubeconfig"
|
||||||
|
)
|
||||||
|
|
||||||
|
var CredentialTypeMap = map[string]string{
|
||||||
|
"SSH Username with private key": CredentialTypeSsh,
|
||||||
|
"Username with password": CredentialTypeUsernamePassword,
|
||||||
|
"Secret text": CredentialTypeSecretText,
|
||||||
|
"Kubernetes configuration (kubeconfig)": CredentialTypeKubeConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
type CredentialOperator interface {
|
||||||
|
CreateCredentialInProject(projectId string, credential *Credential) (*string, error)
|
||||||
|
|
||||||
|
UpdateCredentialInProject(projectId string, credential *Credential) (*string, error)
|
||||||
|
|
||||||
|
GetCredentialInProject(projectId, id string, content bool) (*Credential, error)
|
||||||
|
|
||||||
|
GetCredentialsInProject(projectId string) ([]*Credential, error)
|
||||||
|
|
||||||
|
DeleteCredentialInProject(projectId, id string) (*string, error)
|
||||||
|
}
|
||||||
206
pkg/simple/client/devops/fake/fakedevops.go
Normal file
206
pkg/simple/client/devops/fake/fakedevops.go
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
package fake
|
||||||
|
|
||||||
|
import (
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FakeDevops struct {
|
||||||
|
Data map[string]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFakeDevops(data map[string]interface{}) *FakeDevops {
|
||||||
|
var fakeData FakeDevops
|
||||||
|
fakeData.Data = data
|
||||||
|
return &fakeData
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pipelinne operator interface
|
||||||
|
func (d *FakeDevops) GetPipeline(projectName, pipelineName string, httpParameters *devops.HttpParameters) (*devops.Pipeline, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *FakeDevops) ListPipelines(httpParameters *devops.HttpParameters) (*devops.PipelineList, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetPipelineRun(projectName, pipelineName, runId string, httpParameters *devops.HttpParameters) (*devops.PipelineRun, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) ListPipelineRuns(projectName, pipelineName string, httpParameters *devops.HttpParameters) (*devops.PipelineRunList, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) StopPipeline(projectName, pipelineName, runId string, httpParameters *devops.HttpParameters) (*devops.StopPipeline, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) ReplayPipeline(projectName, pipelineName, runId string, httpParameters *devops.HttpParameters) (*devops.ReplayPipeline, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) RunPipeline(projectName, pipelineName string, httpParameters *devops.HttpParameters) (*devops.RunPipeline, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetArtifacts(projectName, pipelineName, runId string, httpParameters *devops.HttpParameters) ([]devops.Artifacts, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetRunLog(projectName, pipelineName, runId string, httpParameters *devops.HttpParameters) ([]byte, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetStepLog(projectName, pipelineName, runId, nodeId, stepId string, httpParameters *devops.HttpParameters) ([]byte, http.Header, error) {
|
||||||
|
return nil, nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetNodeSteps(projectName, pipelineName, runId, nodeId string, httpParameters *devops.HttpParameters) ([]devops.NodeSteps, error) {
|
||||||
|
s := []string{projectName, pipelineName, runId, nodeId}
|
||||||
|
key := strings.Join(s, "-")
|
||||||
|
res := d.Data[key].([]devops.NodeSteps)
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetPipelineRunNodes(projectName, pipelineName, runId string, httpParameters *devops.HttpParameters) ([]devops.PipelineRunNodes, error) {
|
||||||
|
s := []string{projectName, pipelineName, runId}
|
||||||
|
key := strings.Join(s, "-")
|
||||||
|
res := d.Data[key].([]devops.PipelineRunNodes)
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) SubmitInputStep(projectName, pipelineName, runId, nodeId, stepId string, httpParameters *devops.HttpParameters) ([]byte, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//BranchPipelinne operator interface
|
||||||
|
func (d *FakeDevops) GetBranchPipeline(projectName, pipelineName, branchName string, httpParameters *devops.HttpParameters) (*devops.BranchPipeline, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetBranchPipelineRun(projectName, pipelineName, branchName, runId string, httpParameters *devops.HttpParameters) (*devops.PipelineRun, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) StopBranchPipeline(projectName, pipelineName, branchName, runId string, httpParameters *devops.HttpParameters) (*devops.StopPipeline, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) ReplayBranchPipeline(projectName, pipelineName, branchName, runId string, httpParameters *devops.HttpParameters) (*devops.ReplayPipeline, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) RunBranchPipeline(projectName, pipelineName, branchName string, httpParameters *devops.HttpParameters) (*devops.RunPipeline, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetBranchArtifacts(projectName, pipelineName, branchName, runId string, httpParameters *devops.HttpParameters) ([]devops.Artifacts, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetBranchRunLog(projectName, pipelineName, branchName, runId string, httpParameters *devops.HttpParameters) ([]byte, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetBranchStepLog(projectName, pipelineName, branchName, runId, nodeId, stepId string, httpParameters *devops.HttpParameters) ([]byte, http.Header, error) {
|
||||||
|
return nil, nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetBranchNodeSteps(projectName, pipelineName, branchName, runId, nodeId string, httpParameters *devops.HttpParameters) ([]devops.NodeSteps, error) {
|
||||||
|
s := []string{projectName, pipelineName, branchName, runId, nodeId}
|
||||||
|
key := strings.Join(s, "-")
|
||||||
|
res := d.Data[key].([]devops.NodeSteps)
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetBranchPipelineRunNodes(projectName, pipelineName, branchName, runId string, httpParameters *devops.HttpParameters) ([]devops.BranchPipelineRunNodes, error) {
|
||||||
|
s := []string{projectName, pipelineName, branchName, runId}
|
||||||
|
key := strings.Join(s, "-")
|
||||||
|
res := d.Data[key].([]devops.BranchPipelineRunNodes)
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) SubmitBranchInputStep(projectName, pipelineName, branchName, runId, nodeId, stepId string, httpParameters *devops.HttpParameters) ([]byte, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetPipelineBranch(projectName, pipelineName string, httpParameters *devops.HttpParameters) (*devops.PipelineBranch, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) ScanBranch(projectName, pipelineName string, httpParameters *devops.HttpParameters) ([]byte, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Common pipeline operator interface
|
||||||
|
func (d *FakeDevops) GetConsoleLog(projectName, pipelineName string, httpParameters *devops.HttpParameters) ([]byte, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetCrumb(httpParameters *devops.HttpParameters) (*devops.Crumb, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SCM operator interface
|
||||||
|
func (d *FakeDevops) GetSCMServers(scmId string, httpParameters *devops.HttpParameters) ([]devops.SCMServer, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetSCMOrg(scmId string, httpParameters *devops.HttpParameters) ([]devops.SCMOrg, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetOrgRepo(scmId, organizationId string, httpParameters *devops.HttpParameters) ([]devops.OrgRepo, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) CreateSCMServers(scmId string, httpParameters *devops.HttpParameters) (*devops.SCMServer, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) Validate(scmId string, httpParameters *devops.HttpParameters) (*devops.Validates, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Webhook operator interface
|
||||||
|
func (d *FakeDevops) GetNotifyCommit(httpParameters *devops.HttpParameters) ([]byte, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GithubWebhook(httpParameters *devops.HttpParameters) ([]byte, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *FakeDevops) CheckScriptCompile(projectName, pipelineName string, httpParameters *devops.HttpParameters) (*devops.CheckScript, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) CheckCron(projectName string, httpParameters *devops.HttpParameters) (*devops.CheckCronRes, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) ToJenkinsfile(httpParameters *devops.HttpParameters) (*devops.ResJenkinsfile, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) ToJson(httpParameters *devops.HttpParameters) (*devops.ResJson, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CredentialOperator
|
||||||
|
func (d *FakeDevops) CreateCredentialInProject(projectId string, credential *devops.Credential) (*string, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) UpdateCredentialInProject(projectId string, credential *devops.Credential) (*string, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetCredentialInProject(projectId, id string, content bool) (*devops.Credential, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetCredentialsInProject(projectId string) ([]*devops.Credential, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) DeleteCredentialInProject(projectId, id string) (*string, error) { return nil, nil }
|
||||||
|
|
||||||
|
// BuildGetter
|
||||||
|
func (d *FakeDevops) GetProjectPipelineBuildByType(projectId, pipelineId string, status string) (*devops.Build, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetMultiBranchPipelineBuildByType(projectId, pipelineId, branch string, status string) (*devops.Build, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProjectMemberOperator
|
||||||
|
func (d *FakeDevops) AddProjectMember(membership *devops.ProjectMembership) (*devops.ProjectMembership, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) UpdateProjectMember(oldMembership, newMembership *devops.ProjectMembership) (*devops.ProjectMembership, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) DeleteProjectMember(membership *devops.ProjectMembership) (*devops.ProjectMembership, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProjectPipelineOperator
|
||||||
|
func (d *FakeDevops) CreateProjectPipeline(projectId string, pipeline *devops.ProjectPipeline) (string, error) {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) DeleteProjectPipeline(projectId string, pipelineId string) (string, error) {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) UpdateProjectPipeline(projectId string, pipeline *devops.ProjectPipeline) (string, error) {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
func (d *FakeDevops) GetProjectPipelineConfig(projectId, pipelineId string) (*devops.ProjectPipeline, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
@@ -1,19 +1,13 @@
|
|||||||
package devops
|
package devops
|
||||||
|
|
||||||
type Job struct {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
GetJob(projectId, pipelineName string) (*Job, error)
|
CredentialOperator
|
||||||
|
|
||||||
DeleteJob(projectId, pipelineId string) (bool, error)
|
BuildGetter
|
||||||
|
|
||||||
CreateJobInFolder()
|
PipelineOperator
|
||||||
|
|
||||||
GetGlobalRole(roleName string)
|
ProjectMemberOperator
|
||||||
|
|
||||||
AddGlobalRole(roleName string, permission string)
|
ProjectPipelineOperator
|
||||||
|
|
||||||
GetProjectRole(roleName string)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,14 +12,15 @@
|
|||||||
// License for the specific language governing permissions and limitations
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
package gojenkins
|
package jenkins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
|
"github.com/emicklei/go-restful"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -31,26 +32,26 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Build struct {
|
type Build struct {
|
||||||
Raw *BuildResponse
|
Raw *devops.Build
|
||||||
Job *Job
|
Job *Job
|
||||||
Jenkins *Jenkins
|
Jenkins *Jenkins
|
||||||
Base string
|
Base string
|
||||||
Depth int
|
Depth int
|
||||||
}
|
}
|
||||||
|
|
||||||
type parameter struct {
|
type Parameter struct {
|
||||||
Name string
|
Name string
|
||||||
Value string
|
Value string
|
||||||
}
|
}
|
||||||
|
|
||||||
type branch struct {
|
type Branch struct {
|
||||||
SHA1 string `json:",omitempty"`
|
SHA1 string `json:",omitempty"`
|
||||||
Name string `json:",omitempty"`
|
Name string `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BuildRevision struct {
|
type BuildRevision struct {
|
||||||
SHA1 string `json:"SHA1,omitempty"`
|
SHA1 string `json:"SHA1,omitempty"`
|
||||||
Branch []branch `json:"branch,omitempty"`
|
Branch []Branch `json:"Branch,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Builds struct {
|
type Builds struct {
|
||||||
@@ -66,7 +67,7 @@ type Culprit struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type GeneralObj struct {
|
type GeneralObj struct {
|
||||||
Parameters []parameter `json:"parameters,omitempty"`
|
Parameters []Parameter `json:"parameters,omitempty"`
|
||||||
Causes []map[string]interface{} `json:"causes,omitempty"`
|
Causes []map[string]interface{} `json:"causes,omitempty"`
|
||||||
BuildsByBranchName map[string]Builds `json:"buildsByBranchName,omitempty"`
|
BuildsByBranchName map[string]Builds `json:"buildsByBranchName,omitempty"`
|
||||||
LastBuiltRevision *BuildRevision `json:"lastBuiltRevision,omitempty"`
|
LastBuiltRevision *BuildRevision `json:"lastBuiltRevision,omitempty"`
|
||||||
@@ -114,7 +115,7 @@ type TestResult struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type BuildResponse struct {
|
type BuildResponse struct {
|
||||||
Actions []GeneralObj
|
Actions []devops.GeneralAction
|
||||||
Artifacts []struct {
|
Artifacts []struct {
|
||||||
DisplayPath string `json:"displayPath"`
|
DisplayPath string `json:"displayPath"`
|
||||||
FileName string `json:"fileName"`
|
FileName string `json:"fileName"`
|
||||||
@@ -146,7 +147,7 @@ type BuildResponse struct {
|
|||||||
Revision int
|
Revision int
|
||||||
} `json:"revision"`
|
} `json:"revision"`
|
||||||
} `json:"changeSet"`
|
} `json:"changeSet"`
|
||||||
Culprits []Culprit `json:"culprits"`
|
Culprits []devops.Culprit `json:"culprits"`
|
||||||
Description interface{} `json:"description"`
|
Description interface{} `json:"description"`
|
||||||
Duration int64 `json:"duration"`
|
Duration int64 `json:"duration"`
|
||||||
EstimatedDuration int64 `json:"estimatedDuration"`
|
EstimatedDuration int64 `json:"estimatedDuration"`
|
||||||
@@ -161,7 +162,6 @@ type BuildResponse struct {
|
|||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
MavenArtifacts interface{} `json:"mavenArtifacts"`
|
MavenArtifacts interface{} `json:"mavenArtifacts"`
|
||||||
MavenVersionUsed string `json:"mavenVersionUsed"`
|
MavenVersionUsed string `json:"mavenVersionUsed"`
|
||||||
FingerPrint []FingerPrintResponse
|
|
||||||
Runs []struct {
|
Runs []struct {
|
||||||
Number int64
|
Number int64
|
||||||
URL string
|
URL string
|
||||||
@@ -169,14 +169,10 @@ type BuildResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Builds
|
// Builds
|
||||||
func (b *Build) Info() *BuildResponse {
|
func (b *Build) Info() *devops.Build {
|
||||||
return b.Raw
|
return b.Raw
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Build) GetActions() []GeneralObj {
|
|
||||||
return b.Raw.Actions
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Build) GetUrl() string {
|
func (b *Build) GetUrl() string {
|
||||||
return b.Raw.URL
|
return b.Raw.URL
|
||||||
}
|
}
|
||||||
@@ -188,23 +184,6 @@ func (b *Build) GetResult() string {
|
|||||||
return b.Raw.Result
|
return b.Raw.Result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Build) GetArtifacts() []Artifact {
|
|
||||||
artifacts := make([]Artifact, len(b.Raw.Artifacts))
|
|
||||||
for i, artifact := range b.Raw.Artifacts {
|
|
||||||
artifacts[i] = Artifact{
|
|
||||||
Jenkins: b.Jenkins,
|
|
||||||
Build: b,
|
|
||||||
FileName: artifact.FileName,
|
|
||||||
Path: b.Base + "/artifact/" + artifact.RelativePath,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return artifacts
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Build) GetCulprits() []Culprit {
|
|
||||||
return b.Raw.Culprits
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Build) Stop() (bool, error) {
|
func (b *Build) Stop() (bool, error) {
|
||||||
if b.IsRunning() {
|
if b.IsRunning() {
|
||||||
response, err := b.Jenkins.Requester.Post(b.Base+"/stop", nil, nil, nil)
|
response, err := b.Jenkins.Requester.Post(b.Base+"/stop", nil, nil, nil)
|
||||||
@@ -238,15 +217,6 @@ func (b *Build) GetCauses() ([]map[string]interface{}, error) {
|
|||||||
return nil, errors.New("No Causes")
|
return nil, errors.New("No Causes")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Build) GetParameters() []parameter {
|
|
||||||
for _, a := range b.Raw.Actions {
|
|
||||||
if a.Parameters != nil {
|
|
||||||
return a.Parameters
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Build) GetInjectedEnvVars() (map[string]string, error) {
|
func (b *Build) GetInjectedEnvVars() (map[string]string, error) {
|
||||||
var envVars struct {
|
var envVars struct {
|
||||||
EnvMap map[string]string `json:"envMap"`
|
EnvMap map[string]string `json:"envMap"`
|
||||||
@@ -286,31 +256,6 @@ func (b *Build) GetDownstreamBuilds() ([]*Build, error) {
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Build) GetDownstreamJobNames() []string {
|
|
||||||
result := make([]string, 0)
|
|
||||||
downstreamJobs := b.Job.GetDownstreamJobsMetadata()
|
|
||||||
fingerprints := b.GetAllFingerPrints()
|
|
||||||
for _, fingerprint := range fingerprints {
|
|
||||||
for _, usage := range fingerprint.Raw.Usage {
|
|
||||||
for _, job := range downstreamJobs {
|
|
||||||
if job.Name == usage.Name {
|
|
||||||
result = append(result, job.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Build) GetAllFingerPrints() []*FingerPrint {
|
|
||||||
b.Poll(3)
|
|
||||||
result := make([]*FingerPrint, len(b.Raw.FingerPrint))
|
|
||||||
for i, f := range b.Raw.FingerPrint {
|
|
||||||
result[i] = &FingerPrint{Jenkins: b.Jenkins, Base: "/fingerprint/", Id: f.Hash, Raw: &f}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Build) GetUpstreamJob() (*Job, error) {
|
func (b *Build) GetUpstreamJob() (*Job, error) {
|
||||||
causes, err := b.GetCauses()
|
causes, err := b.GetCauses()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -356,22 +301,6 @@ func (b *Build) GetUpstreamBuild() (*Build, error) {
|
|||||||
return nil, errors.New("Build not found")
|
return nil, errors.New("Build not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Build) GetMatrixRuns() ([]*Build, error) {
|
|
||||||
_, err := b.Poll(0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
runs := b.Raw.Runs
|
|
||||||
result := make([]*Build, len(b.Raw.Runs))
|
|
||||||
r, _ := regexp.Compile(`job/(.*?)/(.*?)/(\d+)/`)
|
|
||||||
|
|
||||||
for i, run := range runs {
|
|
||||||
result[i] = &Build{Jenkins: b.Jenkins, Job: b.Job, Raw: new(BuildResponse), Depth: 1, Base: "/" + r.FindString(run.URL)}
|
|
||||||
result[i].Poll()
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Build) GetResultSet() (*TestResult, error) {
|
func (b *Build) GetResultSet() (*TestResult, error) {
|
||||||
|
|
||||||
url := b.Base + "/testReport"
|
url := b.Base + "/testReport"
|
||||||
@@ -395,24 +324,6 @@ func (b *Build) GetDuration() int64 {
|
|||||||
return b.Raw.Duration
|
return b.Raw.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Build) GetRevision() string {
|
|
||||||
vcs := b.Raw.ChangeSet.Kind
|
|
||||||
|
|
||||||
if vcs == Git || vcs == Hg {
|
|
||||||
for _, a := range b.Raw.Actions {
|
|
||||||
if a.LastBuiltRevision.SHA1 != "" {
|
|
||||||
return a.LastBuiltRevision.SHA1
|
|
||||||
}
|
|
||||||
if a.MercurialRevisionNumber != "" {
|
|
||||||
return a.MercurialRevisionNumber
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if vcs == Svn {
|
|
||||||
return strconv.Itoa(b.Raw.ChangeSet.Revisions[0].Revision)
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Build) GetRevisionBranch() string {
|
func (b *Build) GetRevisionBranch() string {
|
||||||
vcs := b.Raw.ChangeSet.Kind
|
vcs := b.Raw.ChangeSet.Kind
|
||||||
if vcs == Git {
|
if vcs == Git {
|
||||||
@@ -456,7 +367,7 @@ func (b *Build) PauseToggle() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Poll for current data. Optional parameter - depth.
|
// Poll for current data. Optional Parameter - depth.
|
||||||
// More about depth here: https://wiki.jenkins-ci.org/display/JENKINS/Remote+access+API
|
// More about depth here: https://wiki.jenkins-ci.org/display/JENKINS/Remote+access+API
|
||||||
func (b *Build) Poll(options ...interface{}) (int, error) {
|
func (b *Build) Poll(options ...interface{}) (int, error) {
|
||||||
depth := "-1"
|
depth := "-1"
|
||||||
@@ -484,3 +395,20 @@ func (b *Build) Poll(options ...interface{}) (int, error) {
|
|||||||
}
|
}
|
||||||
return response.StatusCode, nil
|
return response.StatusCode, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetProjectPipelineBuildByType(projectId, pipelineId string, status string) (*devops.Build, error) {
|
||||||
|
job, err := j.GetJob(pipelineId, projectId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
build, err := job.getBuildByType(status)
|
||||||
|
return build.Raw, nil
|
||||||
|
}
|
||||||
|
func (j *Jenkins) GetMultiBranchPipelineBuildByType(projectId, pipelineId, branch string, status string) (*devops.Build, error) {
|
||||||
|
job, err := j.GetJob(pipelineId, projectId, branch)
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
build, err := job.getBuildByType(status)
|
||||||
|
return build.Raw, nil
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package gojenkins
|
package jenkins
|
||||||
|
|
||||||
const (
|
const (
|
||||||
STATUS_FAIL = "FAIL"
|
STATUS_FAIL = "FAIL"
|
||||||
341
pkg/simple/client/devops/jenkins/credential.go
Normal file
341
pkg/simple/client/devops/jenkins/credential.go
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 The KubeSphere Authors.
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package jenkins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/PuerkitoBio/goquery"
|
||||||
|
"github.com/emicklei/go-restful"
|
||||||
|
"k8s.io/klog"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const SSHCrenditalStaplerClass = "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
|
||||||
|
const DirectSSHCrenditalStaplerClass = "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource"
|
||||||
|
const UsernamePassswordCredentialStaplerClass = "com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl"
|
||||||
|
const SecretTextCredentialStaplerClass = "org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl"
|
||||||
|
const KubeconfigCredentialStaplerClass = "com.microsoft.jenkins.kubernetes.credentials.KubeconfigCredentials"
|
||||||
|
const DirectKubeconfigCredentialStaperClass = "com.microsoft.jenkins.kubernetes.credentials.KubeconfigCredentials$DirectEntryKubeconfigSource"
|
||||||
|
const GLOBALScope = "GLOBAL"
|
||||||
|
|
||||||
|
type UsernamePasswordCredential struct {
|
||||||
|
Scope string `json:"scope"`
|
||||||
|
Id string `json:"id"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
StaplerClass string `json:"stapler-class"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SshCredential struct {
|
||||||
|
Scope string `json:"scope"`
|
||||||
|
Id string `json:"id"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Passphrase string `json:"passphrase"`
|
||||||
|
KeySource PrivateKeySource `json:"privateKeySource"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
StaplerClass string `json:"stapler-class"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SecretTextCredential struct {
|
||||||
|
Scope string `json:"scope"`
|
||||||
|
Id string `json:"id"`
|
||||||
|
Secret string `json:"secret"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
StaplerClass string `json:"stapler-class"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type KubeconfigCredential struct {
|
||||||
|
Scope string `json:"scope"`
|
||||||
|
Id string `json:"id"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
KubeconfigSource KubeconfigSource `json:"kubeconfigSource"`
|
||||||
|
StaplerClass string `json:"stapler-class"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PrivateKeySource struct {
|
||||||
|
StaplerClass string `json:"stapler-class"`
|
||||||
|
PrivateKey string `json:"privateKey"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type KubeconfigSource struct {
|
||||||
|
StaplerClass string `json:"stapler-class"`
|
||||||
|
Content string `json:"content"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CredentialResponse struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
TypeName string `json:"typeName"`
|
||||||
|
DisplayName string `json:"displayName"`
|
||||||
|
Fingerprint *struct {
|
||||||
|
FileName string `json:"file_name,omitempty" description:"Credential's display name and description"`
|
||||||
|
Hash string `json:"hash,omitempty" description:"Credential's hash"`
|
||||||
|
Usage []*struct {
|
||||||
|
Name string `json:"name,omitempty" description:"Jenkins pipeline full name"`
|
||||||
|
Ranges struct {
|
||||||
|
Ranges []*struct {
|
||||||
|
Start int `json:"start,omitempty" description:"Start build number"`
|
||||||
|
End int `json:"end,omitempty" description:"End build number"`
|
||||||
|
} `json:"ranges,omitempty"`
|
||||||
|
} `json:"ranges,omitempty" description:"The build number of all pipelines that use this credential"`
|
||||||
|
} `json:"usage,omitempty" description:"all usage of Credential"`
|
||||||
|
} `json:"fingerprint,omitempty" description:"usage of the Credential"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
Domain string `json:"domain"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSshCredential(id, username, passphrase, privateKey, description string) *SshCredential {
|
||||||
|
keySource := PrivateKeySource{
|
||||||
|
StaplerClass: DirectSSHCrenditalStaplerClass,
|
||||||
|
PrivateKey: privateKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &SshCredential{
|
||||||
|
Scope: GLOBALScope,
|
||||||
|
Id: id,
|
||||||
|
Username: username,
|
||||||
|
Passphrase: passphrase,
|
||||||
|
KeySource: keySource,
|
||||||
|
Description: description,
|
||||||
|
StaplerClass: SSHCrenditalStaplerClass,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUsernamePasswordCredential(id, username, password, description string) *UsernamePasswordCredential {
|
||||||
|
return &UsernamePasswordCredential{
|
||||||
|
Scope: GLOBALScope,
|
||||||
|
Id: id,
|
||||||
|
Username: username,
|
||||||
|
Password: password,
|
||||||
|
Description: description,
|
||||||
|
StaplerClass: UsernamePassswordCredentialStaplerClass,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSecretTextCredential(id, secret, description string) *SecretTextCredential {
|
||||||
|
return &SecretTextCredential{
|
||||||
|
Scope: GLOBALScope,
|
||||||
|
Id: id,
|
||||||
|
Secret: secret,
|
||||||
|
Description: description,
|
||||||
|
StaplerClass: SecretTextCredentialStaplerClass,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewKubeconfigCredential(id, content, description string) *KubeconfigCredential {
|
||||||
|
credentialSource := KubeconfigSource{
|
||||||
|
StaplerClass: DirectKubeconfigCredentialStaperClass,
|
||||||
|
Content: content,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &KubeconfigCredential{
|
||||||
|
Scope: GLOBALScope,
|
||||||
|
Id: id,
|
||||||
|
Description: description,
|
||||||
|
KubeconfigSource: credentialSource,
|
||||||
|
StaplerClass: KubeconfigCredentialStaplerClass,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetCredentialInProject(projectId, id string, content bool) (*devops.Credential, error) {
|
||||||
|
responseStruct := &devops.Credential{}
|
||||||
|
|
||||||
|
domain := "_"
|
||||||
|
|
||||||
|
response, err := j.Requester.GetJSON(
|
||||||
|
fmt.Sprintf("/job/%s/credentials/store/folder/domain/_/credential/%s", projectId, id),
|
||||||
|
responseStruct, map[string]string{
|
||||||
|
"depth": "2",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return nil, errors.New(strconv.Itoa(response.StatusCode))
|
||||||
|
}
|
||||||
|
responseStruct.Domain = domain
|
||||||
|
if content {
|
||||||
|
|
||||||
|
}
|
||||||
|
contentString := ""
|
||||||
|
response, err = j.Requester.GetHtml(
|
||||||
|
fmt.Sprintf("/job/%s/credentials/store/folder/domain/%s/credential/%s/update", projectId, domain, id),
|
||||||
|
&contentString, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return nil, errors.New(strconv.Itoa(response.StatusCode))
|
||||||
|
}
|
||||||
|
stringReader := strings.NewReader(contentString)
|
||||||
|
doc, err := goquery.NewDocumentFromReader(stringReader)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||||
|
}
|
||||||
|
switch responseStruct.Type {
|
||||||
|
case devops.CredentialTypeKubeConfig:
|
||||||
|
content := &devops.KubeconfigCredential{}
|
||||||
|
doc.Find("textarea[name*=content]").Each(func(i int, selection *goquery.Selection) {
|
||||||
|
value := selection.Text()
|
||||||
|
content.Content = value
|
||||||
|
})
|
||||||
|
responseStruct.KubeconfigCredential = content
|
||||||
|
case devops.CredentialTypeUsernamePassword:
|
||||||
|
content := &devops.UsernamePasswordCredential{}
|
||||||
|
doc.Find("input[name*=username]").Each(func(i int, selection *goquery.Selection) {
|
||||||
|
value, _ := selection.Attr("value")
|
||||||
|
content.Username = value
|
||||||
|
})
|
||||||
|
|
||||||
|
responseStruct.UsernamePasswordCredential = content
|
||||||
|
case devops.CredentialTypeSsh:
|
||||||
|
content := &devops.SshCredential{}
|
||||||
|
doc.Find("input[name*=username]").Each(func(i int, selection *goquery.Selection) {
|
||||||
|
value, _ := selection.Attr("value")
|
||||||
|
content.Username = value
|
||||||
|
})
|
||||||
|
|
||||||
|
doc.Find("textarea[name*=privateKey]").Each(func(i int, selection *goquery.Selection) {
|
||||||
|
value := selection.Text()
|
||||||
|
content.PrivateKey = value
|
||||||
|
})
|
||||||
|
responseStruct.SshCredential = content
|
||||||
|
}
|
||||||
|
return responseStruct, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetCredentialsInProject(projectId string) ([]*devops.Credential, error) {
|
||||||
|
domain := "_"
|
||||||
|
var responseStruct = &struct {
|
||||||
|
Credentials []*devops.Credential `json:"credentials"`
|
||||||
|
}{}
|
||||||
|
response, err := j.Requester.GetJSON(
|
||||||
|
fmt.Sprintf("/job/%s/credentials/store/folder/domain/_", projectId),
|
||||||
|
responseStruct, map[string]string{
|
||||||
|
"depth": "2",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return nil, errors.New(strconv.Itoa(response.StatusCode))
|
||||||
|
}
|
||||||
|
for _, credential := range responseStruct.Credentials {
|
||||||
|
credential.Domain = domain
|
||||||
|
}
|
||||||
|
return responseStruct.Credentials, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) CreateCredentialInProject(projectId string, credential *devops.Credential) (*string, error) {
|
||||||
|
|
||||||
|
var request interface{}
|
||||||
|
responseString := ""
|
||||||
|
switch credential.Type {
|
||||||
|
case devops.CredentialTypeUsernamePassword:
|
||||||
|
request = NewUsernamePasswordCredential(credential.Id,
|
||||||
|
credential.UsernamePasswordCredential.Username, credential.UsernamePasswordCredential.Password,
|
||||||
|
credential.Description)
|
||||||
|
|
||||||
|
case devops.CredentialTypeSsh:
|
||||||
|
request = NewSshCredential(credential.Id,
|
||||||
|
credential.SshCredential.Username, credential.SshCredential.Passphrase,
|
||||||
|
credential.SshCredential.PrivateKey, credential.Description)
|
||||||
|
case devops.CredentialTypeSecretText:
|
||||||
|
request = NewSecretTextCredential(credential.Id,
|
||||||
|
credential.SecretTextCredential.Secret, credential.Description)
|
||||||
|
case devops.CredentialTypeKubeConfig:
|
||||||
|
request = NewKubeconfigCredential(credential.Id,
|
||||||
|
credential.KubeconfigCredential.Content, credential.Description)
|
||||||
|
default:
|
||||||
|
err := fmt.Errorf("error unsupport credential type")
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := j.Requester.Post(
|
||||||
|
fmt.Sprintf("/job/%s/credentials/store/folder/domain/_/createCredentials", projectId),
|
||||||
|
nil, &responseString, map[string]string{
|
||||||
|
"json": makeJson(map[string]interface{}{
|
||||||
|
"credentials": request,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return nil, errors.New(strconv.Itoa(response.StatusCode))
|
||||||
|
}
|
||||||
|
return &credential.Id, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) UpdateCredentialInProject(projectId string, credential *devops.Credential) (*string, error) {
|
||||||
|
|
||||||
|
requestContent := ""
|
||||||
|
switch credential.Type {
|
||||||
|
case devops.CredentialTypeUsernamePassword:
|
||||||
|
requestStruct := NewUsernamePasswordCredential(credential.Id,
|
||||||
|
credential.UsernamePasswordCredential.Username, credential.UsernamePasswordCredential.Password,
|
||||||
|
credential.Description)
|
||||||
|
requestContent = makeJson(requestStruct)
|
||||||
|
|
||||||
|
case devops.CredentialTypeSsh:
|
||||||
|
requestStruct := NewSshCredential(credential.Id,
|
||||||
|
credential.SshCredential.Username, credential.SshCredential.Passphrase,
|
||||||
|
credential.SshCredential.PrivateKey, credential.Description)
|
||||||
|
requestContent = makeJson(requestStruct)
|
||||||
|
case devops.CredentialTypeSecretText:
|
||||||
|
requestStruct := NewSecretTextCredential(credential.Id,
|
||||||
|
credential.SecretTextCredential.Secret, credential.Description)
|
||||||
|
requestContent = makeJson(requestStruct)
|
||||||
|
case devops.CredentialTypeKubeConfig:
|
||||||
|
requestStruct := NewKubeconfigCredential(credential.Id,
|
||||||
|
credential.KubeconfigCredential.Content, credential.Description)
|
||||||
|
requestContent = makeJson(requestStruct)
|
||||||
|
default:
|
||||||
|
err := fmt.Errorf("error unsupport credential type")
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
response, err := j.Requester.Post(
|
||||||
|
fmt.Sprintf("/job/%s/credentials/store/folder/domain/_/credential/%s/updateSubmit", projectId, credential.Id),
|
||||||
|
nil, nil, map[string]string{
|
||||||
|
"json": requestContent,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return nil, errors.New(strconv.Itoa(response.StatusCode))
|
||||||
|
}
|
||||||
|
return &credential.Id, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) DeleteCredentialInProject(projectId, id string) (*string, error) {
|
||||||
|
response, err := j.Requester.Post(
|
||||||
|
fmt.Sprintf("/job/%s/credentials/store/folder/domain/_/credential/%s/doDelete", projectId, id),
|
||||||
|
nil, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return nil, errors.New(strconv.Itoa(response.StatusCode))
|
||||||
|
}
|
||||||
|
return &id, nil
|
||||||
|
}
|
||||||
@@ -11,12 +11,11 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package devops
|
package jenkins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
"kubesphere.io/kubesphere/pkg/gojenkins"
|
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -25,13 +24,13 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
jenkinsClient *gojenkins.Jenkins
|
jenkinsClient *Jenkins
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDevopsClient(options *Options) (*Client, error) {
|
func NewDevopsClient(options *Options) (*Client, error) {
|
||||||
var d Client
|
var d Client
|
||||||
|
|
||||||
jenkins := gojenkins.CreateJenkins(nil, options.Host, options.MaxConnections, options.Username, options.Password)
|
jenkins := CreateJenkins(nil, options.Host, options.MaxConnections, options.Username, options.Password)
|
||||||
jenkins, err := jenkins.Init()
|
jenkins, err := jenkins.Init()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("failed to connecto to jenkins role, %+v", err)
|
klog.Errorf("failed to connecto to jenkins role, %+v", err)
|
||||||
@@ -49,7 +48,7 @@ func NewDevopsClient(options *Options) (*Client, error) {
|
|||||||
return &d, nil
|
return &d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Jenkins() *gojenkins.Jenkins {
|
func (c *Client) Jenkins() *Jenkins {
|
||||||
return c.jenkinsClient
|
return c.jenkinsClient
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,14 +70,14 @@ func (c *Client) initializeJenkins() error {
|
|||||||
|
|
||||||
// Jenkins uninitialized, create global role
|
// Jenkins uninitialized, create global role
|
||||||
if globalRole == nil {
|
if globalRole == nil {
|
||||||
_, err := c.jenkinsClient.AddGlobalRole(jenkinsAllUserRoleName, gojenkins.GlobalPermissionIds{GlobalRead: true}, true)
|
_, err := c.jenkinsClient.AddGlobalRole(jenkinsAllUserRoleName, GlobalPermissionIds{GlobalRead: true}, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = c.jenkinsClient.AddProjectRole(jenkinsAllUserRoleName, "\\n\\s*\\r", gojenkins.ProjectPermissionIds{SCMTag: true}, true)
|
_, err = c.jenkinsClient.AddProjectRole(jenkinsAllUserRoleName, "\\n\\s*\\r", ProjectPermissionIds{SCMTag: true}, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
return err
|
return err
|
||||||
40
pkg/simple/client/devops/jenkins/devops_test.go
Normal file
40
pkg/simple/client/devops/jenkins/devops_test.go
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package jenkins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_parseCronJobTime(t *testing.T) {
|
||||||
|
type Except struct {
|
||||||
|
Last string
|
||||||
|
Next string
|
||||||
|
}
|
||||||
|
|
||||||
|
Items := []struct {
|
||||||
|
Input string
|
||||||
|
Expected Except
|
||||||
|
}{
|
||||||
|
{"上次运行的时间 Tuesday, September 10, 2019 8:59:09 AM UTC; 下次运行的时间 Tuesday, September 10, 2019 9:14:09 AM UTC.", Except{Last: "2019-09-10T08:59:09Z", Next: "2019-09-10T09:14:09Z"}},
|
||||||
|
{"上次运行的时间 Thursday, January 3, 2019 11:56:30 PM UTC; 下次运行的时间 Friday, January 3, 2020 12:11:30 AM UTC.", Except{Last: "2019-01-03T23:56:30Z", Next: "2020-01-03T00:11:30Z"}},
|
||||||
|
{"上次运行的时间 Tuesday, September 10, 2019 8:41:34 AM UTC; 下次运行的时间 Tuesday, September 10, 2019 9:41:34 AM UTC.", Except{Last: "2019-09-10T08:41:34Z", Next: "2019-09-10T09:41:34Z"}},
|
||||||
|
{"上次运行的时间 Tuesday, September 10, 2019 9:15:26 AM UTC; 下次运行的时间 Tuesday, September 10, 2019 10:03:26 AM UTC.", Except{Last: "2019-09-10T09:15:26Z", Next: "2019-09-10T10:03:26Z"}},
|
||||||
|
{"Would last have run at Tuesday, September 10, 2019 9:15:26 AM UTC; would next run at Tuesday, September 10, 2019 10:03:26 AM UTC.", Except{Last: "2019-09-10T09:15:26Z", Next: "2019-09-10T10:03:26Z"}},
|
||||||
|
{"Would last have run at Tuesday, September 10, 2019 8:41:34 AM UTC; would next run at Tuesday, September 10, 2019 9:41:34 AM UTC.", Except{Last: "2019-09-10T08:41:34Z", Next: "2019-09-10T09:41:34Z"}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range Items {
|
||||||
|
last, next, err := parseCronJobTime(item.Input)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("should not get error %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if last != item.Expected.Last {
|
||||||
|
t.Errorf("got %#v, expected %#v", last, item.Expected.Last)
|
||||||
|
}
|
||||||
|
|
||||||
|
if next != item.Expected.Next {
|
||||||
|
t.Errorf("got %#v, expected %#v", next, item.Expected.Next)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
// License for the specific language governing permissions and limitations
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
package gojenkins
|
package jenkins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@@ -33,8 +33,6 @@ type FolderResponse struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
Jobs []InnerJob `json:"jobs"`
|
Jobs []InnerJob `json:"jobs"`
|
||||||
PrimaryView *ViewData `json:"primaryView"`
|
|
||||||
Views []ViewData `json:"views"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Folder) parentBase() string {
|
func (f *Folder) parentBase() string {
|
||||||
803
pkg/simple/client/devops/jenkins/jenkins.go
Normal file
803
pkg/simple/client/devops/jenkins/jenkins.go
Normal file
@@ -0,0 +1,803 @@
|
|||||||
|
// Copyright 2015 Vadim Kravcenko
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||||
|
// not use this file except in compliance with the License. You may obtain
|
||||||
|
// a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
// Gojenkins is a Jenkins Client in Go, that exposes the jenkins REST api in a more developer friendly way.
|
||||||
|
package jenkins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"k8s.io/klog"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Basic Authentication
|
||||||
|
type BasicAuth struct {
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Jenkins struct {
|
||||||
|
Server string
|
||||||
|
Version string
|
||||||
|
Requester *Requester
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loggers
|
||||||
|
var (
|
||||||
|
Info *log.Logger
|
||||||
|
Warning *log.Logger
|
||||||
|
Error *log.Logger
|
||||||
|
)
|
||||||
|
|
||||||
|
// Init Method. Should be called after creating a Jenkins Instance.
|
||||||
|
// e.g jenkins := CreateJenkins("url").Init()
|
||||||
|
// HTTP Client is set here, Connection to jenkins is tested here.
|
||||||
|
func (j *Jenkins) Init() (*Jenkins, error) {
|
||||||
|
j.initLoggers()
|
||||||
|
|
||||||
|
rsp, err := j.Requester.GetJSON("/", nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
j.Version = rsp.Header.Get("X-Jenkins")
|
||||||
|
//if j.Raw == nil {
|
||||||
|
// return nil, errors.New("Connection Failed, Please verify that the host and credentials are correct.")
|
||||||
|
//}
|
||||||
|
|
||||||
|
return j, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) initLoggers() {
|
||||||
|
Info = log.New(os.Stdout,
|
||||||
|
"INFO: ",
|
||||||
|
log.Ldate|log.Ltime|log.Lshortfile)
|
||||||
|
|
||||||
|
Warning = log.New(os.Stdout,
|
||||||
|
"WARNING: ",
|
||||||
|
log.Ldate|log.Ltime|log.Lshortfile)
|
||||||
|
|
||||||
|
Error = log.New(os.Stderr,
|
||||||
|
"ERROR: ",
|
||||||
|
log.Ldate|log.Ltime|log.Lshortfile)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new folder
|
||||||
|
// This folder can be nested in other parent folders
|
||||||
|
// Example: jenkins.CreateFolder("newFolder", "grandparentFolder", "parentFolder")
|
||||||
|
func (j *Jenkins) CreateFolder(name, description string, parents ...string) (*Folder, error) {
|
||||||
|
folderObj := &Folder{Jenkins: j, Raw: new(FolderResponse), Base: "/job/" + strings.Join(append(parents, name), "/job/")}
|
||||||
|
folder, err := folderObj.Create(name, description)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return folder, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new job in the folder
|
||||||
|
// Example: jenkins.CreateJobInFolder("<config></config>", "newJobName", "myFolder", "parentFolder")
|
||||||
|
func (j *Jenkins) CreateJobInFolder(config string, jobName string, parentIDs ...string) (*Job, error) {
|
||||||
|
jobObj := Job{Jenkins: j, Raw: new(JobResponse), Base: "/job/" + strings.Join(append(parentIDs, jobName), "/job/")}
|
||||||
|
qr := map[string]string{
|
||||||
|
"name": jobName,
|
||||||
|
}
|
||||||
|
job, err := jobObj.Create(config, qr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return job, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new job from config File
|
||||||
|
// Method takes XML string as first Parameter, and if the name is not specified in the config file
|
||||||
|
// takes name as string as second Parameter
|
||||||
|
// e.g jenkins.CreateJob("<config></config>","newJobName")
|
||||||
|
func (j *Jenkins) CreateJob(config string, options ...interface{}) (*Job, error) {
|
||||||
|
qr := make(map[string]string)
|
||||||
|
if len(options) > 0 {
|
||||||
|
qr["name"] = options[0].(string)
|
||||||
|
} else {
|
||||||
|
return nil, errors.New("Error Creating Job, job name is missing")
|
||||||
|
}
|
||||||
|
jobObj := Job{Jenkins: j, Raw: new(JobResponse), Base: "/job/" + qr["name"]}
|
||||||
|
job, err := jobObj.Create(config, qr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return job, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename a job.
|
||||||
|
// First Parameter job old name, Second Parameter job new name.
|
||||||
|
func (j *Jenkins) RenameJob(job string, name string) *Job {
|
||||||
|
jobObj := Job{Jenkins: j, Raw: new(JobResponse), Base: "/job/" + job}
|
||||||
|
jobObj.Rename(name)
|
||||||
|
return &jobObj
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a copy of a job.
|
||||||
|
// First Parameter Name of the job to copy from, Second Parameter new job name.
|
||||||
|
func (j *Jenkins) CopyJob(copyFrom string, newName string) (*Job, error) {
|
||||||
|
job := Job{Jenkins: j, Raw: new(JobResponse), Base: "/job/" + copyFrom}
|
||||||
|
_, err := job.Poll()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return job.Copy(newName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete a job.
|
||||||
|
func (j *Jenkins) DeleteJob(name string, parentIDs ...string) (bool, error) {
|
||||||
|
job := Job{Jenkins: j, Raw: new(JobResponse), Base: "/job/" + strings.Join(append(parentIDs, name), "/job/")}
|
||||||
|
return job.Delete()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoke a job.
|
||||||
|
// First Parameter job name, second Parameter is optional Build parameters.
|
||||||
|
func (j *Jenkins) BuildJob(name string, options ...interface{}) (int64, error) {
|
||||||
|
job := Job{Jenkins: j, Raw: new(JobResponse), Base: "/job/" + name}
|
||||||
|
var params map[string]string
|
||||||
|
if len(options) > 0 {
|
||||||
|
params, _ = options[0].(map[string]string)
|
||||||
|
}
|
||||||
|
return job.InvokeSimple(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetBuild(jobName string, number int64) (*Build, error) {
|
||||||
|
job, err := j.GetJob(jobName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
build, err := job.GetBuild(number)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return build, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetJob(id string, parentIDs ...string) (*Job, error) {
|
||||||
|
job := Job{Jenkins: j, Raw: new(JobResponse), Base: "/job/" + strings.Join(append(parentIDs, id), "/job/")}
|
||||||
|
status, err := job.Poll()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if status == 200 {
|
||||||
|
return &job, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New(strconv.Itoa(status))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetFolder(id string, parents ...string) (*Folder, error) {
|
||||||
|
folder := Folder{Jenkins: j, Raw: new(FolderResponse), Base: "/job/" + strings.Join(append(parents, id), "/job/")}
|
||||||
|
status, err := folder.Poll()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("trouble polling folder: %v", err)
|
||||||
|
}
|
||||||
|
if status == 200 {
|
||||||
|
return &folder, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New(strconv.Itoa(status))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all builds Numbers and URLS for a specific job.
|
||||||
|
// There are only build IDs here,
|
||||||
|
// To get all the other info of the build use jenkins.GetBuild(job,buildNumber)
|
||||||
|
// or job.GetBuild(buildNumber)
|
||||||
|
|
||||||
|
func (j *Jenkins) Poll() (int, error) {
|
||||||
|
resp, err := j.Requester.GetJSON("/", nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return resp.StatusCode, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetGlobalRole(roleName string) (*GlobalRole, error) {
|
||||||
|
roleResponse := &GlobalRoleResponse{
|
||||||
|
RoleName: roleName,
|
||||||
|
}
|
||||||
|
stringResponse := ""
|
||||||
|
response, err := j.Requester.Get("/role-strategy/strategy/getRole",
|
||||||
|
&stringResponse,
|
||||||
|
map[string]string{
|
||||||
|
"roleName": roleName,
|
||||||
|
"type": GLOBAL_ROLE,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return nil, errors.New(strconv.Itoa(response.StatusCode))
|
||||||
|
}
|
||||||
|
if stringResponse == "{}" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
err = json.Unmarshal([]byte(stringResponse), roleResponse)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &GlobalRole{
|
||||||
|
Jenkins: j,
|
||||||
|
Raw: *roleResponse,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetProjectRole(roleName string) (*ProjectRole, error) {
|
||||||
|
roleResponse := &ProjectRoleResponse{
|
||||||
|
RoleName: roleName,
|
||||||
|
}
|
||||||
|
stringResponse := ""
|
||||||
|
response, err := j.Requester.Get("/role-strategy/strategy/getRole",
|
||||||
|
&stringResponse,
|
||||||
|
map[string]string{
|
||||||
|
"roleName": roleName,
|
||||||
|
"type": PROJECT_ROLE,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return nil, errors.New(strconv.Itoa(response.StatusCode))
|
||||||
|
}
|
||||||
|
if stringResponse == "{}" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
err = json.Unmarshal([]byte(stringResponse), roleResponse)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &ProjectRole{
|
||||||
|
Jenkins: j,
|
||||||
|
Raw: *roleResponse,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) AddGlobalRole(roleName string, ids GlobalPermissionIds, overwrite bool) (*GlobalRole, error) {
|
||||||
|
responseRole := &GlobalRole{
|
||||||
|
Jenkins: j,
|
||||||
|
Raw: GlobalRoleResponse{
|
||||||
|
RoleName: roleName,
|
||||||
|
PermissionIds: ids,
|
||||||
|
}}
|
||||||
|
var idArray []string
|
||||||
|
values := reflect.ValueOf(ids)
|
||||||
|
for i := 0; i < values.NumField(); i++ {
|
||||||
|
field := values.Field(i)
|
||||||
|
if field.Bool() {
|
||||||
|
idArray = append(idArray, values.Type().Field(i).Tag.Get("json"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
param := map[string]string{
|
||||||
|
"roleName": roleName,
|
||||||
|
"type": GLOBAL_ROLE,
|
||||||
|
"permissionIds": strings.Join(idArray, ","),
|
||||||
|
"overwrite": strconv.FormatBool(overwrite),
|
||||||
|
}
|
||||||
|
responseString := ""
|
||||||
|
response, err := j.Requester.Post("/role-strategy/strategy/addRole", nil, &responseString, param)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return nil, errors.New(strconv.Itoa(response.StatusCode))
|
||||||
|
}
|
||||||
|
return responseRole, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) DeleteProjectRoles(roleName ...string) error {
|
||||||
|
responseString := ""
|
||||||
|
|
||||||
|
response, err := j.Requester.Post("/role-strategy/strategy/removeRoles", nil, &responseString, map[string]string{
|
||||||
|
"type": PROJECT_ROLE,
|
||||||
|
"roleNames": strings.Join(roleName, ","),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
fmt.Println(responseString)
|
||||||
|
return errors.New(strconv.Itoa(response.StatusCode))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) AddProjectRole(roleName string, pattern string, ids ProjectPermissionIds, overwrite bool) (*ProjectRole, error) {
|
||||||
|
responseRole := &ProjectRole{
|
||||||
|
Jenkins: j,
|
||||||
|
Raw: ProjectRoleResponse{
|
||||||
|
RoleName: roleName,
|
||||||
|
PermissionIds: ids,
|
||||||
|
Pattern: pattern,
|
||||||
|
}}
|
||||||
|
var idArray []string
|
||||||
|
values := reflect.ValueOf(ids)
|
||||||
|
for i := 0; i < values.NumField(); i++ {
|
||||||
|
field := values.Field(i)
|
||||||
|
if field.Bool() {
|
||||||
|
idArray = append(idArray, values.Type().Field(i).Tag.Get("json"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
param := map[string]string{
|
||||||
|
"roleName": roleName,
|
||||||
|
"type": PROJECT_ROLE,
|
||||||
|
"permissionIds": strings.Join(idArray, ","),
|
||||||
|
"overwrite": strconv.FormatBool(overwrite),
|
||||||
|
"pattern": pattern,
|
||||||
|
}
|
||||||
|
responseString := ""
|
||||||
|
response, err := j.Requester.Post("/role-strategy/strategy/addRole", nil, &responseString, param)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return nil, errors.New(strconv.Itoa(response.StatusCode))
|
||||||
|
}
|
||||||
|
return responseRole, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) DeleteUserInProject(username string) error {
|
||||||
|
param := map[string]string{
|
||||||
|
"type": PROJECT_ROLE,
|
||||||
|
"sid": username,
|
||||||
|
}
|
||||||
|
responseString := ""
|
||||||
|
response, err := j.Requester.Post("/role-strategy/strategy/deleteSid", nil, &responseString, param)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return errors.New(strconv.Itoa(response.StatusCode))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetPipeline(projectName, pipelineName string, httpParameters *devops.HttpParameters) (*devops.Pipeline, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(GetPipelineUrl, projectName, pipelineName),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GetPipeline()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) ListPipelines(httpParameters *devops.HttpParameters) (*devops.PipelineList, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: ListPipelinesUrl + httpParameters.Url.RawQuery,
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.ListPipelines()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetPipelineRun(projectName, pipelineName, runId string, httpParameters *devops.HttpParameters) (*devops.PipelineRun, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(GetPipelineRunUrl, projectName, pipelineName, runId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GetPipelineRun()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) ListPipelineRuns(projectName, pipelineName string, httpParameters *devops.HttpParameters) (*devops.PipelineRunList, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: ListPipelineRunUrl + httpParameters.Url.RawQuery,
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.ListPipelineRuns()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) StopPipeline(projectName, pipelineName, runId string, httpParameters *devops.HttpParameters) (*devops.StopPipeline, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(StopPipelineUrl, projectName, pipelineName, runId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.StopPipeline()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) ReplayPipeline(projectName, pipelineName, runId string, httpParameters *devops.HttpParameters) (*devops.ReplayPipeline, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(ReplayPipelineUrl+httpParameters.Url.RawQuery, projectName, pipelineName, runId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.ReplayPipeline()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) RunPipeline(projectName, pipelineName string, httpParameters *devops.HttpParameters) (*devops.RunPipeline, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(RunPipelineUrl+httpParameters.Url.RawQuery, projectName, pipelineName),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.RunPipeline()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetArtifacts(projectName, pipelineName, runId string, httpParameters *devops.HttpParameters) ([]devops.Artifacts, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(GetArtifactsUrl+httpParameters.Url.RawQuery, projectName, pipelineName, runId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GetArtifacts()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetRunLog(projectName, pipelineName, runId string, httpParameters *devops.HttpParameters) ([]byte, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(GetRunLogUrl+httpParameters.Url.RawQuery, projectName, pipelineName, runId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GetRunLog()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetStepLog(projectName, pipelineName, runId, nodeId, stepId string, httpParameters *devops.HttpParameters) ([]byte, http.Header, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(GetStepLogUrl+httpParameters.Url.RawQuery, projectName, pipelineName, runId, nodeId, stepId),
|
||||||
|
}
|
||||||
|
res, header, err := PipelineOjb.GetStepLog()
|
||||||
|
return res, header, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetNodeSteps(projectName, pipelineName, runId, nodeId string, httpParameters *devops.HttpParameters) ([]devops.NodeSteps, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(GetNodeStepsUrl+httpParameters.Url.RawQuery, projectName, pipelineName, runId, nodeId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GetNodeSteps()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetPipelineRunNodes(projectName, pipelineName, runId string, httpParameters *devops.HttpParameters) ([]devops.PipelineRunNodes, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(GetPipelineRunNodesUrl+httpParameters.Url.RawQuery, projectName, pipelineName, runId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GetPipelineRunNodes()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) SubmitInputStep(projectName, pipelineName, runId, nodeId, stepId string, httpParameters *devops.HttpParameters) ([]byte, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(SubmitInputStepUrl+httpParameters.Url.RawQuery, projectName, pipelineName, runId, nodeId, stepId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.SubmitInputStep()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetBranchPipeline(projectName, pipelineName, branchName string, httpParameters *devops.HttpParameters) (*devops.BranchPipeline, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(GetBranchPipelineUrl, projectName, pipelineName, branchName),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GetBranchPipeline()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetBranchPipelineRun(projectName, pipelineName, branchName, runId string, httpParameters *devops.HttpParameters) (*devops.PipelineRun, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(GetBranchPipelineRunUrl, projectName, pipelineName, branchName, runId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GetBranchPipelineRun()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) StopBranchPipeline(projectName, pipelineName, branchName, runId string, httpParameters *devops.HttpParameters) (*devops.StopPipeline, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(StopBranchPipelineUrl+httpParameters.Url.RawQuery, projectName, pipelineName, branchName, runId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.StopBranchPipeline()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) ReplayBranchPipeline(projectName, pipelineName, branchName, runId string, httpParameters *devops.HttpParameters) (*devops.ReplayPipeline, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(ReplayBranchPipelineUrl+httpParameters.Url.RawQuery, projectName, pipelineName, branchName, runId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.ReplayBranchPipeline()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) RunBranchPipeline(projectName, pipelineName, branchName string, httpParameters *devops.HttpParameters) (*devops.RunPipeline, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(RunBranchPipelineUrl+httpParameters.Url.RawQuery, projectName, pipelineName, branchName),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.RunBranchPipeline()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetBranchArtifacts(projectName, pipelineName, branchName, runId string, httpParameters *devops.HttpParameters) ([]devops.Artifacts, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(GetBranchArtifactsUrl+httpParameters.Url.RawQuery, projectName, pipelineName, branchName, runId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GetBranchArtifacts()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetBranchRunLog(projectName, pipelineName, branchName, runId string, httpParameters *devops.HttpParameters) ([]byte, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(GetBranchRunLogUrl+httpParameters.Url.RawQuery, projectName, pipelineName, branchName, runId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GetBranchRunLog()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetBranchStepLog(projectName, pipelineName, branchName, runId, nodeId, stepId string, httpParameters *devops.HttpParameters) ([]byte, http.Header, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(GetBranchStepLogUrl+httpParameters.Url.RawQuery, projectName, pipelineName, branchName, runId, nodeId, stepId),
|
||||||
|
}
|
||||||
|
res, header, err := PipelineOjb.GetBranchStepLog()
|
||||||
|
return res, header, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetBranchNodeSteps(projectName, pipelineName, branchName, runId, nodeId string, httpParameters *devops.HttpParameters) ([]devops.NodeSteps, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(GetBranchNodeStepsUrl+httpParameters.Url.RawQuery, projectName, pipelineName, branchName, runId, nodeId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GetBranchNodeSteps()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetBranchPipelineRunNodes(projectName, pipelineName, branchName, runId string, httpParameters *devops.HttpParameters) ([]devops.BranchPipelineRunNodes, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(GetBranchPipeRunNodesUrl+httpParameters.Url.RawQuery, projectName, pipelineName, branchName, runId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GetBranchPipelineRunNodes()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) SubmitBranchInputStep(projectName, pipelineName, branchName, runId, nodeId, stepId string, httpParameters *devops.HttpParameters) ([]byte, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(CheckBranchPipelineUrl+httpParameters.Url.RawQuery, projectName, pipelineName, branchName, runId, nodeId, stepId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.SubmitBranchInputStep()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetPipelineBranch(projectName, pipelineName string, httpParameters *devops.HttpParameters) (*devops.PipelineBranch, error) {
|
||||||
|
path := fmt.Sprintf(GetPipeBranchUrl, projectName, pipelineName) + httpParameters.Url.RawQuery
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: path,
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GetPipelineBranch()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) ScanBranch(projectName, pipelineName string, httpParameters *devops.HttpParameters) ([]byte, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(ScanBranchUrl+httpParameters.Url.RawQuery, projectName, pipelineName),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.ScanBranch()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetConsoleLog(projectName, pipelineName string, httpParameters *devops.HttpParameters) ([]byte, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(GetConsoleLogUrl+httpParameters.Url.RawQuery, projectName, pipelineName),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GetConsoleLog()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetCrumb(httpParameters *devops.HttpParameters) (*devops.Crumb, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: GetCrumbUrl,
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GetCrumb()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetSCMServers(scmId string, httpParameters *devops.HttpParameters) ([]devops.SCMServer, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: GetSCMServersUrl,
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GetSCMServers()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetSCMOrg(scmId string, httpParameters *devops.HttpParameters) ([]devops.SCMOrg, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(GetSCMOrgUrl+httpParameters.Url.RawQuery, scmId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GetSCMOrg()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetOrgRepo(scmId, organizationId string, httpParameters *devops.HttpParameters) ([]devops.OrgRepo, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(GetOrgRepoUrl+httpParameters.Url.RawQuery, scmId, organizationId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GetOrgRepo()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) CreateSCMServers(scmId string, httpParameters *devops.HttpParameters) (*devops.SCMServer, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(CreateSCMServersUrl, scmId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.CreateSCMServers()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetNotifyCommit(httpParameters *devops.HttpParameters) ([]byte, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: GetNotifyCommitUrl + httpParameters.Url.RawQuery,
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GetNotifyCommit()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GithubWebhook(httpParameters *devops.HttpParameters) ([]byte, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: GithubWebhookUrl + httpParameters.Url.RawQuery,
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.GithubWebhook()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) Validate(scmId string, httpParameters *devops.HttpParameters) (*devops.Validates, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(ValidateUrl, scmId),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.Validate()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) CheckScriptCompile(projectName, pipelineName string, httpParameters *devops.HttpParameters) (*devops.CheckScript, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: fmt.Sprintf(CheckScriptCompileUrl, projectName, pipelineName),
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.CheckScriptCompile()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) CheckCron(projectName string, httpParameters *devops.HttpParameters) (*devops.CheckCronRes, error) {
|
||||||
|
var cron = new(devops.CronData)
|
||||||
|
var reader io.ReadCloser
|
||||||
|
var path string
|
||||||
|
|
||||||
|
reader = httpParameters.Body
|
||||||
|
cronData, err := ioutil.ReadAll(reader)
|
||||||
|
err = json.Unmarshal(cronData, cron)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if cron.PipelineName != "" {
|
||||||
|
path = fmt.Sprintf(CheckPipelienCronUrl, projectName, cron.PipelineName, cron.Cron)
|
||||||
|
} else {
|
||||||
|
path = fmt.Sprintf(CheckCronUrl, projectName, cron.Cron)
|
||||||
|
}
|
||||||
|
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: path,
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := PipelineOjb.CheckCron()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) ToJenkinsfile(httpParameters *devops.HttpParameters) (*devops.ResJenkinsfile, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: ToJenkinsfileUrl,
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.ToJenkinsfile()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) ToJson(httpParameters *devops.HttpParameters) (*devops.ResJson, error) {
|
||||||
|
PipelineOjb := &Pipeline{
|
||||||
|
HttpParameters: httpParameters,
|
||||||
|
Jenkins: j,
|
||||||
|
Path: ToJsonUrl,
|
||||||
|
}
|
||||||
|
res, err := PipelineOjb.ToJson()
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new Jenkins Instance
|
||||||
|
// Optional parameters are: client, username, password
|
||||||
|
// After creating an instance call init method.
|
||||||
|
func CreateJenkins(client *http.Client, base string, maxConnection int, auth ...interface{}) *Jenkins {
|
||||||
|
j := &Jenkins{}
|
||||||
|
if strings.HasSuffix(base, "/") {
|
||||||
|
base = base[:len(base)-1]
|
||||||
|
}
|
||||||
|
j.Server = base
|
||||||
|
j.Requester = &Requester{Base: base, SslVerify: true, Client: client, connControl: make(chan struct{}, maxConnection)}
|
||||||
|
if j.Requester.Client == nil {
|
||||||
|
j.Requester.Client = http.DefaultClient
|
||||||
|
}
|
||||||
|
if len(auth) == 2 {
|
||||||
|
j.Requester.BasicAuth = &BasicAuth{Username: auth[0].(string), Password: auth[1].(string)}
|
||||||
|
}
|
||||||
|
return j
|
||||||
|
}
|
||||||
@@ -12,13 +12,14 @@
|
|||||||
// License for the specific language governing permissions and limitations
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
package gojenkins
|
package jenkins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -60,7 +61,7 @@ type ParameterDefinition struct {
|
|||||||
|
|
||||||
type JobResponse struct {
|
type JobResponse struct {
|
||||||
Class string `json:"_class"`
|
Class string `json:"_class"`
|
||||||
Actions []GeneralObj
|
Actions []devops.GeneralAction
|
||||||
Buildable bool `json:"buildable"`
|
Buildable bool `json:"buildable"`
|
||||||
Builds []JobBuild
|
Builds []JobBuild
|
||||||
Color string `json:"color"`
|
Color string `json:"color"`
|
||||||
@@ -96,8 +97,6 @@ type JobResponse struct {
|
|||||||
UpstreamProjects []InnerJob `json:"upstreamProjects"`
|
UpstreamProjects []InnerJob `json:"upstreamProjects"`
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
Jobs []InnerJob `json:"jobs"`
|
Jobs []InnerJob `json:"jobs"`
|
||||||
PrimaryView *ViewData `json:"primaryView"`
|
|
||||||
Views []ViewData `json:"views"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *Job) parentBase() string {
|
func (j *Job) parentBase() string {
|
||||||
@@ -123,7 +122,7 @@ func (j *Job) GetDetails() *JobResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (j *Job) GetBuild(id int64) (*Build, error) {
|
func (j *Job) GetBuild(id int64) (*Build, error) {
|
||||||
build := Build{Jenkins: j.Jenkins, Job: j, Raw: new(BuildResponse), Depth: 1, Base: "/job/" + j.GetName() + "/" + strconv.FormatInt(id, 10)}
|
build := Build{Jenkins: j.Jenkins, Job: j, Raw: new(devops.Build), Depth: 1, Base: "/job/" + j.GetName() + "/" + strconv.FormatInt(id, 10)}
|
||||||
status, err := build.Poll()
|
status, err := build.Poll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -153,7 +152,7 @@ func (j *Job) getBuildByType(buildType string) (*Build, error) {
|
|||||||
Jenkins: j.Jenkins,
|
Jenkins: j.Jenkins,
|
||||||
Depth: 1,
|
Depth: 1,
|
||||||
Job: j,
|
Job: j,
|
||||||
Raw: new(BuildResponse),
|
Raw: new(devops.Build),
|
||||||
Base: j.Base + "/" + number}
|
Base: j.Base + "/" + number}
|
||||||
status, err := build.Poll()
|
status, err := build.Poll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -212,10 +211,6 @@ func (j *Job) GetAllBuildStatus() ([]JobBuildStatus, error) {
|
|||||||
return buildsResp.Builds, nil
|
return buildsResp.Builds, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *Job) GetSubJobsMetadata() []InnerJob {
|
|
||||||
return j.Raw.SubJobs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j *Job) GetUpstreamJobsMetadata() []InnerJob {
|
func (j *Job) GetUpstreamJobsMetadata() []InnerJob {
|
||||||
return j.Raw.UpstreamProjects
|
return j.Raw.UpstreamProjects
|
||||||
}
|
}
|
||||||
@@ -224,18 +219,6 @@ func (j *Job) GetDownstreamJobsMetadata() []InnerJob {
|
|||||||
return j.Raw.DownstreamProjects
|
return j.Raw.DownstreamProjects
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *Job) GetSubJobs() ([]*Job, error) {
|
|
||||||
jobs := make([]*Job, len(j.Raw.SubJobs))
|
|
||||||
for i, job := range j.Raw.SubJobs {
|
|
||||||
ji, err := j.Jenkins.GetSubJob(j.GetName(), job.Name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
jobs[i] = ji
|
|
||||||
}
|
|
||||||
return jobs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j *Job) GetInnerJobsMetadata() []InnerJob {
|
func (j *Job) GetInnerJobsMetadata() []InnerJob {
|
||||||
return j.Raw.Jobs
|
return j.Raw.Jobs
|
||||||
}
|
}
|
||||||
@@ -519,11 +502,3 @@ func (j *Job) Poll() (int, error) {
|
|||||||
}
|
}
|
||||||
return response.StatusCode, nil
|
return response.StatusCode, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *Job) History() ([]*History, error) {
|
|
||||||
resp, err := j.Jenkins.Requester.Get(j.Base+"/buildHistory/ajax", nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return parseBuildHistory(resp.Body), nil
|
|
||||||
}
|
|
||||||
322
pkg/simple/client/devops/jenkins/member.go
Normal file
322
pkg/simple/client/devops/jenkins/member.go
Normal file
@@ -0,0 +1,322 @@
|
|||||||
|
package jenkins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emicklei/go-restful"
|
||||||
|
"k8s.io/klog"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
JenkinsAllUserRoleName = "kubesphere-user"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetProjectRoleName(projectId, role string) string {
|
||||||
|
return fmt.Sprintf("%s-%s-project", projectId, role)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPipelineRoleName(projectId, role string) string {
|
||||||
|
return fmt.Sprintf("%s-%s-pipeline", projectId, role)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProjectRolePattern(projectId string) string {
|
||||||
|
return fmt.Sprintf("^%s$", projectId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPipelineRolePattern(projectId string) string {
|
||||||
|
return fmt.Sprintf("^%s/.*", projectId)
|
||||||
|
}
|
||||||
|
|
||||||
|
var JenkinsOwnerProjectPermissionIds = &ProjectPermissionIds{
|
||||||
|
CredentialCreate: true,
|
||||||
|
CredentialDelete: true,
|
||||||
|
CredentialManageDomains: true,
|
||||||
|
CredentialUpdate: true,
|
||||||
|
CredentialView: true,
|
||||||
|
ItemBuild: true,
|
||||||
|
ItemCancel: true,
|
||||||
|
ItemConfigure: true,
|
||||||
|
ItemCreate: true,
|
||||||
|
ItemDelete: true,
|
||||||
|
ItemDiscover: true,
|
||||||
|
ItemMove: true,
|
||||||
|
ItemRead: true,
|
||||||
|
ItemWorkspace: true,
|
||||||
|
RunDelete: true,
|
||||||
|
RunReplay: true,
|
||||||
|
RunUpdate: true,
|
||||||
|
SCMTag: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
var JenkinsProjectPermissionMap = map[string]ProjectPermissionIds{
|
||||||
|
devops.ProjectOwner: {
|
||||||
|
CredentialCreate: true,
|
||||||
|
CredentialDelete: true,
|
||||||
|
CredentialManageDomains: true,
|
||||||
|
CredentialUpdate: true,
|
||||||
|
CredentialView: true,
|
||||||
|
ItemBuild: true,
|
||||||
|
ItemCancel: true,
|
||||||
|
ItemConfigure: true,
|
||||||
|
ItemCreate: true,
|
||||||
|
ItemDelete: true,
|
||||||
|
ItemDiscover: true,
|
||||||
|
ItemMove: true,
|
||||||
|
ItemRead: true,
|
||||||
|
ItemWorkspace: true,
|
||||||
|
RunDelete: true,
|
||||||
|
RunReplay: true,
|
||||||
|
RunUpdate: true,
|
||||||
|
SCMTag: true,
|
||||||
|
},
|
||||||
|
devops.ProjectMaintainer: {
|
||||||
|
CredentialCreate: true,
|
||||||
|
CredentialDelete: true,
|
||||||
|
CredentialManageDomains: true,
|
||||||
|
CredentialUpdate: true,
|
||||||
|
CredentialView: true,
|
||||||
|
ItemBuild: true,
|
||||||
|
ItemCancel: true,
|
||||||
|
ItemConfigure: false,
|
||||||
|
ItemCreate: true,
|
||||||
|
ItemDelete: false,
|
||||||
|
ItemDiscover: true,
|
||||||
|
ItemMove: false,
|
||||||
|
ItemRead: true,
|
||||||
|
ItemWorkspace: true,
|
||||||
|
RunDelete: true,
|
||||||
|
RunReplay: true,
|
||||||
|
RunUpdate: true,
|
||||||
|
SCMTag: true,
|
||||||
|
},
|
||||||
|
devops.ProjectDeveloper: {
|
||||||
|
CredentialCreate: false,
|
||||||
|
CredentialDelete: false,
|
||||||
|
CredentialManageDomains: false,
|
||||||
|
CredentialUpdate: false,
|
||||||
|
CredentialView: false,
|
||||||
|
ItemBuild: true,
|
||||||
|
ItemCancel: true,
|
||||||
|
ItemConfigure: false,
|
||||||
|
ItemCreate: false,
|
||||||
|
ItemDelete: false,
|
||||||
|
ItemDiscover: true,
|
||||||
|
ItemMove: false,
|
||||||
|
ItemRead: true,
|
||||||
|
ItemWorkspace: true,
|
||||||
|
RunDelete: true,
|
||||||
|
RunReplay: true,
|
||||||
|
RunUpdate: true,
|
||||||
|
SCMTag: false,
|
||||||
|
},
|
||||||
|
devops.ProjectReporter: {
|
||||||
|
CredentialCreate: false,
|
||||||
|
CredentialDelete: false,
|
||||||
|
CredentialManageDomains: false,
|
||||||
|
CredentialUpdate: false,
|
||||||
|
CredentialView: false,
|
||||||
|
ItemBuild: false,
|
||||||
|
ItemCancel: false,
|
||||||
|
ItemConfigure: false,
|
||||||
|
ItemCreate: false,
|
||||||
|
ItemDelete: false,
|
||||||
|
ItemDiscover: true,
|
||||||
|
ItemMove: false,
|
||||||
|
ItemRead: true,
|
||||||
|
ItemWorkspace: false,
|
||||||
|
RunDelete: false,
|
||||||
|
RunReplay: false,
|
||||||
|
RunUpdate: false,
|
||||||
|
SCMTag: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var JenkinsPipelinePermissionMap = map[string]ProjectPermissionIds{
|
||||||
|
devops.ProjectOwner: {
|
||||||
|
CredentialCreate: true,
|
||||||
|
CredentialDelete: true,
|
||||||
|
CredentialManageDomains: true,
|
||||||
|
CredentialUpdate: true,
|
||||||
|
CredentialView: true,
|
||||||
|
ItemBuild: true,
|
||||||
|
ItemCancel: true,
|
||||||
|
ItemConfigure: true,
|
||||||
|
ItemCreate: true,
|
||||||
|
ItemDelete: true,
|
||||||
|
ItemDiscover: true,
|
||||||
|
ItemMove: true,
|
||||||
|
ItemRead: true,
|
||||||
|
ItemWorkspace: true,
|
||||||
|
RunDelete: true,
|
||||||
|
RunReplay: true,
|
||||||
|
RunUpdate: true,
|
||||||
|
SCMTag: true,
|
||||||
|
},
|
||||||
|
devops.ProjectMaintainer: {
|
||||||
|
CredentialCreate: true,
|
||||||
|
CredentialDelete: true,
|
||||||
|
CredentialManageDomains: true,
|
||||||
|
CredentialUpdate: true,
|
||||||
|
CredentialView: true,
|
||||||
|
ItemBuild: true,
|
||||||
|
ItemCancel: true,
|
||||||
|
ItemConfigure: true,
|
||||||
|
ItemCreate: true,
|
||||||
|
ItemDelete: true,
|
||||||
|
ItemDiscover: true,
|
||||||
|
ItemMove: true,
|
||||||
|
ItemRead: true,
|
||||||
|
ItemWorkspace: true,
|
||||||
|
RunDelete: true,
|
||||||
|
RunReplay: true,
|
||||||
|
RunUpdate: true,
|
||||||
|
SCMTag: true,
|
||||||
|
},
|
||||||
|
devops.ProjectDeveloper: {
|
||||||
|
CredentialCreate: false,
|
||||||
|
CredentialDelete: false,
|
||||||
|
CredentialManageDomains: false,
|
||||||
|
CredentialUpdate: false,
|
||||||
|
CredentialView: false,
|
||||||
|
ItemBuild: true,
|
||||||
|
ItemCancel: true,
|
||||||
|
ItemConfigure: false,
|
||||||
|
ItemCreate: false,
|
||||||
|
ItemDelete: false,
|
||||||
|
ItemDiscover: true,
|
||||||
|
ItemMove: false,
|
||||||
|
ItemRead: true,
|
||||||
|
ItemWorkspace: true,
|
||||||
|
RunDelete: true,
|
||||||
|
RunReplay: true,
|
||||||
|
RunUpdate: true,
|
||||||
|
SCMTag: false,
|
||||||
|
},
|
||||||
|
devops.ProjectReporter: {
|
||||||
|
CredentialCreate: false,
|
||||||
|
CredentialDelete: false,
|
||||||
|
CredentialManageDomains: false,
|
||||||
|
CredentialUpdate: false,
|
||||||
|
CredentialView: false,
|
||||||
|
ItemBuild: false,
|
||||||
|
ItemCancel: false,
|
||||||
|
ItemConfigure: false,
|
||||||
|
ItemCreate: false,
|
||||||
|
ItemDelete: false,
|
||||||
|
ItemDiscover: true,
|
||||||
|
ItemMove: false,
|
||||||
|
ItemRead: true,
|
||||||
|
ItemWorkspace: false,
|
||||||
|
RunDelete: false,
|
||||||
|
RunReplay: false,
|
||||||
|
RunUpdate: false,
|
||||||
|
SCMTag: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) AddProjectMember(membership *devops.ProjectMembership) (*devops.ProjectMembership, error) {
|
||||||
|
globalRole, err := j.GetGlobalRole(JenkinsAllUserRoleName)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
if globalRole == nil {
|
||||||
|
_, err := j.AddGlobalRole(JenkinsAllUserRoleName, GlobalPermissionIds{
|
||||||
|
GlobalRead: true,
|
||||||
|
}, true)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("failed to create jenkins global role %+v", err)
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = globalRole.AssignRole(membership.Username)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
projectRole, err := j.GetProjectRole(GetProjectRoleName(membership.ProjectId, membership.Role))
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
err = projectRole.AssignRole(membership.Username)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
pipelineRole, err := j.GetProjectRole(GetPipelineRoleName(membership.ProjectId, membership.Role))
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
err = pipelineRole.AssignRole(membership.Username)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
return membership, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) UpdateProjectMember(oldMembership, newMembership *devops.ProjectMembership) (*devops.ProjectMembership, error) {
|
||||||
|
oldProjectRole, err := j.GetProjectRole(GetProjectRoleName(oldMembership.ProjectId, oldMembership.Role))
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = oldProjectRole.UnAssignRole(newMembership.Username)
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
oldPipelineRole, err := j.GetProjectRole(GetPipelineRoleName(oldMembership.ProjectId, oldMembership.Role))
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = oldPipelineRole.UnAssignRole(newMembership.Username)
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
projectRole, err := j.GetProjectRole(GetProjectRoleName(oldMembership.ProjectId, newMembership.Role))
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = projectRole.AssignRole(newMembership.Username)
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
pipelineRole, err := j.GetProjectRole(GetPipelineRoleName(oldMembership.ProjectId, newMembership.Role))
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = pipelineRole.AssignRole(newMembership.Username)
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
return newMembership, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) DeleteProjectMember(membership *devops.ProjectMembership) (*devops.ProjectMembership, error) {
|
||||||
|
oldProjectRole, err := j.GetProjectRole(GetProjectRoleName(membership.ProjectId, membership.Role))
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
err = oldProjectRole.UnAssignRole(membership.Username)
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
oldPipelineRole, err := j.GetProjectRole(GetPipelineRoleName(membership.ProjectId, membership.Role))
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
err = oldPipelineRole.UnAssignRole(membership.Username)
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
return membership, nil
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package devops
|
package jenkins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
722
pkg/simple/client/devops/jenkins/pipeline.go
Normal file
722
pkg/simple/client/devops/jenkins/pipeline.go
Normal file
@@ -0,0 +1,722 @@
|
|||||||
|
package jenkins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/PuerkitoBio/goquery"
|
||||||
|
"k8s.io/klog"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Pipeline struct {
|
||||||
|
HttpParameters *devops.HttpParameters
|
||||||
|
Jenkins *Jenkins
|
||||||
|
Path string
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
GetPipelineUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/"
|
||||||
|
ListPipelinesUrl = "/blue/rest/search/?"
|
||||||
|
GetPipelineRunUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/%s/"
|
||||||
|
ListPipelineRunUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/?"
|
||||||
|
StopPipelineUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/%s/stop/?"
|
||||||
|
ReplayPipelineUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/%s/replay/"
|
||||||
|
RunPipelineUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/"
|
||||||
|
GetArtifactsUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/%s/artifacts/?"
|
||||||
|
GetRunLogUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/%s/log/?"
|
||||||
|
GetStepLogUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/%s/nodes/%s/steps/%s/log/?"
|
||||||
|
GetPipelineRunNodesUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/%s/nodes/?"
|
||||||
|
SubmitInputStepUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/%s/nodes/%s/steps/%s/"
|
||||||
|
GetNodeStepsUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/runs/%s/nodes/%s/steps/?"
|
||||||
|
|
||||||
|
GetBranchPipelineUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/"
|
||||||
|
GetBranchPipelineRunUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/%s/"
|
||||||
|
StopBranchPipelineUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/%s/stop/?"
|
||||||
|
ReplayBranchPipelineUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/%s/replay/"
|
||||||
|
RunBranchPipelineUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/"
|
||||||
|
GetBranchArtifactsUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/%s/artifacts/?"
|
||||||
|
GetBranchRunLogUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/%s/log/?"
|
||||||
|
GetBranchStepLogUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/%s/nodes/%s/steps/%s/log/?"
|
||||||
|
GetBranchNodeStepsUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/%s/nodes/%s/steps/?"
|
||||||
|
GetBranchPipeRunNodesUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/%s/nodes/?"
|
||||||
|
CheckBranchPipelineUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/%s/runs/%s/nodes/%s/steps/%s/"
|
||||||
|
GetPipeBranchUrl = "/blue/rest/organizations/jenkins/pipelines/%s/pipelines/%s/branches/?"
|
||||||
|
ScanBranchUrl = "/job/%s/job/%s/build?"
|
||||||
|
GetConsoleLogUrl = "/job/%s/job/%s/indexing/consoleText"
|
||||||
|
GetCrumbUrl = "/crumbIssuer/api/json/"
|
||||||
|
GetSCMServersUrl = "/blue/rest/organizations/jenkins/scm/%s/servers/"
|
||||||
|
GetSCMOrgUrl = "/blue/rest/organizations/jenkins/scm/%s/organizations/?"
|
||||||
|
GetOrgRepoUrl = "/blue/rest/organizations/jenkins/scm/%s/organizations/%s/repositories/?"
|
||||||
|
CreateSCMServersUrl = "/blue/rest/organizations/jenkins/scm/%s/servers/"
|
||||||
|
ValidateUrl = "/blue/rest/organizations/jenkins/scm/%s/validate"
|
||||||
|
|
||||||
|
GetNotifyCommitUrl = "/git/notifyCommit/?"
|
||||||
|
GithubWebhookUrl = "/github-webhook/"
|
||||||
|
CheckScriptCompileUrl = "/job/%s/job/%s/descriptorByName/org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition/checkScriptCompile"
|
||||||
|
|
||||||
|
CheckPipelienCronUrl = "/job/%s/job/%s/descriptorByName/hudson.triggers.TimerTrigger/checkSpec?value=%s"
|
||||||
|
CheckCronUrl = "/job/%s/descriptorByName/hudson.triggers.TimerTrigger/checkSpec?value=%s"
|
||||||
|
ToJenkinsfileUrl = "/pipeline-model-converter/toJenkinsfile"
|
||||||
|
ToJsonUrl = "/pipeline-model-converter/toJson"
|
||||||
|
|
||||||
|
cronJobLayout = "Monday, January 2, 2006 15:04:05 PM"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *Pipeline) GetPipeline() (*devops.Pipeline, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
var pipeline devops.Pipeline
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &pipeline)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &pipeline, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) ListPipelines() (*devops.PipelineList, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
count, err := p.searchPipelineCount()
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pipelienList := devops.PipelineList{Total: count}
|
||||||
|
err = json.Unmarshal(res, &pipelienList.Items)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &pipelienList, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) searchPipelineCount() (int, error) {
|
||||||
|
query, _ := parseJenkinsQuery(p.HttpParameters.Url.RawQuery)
|
||||||
|
query.Set("start", "0")
|
||||||
|
query.Set("limit", "1000")
|
||||||
|
query.Set("depth", "-1")
|
||||||
|
|
||||||
|
formatUrl := ListPipelinesUrl + query.Encode()
|
||||||
|
|
||||||
|
res, err := p.Jenkins.SendPureRequest(formatUrl, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
var pipelines []devops.Pipeline
|
||||||
|
err = json.Unmarshal(res, &pipelines)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return len(pipelines), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetPipelineRun() (*devops.PipelineRun, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var pipelineRun devops.PipelineRun
|
||||||
|
err = json.Unmarshal(res, &pipelineRun)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &pipelineRun, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) ListPipelineRuns() (*devops.PipelineRunList, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var pipelineRunList devops.PipelineRunList
|
||||||
|
err = json.Unmarshal(res, &pipelineRunList)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &pipelineRunList, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) searchPipelineRunsCount() (int, error) {
|
||||||
|
query, _ := parseJenkinsQuery(p.HttpParameters.Url.RawQuery)
|
||||||
|
query.Set("start", "0")
|
||||||
|
query.Set("limit", "1000")
|
||||||
|
query.Set("depth", "-1")
|
||||||
|
//formatUrl := fmt.Sprintf(SearchPipelineRunUrl, projectName, pipelineName)
|
||||||
|
|
||||||
|
res, err := p.Jenkins.SendPureRequest(ListPipelineRunUrl+query.Encode(), p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
var runs []devops.PipelineRun
|
||||||
|
err = json.Unmarshal(res, &runs)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return len(runs), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) StopPipeline() (*devops.StopPipeline, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var stopPipeline devops.StopPipeline
|
||||||
|
err = json.Unmarshal(res, &stopPipeline)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &stopPipeline, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) ReplayPipeline() (*devops.ReplayPipeline, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var replayPipeline devops.ReplayPipeline
|
||||||
|
err = json.Unmarshal(res, &replayPipeline)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &replayPipeline, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) RunPipeline() (*devops.RunPipeline, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var runPipeline devops.RunPipeline
|
||||||
|
err = json.Unmarshal(res, &runPipeline)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &runPipeline, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetArtifacts() ([]devops.Artifacts, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var artifacts []devops.Artifacts
|
||||||
|
err = json.Unmarshal(res, &artifacts)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return artifacts, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetRunLog() ([]byte, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetStepLog() ([]byte, http.Header, error) {
|
||||||
|
res, header, err := p.Jenkins.SendPureRequestWithHeaderResp(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, header, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetNodeSteps() ([]devops.NodeSteps, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var nodeSteps []devops.NodeSteps
|
||||||
|
err = json.Unmarshal(res, &nodeSteps)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodeSteps, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetPipelineRunNodes() ([]devops.PipelineRunNodes, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var pipelineRunNodes []devops.PipelineRunNodes
|
||||||
|
err = json.Unmarshal(res, &pipelineRunNodes)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return pipelineRunNodes, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) SubmitInputStep() ([]byte, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetBranchPipeline() (*devops.BranchPipeline, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
var branchPipeline devops.BranchPipeline
|
||||||
|
err = json.Unmarshal(res, &branchPipeline)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &branchPipeline, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetBranchPipelineRun() (*devops.PipelineRun, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
var branchPipelineRun devops.PipelineRun
|
||||||
|
err = json.Unmarshal(res, &branchPipelineRun)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &branchPipelineRun, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) StopBranchPipeline() (*devops.StopPipeline, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
var branchStopPipeline devops.StopPipeline
|
||||||
|
err = json.Unmarshal(res, &branchStopPipeline)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &branchStopPipeline, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) ReplayBranchPipeline() (*devops.ReplayPipeline, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
var branchReplayPipeline devops.ReplayPipeline
|
||||||
|
err = json.Unmarshal(res, &branchReplayPipeline)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &branchReplayPipeline, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) RunBranchPipeline() (*devops.RunPipeline, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
var branchRunPipeline devops.RunPipeline
|
||||||
|
err = json.Unmarshal(res, &branchRunPipeline)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &branchRunPipeline, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetBranchArtifacts() ([]devops.Artifacts, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var artifacts []devops.Artifacts
|
||||||
|
err = json.Unmarshal(res, &artifacts)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return artifacts, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetBranchRunLog() ([]byte, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetBranchStepLog() ([]byte, http.Header, error) {
|
||||||
|
res, header, err := p.Jenkins.SendPureRequestWithHeaderResp(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, header, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetBranchNodeSteps() ([]devops.NodeSteps, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
var branchNodeSteps []devops.NodeSteps
|
||||||
|
err = json.Unmarshal(res, &branchNodeSteps)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return branchNodeSteps, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetBranchPipelineRunNodes() ([]devops.BranchPipelineRunNodes, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
var branchPipelineRunNodes []devops.BranchPipelineRunNodes
|
||||||
|
err = json.Unmarshal(res, &branchPipelineRunNodes)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return branchPipelineRunNodes, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) SubmitBranchInputStep() ([]byte, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetPipelineBranch() (*devops.PipelineBranch, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
var pipelineBranch devops.PipelineBranch
|
||||||
|
err = json.Unmarshal(res, &pipelineBranch)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pipelineBranch, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) ScanBranch() ([]byte, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetConsoleLog() ([]byte, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetCrumb() (*devops.Crumb, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
var crumb devops.Crumb
|
||||||
|
err = json.Unmarshal(res, &crumb)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &crumb, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetSCMServers() ([]devops.SCMServer, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
var SCMServer []devops.SCMServer
|
||||||
|
err = json.Unmarshal(res, &SCMServer)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return SCMServer, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetSCMOrg() ([]devops.SCMOrg, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
var SCMOrg []devops.SCMOrg
|
||||||
|
err = json.Unmarshal(res, &SCMOrg)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return SCMOrg, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetOrgRepo() ([]devops.OrgRepo, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
var OrgRepo []devops.OrgRepo
|
||||||
|
err = json.Unmarshal(res, &OrgRepo)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return OrgRepo, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) CreateSCMServers() (*devops.SCMServer, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
var SCMServer devops.SCMServer
|
||||||
|
err = json.Unmarshal(res, &SCMServer)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &SCMServer, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GetNotifyCommit() ([]byte, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) GithubWebhook() ([]byte, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) Validate() (*devops.Validates, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var validates devops.Validates
|
||||||
|
err = json.Unmarshal(res, &validates)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &validates, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) CheckScriptCompile() (*devops.CheckScript, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jenkins will return different struct according to different results.
|
||||||
|
var checkScript devops.CheckScript
|
||||||
|
ok := json.Unmarshal(res, &checkScript)
|
||||||
|
if ok != nil {
|
||||||
|
var resJson []*devops.CheckScript
|
||||||
|
err := json.Unmarshal(res, &resJson)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resJson[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &checkScript, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) CheckCron() (*devops.CheckCronRes, error) {
|
||||||
|
|
||||||
|
var res = new(devops.CheckCronRes)
|
||||||
|
|
||||||
|
Url, err := url.Parse(p.Jenkins.Server + p.Path)
|
||||||
|
|
||||||
|
reqJenkins := &http.Request{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
URL: Url,
|
||||||
|
Header: p.HttpParameters.Header,
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &http.Client{Timeout: 30 * time.Second}
|
||||||
|
|
||||||
|
resp, err := client.Do(reqJenkins)
|
||||||
|
|
||||||
|
if resp != nil && resp.StatusCode != http.StatusOK {
|
||||||
|
resBody, _ := getRespBody(resp)
|
||||||
|
return &devops.CheckCronRes{
|
||||||
|
Result: "error",
|
||||||
|
Message: string(resBody),
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
doc, err := goquery.NewDocumentFromReader(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
doc.Find("div").Each(func(i int, selection *goquery.Selection) {
|
||||||
|
res.Message = selection.Text()
|
||||||
|
res.Result, _ = selection.Attr("class")
|
||||||
|
})
|
||||||
|
if res.Result == "ok" {
|
||||||
|
res.LastTime, res.NextTime, err = parseCronJobTime(res.Message)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseCronJobTime(msg string) (string, string, error) {
|
||||||
|
|
||||||
|
times := strings.Split(msg, ";")
|
||||||
|
|
||||||
|
lastTmp := strings.Split(times[0], " ")
|
||||||
|
lastCount := len(lastTmp)
|
||||||
|
lastTmp = lastTmp[lastCount-7 : lastCount-1]
|
||||||
|
lastTime := strings.Join(lastTmp, " ")
|
||||||
|
lastUinx, err := time.Parse(cronJobLayout, lastTime)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
last := lastUinx.Format(time.RFC3339)
|
||||||
|
|
||||||
|
nextTmp := strings.Split(times[1], " ")
|
||||||
|
nextCount := len(nextTmp)
|
||||||
|
nextTmp = nextTmp[nextCount-7 : nextCount-1]
|
||||||
|
nextTime := strings.Join(nextTmp, " ")
|
||||||
|
nextUinx, err := time.Parse(cronJobLayout, nextTime)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
next := nextUinx.Format(time.RFC3339)
|
||||||
|
|
||||||
|
return last, next, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) ToJenkinsfile() (*devops.ResJenkinsfile, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var jenkinsfile devops.ResJenkinsfile
|
||||||
|
err = json.Unmarshal(res, &jenkinsfile)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &jenkinsfile, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) ToJson() (*devops.ResJson, error) {
|
||||||
|
res, err := p.Jenkins.SendPureRequest(p.Path, p.HttpParameters)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var toJson devops.ResJson
|
||||||
|
err = json.Unmarshal(res, &toJson)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &toJson, err
|
||||||
|
}
|
||||||
@@ -1,179 +1,14 @@
|
|||||||
/*
|
package jenkins
|
||||||
Copyright 2019 The KubeSphere Authors.
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package devops
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/beevik/etree"
|
"github.com/beevik/etree"
|
||||||
"github.com/kubesphere/sonargo/sonar"
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
"k8s.io/klog"
|
|
||||||
"kubesphere.io/kubesphere/pkg/gojenkins"
|
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
NoScmPipelineType = "pipeline"
|
|
||||||
MultiBranchPipelineType = "multi-branch-pipeline"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Parameters []*Parameter
|
|
||||||
|
|
||||||
var ParameterTypeMap = map[string]string{
|
|
||||||
"hudson.model.StringParameterDefinition": "string",
|
|
||||||
"hudson.model.ChoiceParameterDefinition": "choice",
|
|
||||||
"hudson.model.TextParameterDefinition": "text",
|
|
||||||
"hudson.model.BooleanParameterDefinition": "boolean",
|
|
||||||
"hudson.model.FileParameterDefinition": "file",
|
|
||||||
"hudson.model.PasswordParameterDefinition": "password",
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
SonarAnalysisActionClass = "hudson.plugins.sonar.action.SonarAnalysisAction"
|
|
||||||
SonarMetricKeys = "alert_status,quality_gate_details,bugs,new_bugs,reliability_rating,new_reliability_rating,vulnerabilities,new_vulnerabilities,security_rating,new_security_rating,code_smells,new_code_smells,sqale_rating,new_maintainability_rating,sqale_index,new_technical_debt,coverage,new_coverage,new_lines_to_cover,tests,duplicated_lines_density,new_duplicated_lines_density,duplicated_blocks,ncloc,ncloc_language_distribution,projects,new_lines"
|
|
||||||
SonarAdditionalFields = "metrics,periods"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SonarStatus struct {
|
|
||||||
Measures *sonargo.MeasuresComponentObject `json:"measures,omitempty"`
|
|
||||||
Issues *sonargo.IssuesSearchObject `json:"issues,omitempty"`
|
|
||||||
JenkinsAction *gojenkins.GeneralObj `json:"jenkinsAction,omitempty"`
|
|
||||||
Task *sonargo.CeTaskObject `json:"task,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ProjectPipeline struct {
|
|
||||||
Type string `json:"type" description:"type of devops pipeline, in scm or no scm"`
|
|
||||||
Pipeline *NoScmPipeline `json:"pipeline,omitempty" description:"no scm pipeline structs"`
|
|
||||||
MultiBranchPipeline *MultiBranchPipeline `json:"multi_branch_pipeline,omitempty" description:"in scm pipeline structs"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type NoScmPipeline struct {
|
|
||||||
Name string `json:"name" description:"name of pipeline"`
|
|
||||||
Description string `json:"descriptio,omitempty" description:"description of pipeline"`
|
|
||||||
Discarder *DiscarderProperty `json:"discarder,omitempty" description:"Discarder of pipeline, managing when to drop a pipeline"`
|
|
||||||
Parameters *Parameters `json:"parameters,omitempty" description:"Parameters define of pipeline,user could pass param when run pipeline"`
|
|
||||||
DisableConcurrent bool `json:"disable_concurrent,omitempty" mapstructure:"disable_concurrent" description:"Whether to prohibit the pipeline from running in parallel"`
|
|
||||||
TimerTrigger *TimerTrigger `json:"timer_trigger,omitempty" mapstructure:"timer_trigger" description:"Timer to trigger pipeline run"`
|
|
||||||
RemoteTrigger *RemoteTrigger `json:"remote_trigger,omitempty" mapstructure:"remote_trigger" description:"Remote api define to trigger pipeline run"`
|
|
||||||
Jenkinsfile string `json:"jenkinsfile,omitempty" description:"Jenkinsfile's content'"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type MultiBranchPipeline struct {
|
|
||||||
Name string `json:"name" description:"name of pipeline"`
|
|
||||||
Description string `json:"descriptio,omitempty" description:"description of pipeline"`
|
|
||||||
Discarder *DiscarderProperty `json:"discarder,omitempty" description:"Discarder of pipeline, managing when to drop a pipeline"`
|
|
||||||
TimerTrigger *TimerTrigger `json:"timer_trigger,omitempty" mapstructure:"timer_trigger" description:"Timer to trigger pipeline run"`
|
|
||||||
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"`
|
|
||||||
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"`
|
|
||||||
ScriptPath string `json:"script_path" mapstructure:"script_path" description:"script path in scm"`
|
|
||||||
MultiBranchJobTrigger *MultiBranchJobTrigger `json:"multibranch_job_trigger,omitempty" mapstructure:"multibranch_job_trigger" description:"Pipeline tasks that need to be triggered when branch creation/deletion"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GitSource struct {
|
|
||||||
ScmId string `json:"scm_id,omitempty" description:"uid of scm"`
|
|
||||||
Url string `json:"url,omitempty" mapstructure:"url" description:"url of git source"`
|
|
||||||
CredentialId string `json:"credential_id,omitempty" mapstructure:"credential_id" description:"credential id to access git source"`
|
|
||||||
DiscoverBranches bool `json:"discover_branches,omitempty" mapstructure:"discover_branches" description:"Whether to discover a branch"`
|
|
||||||
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 GithubSource struct {
|
|
||||||
ScmId string `json:"scm_id,omitempty" description:"uid of scm"`
|
|
||||||
Owner string `json:"owner,omitempty" mapstructure:"owner" description:"owner of github repo"`
|
|
||||||
Repo string `json:"repo,omitempty" mapstructure:"repo" description:"repo name of github repo"`
|
|
||||||
CredentialId string `json:"credential_id,omitempty" mapstructure:"credential_id" description:"credential id to access github source"`
|
|
||||||
ApiUri string `json:"api_uri,omitempty" mapstructure:"api_uri" description:"The api url can specify the location of the github 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"`
|
|
||||||
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 MultiBranchJobTrigger struct {
|
|
||||||
CreateActionJobsToTrigger string `json:"create_action_job_to_trigger,omitempty" description:"pipeline name to trigger"`
|
|
||||||
DeleteActionJobsToTrigger string `json:"delete_action_job_to_trigger,omitempty" description:"pipeline name to trigger"`
|
|
||||||
}
|
|
||||||
|
|
||||||
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"`
|
|
||||||
Repo string `json:"repo,omitempty" mapstructure:"repo" description:"repo name of github repo"`
|
|
||||||
CredentialId string `json:"credential_id,omitempty" mapstructure:"credential_id" description:"credential id to access github source"`
|
|
||||||
ApiUri string `json:"api_uri,omitempty" mapstructure:"api_uri" description:"The api url can specify the location of the github 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"`
|
|
||||||
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 GitCloneOption struct {
|
|
||||||
Shallow bool `json:"shallow,omitempty" mapstructure:"shallow" description:"Whether to use git shallow clone"`
|
|
||||||
Timeout int `json:"timeout,omitempty" mapstructure:"timeout" description:"git clone timeout mins"`
|
|
||||||
Depth int `json:"depth,omitempty" mapstructure:"depth" description:"git clone depth"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SvnSource struct {
|
|
||||||
ScmId string `json:"scm_id,omitempty" description:"uid of scm"`
|
|
||||||
Remote string `json:"remote,omitempty" description:"remote address url"`
|
|
||||||
CredentialId string `json:"credential_id,omitempty" mapstructure:"credential_id" description:"credential id to access svn source"`
|
|
||||||
Includes string `json:"includes,omitempty" description:"branches to run pipeline"`
|
|
||||||
Excludes string `json:"excludes,omitempty" description:"branches do not run pipeline"`
|
|
||||||
}
|
|
||||||
type SingleSvnSource struct {
|
|
||||||
ScmId string `json:"scm_id,omitempty" description:"uid of scm"`
|
|
||||||
Remote string `json:"remote,omitempty" description:"remote address url"`
|
|
||||||
CredentialId string `json:"credential_id,omitempty" mapstructure:"credential_id" description:"credential id to access svn source"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DiscoverPRFromForks struct {
|
|
||||||
Strategy int `json:"strategy,omitempty" mapstructure:"strategy" description:"github discover strategy"`
|
|
||||||
Trust int `json:"trust,omitempty" mapstructure:"trust" description:"trust user type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DiscarderProperty struct {
|
|
||||||
DaysToKeep string `json:"days_to_keep,omitempty" mapstructure:"days_to_keep" description:"days to keep pipeline"`
|
|
||||||
NumToKeep string `json:"num_to_keep,omitempty" mapstructure:"num_to_keep" description:"nums to keep pipeline"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Parameter struct {
|
|
||||||
Name string `json:"name" description:"name of param"`
|
|
||||||
DefaultValue string `json:"default_value,omitempty" mapstructure:"default_value" description:"default value of param"`
|
|
||||||
Type string `json:"type" description:"type of param"`
|
|
||||||
Description string `json:"description,omitempty" description:"description of pipeline"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TimerTrigger struct {
|
|
||||||
// user in no scm job
|
|
||||||
Cron string `json:"cron,omitempty" description:"jenkins cron script"`
|
|
||||||
|
|
||||||
// use in multi-branch job
|
|
||||||
Interval string `json:"interval,omitempty" description:"interval ms"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RemoteTrigger struct {
|
|
||||||
Token string `json:"token,omitempty" description:"remote trigger token"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func replaceXmlVersion(config, oldVersion, targetVersion string) string {
|
func replaceXmlVersion(config, oldVersion, targetVersion string) string {
|
||||||
lines := strings.Split(config, "\n")
|
lines := strings.Split(config, "\n")
|
||||||
lines[0] = strings.Replace(lines[0], oldVersion, targetVersion, -1)
|
lines[0] = strings.Replace(lines[0], oldVersion, targetVersion, -1)
|
||||||
@@ -181,7 +16,7 @@ func replaceXmlVersion(config, oldVersion, targetVersion string) string {
|
|||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
func createPipelineConfigXml(pipeline *NoScmPipeline) (string, error) {
|
func createPipelineConfigXml(pipeline *devops.NoScmPipeline) (string, error) {
|
||||||
doc := etree.NewDocument()
|
doc := etree.NewDocument()
|
||||||
xmlString := `<?xml version='1.0' encoding='UTF-8'?>
|
xmlString := `<?xml version='1.0' encoding='UTF-8'?>
|
||||||
<flow-definition plugin="workflow-job">
|
<flow-definition plugin="workflow-job">
|
||||||
@@ -215,7 +50,7 @@ func createPipelineConfigXml(pipeline *NoScmPipeline) (string, error) {
|
|||||||
strategy.CreateElement("artifactNumToKeep").SetText("-1")
|
strategy.CreateElement("artifactNumToKeep").SetText("-1")
|
||||||
}
|
}
|
||||||
if pipeline.Parameters != nil {
|
if pipeline.Parameters != nil {
|
||||||
pipeline.Parameters.appendToEtree(properties)
|
appendParametersToEtree(properties, pipeline.Parameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pipeline.TimerTrigger != nil {
|
if pipeline.TimerTrigger != nil {
|
||||||
@@ -247,8 +82,8 @@ func createPipelineConfigXml(pipeline *NoScmPipeline) (string, error) {
|
|||||||
return replaceXmlVersion(stringXml, "1.0", "1.1"), err
|
return replaceXmlVersion(stringXml, "1.0", "1.1"), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsePipelineConfigXml(config string) (*NoScmPipeline, error) {
|
func parsePipelineConfigXml(config string) (*devops.NoScmPipeline, error) {
|
||||||
pipeline := &NoScmPipeline{}
|
pipeline := &devops.NoScmPipeline{}
|
||||||
config = replaceXmlVersion(config, "1.1", "1.0")
|
config = replaceXmlVersion(config, "1.1", "1.0")
|
||||||
doc := etree.NewDocument()
|
doc := etree.NewDocument()
|
||||||
err := doc.ReadFromString(config)
|
err := doc.ReadFromString(config)
|
||||||
@@ -271,13 +106,13 @@ func parsePipelineConfigXml(config string) (*NoScmPipeline, error) {
|
|||||||
strategy := properties.
|
strategy := properties.
|
||||||
SelectElement("jenkins.model.BuildDiscarderProperty").
|
SelectElement("jenkins.model.BuildDiscarderProperty").
|
||||||
SelectElement("strategy")
|
SelectElement("strategy")
|
||||||
pipeline.Discarder = &DiscarderProperty{
|
pipeline.Discarder = &devops.DiscarderProperty{
|
||||||
DaysToKeep: strategy.SelectElement("daysToKeep").Text(),
|
DaysToKeep: strategy.SelectElement("daysToKeep").Text(),
|
||||||
NumToKeep: strategy.SelectElement("numToKeep").Text(),
|
NumToKeep: strategy.SelectElement("numToKeep").Text(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pipeline.Parameters = &Parameters{}
|
pipeline.Parameters = &devops.Parameters{}
|
||||||
pipeline.Parameters = pipeline.Parameters.fromEtree(properties)
|
pipeline.Parameters = getParametersfromEtree(properties)
|
||||||
if len(*pipeline.Parameters) == 0 {
|
if len(*pipeline.Parameters) == 0 {
|
||||||
pipeline.Parameters = nil
|
pipeline.Parameters = nil
|
||||||
}
|
}
|
||||||
@@ -287,13 +122,13 @@ func parsePipelineConfigXml(config string) (*NoScmPipeline, error) {
|
|||||||
"org.jenkinsci.plugins.workflow.job.properties.PipelineTriggersJobProperty"); triggerProperty != nil {
|
"org.jenkinsci.plugins.workflow.job.properties.PipelineTriggersJobProperty"); triggerProperty != nil {
|
||||||
triggers := triggerProperty.SelectElement("triggers")
|
triggers := triggerProperty.SelectElement("triggers")
|
||||||
if timerTrigger := triggers.SelectElement("hudson.triggers.TimerTrigger"); timerTrigger != nil {
|
if timerTrigger := triggers.SelectElement("hudson.triggers.TimerTrigger"); timerTrigger != nil {
|
||||||
pipeline.TimerTrigger = &TimerTrigger{
|
pipeline.TimerTrigger = &devops.TimerTrigger{
|
||||||
Cron: timerTrigger.SelectElement("spec").Text(),
|
Cron: timerTrigger.SelectElement("spec").Text(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if authToken := flow.SelectElement("authToken"); authToken != nil {
|
if authToken := flow.SelectElement("authToken"); authToken != nil {
|
||||||
pipeline.RemoteTrigger = &RemoteTrigger{
|
pipeline.RemoteTrigger = &devops.RemoteTrigger{
|
||||||
Token: authToken.Text(),
|
Token: authToken.Text(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -305,11 +140,11 @@ func parsePipelineConfigXml(config string) (*NoScmPipeline, error) {
|
|||||||
return pipeline, nil
|
return pipeline, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Parameters) appendToEtree(properties *etree.Element) *Parameters {
|
func appendParametersToEtree(properties *etree.Element, parameters *devops.Parameters) {
|
||||||
parameterDefinitions := properties.CreateElement("hudson.model.ParametersDefinitionProperty").
|
parameterDefinitions := properties.CreateElement("hudson.model.ParametersDefinitionProperty").
|
||||||
CreateElement("parameterDefinitions")
|
CreateElement("parameterDefinitions")
|
||||||
for _, parameter := range *s {
|
for _, parameter := range *parameters {
|
||||||
for className, typeName := range ParameterTypeMap {
|
for className, typeName := range devops.ParameterTypeMap {
|
||||||
if typeName == parameter.Type {
|
if typeName == parameter.Type {
|
||||||
paramDefine := parameterDefinitions.CreateElement(className)
|
paramDefine := parameterDefinitions.CreateElement(className)
|
||||||
paramDefine.CreateElement("name").SetText(parameter.Name)
|
paramDefine.CreateElement("name").SetText(parameter.Name)
|
||||||
@@ -332,66 +167,62 @@ func (s *Parameters) appendToEtree(properties *etree.Element) *Parameters {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Parameters) fromEtree(properties *etree.Element) *Parameters {
|
func getParametersfromEtree(properties *etree.Element) *devops.Parameters {
|
||||||
|
var parameters devops.Parameters
|
||||||
if parametersProperty := properties.SelectElement("hudson.model.ParametersDefinitionProperty"); parametersProperty != nil {
|
if parametersProperty := properties.SelectElement("hudson.model.ParametersDefinitionProperty"); parametersProperty != nil {
|
||||||
params := parametersProperty.SelectElement("parameterDefinitions").ChildElements()
|
params := parametersProperty.SelectElement("parameterDefinitions").ChildElements()
|
||||||
if *s == nil {
|
|
||||||
*s = make([]*Parameter, 0)
|
|
||||||
}
|
|
||||||
for _, param := range params {
|
for _, param := range params {
|
||||||
switch param.Tag {
|
switch param.Tag {
|
||||||
case "hudson.model.StringParameterDefinition":
|
case "hudson.model.StringParameterDefinition":
|
||||||
*s = append(*s, &Parameter{
|
parameters = append(parameters, &devops.Parameter{
|
||||||
Name: param.SelectElement("name").Text(),
|
Name: param.SelectElement("name").Text(),
|
||||||
Description: param.SelectElement("description").Text(),
|
Description: param.SelectElement("description").Text(),
|
||||||
DefaultValue: param.SelectElement("defaultValue").Text(),
|
DefaultValue: param.SelectElement("defaultValue").Text(),
|
||||||
Type: ParameterTypeMap["hudson.model.StringParameterDefinition"],
|
Type: devops.ParameterTypeMap["hudson.model.StringParameterDefinition"],
|
||||||
})
|
})
|
||||||
case "hudson.model.BooleanParameterDefinition":
|
case "hudson.model.BooleanParameterDefinition":
|
||||||
*s = append(*s, &Parameter{
|
parameters = append(parameters, &devops.Parameter{
|
||||||
Name: param.SelectElement("name").Text(),
|
Name: param.SelectElement("name").Text(),
|
||||||
Description: param.SelectElement("description").Text(),
|
Description: param.SelectElement("description").Text(),
|
||||||
DefaultValue: param.SelectElement("defaultValue").Text(),
|
DefaultValue: param.SelectElement("defaultValue").Text(),
|
||||||
Type: ParameterTypeMap["hudson.model.BooleanParameterDefinition"],
|
Type: devops.ParameterTypeMap["hudson.model.BooleanParameterDefinition"],
|
||||||
})
|
})
|
||||||
case "hudson.model.TextParameterDefinition":
|
case "hudson.model.TextParameterDefinition":
|
||||||
*s = append(*s, &Parameter{
|
parameters = append(parameters, &devops.Parameter{
|
||||||
Name: param.SelectElement("name").Text(),
|
Name: param.SelectElement("name").Text(),
|
||||||
Description: param.SelectElement("description").Text(),
|
Description: param.SelectElement("description").Text(),
|
||||||
DefaultValue: param.SelectElement("defaultValue").Text(),
|
DefaultValue: param.SelectElement("defaultValue").Text(),
|
||||||
Type: ParameterTypeMap["hudson.model.TextParameterDefinition"],
|
Type: devops.ParameterTypeMap["hudson.model.TextParameterDefinition"],
|
||||||
})
|
})
|
||||||
case "hudson.model.FileParameterDefinition":
|
case "hudson.model.FileParameterDefinition":
|
||||||
*s = append(*s, &Parameter{
|
parameters = append(parameters, &devops.Parameter{
|
||||||
Name: param.SelectElement("name").Text(),
|
Name: param.SelectElement("name").Text(),
|
||||||
Description: param.SelectElement("description").Text(),
|
Description: param.SelectElement("description").Text(),
|
||||||
Type: ParameterTypeMap["hudson.model.FileParameterDefinition"],
|
Type: devops.ParameterTypeMap["hudson.model.FileParameterDefinition"],
|
||||||
})
|
})
|
||||||
case "hudson.model.PasswordParameterDefinition":
|
case "hudson.model.PasswordParameterDefinition":
|
||||||
*s = append(*s, &Parameter{
|
parameters = append(parameters, &devops.Parameter{
|
||||||
Name: param.SelectElement("name").Text(),
|
Name: param.SelectElement("name").Text(),
|
||||||
Description: param.SelectElement("description").Text(),
|
Description: param.SelectElement("description").Text(),
|
||||||
DefaultValue: param.SelectElement("name").Text(),
|
DefaultValue: param.SelectElement("name").Text(),
|
||||||
Type: ParameterTypeMap["hudson.model.PasswordParameterDefinition"],
|
Type: devops.ParameterTypeMap["hudson.model.PasswordParameterDefinition"],
|
||||||
})
|
})
|
||||||
case "hudson.model.ChoiceParameterDefinition":
|
case "hudson.model.ChoiceParameterDefinition":
|
||||||
choiceParameter := &Parameter{
|
choiceParameter := &devops.Parameter{
|
||||||
Name: param.SelectElement("name").Text(),
|
Name: param.SelectElement("name").Text(),
|
||||||
Description: param.SelectElement("description").Text(),
|
Description: param.SelectElement("description").Text(),
|
||||||
Type: ParameterTypeMap["hudson.model.ChoiceParameterDefinition"],
|
Type: devops.ParameterTypeMap["hudson.model.ChoiceParameterDefinition"],
|
||||||
}
|
}
|
||||||
choices := param.SelectElement("choices").SelectElement("a").SelectElements("string")
|
choices := param.SelectElement("choices").SelectElement("a").SelectElements("string")
|
||||||
for _, choice := range choices {
|
for _, choice := range choices {
|
||||||
choiceParameter.DefaultValue += fmt.Sprintf("%s\n", choice.Text())
|
choiceParameter.DefaultValue += fmt.Sprintf("%s\n", choice.Text())
|
||||||
}
|
}
|
||||||
choiceParameter.DefaultValue = strings.TrimSpace(choiceParameter.DefaultValue)
|
choiceParameter.DefaultValue = strings.TrimSpace(choiceParameter.DefaultValue)
|
||||||
*s = append(*s, choiceParameter)
|
parameters = append(parameters, choiceParameter)
|
||||||
default:
|
default:
|
||||||
*s = append(*s, &Parameter{
|
parameters = append(parameters, &devops.Parameter{
|
||||||
Name: param.SelectElement("name").Text(),
|
Name: param.SelectElement("name").Text(),
|
||||||
Description: param.SelectElement("description").Text(),
|
Description: param.SelectElement("description").Text(),
|
||||||
DefaultValue: "unknown",
|
DefaultValue: "unknown",
|
||||||
@@ -400,110 +231,112 @@ func (s *Parameters) fromEtree(properties *etree.Element) *Parameters {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s
|
return ¶meters
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *GitSource) appendToEtree(source *etree.Element) *GitSource {
|
func appendGitSourceToEtree(source *etree.Element, gitSource *devops.GitSource) {
|
||||||
source.CreateAttr("class", "jenkins.plugins.git.GitSCMSource")
|
source.CreateAttr("class", "jenkins.plugins.git.GitSCMSource")
|
||||||
source.CreateAttr("plugin", "git")
|
source.CreateAttr("plugin", "git")
|
||||||
source.CreateElement("id").SetText(s.ScmId)
|
source.CreateElement("id").SetText(gitSource.ScmId)
|
||||||
source.CreateElement("remote").SetText(s.Url)
|
source.CreateElement("remote").SetText(gitSource.Url)
|
||||||
if s.CredentialId != "" {
|
if gitSource.CredentialId != "" {
|
||||||
source.CreateElement("credentialsId").SetText(s.CredentialId)
|
source.CreateElement("credentialsId").SetText(gitSource.CredentialId)
|
||||||
}
|
}
|
||||||
traits := source.CreateElement("traits")
|
traits := source.CreateElement("traits")
|
||||||
if s.DiscoverBranches {
|
if gitSource.DiscoverBranches {
|
||||||
traits.CreateElement("jenkins.plugins.git.traits.BranchDiscoveryTrait")
|
traits.CreateElement("jenkins.plugins.git.traits.BranchDiscoveryTrait")
|
||||||
}
|
}
|
||||||
if s.CloneOption != nil {
|
if gitSource.CloneOption != nil {
|
||||||
cloneExtension := traits.CreateElement("jenkins.plugins.git.traits.CloneOptionTrait").CreateElement("extension")
|
cloneExtension := traits.CreateElement("jenkins.plugins.git.traits.CloneOptionTrait").CreateElement("extension")
|
||||||
cloneExtension.CreateAttr("class", "hudson.plugins.git.extensions.impl.CloneOption")
|
cloneExtension.CreateAttr("class", "hudson.plugins.git.extensions.impl.CloneOption")
|
||||||
cloneExtension.CreateElement("shallow").SetText(strconv.FormatBool(s.CloneOption.Shallow))
|
cloneExtension.CreateElement("shallow").SetText(strconv.FormatBool(gitSource.CloneOption.Shallow))
|
||||||
cloneExtension.CreateElement("noTags").SetText(strconv.FormatBool(false))
|
cloneExtension.CreateElement("noTags").SetText(strconv.FormatBool(false))
|
||||||
cloneExtension.CreateElement("honorRefspec").SetText(strconv.FormatBool(true))
|
cloneExtension.CreateElement("honorRefspec").SetText(strconv.FormatBool(true))
|
||||||
cloneExtension.CreateElement("reference")
|
cloneExtension.CreateElement("reference")
|
||||||
if s.CloneOption.Timeout >= 0 {
|
if gitSource.CloneOption.Timeout >= 0 {
|
||||||
cloneExtension.CreateElement("timeout").SetText(strconv.Itoa(s.CloneOption.Timeout))
|
cloneExtension.CreateElement("timeout").SetText(strconv.Itoa(gitSource.CloneOption.Timeout))
|
||||||
} else {
|
} else {
|
||||||
cloneExtension.CreateElement("timeout").SetText(strconv.Itoa(10))
|
cloneExtension.CreateElement("timeout").SetText(strconv.Itoa(10))
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.CloneOption.Depth >= 0 {
|
if gitSource.CloneOption.Depth >= 0 {
|
||||||
cloneExtension.CreateElement("depth").SetText(strconv.Itoa(s.CloneOption.Depth))
|
cloneExtension.CreateElement("depth").SetText(strconv.Itoa(gitSource.CloneOption.Depth))
|
||||||
} else {
|
} else {
|
||||||
cloneExtension.CreateElement("depth").SetText(strconv.Itoa(1))
|
cloneExtension.CreateElement("depth").SetText(strconv.Itoa(1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.RegexFilter != "" {
|
if gitSource.RegexFilter != "" {
|
||||||
regexTraits := traits.CreateElement("jenkins.scm.impl.trait.RegexSCMHeadFilterTrait")
|
regexTraits := traits.CreateElement("jenkins.scm.impl.trait.RegexSCMHeadFilterTrait")
|
||||||
regexTraits.CreateAttr("plugin", "scm-api@2.4.0")
|
regexTraits.CreateAttr("plugin", "scm-api@2.4.0")
|
||||||
regexTraits.CreateElement("regex").SetText(s.RegexFilter)
|
regexTraits.CreateElement("regex").SetText(gitSource.RegexFilter)
|
||||||
}
|
}
|
||||||
return s
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *GitSource) fromEtree(source *etree.Element) *GitSource {
|
func getGitSourcefromEtree(source *etree.Element) *devops.GitSource {
|
||||||
|
var gitSource devops.GitSource
|
||||||
if credential := source.SelectElement("credentialsId"); credential != nil {
|
if credential := source.SelectElement("credentialsId"); credential != nil {
|
||||||
s.CredentialId = credential.Text()
|
gitSource.CredentialId = credential.Text()
|
||||||
}
|
}
|
||||||
if remote := source.SelectElement("remote"); remote != nil {
|
if remote := source.SelectElement("remote"); remote != nil {
|
||||||
s.Url = remote.Text()
|
gitSource.Url = remote.Text()
|
||||||
}
|
}
|
||||||
|
|
||||||
traits := source.SelectElement("traits")
|
traits := source.SelectElement("traits")
|
||||||
if branchDiscoverTrait := traits.SelectElement(
|
if branchDiscoverTrait := traits.SelectElement(
|
||||||
"jenkins.plugins.git.traits.BranchDiscoveryTrait"); branchDiscoverTrait != nil {
|
"jenkins.plugins.git.traits.BranchDiscoveryTrait"); branchDiscoverTrait != nil {
|
||||||
s.DiscoverBranches = true
|
gitSource.DiscoverBranches = true
|
||||||
}
|
}
|
||||||
if cloneTrait := traits.SelectElement(
|
if cloneTrait := traits.SelectElement(
|
||||||
"jenkins.plugins.git.traits.CloneOptionTrait"); cloneTrait != nil {
|
"jenkins.plugins.git.traits.CloneOptionTrait"); cloneTrait != nil {
|
||||||
if cloneExtension := cloneTrait.SelectElement(
|
if cloneExtension := cloneTrait.SelectElement(
|
||||||
"extension"); cloneExtension != nil {
|
"extension"); cloneExtension != nil {
|
||||||
s.CloneOption = &GitCloneOption{}
|
gitSource.CloneOption = &devops.GitCloneOption{}
|
||||||
if value, err := strconv.ParseBool(cloneExtension.SelectElement("shallow").Text()); err == nil {
|
if value, err := strconv.ParseBool(cloneExtension.SelectElement("shallow").Text()); err == nil {
|
||||||
s.CloneOption.Shallow = value
|
gitSource.CloneOption.Shallow = value
|
||||||
}
|
}
|
||||||
if value, err := strconv.ParseInt(cloneExtension.SelectElement("timeout").Text(), 10, 32); err == nil {
|
if value, err := strconv.ParseInt(cloneExtension.SelectElement("timeout").Text(), 10, 32); err == nil {
|
||||||
s.CloneOption.Timeout = int(value)
|
gitSource.CloneOption.Timeout = int(value)
|
||||||
}
|
}
|
||||||
if value, err := strconv.ParseInt(cloneExtension.SelectElement("depth").Text(), 10, 32); err == nil {
|
if value, err := strconv.ParseInt(cloneExtension.SelectElement("depth").Text(), 10, 32); err == nil {
|
||||||
s.CloneOption.Depth = int(value)
|
gitSource.CloneOption.Depth = int(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if regexTrait := traits.SelectElement(
|
if regexTrait := traits.SelectElement(
|
||||||
"jenkins.scm.impl.trait.RegexSCMHeadFilterTrait"); regexTrait != nil {
|
"jenkins.scm.impl.trait.RegexSCMHeadFilterTrait"); regexTrait != nil {
|
||||||
if regex := regexTrait.SelectElement("regex"); regex != nil {
|
if regex := regexTrait.SelectElement("regex"); regex != nil {
|
||||||
s.RegexFilter = regex.Text()
|
gitSource.RegexFilter = regex.Text()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s
|
return &gitSource
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *GithubSource) fromEtree(source *etree.Element) *GithubSource {
|
func getGithubSourcefromEtree(source *etree.Element) *devops.GithubSource {
|
||||||
|
var githubSource devops.GithubSource
|
||||||
if credential := source.SelectElement("credentialsId"); credential != nil {
|
if credential := source.SelectElement("credentialsId"); credential != nil {
|
||||||
s.CredentialId = credential.Text()
|
githubSource.CredentialId = credential.Text()
|
||||||
}
|
}
|
||||||
if repoOwner := source.SelectElement("repoOwner"); repoOwner != nil {
|
if repoOwner := source.SelectElement("repoOwner"); repoOwner != nil {
|
||||||
s.Owner = repoOwner.Text()
|
githubSource.Owner = repoOwner.Text()
|
||||||
}
|
}
|
||||||
if repository := source.SelectElement("repository"); repository != nil {
|
if repository := source.SelectElement("repository"); repository != nil {
|
||||||
s.Repo = repository.Text()
|
githubSource.Repo = repository.Text()
|
||||||
}
|
}
|
||||||
if apiUri := source.SelectElement("apiUri"); apiUri != nil {
|
if apiUri := source.SelectElement("apiUri"); apiUri != nil {
|
||||||
s.ApiUri = apiUri.Text()
|
githubSource.ApiUri = apiUri.Text()
|
||||||
}
|
}
|
||||||
traits := source.SelectElement("traits")
|
traits := source.SelectElement("traits")
|
||||||
if branchDiscoverTrait := traits.SelectElement(
|
if branchDiscoverTrait := traits.SelectElement(
|
||||||
"org.jenkinsci.plugins.github__branch__source.BranchDiscoveryTrait"); branchDiscoverTrait != nil {
|
"org.jenkinsci.plugins.github__branch__source.BranchDiscoveryTrait"); branchDiscoverTrait != nil {
|
||||||
strategyId, _ := strconv.Atoi(branchDiscoverTrait.SelectElement("strategyId").Text())
|
strategyId, _ := strconv.Atoi(branchDiscoverTrait.SelectElement("strategyId").Text())
|
||||||
s.DiscoverBranches = strategyId
|
githubSource.DiscoverBranches = strategyId
|
||||||
}
|
}
|
||||||
if originPRDiscoverTrait := traits.SelectElement(
|
if originPRDiscoverTrait := traits.SelectElement(
|
||||||
"org.jenkinsci.plugins.github__branch__source.OriginPullRequestDiscoveryTrait"); originPRDiscoverTrait != nil {
|
"org.jenkinsci.plugins.github__branch__source.OriginPullRequestDiscoveryTrait"); originPRDiscoverTrait != nil {
|
||||||
strategyId, _ := strconv.Atoi(originPRDiscoverTrait.SelectElement("strategyId").Text())
|
strategyId, _ := strconv.Atoi(originPRDiscoverTrait.SelectElement("strategyId").Text())
|
||||||
s.DiscoverPRFromOrigin = strategyId
|
githubSource.DiscoverPRFromOrigin = strategyId
|
||||||
}
|
}
|
||||||
if forkPRDiscoverTrait := traits.SelectElement(
|
if forkPRDiscoverTrait := traits.SelectElement(
|
||||||
"org.jenkinsci.plugins.github__branch__source.ForkPullRequestDiscoveryTrait"); forkPRDiscoverTrait != nil {
|
"org.jenkinsci.plugins.github__branch__source.ForkPullRequestDiscoveryTrait"); forkPRDiscoverTrait != nil {
|
||||||
@@ -512,22 +345,22 @@ func (s *GithubSource) fromEtree(source *etree.Element) *GithubSource {
|
|||||||
trust := strings.Split(trustClass, "$")
|
trust := strings.Split(trustClass, "$")
|
||||||
switch trust[1] {
|
switch trust[1] {
|
||||||
case "TrustContributors":
|
case "TrustContributors":
|
||||||
s.DiscoverPRFromForks = &DiscoverPRFromForks{
|
githubSource.DiscoverPRFromForks = &devops.DiscoverPRFromForks{
|
||||||
Strategy: strategyId,
|
Strategy: strategyId,
|
||||||
Trust: 1,
|
Trust: 1,
|
||||||
}
|
}
|
||||||
case "TrustEveryone":
|
case "TrustEveryone":
|
||||||
s.DiscoverPRFromForks = &DiscoverPRFromForks{
|
githubSource.DiscoverPRFromForks = &devops.DiscoverPRFromForks{
|
||||||
Strategy: strategyId,
|
Strategy: strategyId,
|
||||||
Trust: 2,
|
Trust: 2,
|
||||||
}
|
}
|
||||||
case "TrustPermission":
|
case "TrustPermission":
|
||||||
s.DiscoverPRFromForks = &DiscoverPRFromForks{
|
githubSource.DiscoverPRFromForks = &devops.DiscoverPRFromForks{
|
||||||
Strategy: strategyId,
|
Strategy: strategyId,
|
||||||
Trust: 3,
|
Trust: 3,
|
||||||
}
|
}
|
||||||
case "TrustNobody":
|
case "TrustNobody":
|
||||||
s.DiscoverPRFromForks = &DiscoverPRFromForks{
|
githubSource.DiscoverPRFromForks = &devops.DiscoverPRFromForks{
|
||||||
Strategy: strategyId,
|
Strategy: strategyId,
|
||||||
Trust: 4,
|
Trust: 4,
|
||||||
}
|
}
|
||||||
@@ -536,15 +369,15 @@ func (s *GithubSource) fromEtree(source *etree.Element) *GithubSource {
|
|||||||
"jenkins.plugins.git.traits.CloneOptionTrait"); cloneTrait != nil {
|
"jenkins.plugins.git.traits.CloneOptionTrait"); cloneTrait != nil {
|
||||||
if cloneExtension := cloneTrait.SelectElement(
|
if cloneExtension := cloneTrait.SelectElement(
|
||||||
"extension"); cloneExtension != nil {
|
"extension"); cloneExtension != nil {
|
||||||
s.CloneOption = &GitCloneOption{}
|
githubSource.CloneOption = &devops.GitCloneOption{}
|
||||||
if value, err := strconv.ParseBool(cloneExtension.SelectElement("shallow").Text()); err == nil {
|
if value, err := strconv.ParseBool(cloneExtension.SelectElement("shallow").Text()); err == nil {
|
||||||
s.CloneOption.Shallow = value
|
githubSource.CloneOption.Shallow = value
|
||||||
}
|
}
|
||||||
if value, err := strconv.ParseInt(cloneExtension.SelectElement("timeout").Text(), 10, 32); err == nil {
|
if value, err := strconv.ParseInt(cloneExtension.SelectElement("timeout").Text(), 10, 32); err == nil {
|
||||||
s.CloneOption.Timeout = int(value)
|
githubSource.CloneOption.Timeout = int(value)
|
||||||
}
|
}
|
||||||
if value, err := strconv.ParseInt(cloneExtension.SelectElement("depth").Text(), 10, 32); err == nil {
|
if value, err := strconv.ParseInt(cloneExtension.SelectElement("depth").Text(), 10, 32); err == nil {
|
||||||
s.CloneOption.Depth = int(value)
|
githubSource.CloneOption.Depth = int(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -552,37 +385,37 @@ func (s *GithubSource) fromEtree(source *etree.Element) *GithubSource {
|
|||||||
if regexTrait := traits.SelectElement(
|
if regexTrait := traits.SelectElement(
|
||||||
"jenkins.scm.impl.trait.RegexSCMHeadFilterTrait"); regexTrait != nil {
|
"jenkins.scm.impl.trait.RegexSCMHeadFilterTrait"); regexTrait != nil {
|
||||||
if regex := regexTrait.SelectElement("regex"); regex != nil {
|
if regex := regexTrait.SelectElement("regex"); regex != nil {
|
||||||
s.RegexFilter = regex.Text()
|
githubSource.RegexFilter = regex.Text()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s
|
return &githubSource
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *GithubSource) appendToEtree(source *etree.Element) *GithubSource {
|
func appendGithubSourceToEtree(source *etree.Element, githubSource *devops.GithubSource) {
|
||||||
source.CreateAttr("class", "org.jenkinsci.plugins.github_branch_source.GitHubSCMSource")
|
source.CreateAttr("class", "org.jenkinsci.plugins.github_branch_source.GitHubSCMSource")
|
||||||
source.CreateAttr("plugin", "github-branch-source")
|
source.CreateAttr("plugin", "github-branch-source")
|
||||||
source.CreateElement("id").SetText(s.ScmId)
|
source.CreateElement("id").SetText(githubSource.ScmId)
|
||||||
source.CreateElement("credentialsId").SetText(s.CredentialId)
|
source.CreateElement("credentialsId").SetText(githubSource.CredentialId)
|
||||||
source.CreateElement("repoOwner").SetText(s.Owner)
|
source.CreateElement("repoOwner").SetText(githubSource.Owner)
|
||||||
source.CreateElement("repository").SetText(s.Repo)
|
source.CreateElement("repository").SetText(githubSource.Repo)
|
||||||
if s.ApiUri != "" {
|
if githubSource.ApiUri != "" {
|
||||||
source.CreateElement("apiUri").SetText(s.ApiUri)
|
source.CreateElement("apiUri").SetText(githubSource.ApiUri)
|
||||||
}
|
}
|
||||||
traits := source.CreateElement("traits")
|
traits := source.CreateElement("traits")
|
||||||
if s.DiscoverBranches != 0 {
|
if githubSource.DiscoverBranches != 0 {
|
||||||
traits.CreateElement("org.jenkinsci.plugins.github__branch__source.BranchDiscoveryTrait").
|
traits.CreateElement("org.jenkinsci.plugins.github__branch__source.BranchDiscoveryTrait").
|
||||||
CreateElement("strategyId").SetText(strconv.Itoa(s.DiscoverBranches))
|
CreateElement("strategyId").SetText(strconv.Itoa(githubSource.DiscoverBranches))
|
||||||
}
|
}
|
||||||
if s.DiscoverPRFromOrigin != 0 {
|
if githubSource.DiscoverPRFromOrigin != 0 {
|
||||||
traits.CreateElement("org.jenkinsci.plugins.github__branch__source.OriginPullRequestDiscoveryTrait").
|
traits.CreateElement("org.jenkinsci.plugins.github__branch__source.OriginPullRequestDiscoveryTrait").
|
||||||
CreateElement("strategyId").SetText(strconv.Itoa(s.DiscoverPRFromOrigin))
|
CreateElement("strategyId").SetText(strconv.Itoa(githubSource.DiscoverPRFromOrigin))
|
||||||
}
|
}
|
||||||
if s.DiscoverPRFromForks != nil {
|
if githubSource.DiscoverPRFromForks != nil {
|
||||||
forkTrait := traits.CreateElement("org.jenkinsci.plugins.github__branch__source.ForkPullRequestDiscoveryTrait")
|
forkTrait := traits.CreateElement("org.jenkinsci.plugins.github__branch__source.ForkPullRequestDiscoveryTrait")
|
||||||
forkTrait.CreateElement("strategyId").SetText(strconv.Itoa(s.DiscoverPRFromForks.Strategy))
|
forkTrait.CreateElement("strategyId").SetText(strconv.Itoa(githubSource.DiscoverPRFromForks.Strategy))
|
||||||
trustClass := "org.jenkinsci.plugins.github_branch_source.ForkPullRequestDiscoveryTrait$"
|
trustClass := "org.jenkinsci.plugins.github_branch_source.ForkPullRequestDiscoveryTrait$"
|
||||||
switch s.DiscoverPRFromForks.Trust {
|
switch githubSource.DiscoverPRFromForks.Trust {
|
||||||
case 1:
|
case 1:
|
||||||
trustClass += "TrustContributors"
|
trustClass += "TrustContributors"
|
||||||
case 2:
|
case 2:
|
||||||
@@ -595,34 +428,35 @@ func (s *GithubSource) appendToEtree(source *etree.Element) *GithubSource {
|
|||||||
}
|
}
|
||||||
forkTrait.CreateElement("trust").CreateAttr("class", trustClass)
|
forkTrait.CreateElement("trust").CreateAttr("class", trustClass)
|
||||||
}
|
}
|
||||||
if s.CloneOption != nil {
|
if githubSource.CloneOption != nil {
|
||||||
cloneExtension := traits.CreateElement("jenkins.plugins.git.traits.CloneOptionTrait").CreateElement("extension")
|
cloneExtension := traits.CreateElement("jenkins.plugins.git.traits.CloneOptionTrait").CreateElement("extension")
|
||||||
cloneExtension.CreateAttr("class", "hudson.plugins.git.extensions.impl.CloneOption")
|
cloneExtension.CreateAttr("class", "hudson.plugins.git.extensions.impl.CloneOption")
|
||||||
cloneExtension.CreateElement("shallow").SetText(strconv.FormatBool(s.CloneOption.Shallow))
|
cloneExtension.CreateElement("shallow").SetText(strconv.FormatBool(githubSource.CloneOption.Shallow))
|
||||||
cloneExtension.CreateElement("noTags").SetText(strconv.FormatBool(false))
|
cloneExtension.CreateElement("noTags").SetText(strconv.FormatBool(false))
|
||||||
cloneExtension.CreateElement("honorRefspec").SetText(strconv.FormatBool(true))
|
cloneExtension.CreateElement("honorRefspec").SetText(strconv.FormatBool(true))
|
||||||
cloneExtension.CreateElement("reference")
|
cloneExtension.CreateElement("reference")
|
||||||
if s.CloneOption.Timeout >= 0 {
|
if githubSource.CloneOption.Timeout >= 0 {
|
||||||
cloneExtension.CreateElement("timeout").SetText(strconv.Itoa(s.CloneOption.Timeout))
|
cloneExtension.CreateElement("timeout").SetText(strconv.Itoa(githubSource.CloneOption.Timeout))
|
||||||
} else {
|
} else {
|
||||||
cloneExtension.CreateElement("timeout").SetText(strconv.Itoa(10))
|
cloneExtension.CreateElement("timeout").SetText(strconv.Itoa(10))
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.CloneOption.Depth >= 0 {
|
if githubSource.CloneOption.Depth >= 0 {
|
||||||
cloneExtension.CreateElement("depth").SetText(strconv.Itoa(s.CloneOption.Depth))
|
cloneExtension.CreateElement("depth").SetText(strconv.Itoa(githubSource.CloneOption.Depth))
|
||||||
} else {
|
} else {
|
||||||
cloneExtension.CreateElement("depth").SetText(strconv.Itoa(1))
|
cloneExtension.CreateElement("depth").SetText(strconv.Itoa(1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.RegexFilter != "" {
|
if githubSource.RegexFilter != "" {
|
||||||
regexTraits := traits.CreateElement("jenkins.scm.impl.trait.RegexSCMHeadFilterTrait")
|
regexTraits := traits.CreateElement("jenkins.scm.impl.trait.RegexSCMHeadFilterTrait")
|
||||||
regexTraits.CreateAttr("plugin", "scm-api@2.4.0")
|
regexTraits.CreateAttr("plugin", "scm-api@2.4.0")
|
||||||
regexTraits.CreateElement("regex").SetText(s.RegexFilter)
|
regexTraits.CreateElement("regex").SetText(githubSource.RegexFilter)
|
||||||
}
|
}
|
||||||
return s
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *BitbucketServerSource) fromEtree(source *etree.Element) *BitbucketServerSource {
|
func getBitbucketServerSourceFromEtree(source *etree.Element) *devops.BitbucketServerSource {
|
||||||
|
var s devops.BitbucketServerSource
|
||||||
if credential := source.SelectElement("credentialsId"); credential != nil {
|
if credential := source.SelectElement("credentialsId"); credential != nil {
|
||||||
s.CredentialId = credential.Text()
|
s.CredentialId = credential.Text()
|
||||||
}
|
}
|
||||||
@@ -653,17 +487,17 @@ func (s *BitbucketServerSource) fromEtree(source *etree.Element) *BitbucketServe
|
|||||||
trust := strings.Split(trustClass, "$")
|
trust := strings.Split(trustClass, "$")
|
||||||
switch trust[1] {
|
switch trust[1] {
|
||||||
case "TrustEveryone":
|
case "TrustEveryone":
|
||||||
s.DiscoverPRFromForks = &DiscoverPRFromForks{
|
s.DiscoverPRFromForks = &devops.DiscoverPRFromForks{
|
||||||
Strategy: strategyId,
|
Strategy: strategyId,
|
||||||
Trust: 1,
|
Trust: 1,
|
||||||
}
|
}
|
||||||
case "TrustTeamForks":
|
case "TrustTeamForks":
|
||||||
s.DiscoverPRFromForks = &DiscoverPRFromForks{
|
s.DiscoverPRFromForks = &devops.DiscoverPRFromForks{
|
||||||
Strategy: strategyId,
|
Strategy: strategyId,
|
||||||
Trust: 2,
|
Trust: 2,
|
||||||
}
|
}
|
||||||
case "TrustNobody":
|
case "TrustNobody":
|
||||||
s.DiscoverPRFromForks = &DiscoverPRFromForks{
|
s.DiscoverPRFromForks = &devops.DiscoverPRFromForks{
|
||||||
Strategy: strategyId,
|
Strategy: strategyId,
|
||||||
Trust: 3,
|
Trust: 3,
|
||||||
}
|
}
|
||||||
@@ -672,7 +506,7 @@ func (s *BitbucketServerSource) fromEtree(source *etree.Element) *BitbucketServe
|
|||||||
"jenkins.plugins.git.traits.CloneOptionTrait"); cloneTrait != nil {
|
"jenkins.plugins.git.traits.CloneOptionTrait"); cloneTrait != nil {
|
||||||
if cloneExtension := cloneTrait.SelectElement(
|
if cloneExtension := cloneTrait.SelectElement(
|
||||||
"extension"); cloneExtension != nil {
|
"extension"); cloneExtension != nil {
|
||||||
s.CloneOption = &GitCloneOption{}
|
s.CloneOption = &devops.GitCloneOption{}
|
||||||
if value, err := strconv.ParseBool(cloneExtension.SelectElement("shallow").Text()); err == nil {
|
if value, err := strconv.ParseBool(cloneExtension.SelectElement("shallow").Text()); err == nil {
|
||||||
s.CloneOption.Shallow = value
|
s.CloneOption.Shallow = value
|
||||||
}
|
}
|
||||||
@@ -692,10 +526,10 @@ func (s *BitbucketServerSource) fromEtree(source *etree.Element) *BitbucketServe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s
|
return &s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *BitbucketServerSource) appendToEtree(source *etree.Element) *BitbucketServerSource {
|
func appendBitbucketServerSourceToEtree(source *etree.Element, s *devops.BitbucketServerSource) {
|
||||||
source.CreateAttr("class", "com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMSource")
|
source.CreateAttr("class", "com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMSource")
|
||||||
source.CreateAttr("plugin", "cloudbees-bitbucket-branch-source")
|
source.CreateAttr("plugin", "cloudbees-bitbucket-branch-source")
|
||||||
source.CreateElement("id").SetText(s.ScmId)
|
source.CreateElement("id").SetText(s.ScmId)
|
||||||
@@ -753,10 +587,11 @@ func (s *BitbucketServerSource) appendToEtree(source *etree.Element) *BitbucketS
|
|||||||
regexTraits.CreateAttr("plugin", "scm-api@2.4.0")
|
regexTraits.CreateAttr("plugin", "scm-api@2.4.0")
|
||||||
regexTraits.CreateElement("regex").SetText(s.RegexFilter)
|
regexTraits.CreateElement("regex").SetText(s.RegexFilter)
|
||||||
}
|
}
|
||||||
return s
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SvnSource) fromEtree(source *etree.Element) *SvnSource {
|
func getSvnSourcefromEtree(source *etree.Element) *devops.SvnSource {
|
||||||
|
var s devops.SvnSource
|
||||||
if remote := source.SelectElement("remoteBase"); remote != nil {
|
if remote := source.SelectElement("remoteBase"); remote != nil {
|
||||||
s.Remote = remote.Text()
|
s.Remote = remote.Text()
|
||||||
}
|
}
|
||||||
@@ -772,10 +607,10 @@ func (s *SvnSource) fromEtree(source *etree.Element) *SvnSource {
|
|||||||
if excludes := source.SelectElement("excludes"); excludes != nil {
|
if excludes := source.SelectElement("excludes"); excludes != nil {
|
||||||
s.Excludes = excludes.Text()
|
s.Excludes = excludes.Text()
|
||||||
}
|
}
|
||||||
return s
|
return &s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SvnSource) appendToEtree(source *etree.Element) *SvnSource {
|
func appendSvnSourceToEtree(source *etree.Element, s *devops.SvnSource) {
|
||||||
source.CreateAttr("class", "jenkins.scm.impl.subversion.SubversionSCMSource")
|
source.CreateAttr("class", "jenkins.scm.impl.subversion.SubversionSCMSource")
|
||||||
source.CreateAttr("plugin", "subversion")
|
source.CreateAttr("plugin", "subversion")
|
||||||
source.CreateElement("id").SetText(s.ScmId)
|
source.CreateElement("id").SetText(s.ScmId)
|
||||||
@@ -791,10 +626,11 @@ func (s *SvnSource) appendToEtree(source *etree.Element) *SvnSource {
|
|||||||
if s.Excludes != "" {
|
if s.Excludes != "" {
|
||||||
source.CreateElement("excludes").SetText(s.Excludes)
|
source.CreateElement("excludes").SetText(s.Excludes)
|
||||||
}
|
}
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SingleSvnSource) fromEtree(source *etree.Element) *SingleSvnSource {
|
func getSingleSvnSourceFromEtree(source *etree.Element) *devops.SingleSvnSource {
|
||||||
|
var s devops.SingleSvnSource
|
||||||
if scm := source.SelectElement("scm"); scm != nil {
|
if scm := source.SelectElement("scm"); scm != nil {
|
||||||
if locations := scm.SelectElement("locations"); locations != nil {
|
if locations := scm.SelectElement("locations"); locations != nil {
|
||||||
if moduleLocations := locations.SelectElement("hudson.scm.SubversionSCM_-ModuleLocation"); moduleLocations != nil {
|
if moduleLocations := locations.SelectElement("hudson.scm.SubversionSCM_-ModuleLocation"); moduleLocations != nil {
|
||||||
@@ -807,10 +643,10 @@ func (s *SingleSvnSource) fromEtree(source *etree.Element) *SingleSvnSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s
|
return &s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SingleSvnSource) appendToEtree(source *etree.Element) *SingleSvnSource {
|
func appendSingleSvnSourceToEtree(source *etree.Element, s *devops.SingleSvnSource) {
|
||||||
|
|
||||||
source.CreateAttr("class", "jenkins.scm.impl.SingleSCMSource")
|
source.CreateAttr("class", "jenkins.scm.impl.SingleSCMSource")
|
||||||
source.CreateAttr("plugin", "scm-api")
|
source.CreateAttr("plugin", "scm-api")
|
||||||
@@ -843,26 +679,27 @@ func (s *SingleSvnSource) appendToEtree(source *etree.Element) *SingleSvnSource
|
|||||||
source.CreateElement("filterChangelog").SetText("false")
|
source.CreateElement("filterChangelog").SetText("false")
|
||||||
source.CreateElement("quietOperation").SetText("true")
|
source.CreateElement("quietOperation").SetText("true")
|
||||||
|
|
||||||
return s
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MultiBranchJobTrigger) appendToEtree(properties *etree.Element) *MultiBranchJobTrigger {
|
func appendMultiBranchJobTriggerToEtree(properties *etree.Element, s *devops.MultiBranchJobTrigger) {
|
||||||
triggerProperty := properties.CreateElement("org.jenkinsci.plugins.workflow.multibranch.PipelineTriggerProperty")
|
triggerProperty := properties.CreateElement("org.jenkinsci.plugins.workflow.multibranch.PipelineTriggerProperty")
|
||||||
triggerProperty.CreateAttr("plugin", "multibranch-action-triggers")
|
triggerProperty.CreateAttr("plugin", "multibranch-action-triggers")
|
||||||
triggerProperty.CreateElement("createActionJobsToTrigger").SetText(s.CreateActionJobsToTrigger)
|
triggerProperty.CreateElement("createActionJobsToTrigger").SetText(s.CreateActionJobsToTrigger)
|
||||||
triggerProperty.CreateElement("deleteActionJobsToTrigger").SetText(s.DeleteActionJobsToTrigger)
|
triggerProperty.CreateElement("deleteActionJobsToTrigger").SetText(s.DeleteActionJobsToTrigger)
|
||||||
return s
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MultiBranchJobTrigger) fromEtree(properties *etree.Element) *MultiBranchJobTrigger {
|
func getMultiBranchJobTriggerfromEtree(properties *etree.Element) *devops.MultiBranchJobTrigger {
|
||||||
|
var s devops.MultiBranchJobTrigger
|
||||||
triggerProperty := properties.SelectElement("org.jenkinsci.plugins.workflow.multibranch.PipelineTriggerProperty")
|
triggerProperty := properties.SelectElement("org.jenkinsci.plugins.workflow.multibranch.PipelineTriggerProperty")
|
||||||
if triggerProperty != nil {
|
if triggerProperty != nil {
|
||||||
s.CreateActionJobsToTrigger = triggerProperty.SelectElement("createActionJobsToTrigger").Text()
|
s.CreateActionJobsToTrigger = triggerProperty.SelectElement("createActionJobsToTrigger").Text()
|
||||||
s.DeleteActionJobsToTrigger = triggerProperty.SelectElement("deleteActionJobsToTrigger").Text()
|
s.DeleteActionJobsToTrigger = triggerProperty.SelectElement("deleteActionJobsToTrigger").Text()
|
||||||
}
|
}
|
||||||
return s
|
return &s
|
||||||
}
|
}
|
||||||
func createMultiBranchPipelineConfigXml(projectName string, pipeline *MultiBranchPipeline) (string, error) {
|
func createMultiBranchPipelineConfigXml(projectName string, pipeline *devops.MultiBranchPipeline) (string, error) {
|
||||||
doc := etree.NewDocument()
|
doc := etree.NewDocument()
|
||||||
xmlString := `
|
xmlString := `
|
||||||
<?xml version='1.0' encoding='UTF-8'?>
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
@@ -896,7 +733,7 @@ func createMultiBranchPipelineConfigXml(projectName string, pipeline *MultiBranc
|
|||||||
|
|
||||||
if pipeline.MultiBranchJobTrigger != nil {
|
if pipeline.MultiBranchJobTrigger != nil {
|
||||||
properties := project.SelectElement("properties")
|
properties := project.SelectElement("properties")
|
||||||
pipeline.MultiBranchJobTrigger.appendToEtree(properties)
|
appendMultiBranchJobTriggerToEtree(properties, pipeline.MultiBranchJobTrigger)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pipeline.Discarder != nil {
|
if pipeline.Discarder != nil {
|
||||||
@@ -939,27 +776,15 @@ func createMultiBranchPipelineConfigXml(projectName string, pipeline *MultiBranc
|
|||||||
|
|
||||||
switch pipeline.SourceType {
|
switch pipeline.SourceType {
|
||||||
case "git":
|
case "git":
|
||||||
gitDefine := pipeline.GitSource
|
appendGitSourceToEtree(source, pipeline.GitSource)
|
||||||
gitDefine.ScmId = projectName + pipeline.Name
|
|
||||||
gitDefine.appendToEtree(source)
|
|
||||||
case "github":
|
case "github":
|
||||||
githubDefine := pipeline.GitHubSource
|
appendGithubSourceToEtree(source, pipeline.GitHubSource)
|
||||||
githubDefine.ScmId = projectName + pipeline.Name
|
|
||||||
githubDefine.appendToEtree(source)
|
|
||||||
case "svn":
|
case "svn":
|
||||||
svnDefine := pipeline.SvnSource
|
appendSvnSourceToEtree(source, pipeline.SvnSource)
|
||||||
svnDefine.ScmId = projectName + pipeline.Name
|
|
||||||
svnDefine.appendToEtree(source)
|
|
||||||
|
|
||||||
case "single_svn":
|
case "single_svn":
|
||||||
singSvnDefine := pipeline.SingleSvnSource
|
appendSingleSvnSourceToEtree(source, pipeline.SingleSvnSource)
|
||||||
singSvnDefine.ScmId = projectName + pipeline.Name
|
|
||||||
singSvnDefine.appendToEtree(source)
|
|
||||||
|
|
||||||
case "bitbucket_server":
|
case "bitbucket_server":
|
||||||
bitbucketServerDefine := pipeline.BitbucketServerSource
|
appendBitbucketServerSourceToEtree(source, pipeline.BitbucketServerSource)
|
||||||
bitbucketServerDefine.ScmId = projectName + pipeline.Name
|
|
||||||
bitbucketServerDefine.appendToEtree(source)
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return "", fmt.Errorf("unsupport source type")
|
return "", fmt.Errorf("unsupport source type")
|
||||||
@@ -977,8 +802,8 @@ func createMultiBranchPipelineConfigXml(projectName string, pipeline *MultiBranc
|
|||||||
return replaceXmlVersion(stringXml, "1.0", "1.1"), err
|
return replaceXmlVersion(stringXml, "1.0", "1.1"), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseMultiBranchPipelineConfigXml(config string) (*MultiBranchPipeline, error) {
|
func parseMultiBranchPipelineConfigXml(config string) (*devops.MultiBranchPipeline, error) {
|
||||||
pipeline := &MultiBranchPipeline{}
|
pipeline := &devops.MultiBranchPipeline{}
|
||||||
config = replaceXmlVersion(config, "1.1", "1.0")
|
config = replaceXmlVersion(config, "1.1", "1.0")
|
||||||
doc := etree.NewDocument()
|
doc := etree.NewDocument()
|
||||||
err := doc.ReadFromString(config)
|
err := doc.ReadFromString(config)
|
||||||
@@ -992,15 +817,13 @@ func parseMultiBranchPipelineConfigXml(config string) (*MultiBranchPipeline, err
|
|||||||
if properties := project.SelectElement("properties"); properties != nil {
|
if properties := project.SelectElement("properties"); properties != nil {
|
||||||
if multibranchTrigger := properties.SelectElement(
|
if multibranchTrigger := properties.SelectElement(
|
||||||
"org.jenkinsci.plugins.workflow.multibranch.PipelineTriggerProperty"); multibranchTrigger != nil {
|
"org.jenkinsci.plugins.workflow.multibranch.PipelineTriggerProperty"); multibranchTrigger != nil {
|
||||||
trigger := &MultiBranchJobTrigger{}
|
pipeline.MultiBranchJobTrigger = getMultiBranchJobTriggerfromEtree(properties)
|
||||||
trigger.fromEtree(properties)
|
|
||||||
pipeline.MultiBranchJobTrigger = trigger
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pipeline.Description = project.SelectElement("description").Text()
|
pipeline.Description = project.SelectElement("description").Text()
|
||||||
|
|
||||||
if discarder := project.SelectElement("orphanedItemStrategy"); discarder != nil {
|
if discarder := project.SelectElement("orphanedItemStrategy"); discarder != nil {
|
||||||
pipeline.Discarder = &DiscarderProperty{
|
pipeline.Discarder = &devops.DiscarderProperty{
|
||||||
DaysToKeep: discarder.SelectElement("daysToKeep").Text(),
|
DaysToKeep: discarder.SelectElement("daysToKeep").Text(),
|
||||||
NumToKeep: discarder.SelectElement("numToKeep").Text(),
|
NumToKeep: discarder.SelectElement("numToKeep").Text(),
|
||||||
}
|
}
|
||||||
@@ -1008,7 +831,7 @@ func parseMultiBranchPipelineConfigXml(config string) (*MultiBranchPipeline, err
|
|||||||
if triggers := project.SelectElement("triggers"); triggers != nil {
|
if triggers := project.SelectElement("triggers"); triggers != nil {
|
||||||
if timerTrigger := triggers.SelectElement(
|
if timerTrigger := triggers.SelectElement(
|
||||||
"com.cloudbees.hudson.plugins.folder.computed.PeriodicFolderTrigger"); timerTrigger != nil {
|
"com.cloudbees.hudson.plugins.folder.computed.PeriodicFolderTrigger"); timerTrigger != nil {
|
||||||
pipeline.TimerTrigger = &TimerTrigger{
|
pipeline.TimerTrigger = &devops.TimerTrigger{
|
||||||
Interval: timerTrigger.SelectElement("interval").Text(),
|
Interval: timerTrigger.SelectElement("interval").Text(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1020,33 +843,23 @@ func parseMultiBranchPipelineConfigXml(config string) (*MultiBranchPipeline, err
|
|||||||
source := branchSource.SelectElement("source")
|
source := branchSource.SelectElement("source")
|
||||||
switch source.SelectAttr("class").Value {
|
switch source.SelectAttr("class").Value {
|
||||||
case "org.jenkinsci.plugins.github_branch_source.GitHubSCMSource":
|
case "org.jenkinsci.plugins.github_branch_source.GitHubSCMSource":
|
||||||
githubSource := &GithubSource{}
|
pipeline.GitHubSource = getGithubSourcefromEtree(source)
|
||||||
githubSource.fromEtree(source)
|
|
||||||
pipeline.GitHubSource = githubSource
|
|
||||||
pipeline.SourceType = "github"
|
pipeline.SourceType = "github"
|
||||||
case "com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMSource":
|
case "com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMSource":
|
||||||
bitbucketServerSource := &BitbucketServerSource{}
|
pipeline.BitbucketServerSource = getBitbucketServerSourceFromEtree(source)
|
||||||
bitbucketServerSource.fromEtree(source)
|
|
||||||
pipeline.BitbucketServerSource = bitbucketServerSource
|
|
||||||
pipeline.SourceType = "bitbucket_server"
|
pipeline.SourceType = "bitbucket_server"
|
||||||
|
|
||||||
case "jenkins.plugins.git.GitSCMSource":
|
case "jenkins.plugins.git.GitSCMSource":
|
||||||
gitSource := &GitSource{}
|
|
||||||
gitSource.fromEtree(source)
|
|
||||||
pipeline.SourceType = "git"
|
pipeline.SourceType = "git"
|
||||||
pipeline.GitSource = gitSource
|
pipeline.GitSource = getGitSourcefromEtree(source)
|
||||||
|
|
||||||
case "jenkins.scm.impl.SingleSCMSource":
|
case "jenkins.scm.impl.SingleSCMSource":
|
||||||
singleSvnSource := &SingleSvnSource{}
|
|
||||||
singleSvnSource.fromEtree(source)
|
|
||||||
pipeline.SourceType = "single_svn"
|
pipeline.SourceType = "single_svn"
|
||||||
pipeline.SingleSvnSource = singleSvnSource
|
pipeline.SingleSvnSource = getSingleSvnSourceFromEtree(source)
|
||||||
|
|
||||||
case "jenkins.scm.impl.subversion.SubversionSCMSource":
|
case "jenkins.scm.impl.subversion.SubversionSCMSource":
|
||||||
svnSource := &SvnSource{}
|
|
||||||
svnSource.fromEtree(source)
|
|
||||||
pipeline.SourceType = "svn"
|
pipeline.SourceType = "svn"
|
||||||
pipeline.SvnSource = svnSource
|
pipeline.SvnSource = getSvnSourcefromEtree(source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1078,55 +891,3 @@ func toCrontab(millis int64) string {
|
|||||||
return "H H * * *"
|
return "H H * * *"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBuildSonarResults(build *gojenkins.Build) ([]*SonarStatus, error) {
|
|
||||||
|
|
||||||
sonarClient, err := client.ClientSets().SonarQube()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
actions := build.GetActions()
|
|
||||||
sonarStatuses := make([]*SonarStatus, 0)
|
|
||||||
for _, action := range actions {
|
|
||||||
if action.ClassName == SonarAnalysisActionClass {
|
|
||||||
sonarStatus := &SonarStatus{}
|
|
||||||
taskOptions := &sonargo.CeTaskOption{
|
|
||||||
Id: action.SonarTaskId,
|
|
||||||
}
|
|
||||||
ceTask, _, err := sonarClient.SonarQube().Ce.Task(taskOptions)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("get sonar task error [%+v]", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
sonarStatus.Task = ceTask
|
|
||||||
measuresComponentOption := &sonargo.MeasuresComponentOption{
|
|
||||||
Component: ceTask.Task.ComponentKey,
|
|
||||||
AdditionalFields: SonarAdditionalFields,
|
|
||||||
MetricKeys: SonarMetricKeys,
|
|
||||||
}
|
|
||||||
measures, _, err := sonarClient.SonarQube().Measures.Component(measuresComponentOption)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("get sonar task error [%+v]", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
sonarStatus.Measures = measures
|
|
||||||
|
|
||||||
issuesSearchOption := &sonargo.IssuesSearchOption{
|
|
||||||
AdditionalFields: "_all",
|
|
||||||
ComponentKeys: ceTask.Task.ComponentKey,
|
|
||||||
Resolved: "false",
|
|
||||||
Ps: "10",
|
|
||||||
S: "FILE_LINE",
|
|
||||||
Facets: "severities,types",
|
|
||||||
}
|
|
||||||
issuesSearch, _, err := sonarClient.SonarQube().Issues.Search(issuesSearchOption)
|
|
||||||
sonarStatus.Issues = issuesSearch
|
|
||||||
jenkinsAction := action
|
|
||||||
sonarStatus.JenkinsAction = &jenkinsAction
|
|
||||||
|
|
||||||
sonarStatuses = append(sonarStatuses, sonarStatus)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sonarStatuses, nil
|
|
||||||
}
|
|
||||||
@@ -1,25 +1,13 @@
|
|||||||
/*
|
package jenkins
|
||||||
Copyright 2019 The KubeSphere Authors.
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package devops
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_NoScmPipelineConfig(t *testing.T) {
|
func Test_NoScmPipelineConfig(t *testing.T) {
|
||||||
inputs := []*NoScmPipeline{
|
inputs := []*devops.NoScmPipeline{
|
||||||
{
|
{
|
||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
@@ -54,12 +42,12 @@ func Test_NoScmPipelineConfig(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_NoScmPipelineConfig_Discarder(t *testing.T) {
|
func Test_NoScmPipelineConfig_Discarder(t *testing.T) {
|
||||||
inputs := []*NoScmPipeline{
|
inputs := []*devops.NoScmPipeline{
|
||||||
{
|
{
|
||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
Jenkinsfile: "node{echo 'hello'}",
|
Jenkinsfile: "node{echo 'hello'}",
|
||||||
Discarder: &DiscarderProperty{
|
Discarder: &devops.DiscarderProperty{
|
||||||
"3", "5",
|
"3", "5",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -67,7 +55,7 @@ func Test_NoScmPipelineConfig_Discarder(t *testing.T) {
|
|||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
Jenkinsfile: "node{echo 'hello'}",
|
Jenkinsfile: "node{echo 'hello'}",
|
||||||
Discarder: &DiscarderProperty{
|
Discarder: &devops.DiscarderProperty{
|
||||||
"3", "",
|
"3", "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -75,7 +63,7 @@ func Test_NoScmPipelineConfig_Discarder(t *testing.T) {
|
|||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
Jenkinsfile: "node{echo 'hello'}",
|
Jenkinsfile: "node{echo 'hello'}",
|
||||||
Discarder: &DiscarderProperty{
|
Discarder: &devops.DiscarderProperty{
|
||||||
"", "21321",
|
"", "21321",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -83,7 +71,7 @@ func Test_NoScmPipelineConfig_Discarder(t *testing.T) {
|
|||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
Jenkinsfile: "node{echo 'hello'}",
|
Jenkinsfile: "node{echo 'hello'}",
|
||||||
Discarder: &DiscarderProperty{
|
Discarder: &devops.DiscarderProperty{
|
||||||
"", "",
|
"", "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -105,13 +93,13 @@ func Test_NoScmPipelineConfig_Discarder(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_NoScmPipelineConfig_Param(t *testing.T) {
|
func Test_NoScmPipelineConfig_Param(t *testing.T) {
|
||||||
inputs := []*NoScmPipeline{
|
inputs := []*devops.NoScmPipeline{
|
||||||
{
|
{
|
||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
Jenkinsfile: "node{echo 'hello'}",
|
Jenkinsfile: "node{echo 'hello'}",
|
||||||
Parameters: &Parameters{
|
Parameters: &devops.Parameters{
|
||||||
&Parameter{
|
&devops.Parameter{
|
||||||
Name: "d",
|
Name: "d",
|
||||||
DefaultValue: "a\nb",
|
DefaultValue: "a\nb",
|
||||||
Type: "choice",
|
Type: "choice",
|
||||||
@@ -123,26 +111,26 @@ func Test_NoScmPipelineConfig_Param(t *testing.T) {
|
|||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
Jenkinsfile: "node{echo 'hello'}",
|
Jenkinsfile: "node{echo 'hello'}",
|
||||||
Parameters: &Parameters{
|
Parameters: &devops.Parameters{
|
||||||
&Parameter{
|
&devops.Parameter{
|
||||||
Name: "a",
|
Name: "a",
|
||||||
DefaultValue: "abc",
|
DefaultValue: "abc",
|
||||||
Type: "string",
|
Type: "string",
|
||||||
Description: "fortest",
|
Description: "fortest",
|
||||||
},
|
},
|
||||||
&Parameter{
|
&devops.Parameter{
|
||||||
Name: "b",
|
Name: "b",
|
||||||
DefaultValue: "false",
|
DefaultValue: "false",
|
||||||
Type: "boolean",
|
Type: "boolean",
|
||||||
Description: "fortest",
|
Description: "fortest",
|
||||||
},
|
},
|
||||||
&Parameter{
|
&devops.Parameter{
|
||||||
Name: "c",
|
Name: "c",
|
||||||
DefaultValue: "password \n aaa",
|
DefaultValue: "password \n aaa",
|
||||||
Type: "text",
|
Type: "text",
|
||||||
Description: "fortest",
|
Description: "fortest",
|
||||||
},
|
},
|
||||||
&Parameter{
|
&devops.Parameter{
|
||||||
Name: "d",
|
Name: "d",
|
||||||
DefaultValue: "a\nb",
|
DefaultValue: "a\nb",
|
||||||
Type: "choice",
|
Type: "choice",
|
||||||
@@ -168,12 +156,12 @@ func Test_NoScmPipelineConfig_Param(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_NoScmPipelineConfig_Trigger(t *testing.T) {
|
func Test_NoScmPipelineConfig_Trigger(t *testing.T) {
|
||||||
inputs := []*NoScmPipeline{
|
inputs := []*devops.NoScmPipeline{
|
||||||
{
|
{
|
||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
Jenkinsfile: "node{echo 'hello'}",
|
Jenkinsfile: "node{echo 'hello'}",
|
||||||
TimerTrigger: &TimerTrigger{
|
TimerTrigger: &devops.TimerTrigger{
|
||||||
Cron: "1 1 1 * * *",
|
Cron: "1 1 1 * * *",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -182,7 +170,7 @@ func Test_NoScmPipelineConfig_Trigger(t *testing.T) {
|
|||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
Jenkinsfile: "node{echo 'hello'}",
|
Jenkinsfile: "node{echo 'hello'}",
|
||||||
RemoteTrigger: &RemoteTrigger{
|
RemoteTrigger: &devops.RemoteTrigger{
|
||||||
Token: "abc",
|
Token: "abc",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -190,10 +178,10 @@ func Test_NoScmPipelineConfig_Trigger(t *testing.T) {
|
|||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
Jenkinsfile: "node{echo 'hello'}",
|
Jenkinsfile: "node{echo 'hello'}",
|
||||||
TimerTrigger: &TimerTrigger{
|
TimerTrigger: &devops.TimerTrigger{
|
||||||
Cron: "1 1 1 * * *",
|
Cron: "1 1 1 * * *",
|
||||||
},
|
},
|
||||||
RemoteTrigger: &RemoteTrigger{
|
RemoteTrigger: &devops.RemoteTrigger{
|
||||||
Token: "abc",
|
Token: "abc",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -217,34 +205,34 @@ func Test_NoScmPipelineConfig_Trigger(t *testing.T) {
|
|||||||
|
|
||||||
func Test_MultiBranchPipelineConfig(t *testing.T) {
|
func Test_MultiBranchPipelineConfig(t *testing.T) {
|
||||||
|
|
||||||
inputs := []*MultiBranchPipeline{
|
inputs := []*devops.MultiBranchPipeline{
|
||||||
{
|
{
|
||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
ScriptPath: "Jenkinsfile",
|
ScriptPath: "Jenkinsfile",
|
||||||
SourceType: "git",
|
SourceType: "git",
|
||||||
GitSource: &GitSource{},
|
GitSource: &devops.GitSource{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
ScriptPath: "Jenkinsfile",
|
ScriptPath: "Jenkinsfile",
|
||||||
SourceType: "github",
|
SourceType: "github",
|
||||||
GitHubSource: &GithubSource{},
|
GitHubSource: &devops.GithubSource{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
ScriptPath: "Jenkinsfile",
|
ScriptPath: "Jenkinsfile",
|
||||||
SourceType: "single_svn",
|
SourceType: "single_svn",
|
||||||
SingleSvnSource: &SingleSvnSource{},
|
SingleSvnSource: &devops.SingleSvnSource{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
ScriptPath: "Jenkinsfile",
|
ScriptPath: "Jenkinsfile",
|
||||||
SourceType: "svn",
|
SourceType: "svn",
|
||||||
SvnSource: &SvnSource{},
|
SvnSource: &devops.SvnSource{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, input := range inputs {
|
for _, input := range inputs {
|
||||||
@@ -265,17 +253,17 @@ func Test_MultiBranchPipelineConfig(t *testing.T) {
|
|||||||
|
|
||||||
func Test_MultiBranchPipelineConfig_Discarder(t *testing.T) {
|
func Test_MultiBranchPipelineConfig_Discarder(t *testing.T) {
|
||||||
|
|
||||||
inputs := []*MultiBranchPipeline{
|
inputs := []*devops.MultiBranchPipeline{
|
||||||
{
|
{
|
||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
ScriptPath: "Jenkinsfile",
|
ScriptPath: "Jenkinsfile",
|
||||||
SourceType: "git",
|
SourceType: "git",
|
||||||
Discarder: &DiscarderProperty{
|
Discarder: &devops.DiscarderProperty{
|
||||||
DaysToKeep: "1",
|
DaysToKeep: "1",
|
||||||
NumToKeep: "2",
|
NumToKeep: "2",
|
||||||
},
|
},
|
||||||
GitSource: &GitSource{},
|
GitSource: &devops.GitSource{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, input := range inputs {
|
for _, input := range inputs {
|
||||||
@@ -295,16 +283,16 @@ func Test_MultiBranchPipelineConfig_Discarder(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_MultiBranchPipelineConfig_TimerTrigger(t *testing.T) {
|
func Test_MultiBranchPipelineConfig_TimerTrigger(t *testing.T) {
|
||||||
inputs := []*MultiBranchPipeline{
|
inputs := []*devops.MultiBranchPipeline{
|
||||||
{
|
{
|
||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
ScriptPath: "Jenkinsfile",
|
ScriptPath: "Jenkinsfile",
|
||||||
SourceType: "git",
|
SourceType: "git",
|
||||||
TimerTrigger: &TimerTrigger{
|
TimerTrigger: &devops.TimerTrigger{
|
||||||
Interval: "12345566",
|
Interval: "12345566",
|
||||||
},
|
},
|
||||||
GitSource: &GitSource{},
|
GitSource: &devops.GitSource{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, input := range inputs {
|
for _, input := range inputs {
|
||||||
@@ -325,16 +313,16 @@ func Test_MultiBranchPipelineConfig_TimerTrigger(t *testing.T) {
|
|||||||
|
|
||||||
func Test_MultiBranchPipelineConfig_Source(t *testing.T) {
|
func Test_MultiBranchPipelineConfig_Source(t *testing.T) {
|
||||||
|
|
||||||
inputs := []*MultiBranchPipeline{
|
inputs := []*devops.MultiBranchPipeline{
|
||||||
{
|
{
|
||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
ScriptPath: "Jenkinsfile",
|
ScriptPath: "Jenkinsfile",
|
||||||
SourceType: "git",
|
SourceType: "git",
|
||||||
TimerTrigger: &TimerTrigger{
|
TimerTrigger: &devops.TimerTrigger{
|
||||||
Interval: "12345566",
|
Interval: "12345566",
|
||||||
},
|
},
|
||||||
GitSource: &GitSource{
|
GitSource: &devops.GitSource{
|
||||||
Url: "https://github.com/kubesphere/devops",
|
Url: "https://github.com/kubesphere/devops",
|
||||||
CredentialId: "git",
|
CredentialId: "git",
|
||||||
DiscoverBranches: true,
|
DiscoverBranches: true,
|
||||||
@@ -345,17 +333,17 @@ func Test_MultiBranchPipelineConfig_Source(t *testing.T) {
|
|||||||
Description: "for test",
|
Description: "for test",
|
||||||
ScriptPath: "Jenkinsfile",
|
ScriptPath: "Jenkinsfile",
|
||||||
SourceType: "github",
|
SourceType: "github",
|
||||||
TimerTrigger: &TimerTrigger{
|
TimerTrigger: &devops.TimerTrigger{
|
||||||
Interval: "12345566",
|
Interval: "12345566",
|
||||||
},
|
},
|
||||||
GitHubSource: &GithubSource{
|
GitHubSource: &devops.GithubSource{
|
||||||
Owner: "kubesphere",
|
Owner: "kubesphere",
|
||||||
Repo: "devops",
|
Repo: "devops",
|
||||||
CredentialId: "github",
|
CredentialId: "github",
|
||||||
ApiUri: "https://api.github.com",
|
ApiUri: "https://api.github.com",
|
||||||
DiscoverBranches: 1,
|
DiscoverBranches: 1,
|
||||||
DiscoverPRFromOrigin: 2,
|
DiscoverPRFromOrigin: 2,
|
||||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
DiscoverPRFromForks: &devops.DiscoverPRFromForks{
|
||||||
Strategy: 1,
|
Strategy: 1,
|
||||||
Trust: 1,
|
Trust: 1,
|
||||||
},
|
},
|
||||||
@@ -366,17 +354,17 @@ func Test_MultiBranchPipelineConfig_Source(t *testing.T) {
|
|||||||
Description: "for test",
|
Description: "for test",
|
||||||
ScriptPath: "Jenkinsfile",
|
ScriptPath: "Jenkinsfile",
|
||||||
SourceType: "bitbucket_server",
|
SourceType: "bitbucket_server",
|
||||||
TimerTrigger: &TimerTrigger{
|
TimerTrigger: &devops.TimerTrigger{
|
||||||
Interval: "12345566",
|
Interval: "12345566",
|
||||||
},
|
},
|
||||||
BitbucketServerSource: &BitbucketServerSource{
|
BitbucketServerSource: &devops.BitbucketServerSource{
|
||||||
Owner: "kubesphere",
|
Owner: "kubesphere",
|
||||||
Repo: "devops",
|
Repo: "devops",
|
||||||
CredentialId: "github",
|
CredentialId: "github",
|
||||||
ApiUri: "https://api.github.com",
|
ApiUri: "https://api.github.com",
|
||||||
DiscoverBranches: 1,
|
DiscoverBranches: 1,
|
||||||
DiscoverPRFromOrigin: 2,
|
DiscoverPRFromOrigin: 2,
|
||||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
DiscoverPRFromForks: &devops.DiscoverPRFromForks{
|
||||||
Strategy: 1,
|
Strategy: 1,
|
||||||
Trust: 1,
|
Trust: 1,
|
||||||
},
|
},
|
||||||
@@ -388,10 +376,10 @@ func Test_MultiBranchPipelineConfig_Source(t *testing.T) {
|
|||||||
Description: "for test",
|
Description: "for test",
|
||||||
ScriptPath: "Jenkinsfile",
|
ScriptPath: "Jenkinsfile",
|
||||||
SourceType: "svn",
|
SourceType: "svn",
|
||||||
TimerTrigger: &TimerTrigger{
|
TimerTrigger: &devops.TimerTrigger{
|
||||||
Interval: "12345566",
|
Interval: "12345566",
|
||||||
},
|
},
|
||||||
SvnSource: &SvnSource{
|
SvnSource: &devops.SvnSource{
|
||||||
Remote: "https://api.svn.com/bcd",
|
Remote: "https://api.svn.com/bcd",
|
||||||
CredentialId: "svn",
|
CredentialId: "svn",
|
||||||
Excludes: "truck",
|
Excludes: "truck",
|
||||||
@@ -403,10 +391,10 @@ func Test_MultiBranchPipelineConfig_Source(t *testing.T) {
|
|||||||
Description: "for test",
|
Description: "for test",
|
||||||
ScriptPath: "Jenkinsfile",
|
ScriptPath: "Jenkinsfile",
|
||||||
SourceType: "single_svn",
|
SourceType: "single_svn",
|
||||||
TimerTrigger: &TimerTrigger{
|
TimerTrigger: &devops.TimerTrigger{
|
||||||
Interval: "12345566",
|
Interval: "12345566",
|
||||||
},
|
},
|
||||||
SingleSvnSource: &SingleSvnSource{
|
SingleSvnSource: &devops.SingleSvnSource{
|
||||||
Remote: "https://api.svn.com/bcd",
|
Remote: "https://api.svn.com/bcd",
|
||||||
CredentialId: "svn",
|
CredentialId: "svn",
|
||||||
},
|
},
|
||||||
@@ -431,17 +419,17 @@ func Test_MultiBranchPipelineConfig_Source(t *testing.T) {
|
|||||||
|
|
||||||
func Test_MultiBranchPipelineCloneConfig(t *testing.T) {
|
func Test_MultiBranchPipelineCloneConfig(t *testing.T) {
|
||||||
|
|
||||||
inputs := []*MultiBranchPipeline{
|
inputs := []*devops.MultiBranchPipeline{
|
||||||
{
|
{
|
||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
ScriptPath: "Jenkinsfile",
|
ScriptPath: "Jenkinsfile",
|
||||||
SourceType: "git",
|
SourceType: "git",
|
||||||
GitSource: &GitSource{
|
GitSource: &devops.GitSource{
|
||||||
Url: "https://github.com/kubesphere/devops",
|
Url: "https://github.com/kubesphere/devops",
|
||||||
CredentialId: "git",
|
CredentialId: "git",
|
||||||
DiscoverBranches: true,
|
DiscoverBranches: true,
|
||||||
CloneOption: &GitCloneOption{
|
CloneOption: &devops.GitCloneOption{
|
||||||
Shallow: false,
|
Shallow: false,
|
||||||
Depth: 3,
|
Depth: 3,
|
||||||
Timeout: 20,
|
Timeout: 20,
|
||||||
@@ -453,18 +441,18 @@ func Test_MultiBranchPipelineCloneConfig(t *testing.T) {
|
|||||||
Description: "for test",
|
Description: "for test",
|
||||||
ScriptPath: "Jenkinsfile",
|
ScriptPath: "Jenkinsfile",
|
||||||
SourceType: "github",
|
SourceType: "github",
|
||||||
GitHubSource: &GithubSource{
|
GitHubSource: &devops.GithubSource{
|
||||||
Owner: "kubesphere",
|
Owner: "kubesphere",
|
||||||
Repo: "devops",
|
Repo: "devops",
|
||||||
CredentialId: "github",
|
CredentialId: "github",
|
||||||
ApiUri: "https://api.github.com",
|
ApiUri: "https://api.github.com",
|
||||||
DiscoverBranches: 1,
|
DiscoverBranches: 1,
|
||||||
DiscoverPRFromOrigin: 2,
|
DiscoverPRFromOrigin: 2,
|
||||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
DiscoverPRFromForks: &devops.DiscoverPRFromForks{
|
||||||
Strategy: 1,
|
Strategy: 1,
|
||||||
Trust: 1,
|
Trust: 1,
|
||||||
},
|
},
|
||||||
CloneOption: &GitCloneOption{
|
CloneOption: &devops.GitCloneOption{
|
||||||
Shallow: false,
|
Shallow: false,
|
||||||
Depth: 3,
|
Depth: 3,
|
||||||
Timeout: 20,
|
Timeout: 20,
|
||||||
@@ -492,13 +480,13 @@ func Test_MultiBranchPipelineCloneConfig(t *testing.T) {
|
|||||||
|
|
||||||
func Test_MultiBranchPipelineRegexFilter(t *testing.T) {
|
func Test_MultiBranchPipelineRegexFilter(t *testing.T) {
|
||||||
|
|
||||||
inputs := []*MultiBranchPipeline{
|
inputs := []*devops.MultiBranchPipeline{
|
||||||
{
|
{
|
||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
ScriptPath: "Jenkinsfile",
|
ScriptPath: "Jenkinsfile",
|
||||||
SourceType: "git",
|
SourceType: "git",
|
||||||
GitSource: &GitSource{
|
GitSource: &devops.GitSource{
|
||||||
Url: "https://github.com/kubesphere/devops",
|
Url: "https://github.com/kubesphere/devops",
|
||||||
CredentialId: "git",
|
CredentialId: "git",
|
||||||
DiscoverBranches: true,
|
DiscoverBranches: true,
|
||||||
@@ -510,14 +498,14 @@ func Test_MultiBranchPipelineRegexFilter(t *testing.T) {
|
|||||||
Description: "for test",
|
Description: "for test",
|
||||||
ScriptPath: "Jenkinsfile",
|
ScriptPath: "Jenkinsfile",
|
||||||
SourceType: "github",
|
SourceType: "github",
|
||||||
GitHubSource: &GithubSource{
|
GitHubSource: &devops.GithubSource{
|
||||||
Owner: "kubesphere",
|
Owner: "kubesphere",
|
||||||
Repo: "devops",
|
Repo: "devops",
|
||||||
CredentialId: "github",
|
CredentialId: "github",
|
||||||
ApiUri: "https://api.github.com",
|
ApiUri: "https://api.github.com",
|
||||||
DiscoverBranches: 1,
|
DiscoverBranches: 1,
|
||||||
DiscoverPRFromOrigin: 2,
|
DiscoverPRFromOrigin: 2,
|
||||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
DiscoverPRFromForks: &devops.DiscoverPRFromForks{
|
||||||
Strategy: 1,
|
Strategy: 1,
|
||||||
Trust: 1,
|
Trust: 1,
|
||||||
},
|
},
|
||||||
@@ -545,26 +533,26 @@ func Test_MultiBranchPipelineRegexFilter(t *testing.T) {
|
|||||||
|
|
||||||
func Test_MultiBranchPipelineMultibranchTrigger(t *testing.T) {
|
func Test_MultiBranchPipelineMultibranchTrigger(t *testing.T) {
|
||||||
|
|
||||||
inputs := []*MultiBranchPipeline{
|
inputs := []*devops.MultiBranchPipeline{
|
||||||
{
|
{
|
||||||
Name: "",
|
Name: "",
|
||||||
Description: "for test",
|
Description: "for test",
|
||||||
ScriptPath: "Jenkinsfile",
|
ScriptPath: "Jenkinsfile",
|
||||||
SourceType: "github",
|
SourceType: "github",
|
||||||
GitHubSource: &GithubSource{
|
GitHubSource: &devops.GithubSource{
|
||||||
Owner: "kubesphere",
|
Owner: "kubesphere",
|
||||||
Repo: "devops",
|
Repo: "devops",
|
||||||
CredentialId: "github",
|
CredentialId: "github",
|
||||||
ApiUri: "https://api.github.com",
|
ApiUri: "https://api.github.com",
|
||||||
DiscoverBranches: 1,
|
DiscoverBranches: 1,
|
||||||
DiscoverPRFromOrigin: 2,
|
DiscoverPRFromOrigin: 2,
|
||||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
DiscoverPRFromForks: &devops.DiscoverPRFromForks{
|
||||||
Strategy: 1,
|
Strategy: 1,
|
||||||
Trust: 1,
|
Trust: 1,
|
||||||
},
|
},
|
||||||
RegexFilter: ".*",
|
RegexFilter: ".*",
|
||||||
},
|
},
|
||||||
MultiBranchJobTrigger: &MultiBranchJobTrigger{
|
MultiBranchJobTrigger: &devops.MultiBranchJobTrigger{
|
||||||
CreateActionJobsToTrigger: "abc",
|
CreateActionJobsToTrigger: "abc",
|
||||||
DeleteActionJobsToTrigger: "ddd",
|
DeleteActionJobsToTrigger: "ddd",
|
||||||
},
|
},
|
||||||
@@ -574,20 +562,20 @@ func Test_MultiBranchPipelineMultibranchTrigger(t *testing.T) {
|
|||||||
Description: "for test",
|
Description: "for test",
|
||||||
ScriptPath: "Jenkinsfile",
|
ScriptPath: "Jenkinsfile",
|
||||||
SourceType: "github",
|
SourceType: "github",
|
||||||
GitHubSource: &GithubSource{
|
GitHubSource: &devops.GithubSource{
|
||||||
Owner: "kubesphere",
|
Owner: "kubesphere",
|
||||||
Repo: "devops",
|
Repo: "devops",
|
||||||
CredentialId: "github",
|
CredentialId: "github",
|
||||||
ApiUri: "https://api.github.com",
|
ApiUri: "https://api.github.com",
|
||||||
DiscoverBranches: 1,
|
DiscoverBranches: 1,
|
||||||
DiscoverPRFromOrigin: 2,
|
DiscoverPRFromOrigin: 2,
|
||||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
DiscoverPRFromForks: &devops.DiscoverPRFromForks{
|
||||||
Strategy: 1,
|
Strategy: 1,
|
||||||
Trust: 1,
|
Trust: 1,
|
||||||
},
|
},
|
||||||
RegexFilter: ".*",
|
RegexFilter: ".*",
|
||||||
},
|
},
|
||||||
MultiBranchJobTrigger: &MultiBranchJobTrigger{
|
MultiBranchJobTrigger: &devops.MultiBranchJobTrigger{
|
||||||
CreateActionJobsToTrigger: "abc",
|
CreateActionJobsToTrigger: "abc",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -596,20 +584,20 @@ func Test_MultiBranchPipelineMultibranchTrigger(t *testing.T) {
|
|||||||
Description: "for test",
|
Description: "for test",
|
||||||
ScriptPath: "Jenkinsfile",
|
ScriptPath: "Jenkinsfile",
|
||||||
SourceType: "github",
|
SourceType: "github",
|
||||||
GitHubSource: &GithubSource{
|
GitHubSource: &devops.GithubSource{
|
||||||
Owner: "kubesphere",
|
Owner: "kubesphere",
|
||||||
Repo: "devops",
|
Repo: "devops",
|
||||||
CredentialId: "github",
|
CredentialId: "github",
|
||||||
ApiUri: "https://api.github.com",
|
ApiUri: "https://api.github.com",
|
||||||
DiscoverBranches: 1,
|
DiscoverBranches: 1,
|
||||||
DiscoverPRFromOrigin: 2,
|
DiscoverPRFromOrigin: 2,
|
||||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
DiscoverPRFromForks: &devops.DiscoverPRFromForks{
|
||||||
Strategy: 1,
|
Strategy: 1,
|
||||||
Trust: 1,
|
Trust: 1,
|
||||||
},
|
},
|
||||||
RegexFilter: ".*",
|
RegexFilter: ".*",
|
||||||
},
|
},
|
||||||
MultiBranchJobTrigger: &MultiBranchJobTrigger{
|
MultiBranchJobTrigger: &devops.MultiBranchJobTrigger{
|
||||||
DeleteActionJobsToTrigger: "ddd",
|
DeleteActionJobsToTrigger: "ddd",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -11,7 +11,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package gojenkins
|
package jenkins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
109
pkg/simple/client/devops/jenkins/project.go
Normal file
109
pkg/simple/client/devops/jenkins/project.go
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package jenkins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/emicklei/go-restful"
|
||||||
|
"k8s.io/klog"
|
||||||
|
"kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
|
"net/http"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DevOpsProjectRoleResponse struct {
|
||||||
|
ProjectRole *ProjectRole
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) CreateDevOpsProject(username string, project *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, error) {
|
||||||
|
_, err := j.CreateFolder(project.ProjectId, project.Description)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
var addRoleCh = make(chan *DevOpsProjectRoleResponse, 8)
|
||||||
|
var addRoleWg sync.WaitGroup
|
||||||
|
for role, permission := range JenkinsProjectPermissionMap {
|
||||||
|
addRoleWg.Add(1)
|
||||||
|
go func(role string, permission ProjectPermissionIds) {
|
||||||
|
_, err := j.AddProjectRole(GetProjectRoleName(project.ProjectId, role),
|
||||||
|
GetProjectRolePattern(project.ProjectId), permission, true)
|
||||||
|
addRoleCh <- &DevOpsProjectRoleResponse{nil, err}
|
||||||
|
addRoleWg.Done()
|
||||||
|
}(role, permission)
|
||||||
|
}
|
||||||
|
for role, permission := range JenkinsPipelinePermissionMap {
|
||||||
|
addRoleWg.Add(1)
|
||||||
|
go func(role string, permission ProjectPermissionIds) {
|
||||||
|
_, err := j.AddProjectRole(GetPipelineRoleName(project.ProjectId, role),
|
||||||
|
GetPipelineRolePattern(project.ProjectId), permission, true)
|
||||||
|
addRoleCh <- &DevOpsProjectRoleResponse{nil, err}
|
||||||
|
addRoleWg.Done()
|
||||||
|
}(role, permission)
|
||||||
|
}
|
||||||
|
addRoleWg.Wait()
|
||||||
|
close(addRoleCh)
|
||||||
|
for addRoleResponse := range addRoleCh {
|
||||||
|
if addRoleResponse.Err != nil {
|
||||||
|
klog.Errorf("%+v", addRoleResponse.Err)
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(addRoleResponse.Err), addRoleResponse.Err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
globalRole, err := j.GetGlobalRole(JenkinsAllUserRoleName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
if globalRole == nil {
|
||||||
|
_, err := j.AddGlobalRole(JenkinsAllUserRoleName, GlobalPermissionIds{
|
||||||
|
GlobalRead: true,
|
||||||
|
}, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = globalRole.AssignRole(username)
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
projectRole, err := j.GetProjectRole(GetProjectRoleName(project.ProjectId, devops.ProjectOwner))
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
err = projectRole.AssignRole(username)
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
pipelineRole, err := j.GetProjectRole(GetPipelineRoleName(project.ProjectId, devops.ProjectOwner))
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
err = pipelineRole.AssignRole(username)
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
return project, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) DeleteDevOpsProject(projectId string) error {
|
||||||
|
_, err := j.DeleteJob(projectId)
|
||||||
|
|
||||||
|
if err != nil && GetJenkinsStatusCode(err) != http.StatusNotFound {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
roleNames := make([]string, 0)
|
||||||
|
for role := range JenkinsProjectPermissionMap {
|
||||||
|
roleNames = append(roleNames, GetProjectRoleName(projectId, role))
|
||||||
|
roleNames = append(roleNames, GetPipelineRoleName(projectId, role))
|
||||||
|
}
|
||||||
|
err = j.DeleteProjectRoles(roleNames...)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
165
pkg/simple/client/devops/jenkins/project_pipeline.go
Normal file
165
pkg/simple/client/devops/jenkins/project_pipeline.go
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
package jenkins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emicklei/go-restful"
|
||||||
|
"k8s.io/klog"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (j *Jenkins) CreateProjectPipeline(projectId string, pipeline *devops.ProjectPipeline) (string, error) {
|
||||||
|
switch pipeline.Type {
|
||||||
|
case devops.NoScmPipelineType:
|
||||||
|
|
||||||
|
config, err := createPipelineConfigXml(pipeline.Pipeline)
|
||||||
|
if err != nil {
|
||||||
|
return "", restful.NewError(http.StatusInternalServerError, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
job, err := j.GetJob(pipeline.Pipeline.Name, projectId)
|
||||||
|
if job != nil {
|
||||||
|
err := fmt.Errorf("job name [%s] has been used", job.GetName())
|
||||||
|
return "", restful.NewError(http.StatusConflict, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil && GetJenkinsStatusCode(err) != http.StatusNotFound {
|
||||||
|
return "", restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = j.CreateJobInFolder(config, pipeline.Pipeline.Name, projectId)
|
||||||
|
if err != nil {
|
||||||
|
return "", restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return pipeline.Pipeline.Name, nil
|
||||||
|
case devops.MultiBranchPipelineType:
|
||||||
|
config, err := createMultiBranchPipelineConfigXml(projectId, pipeline.MultiBranchPipeline)
|
||||||
|
if err != nil {
|
||||||
|
return "", restful.NewError(http.StatusInternalServerError, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
job, err := j.GetJob(pipeline.MultiBranchPipeline.Name, projectId)
|
||||||
|
if job != nil {
|
||||||
|
err := fmt.Errorf("job name [%s] has been used", job.GetName())
|
||||||
|
return "", restful.NewError(http.StatusConflict, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil && GetJenkinsStatusCode(err) != http.StatusNotFound {
|
||||||
|
return "", restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = j.CreateJobInFolder(config, pipeline.MultiBranchPipeline.Name, projectId)
|
||||||
|
if err != nil {
|
||||||
|
return "", restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return pipeline.MultiBranchPipeline.Name, nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
err := fmt.Errorf("error unsupport job type")
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) DeleteProjectPipeline(projectId string, pipelineId string) (string, error) {
|
||||||
|
_, err := j.DeleteJob(pipelineId, projectId)
|
||||||
|
if err != nil {
|
||||||
|
return "", restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
return pipelineId, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
func (j *Jenkins) UpdateProjectPipeline(projectId string, pipeline *devops.ProjectPipeline) (string, error) {
|
||||||
|
switch pipeline.Type {
|
||||||
|
case devops.NoScmPipelineType:
|
||||||
|
|
||||||
|
config, err := createPipelineConfigXml(pipeline.Pipeline)
|
||||||
|
if err != nil {
|
||||||
|
return "", restful.NewError(http.StatusInternalServerError, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
job, err := j.GetJob(pipeline.Pipeline.Name, projectId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = job.UpdateConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
return "", restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return pipeline.Pipeline.Name, nil
|
||||||
|
case devops.MultiBranchPipelineType:
|
||||||
|
|
||||||
|
config, err := createMultiBranchPipelineConfigXml(projectId, pipeline.MultiBranchPipeline)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
|
||||||
|
return "", restful.NewError(http.StatusInternalServerError, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
job, err := j.GetJob(pipeline.MultiBranchPipeline.Name, projectId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err = job.UpdateConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return "", restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return pipeline.MultiBranchPipeline.Name, nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
err := fmt.Errorf("error unsupport job type")
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) GetProjectPipelineConfig(projectId, pipelineId string) (*devops.ProjectPipeline, error) {
|
||||||
|
job, err := j.GetJob(pipelineId, projectId)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
switch job.Raw.Class {
|
||||||
|
case "org.jenkinsci.plugins.workflow.job.WorkflowJob":
|
||||||
|
config, err := job.GetConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
pipeline, err := parsePipelineConfigXml(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
pipeline.Name = pipelineId
|
||||||
|
return &devops.ProjectPipeline{
|
||||||
|
Type: devops.NoScmPipelineType,
|
||||||
|
Pipeline: pipeline,
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
case "org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject":
|
||||||
|
config, err := job.GetConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
pipeline, err := parseMultiBranchPipelineConfigXml(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, restful.NewError(GetJenkinsStatusCode(err), err.Error())
|
||||||
|
}
|
||||||
|
pipeline.Name = pipelineId
|
||||||
|
return &devops.ProjectPipeline{
|
||||||
|
Type: devops.MultiBranchPipelineType,
|
||||||
|
MultiBranchPipeline: pipeline,
|
||||||
|
}, nil
|
||||||
|
default:
|
||||||
|
klog.Errorf("%+v", err)
|
||||||
|
return nil, restful.NewError(http.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
54
pkg/simple/client/devops/jenkins/pure_request.go
Normal file
54
pkg/simple/client/devops/jenkins/pure_request.go
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package jenkins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/klog"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: deprecated, use SendJenkinsRequestWithHeaderResp() instead
|
||||||
|
func (j *Jenkins) SendPureRequest(path string, httpParameters *devops.HttpParameters) ([]byte, error) {
|
||||||
|
resBody, _, err := j.SendPureRequestWithHeaderResp(path, httpParameters)
|
||||||
|
|
||||||
|
return resBody, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *Jenkins) SendPureRequestWithHeaderResp(path string, httpParameters *devops.HttpParameters) ([]byte, http.Header, error) {
|
||||||
|
Url, err := url.Parse(j.Server + path)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &http.Client{Timeout: 30 * time.Second}
|
||||||
|
|
||||||
|
newRequest := &http.Request{
|
||||||
|
Method: httpParameters.Method,
|
||||||
|
URL: Url,
|
||||||
|
Header: httpParameters.Header,
|
||||||
|
Body: httpParameters.Body,
|
||||||
|
Form: httpParameters.Form,
|
||||||
|
PostForm: httpParameters.PostForm,
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.Do(newRequest)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resBody, _ := getRespBody(resp)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode >= http.StatusBadRequest {
|
||||||
|
klog.Errorf("%+v", string(resBody))
|
||||||
|
jkerr := new(JkError)
|
||||||
|
jkerr.Code = resp.StatusCode
|
||||||
|
jkerr.Message = string(resBody)
|
||||||
|
return nil, nil, jkerr
|
||||||
|
}
|
||||||
|
|
||||||
|
return resBody, resp.Header, nil
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
// License for the specific language governing permissions and limitations
|
// License for the specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
package gojenkins
|
package jenkins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package gojenkins
|
package jenkins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
146
pkg/simple/client/devops/jenkins/utils.go
Normal file
146
pkg/simple/client/devops/jenkins/utils.go
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
// Copyright 2015 Vadim Kravcenko
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||||
|
// not use this file except in compliance with the License. You may obtain
|
||||||
|
// a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
// License for the specific language governing permissions and limitations
|
||||||
|
// under the License.
|
||||||
|
|
||||||
|
package jenkins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"compress/gzip"
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/asaskevich/govalidator"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"k8s.io/klog"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
func makeJson(data interface{}) string {
|
||||||
|
str, err := json.Marshal(data)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(json.RawMessage(str))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Reverse(s string) string {
|
||||||
|
size := len(s)
|
||||||
|
buf := make([]byte, size)
|
||||||
|
for start := 0; start < size; {
|
||||||
|
r, n := utf8.DecodeRuneInString(s[start:])
|
||||||
|
start += n
|
||||||
|
utf8.EncodeRune(buf[size-start:], r)
|
||||||
|
}
|
||||||
|
return string(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
type JkError struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
Code int `json:"code"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err *JkError) Error() string {
|
||||||
|
return err.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decompress response.body of JenkinsAPIResponse
|
||||||
|
func getRespBody(resp *http.Response) ([]byte, error) {
|
||||||
|
var reader io.ReadCloser
|
||||||
|
if resp.Header.Get("Content-Encoding") == "gzip" {
|
||||||
|
reader, _ = gzip.NewReader(resp.Body)
|
||||||
|
} else {
|
||||||
|
reader = resp.Body
|
||||||
|
}
|
||||||
|
resBody, err := ioutil.ReadAll(reader)
|
||||||
|
if err != nil {
|
||||||
|
klog.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return resBody, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseJenkinsQuery Parse the special query of jenkins.
|
||||||
|
// ParseQuery in the standard library makes the query not re-encode
|
||||||
|
func parseJenkinsQuery(query string) (url.Values, error) {
|
||||||
|
m := make(url.Values)
|
||||||
|
err := error(nil)
|
||||||
|
for query != "" {
|
||||||
|
key := query
|
||||||
|
if i := strings.IndexAny(key, "&"); i >= 0 {
|
||||||
|
key, query = key[:i], key[i+1:]
|
||||||
|
} else {
|
||||||
|
query = ""
|
||||||
|
}
|
||||||
|
if key == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
value := ""
|
||||||
|
if i := strings.Index(key, "="); i >= 0 {
|
||||||
|
key, value = key[:i], key[i+1:]
|
||||||
|
}
|
||||||
|
key, err1 := url.QueryUnescape(key)
|
||||||
|
if err1 != nil {
|
||||||
|
if err == nil {
|
||||||
|
err = err1
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
value, err1 = url.QueryUnescape(value)
|
||||||
|
if err1 != nil {
|
||||||
|
if err == nil {
|
||||||
|
err = err1
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
m[key] = append(m[key], value)
|
||||||
|
}
|
||||||
|
return m, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type JenkinsBlueTime time.Time
|
||||||
|
|
||||||
|
func (t *JenkinsBlueTime) UnmarshalJSON(b []byte) error {
|
||||||
|
if b == nil || strings.Trim(string(b), "\"") == "null" {
|
||||||
|
*t = JenkinsBlueTime(time.Time{})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
j, err := time.Parse("2006-01-02T15:04:05.000-0700", strings.Trim(string(b), "\""))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*t = JenkinsBlueTime(j)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t JenkinsBlueTime) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(time.Time(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetJenkinsStatusCode(jenkinsErr error) int {
|
||||||
|
if code, err := strconv.Atoi(jenkinsErr.Error()); err == nil {
|
||||||
|
message := http.StatusText(code)
|
||||||
|
if !govalidator.IsNull(message) {
|
||||||
|
return code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if jErr, ok := jenkinsErr.(*ErrorResponse); ok {
|
||||||
|
return jErr.Response.StatusCode
|
||||||
|
}
|
||||||
|
return http.StatusInternalServerError
|
||||||
|
}
|
||||||
48
pkg/simple/client/devops/member.go
Normal file
48
pkg/simple/client/devops/member.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package devops
|
||||||
|
|
||||||
|
type ProjectMembership struct {
|
||||||
|
Username string `json:"username" description:"Member's username,username can uniquely identify a user"`
|
||||||
|
ProjectId string `json:"project_id" db:"project_id" description:"the DevOps Projects which project membership belongs to"`
|
||||||
|
Role string `json:"role" description:"DevOps Project membership's role type. e.g. owner '"`
|
||||||
|
Status string `json:"status" description:"Deprecated, Status of project membership. e.g. active "`
|
||||||
|
GrantBy string `json:"grand_by,omitempty" description:"Username of the user who assigned the role"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProjectMemberOperator interface {
|
||||||
|
AddProjectMember(membership *ProjectMembership) (*ProjectMembership, error)
|
||||||
|
UpdateProjectMember(oldMembership, newMembership *ProjectMembership) (*ProjectMembership, error)
|
||||||
|
DeleteProjectMember(membership *ProjectMembership) (*ProjectMembership, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
var DefaultRoles = []*Role{
|
||||||
|
{
|
||||||
|
Name: ProjectOwner,
|
||||||
|
Description: "Owner have access to do all the operations of a DevOps project and own the highest permissions as well.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: ProjectMaintainer,
|
||||||
|
Description: "Maintainer have access to manage pipeline and credential configuration in a DevOps project.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: ProjectDeveloper,
|
||||||
|
Description: "Developer is able to view and trigger the pipeline.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: ProjectReporter,
|
||||||
|
Description: "Reporter is only allowed to view the status of the pipeline.",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var AllRoleSlice = []string{ProjectDeveloper, ProjectReporter, ProjectMaintainer, ProjectOwner}
|
||||||
|
|
||||||
|
const (
|
||||||
|
ProjectOwner = "owner"
|
||||||
|
ProjectMaintainer = "maintainer"
|
||||||
|
ProjectDeveloper = "developer"
|
||||||
|
ProjectReporter = "reporter"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Role struct {
|
||||||
|
Name string `json:"name" description:"role's name e.g. owner'"`
|
||||||
|
Description string `json:"description" description:"role 's description'"`
|
||||||
|
}
|
||||||
@@ -1,22 +1,16 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright 2019 The KubeSphere Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
*/
|
|
||||||
package devops
|
package devops
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PipelineList struct {
|
||||||
|
Items []Pipeline `json:"items"`
|
||||||
|
Total int `json:"total_count"`
|
||||||
|
}
|
||||||
|
|
||||||
// GetPipeline & SearchPipelines
|
// GetPipeline & SearchPipelines
|
||||||
type Pipeline struct {
|
type Pipeline struct {
|
||||||
Class string `json:"_class,omitempty" description:"It’s a fully qualified name and is an identifier of the producer of this resource's capability." `
|
Class string `json:"_class,omitempty" description:"It’s a fully qualified name and is an identifier of the producer of this resource's capability." `
|
||||||
@@ -85,7 +79,7 @@ type Pipeline struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetPipeBranchRun & SearchPipelineRuns
|
// GetPipeBranchRun & SearchPipelineRuns
|
||||||
type BranchPipelineRun struct {
|
type PipelineRunList struct {
|
||||||
Class string `json:"_class,omitempty" description:"It’s a fully qualified name and is an identifier of the producer of this resource's capability."`
|
Class string `json:"_class,omitempty" description:"It’s a fully qualified name and is an identifier of the producer of this resource's capability."`
|
||||||
Links struct {
|
Links struct {
|
||||||
PrevRun struct {
|
PrevRun struct {
|
||||||
@@ -316,7 +310,7 @@ type OrgRepo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// StopPipeline
|
// StopPipeline
|
||||||
type StopPipe struct {
|
type StopPipeline struct {
|
||||||
Class string `json:"_class,omitempty" description:"It’s a fully qualified name and is an identifier of the producer of this resource's capability."`
|
Class string `json:"_class,omitempty" description:"It’s a fully qualified name and is an identifier of the producer of this resource's capability."`
|
||||||
Links struct {
|
Links struct {
|
||||||
Parent struct {
|
Parent struct {
|
||||||
@@ -390,7 +384,7 @@ type StopPipe struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ReplayPipeline
|
// ReplayPipeline
|
||||||
type ReplayPipe struct {
|
type ReplayPipeline struct {
|
||||||
Class string `json:"_class,omitempty" description:"It’s a fully qualified name and is an identifier of the producer of this resource's capability."`
|
Class string `json:"_class,omitempty" description:"It’s a fully qualified name and is an identifier of the producer of this resource's capability."`
|
||||||
Links struct {
|
Links struct {
|
||||||
Parent struct {
|
Parent struct {
|
||||||
@@ -468,7 +462,7 @@ type Artifacts struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetPipeBranch
|
// GetPipeBranch
|
||||||
type PipeBranch struct {
|
type PipelineBranch struct {
|
||||||
Class string `json:"_class,omitempty" description:"It’s a fully qualified name and is an identifier of the producer of this resource's capability."`
|
Class string `json:"_class,omitempty" description:"It’s a fully qualified name and is an identifier of the producer of this resource's capability."`
|
||||||
Links struct {
|
Links struct {
|
||||||
Self struct {
|
Self struct {
|
||||||
@@ -598,7 +592,7 @@ type RunPayload struct {
|
|||||||
} `json:"parameters,omitempty"`
|
} `json:"parameters,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type QueuedBlueRun struct {
|
type RunPipeline struct {
|
||||||
Class string `json:"_class,omitempty" description:"It’s a fully qualified name and is an identifier of the producer of this resource's capability."`
|
Class string `json:"_class,omitempty" description:"It’s a fully qualified name and is an identifier of the producer of this resource's capability."`
|
||||||
Links struct {
|
Links struct {
|
||||||
Parent struct {
|
Parent struct {
|
||||||
@@ -1108,19 +1102,15 @@ type NodesDetail struct {
|
|||||||
Actions []interface{} `json:"actions,omitempty" description:"the list of all actions"`
|
Actions []interface{} `json:"actions,omitempty" description:"the list of all actions"`
|
||||||
DisplayDescription interface{} `json:"displayDescription,omitempty" description:"display description"`
|
DisplayDescription interface{} `json:"displayDescription,omitempty" description:"display description"`
|
||||||
DisplayName string `json:"displayName,omitempty" description:"display name"`
|
DisplayName string `json:"displayName,omitempty" description:"display name"`
|
||||||
DurationInMillis int `json:"durationInMillis,omitempty" description:"duration time in millis"`
|
DurationInMillis int `json:"durationInMillis,omitempty" description:"duration time in mullis"`
|
||||||
ID string `json:"id,omitempty" description:"id"`
|
ID string `json:"id,omitempty" description:"id"`
|
||||||
Input *Input `json:"input,omitempty" description:"the action should user input"`
|
Input *Input `json:"input,omitempty" description:"the action should user input"`
|
||||||
Result string `json:"result,omitempty" description:"the result of pipeline run. e.g. SUCCESS"`
|
Result string `json:"result,omitempty" description:"the result of pipeline run. e.g. SUCCESS"`
|
||||||
StartTime string `json:"startTime,omitempty" description:"the time of start"`
|
StartTime string `json:"startTime,omitempty" description:"the time of start"`
|
||||||
State string `json:"state,omitempty" description:"run state. e.g. SKIPPED"`
|
State string `json:"state,omitempty" description:"run state. e.g. FINISHED"`
|
||||||
Type string `json:"type,omitempty" description:"type"`
|
Type string `json:"type,omitempty" description:"type"`
|
||||||
CauseOfBlockage interface{} `json:"causeOfBlockage,omitempty" description:"the cause of blockage"`
|
CauseOfBlockage interface{} `json:"causeOfBlockage,omitempty" description:"the cause of blockage"`
|
||||||
Edges []struct {
|
Edges []interface{} `json:"edges,omitempty" description:"edges"`
|
||||||
Class string `json:"_class,omitempty" description:"It’s a fully qualified name and is an identifier of the producer of this resource's capability."`
|
|
||||||
ID string `json:"id,omitempty" description:"id"`
|
|
||||||
Type string `json:"type,omitempty" description:"type"`
|
|
||||||
} `json:"edges,omitempty"`
|
|
||||||
FirstParent interface{} `json:"firstParent,omitempty" description:"first parent"`
|
FirstParent interface{} `json:"firstParent,omitempty" description:"first parent"`
|
||||||
Restartable bool `json:"restartable,omitempty" description:"restartable or not"`
|
Restartable bool `json:"restartable,omitempty" description:"restartable or not"`
|
||||||
Steps []NodeSteps `json:"steps,omitempty" description:"steps"`
|
Steps []NodeSteps `json:"steps,omitempty" description:"steps"`
|
||||||
@@ -1145,3 +1135,65 @@ type Input struct {
|
|||||||
Parameters []interface{} `json:"parameters,omitempty" description:"the parameters of check action"`
|
Parameters []interface{} `json:"parameters,omitempty" description:"the parameters of check action"`
|
||||||
Submitter interface{} `json:"submitter,omitempty" description:"check submitter"`
|
Submitter interface{} `json:"submitter,omitempty" description:"check submitter"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HttpParameters struct {
|
||||||
|
Method string `json:"method,omitempty"`
|
||||||
|
Header http.Header `json:"header,omitempty"`
|
||||||
|
Body io.ReadCloser `json:"body,omitempty"`
|
||||||
|
Form url.Values `json:"form,omitempty"`
|
||||||
|
PostForm url.Values `json:"postForm,omitempty"`
|
||||||
|
Url *url.URL `json:"url,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PipelineOperator interface {
|
||||||
|
|
||||||
|
// Pipelinne operator interface
|
||||||
|
GetPipeline(projectName, pipelineName string, httpParameters *HttpParameters) (*Pipeline, error)
|
||||||
|
ListPipelines(httpParameters *HttpParameters) (*PipelineList, error)
|
||||||
|
GetPipelineRun(projectName, pipelineName, runId string, httpParameters *HttpParameters) (*PipelineRun, error)
|
||||||
|
ListPipelineRuns(projectName, pipelineName string, httpParameters *HttpParameters) (*PipelineRunList, error)
|
||||||
|
StopPipeline(projectName, pipelineName, runId string, httpParameters *HttpParameters) (*StopPipeline, error)
|
||||||
|
ReplayPipeline(projectName, pipelineName, runId string, httpParameters *HttpParameters) (*ReplayPipeline, error)
|
||||||
|
RunPipeline(projectName, pipelineName string, httpParameters *HttpParameters) (*RunPipeline, error)
|
||||||
|
GetArtifacts(projectName, pipelineName, runId string, httpParameters *HttpParameters) ([]Artifacts, error)
|
||||||
|
GetRunLog(projectName, pipelineName, runId string, httpParameters *HttpParameters) ([]byte, error)
|
||||||
|
GetStepLog(projectName, pipelineName, runId, nodeId, stepId string, httpParameters *HttpParameters) ([]byte, http.Header, error)
|
||||||
|
GetNodeSteps(projectName, pipelineName, runId, nodeId string, httpParameters *HttpParameters) ([]NodeSteps, error)
|
||||||
|
GetPipelineRunNodes(projectName, pipelineName, runId string, httpParameters *HttpParameters) ([]PipelineRunNodes, error)
|
||||||
|
SubmitInputStep(projectName, pipelineName, runId, nodeId, stepId string, httpParameters *HttpParameters) ([]byte, error)
|
||||||
|
|
||||||
|
//BranchPipelinne operator interface
|
||||||
|
GetBranchPipeline(projectName, pipelineName, branchName string, httpParameters *HttpParameters) (*BranchPipeline, error)
|
||||||
|
GetBranchPipelineRun(projectName, pipelineName, branchName, runId string, httpParameters *HttpParameters) (*PipelineRun, error)
|
||||||
|
StopBranchPipeline(projectName, pipelineName, branchName, runId string, httpParameters *HttpParameters) (*StopPipeline, error)
|
||||||
|
ReplayBranchPipeline(projectName, pipelineName, branchName, runId string, httpParameters *HttpParameters) (*ReplayPipeline, error)
|
||||||
|
RunBranchPipeline(projectName, pipelineName, branchName string, httpParameters *HttpParameters) (*RunPipeline, error)
|
||||||
|
GetBranchArtifacts(projectName, pipelineName, branchName, runId string, httpParameters *HttpParameters) ([]Artifacts, error)
|
||||||
|
GetBranchRunLog(projectName, pipelineName, branchName, runId string, httpParameters *HttpParameters) ([]byte, error)
|
||||||
|
GetBranchStepLog(projectName, pipelineName, branchName, runId, nodeId, stepId string, httpParameters *HttpParameters) ([]byte, http.Header, error)
|
||||||
|
GetBranchNodeSteps(projectName, pipelineName, branchName, runId, nodeId string, httpParameters *HttpParameters) ([]NodeSteps, error)
|
||||||
|
GetBranchPipelineRunNodes(projectName, pipelineName, branchName, runId string, httpParameters *HttpParameters) ([]BranchPipelineRunNodes, error)
|
||||||
|
SubmitBranchInputStep(projectName, pipelineName, branchName, runId, nodeId, stepId string, httpParameters *HttpParameters) ([]byte, error)
|
||||||
|
GetPipelineBranch(projectName, pipelineName string, httpParameters *HttpParameters) (*PipelineBranch, error)
|
||||||
|
ScanBranch(projectName, pipelineName string, httpParameters *HttpParameters) ([]byte, error)
|
||||||
|
|
||||||
|
// Common pipeline operator interface
|
||||||
|
GetConsoleLog(projectName, pipelineName string, httpParameters *HttpParameters) ([]byte, error)
|
||||||
|
GetCrumb(httpParameters *HttpParameters) (*Crumb, error)
|
||||||
|
|
||||||
|
// SCM operator interface
|
||||||
|
GetSCMServers(scmId string, httpParameters *HttpParameters) ([]SCMServer, error)
|
||||||
|
GetSCMOrg(scmId string, httpParameters *HttpParameters) ([]SCMOrg, error)
|
||||||
|
GetOrgRepo(scmId, organizationId string, httpParameters *HttpParameters) ([]OrgRepo, error)
|
||||||
|
CreateSCMServers(scmId string, httpParameters *HttpParameters) (*SCMServer, error)
|
||||||
|
Validate(scmId string, httpParameters *HttpParameters) (*Validates, error)
|
||||||
|
|
||||||
|
//Webhook operator interface
|
||||||
|
GetNotifyCommit(httpParameters *HttpParameters) ([]byte, error)
|
||||||
|
GithubWebhook(httpParameters *HttpParameters) ([]byte, error)
|
||||||
|
|
||||||
|
CheckScriptCompile(projectName, pipelineName string, httpParameters *HttpParameters) (*CheckScript, error)
|
||||||
|
CheckCron(projectName string, httpParameters *HttpParameters) (*CheckCronRes, error)
|
||||||
|
ToJenkinsfile(httpParameters *HttpParameters) (*ResJenkinsfile, error)
|
||||||
|
ToJson(httpParameters *HttpParameters) (*ResJson, error)
|
||||||
|
}
|
||||||
8
pkg/simple/client/devops/project.go
Normal file
8
pkg/simple/client/devops/project.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package devops
|
||||||
|
|
||||||
|
import "kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
|
||||||
|
|
||||||
|
type ProjectOperator interface {
|
||||||
|
CreateDevOpsProject(username string, project *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, error)
|
||||||
|
DeleteDevOpsProject(projectId string) error
|
||||||
|
}
|
||||||
144
pkg/simple/client/devops/project_pipeline.go
Normal file
144
pkg/simple/client/devops/project_pipeline.go
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
package devops
|
||||||
|
|
||||||
|
const (
|
||||||
|
NoScmPipelineType = "pipeline"
|
||||||
|
MultiBranchPipelineType = "multi-branch-pipeline"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Parameters []*Parameter
|
||||||
|
|
||||||
|
var ParameterTypeMap = map[string]string{
|
||||||
|
"hudson.model.StringParameterDefinition": "string",
|
||||||
|
"hudson.model.ChoiceParameterDefinition": "choice",
|
||||||
|
"hudson.model.TextParameterDefinition": "text",
|
||||||
|
"hudson.model.BooleanParameterDefinition": "boolean",
|
||||||
|
"hudson.model.FileParameterDefinition": "file",
|
||||||
|
"hudson.model.PasswordParameterDefinition": "password",
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProjectPipeline struct {
|
||||||
|
Type string `json:"type" description:"type of devops pipeline, in scm or no scm"`
|
||||||
|
Pipeline *NoScmPipeline `json:"pipeline,omitempty" description:"no scm pipeline structs"`
|
||||||
|
MultiBranchPipeline *MultiBranchPipeline `json:"multi_branch_pipeline,omitempty" description:"in scm pipeline structs"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type NoScmPipeline struct {
|
||||||
|
Name string `json:"name" description:"name of pipeline"`
|
||||||
|
Description string `json:"descriptio,omitempty" description:"description of pipeline"`
|
||||||
|
Discarder *DiscarderProperty `json:"discarder,omitempty" description:"Discarder of pipeline, managing when to drop a pipeline"`
|
||||||
|
Parameters *Parameters `json:"parameters,omitempty" description:"Parameters define of pipeline,user could pass param when run pipeline"`
|
||||||
|
DisableConcurrent bool `json:"disable_concurrent,omitempty" mapstructure:"disable_concurrent" description:"Whether to prohibit the pipeline from running in parallel"`
|
||||||
|
TimerTrigger *TimerTrigger `json:"timer_trigger,omitempty" mapstructure:"timer_trigger" description:"Timer to trigger pipeline run"`
|
||||||
|
RemoteTrigger *RemoteTrigger `json:"remote_trigger,omitempty" mapstructure:"remote_trigger" description:"Remote api define to trigger pipeline run"`
|
||||||
|
Jenkinsfile string `json:"jenkinsfile,omitempty" description:"Jenkinsfile's content'"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MultiBranchPipeline struct {
|
||||||
|
Name string `json:"name" description:"name of pipeline"`
|
||||||
|
Description string `json:"descriptio,omitempty" description:"description of pipeline"`
|
||||||
|
Discarder *DiscarderProperty `json:"discarder,omitempty" description:"Discarder of pipeline, managing when to drop a pipeline"`
|
||||||
|
TimerTrigger *TimerTrigger `json:"timer_trigger,omitempty" mapstructure:"timer_trigger" description:"Timer to trigger pipeline run"`
|
||||||
|
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"`
|
||||||
|
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"`
|
||||||
|
ScriptPath string `json:"script_path" mapstructure:"script_path" description:"script path in scm"`
|
||||||
|
MultiBranchJobTrigger *MultiBranchJobTrigger `json:"multibranch_job_trigger,omitempty" mapstructure:"multibranch_job_trigger" description:"Pipeline tasks that need to be triggered when branch creation/deletion"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GitSource struct {
|
||||||
|
ScmId string `json:"scm_id,omitempty" description:"uid of scm"`
|
||||||
|
Url string `json:"url,omitempty" mapstructure:"url" description:"url of git source"`
|
||||||
|
CredentialId string `json:"credential_id,omitempty" mapstructure:"credential_id" description:"credential id to access git source"`
|
||||||
|
DiscoverBranches bool `json:"discover_branches,omitempty" mapstructure:"discover_branches" description:"Whether to discover a branch"`
|
||||||
|
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 GithubSource struct {
|
||||||
|
ScmId string `json:"scm_id,omitempty" description:"uid of scm"`
|
||||||
|
Owner string `json:"owner,omitempty" mapstructure:"owner" description:"owner of github repo"`
|
||||||
|
Repo string `json:"repo,omitempty" mapstructure:"repo" description:"repo name of github repo"`
|
||||||
|
CredentialId string `json:"credential_id,omitempty" mapstructure:"credential_id" description:"credential id to access github source"`
|
||||||
|
ApiUri string `json:"api_uri,omitempty" mapstructure:"api_uri" description:"The api url can specify the location of the github 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"`
|
||||||
|
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 MultiBranchJobTrigger struct {
|
||||||
|
CreateActionJobsToTrigger string `json:"create_action_job_to_trigger,omitempty" description:"pipeline name to trigger"`
|
||||||
|
DeleteActionJobsToTrigger string `json:"delete_action_job_to_trigger,omitempty" description:"pipeline name to trigger"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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"`
|
||||||
|
Repo string `json:"repo,omitempty" mapstructure:"repo" description:"repo name of github repo"`
|
||||||
|
CredentialId string `json:"credential_id,omitempty" mapstructure:"credential_id" description:"credential id to access github source"`
|
||||||
|
ApiUri string `json:"api_uri,omitempty" mapstructure:"api_uri" description:"The api url can specify the location of the github 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"`
|
||||||
|
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 GitCloneOption struct {
|
||||||
|
Shallow bool `json:"shallow,omitempty" mapstructure:"shallow" description:"Whether to use git shallow clone"`
|
||||||
|
Timeout int `json:"timeout,omitempty" mapstructure:"timeout" description:"git clone timeout mins"`
|
||||||
|
Depth int `json:"depth,omitempty" mapstructure:"depth" description:"git clone depth"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SvnSource struct {
|
||||||
|
ScmId string `json:"scm_id,omitempty" description:"uid of scm"`
|
||||||
|
Remote string `json:"remote,omitempty" description:"remote address url"`
|
||||||
|
CredentialId string `json:"credential_id,omitempty" mapstructure:"credential_id" description:"credential id to access svn source"`
|
||||||
|
Includes string `json:"includes,omitempty" description:"branches to run pipeline"`
|
||||||
|
Excludes string `json:"excludes,omitempty" description:"branches do not run pipeline"`
|
||||||
|
}
|
||||||
|
type SingleSvnSource struct {
|
||||||
|
ScmId string `json:"scm_id,omitempty" description:"uid of scm"`
|
||||||
|
Remote string `json:"remote,omitempty" description:"remote address url"`
|
||||||
|
CredentialId string `json:"credential_id,omitempty" mapstructure:"credential_id" description:"credential id to access svn source"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DiscoverPRFromForks struct {
|
||||||
|
Strategy int `json:"strategy,omitempty" mapstructure:"strategy" description:"github discover strategy"`
|
||||||
|
Trust int `json:"trust,omitempty" mapstructure:"trust" description:"trust user type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DiscarderProperty struct {
|
||||||
|
DaysToKeep string `json:"days_to_keep,omitempty" mapstructure:"days_to_keep" description:"days to keep pipeline"`
|
||||||
|
NumToKeep string `json:"num_to_keep,omitempty" mapstructure:"num_to_keep" description:"nums to keep pipeline"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Parameter struct {
|
||||||
|
Name string `json:"name" description:"name of param"`
|
||||||
|
DefaultValue string `json:"default_value,omitempty" mapstructure:"default_value" description:"default value of param"`
|
||||||
|
Type string `json:"type" description:"type of param"`
|
||||||
|
Description string `json:"description,omitempty" description:"description of pipeline"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TimerTrigger struct {
|
||||||
|
// user in no scm job
|
||||||
|
Cron string `json:"cron,omitempty" description:"jenkins cron script"`
|
||||||
|
|
||||||
|
// use in multi-branch job
|
||||||
|
Interval string `json:"interval,omitempty" description:"interval ms"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RemoteTrigger struct {
|
||||||
|
Token string `json:"token,omitempty" description:"remote trigger token"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProjectPipelineOperator interface {
|
||||||
|
CreateProjectPipeline(projectId string, pipeline *ProjectPipeline) (string, error)
|
||||||
|
DeleteProjectPipeline(projectId string, pipelineId string) (string, error)
|
||||||
|
UpdateProjectPipeline(projectId string, pipeline *ProjectPipeline) (string, error)
|
||||||
|
GetProjectPipelineConfig(projectId, pipelineId string) (*ProjectPipeline, error)
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/cache"
|
"kubesphere.io/kubesphere/pkg/simple/client/cache"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops/jenkins"
|
||||||
esclient "kubesphere.io/kubesphere/pkg/simple/client/elasticsearch"
|
esclient "kubesphere.io/kubesphere/pkg/simple/client/elasticsearch"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/kubesphere"
|
"kubesphere.io/kubesphere/pkg/simple/client/kubesphere"
|
||||||
@@ -22,7 +23,7 @@ type ClientSetOptions struct {
|
|||||||
mySQLOptions *mysql.Options
|
mySQLOptions *mysql.Options
|
||||||
redisOptions *cache.Options
|
redisOptions *cache.Options
|
||||||
kubernetesOptions *k8s.KubernetesOptions
|
kubernetesOptions *k8s.KubernetesOptions
|
||||||
devopsOptions *devops.Options
|
devopsOptions *jenkins.Options
|
||||||
sonarqubeOptions *sonarqube.Options
|
sonarqubeOptions *sonarqube.Options
|
||||||
ldapOptions *ldap.Options
|
ldapOptions *ldap.Options
|
||||||
s3Options *s3.Options
|
s3Options *s3.Options
|
||||||
@@ -38,7 +39,7 @@ func NewClientSetOptions() *ClientSetOptions {
|
|||||||
redisOptions: cache.NewRedisOptions(),
|
redisOptions: cache.NewRedisOptions(),
|
||||||
kubernetesOptions: k8s.NewKubernetesOptions(),
|
kubernetesOptions: k8s.NewKubernetesOptions(),
|
||||||
ldapOptions: ldap.NewLdapOptions(),
|
ldapOptions: ldap.NewLdapOptions(),
|
||||||
devopsOptions: devops.NewDevopsOptions(),
|
devopsOptions: jenkins.NewDevopsOptions(),
|
||||||
sonarqubeOptions: sonarqube.NewSonarQubeOptions(),
|
sonarqubeOptions: sonarqube.NewSonarQubeOptions(),
|
||||||
s3Options: s3.NewS3Options(),
|
s3Options: s3.NewS3Options(),
|
||||||
openPitrixOptions: openpitrix.NewOpenPitrixOptions(),
|
openPitrixOptions: openpitrix.NewOpenPitrixOptions(),
|
||||||
@@ -63,7 +64,7 @@ func (c *ClientSetOptions) SetKubernetesOptions(options *k8s.KubernetesOptions)
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClientSetOptions) SetDevopsOptions(options *devops.Options) *ClientSetOptions {
|
func (c *ClientSetOptions) SetDevopsOptions(options *jenkins.Options) *ClientSetOptions {
|
||||||
c.devopsOptions = options
|
c.devopsOptions = options
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
@@ -114,7 +115,7 @@ type ClientSet struct {
|
|||||||
|
|
||||||
k8sClient k8s.Client
|
k8sClient k8s.Client
|
||||||
ldapClient *ldap.Client
|
ldapClient *ldap.Client
|
||||||
devopsClient *devops.Client
|
devopsClient *jenkins.Client
|
||||||
sonarQubeClient *sonarqube.Client
|
sonarQubeClient *sonarqube.Client
|
||||||
redisClient cache.Interface
|
redisClient cache.Interface
|
||||||
s3Client s3.Interface
|
s3Client s3.Interface
|
||||||
@@ -194,27 +195,28 @@ func (cs *ClientSet) Cache() (cache.Interface, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ClientSet) Devops() (*devops.Client, error) {
|
func (cs *ClientSet) Devops() (devops.Interface, error) {
|
||||||
var err error
|
//var err error
|
||||||
|
//
|
||||||
if cs.csoptions.devopsOptions == nil || cs.csoptions.devopsOptions.Host == "" {
|
//if cs.csoptions.devopsOptions == nil || cs.csoptions.devopsOptions.Host == "" {
|
||||||
return nil, ErrClientSetNotEnabled
|
// return nil, ErrClientSetNotEnabled
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
if cs.devopsClient != nil {
|
//if cs.devopsClient != nil {
|
||||||
return cs.devopsClient, nil
|
// return cs.devopsClient, nil
|
||||||
} else {
|
//} else {
|
||||||
mutex.Lock()
|
// mutex.Lock()
|
||||||
defer mutex.Unlock()
|
// defer mutex.Unlock()
|
||||||
|
//
|
||||||
if cs.devopsClient == nil {
|
// if cs.devopsClient == nil {
|
||||||
cs.devopsClient, err = devops.NewDevopsClient(cs.csoptions.devopsOptions)
|
// cs.devopsClient, err = jenkins.NewDevopsClient(cs.csoptions.devopsOptions)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil, err
|
// return nil, err
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return cs.devopsClient, nil
|
// return cs.devopsClient, nil
|
||||||
}
|
//}
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ClientSet) SonarQube() (*sonarqube.Client, error) {
|
func (cs *ClientSet) SonarQube() (*sonarqube.Client, error) {
|
||||||
|
|||||||
@@ -1,28 +1,21 @@
|
|||||||
package monitoring
|
package monitoring
|
||||||
|
|
||||||
|
|
||||||
type ClusterQuery struct {
|
type ClusterQuery struct {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClusterMetrics struct {
|
type ClusterMetrics struct {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type WorkspaceQuery struct {
|
type WorkspaceQuery struct {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type WorkspaceMetrics struct {
|
type WorkspaceMetrics struct {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type NamespaceQuery struct {
|
type NamespaceQuery struct {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type NamespaceMetrics struct {
|
type NamespaceMetrics struct {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interface defines all the abstract behaviors of monitoring
|
// Interface defines all the abstract behaviors of monitoring
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
client *http.Client
|
client *http.Client
|
||||||
endpoint string
|
endpoint string
|
||||||
|
|||||||
43
pkg/simple/client/s3/fake/fakes3.go
Normal file
43
pkg/simple/client/s3/fake/fakes3.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package fake
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||||
|
"github.com/aws/aws-sdk-go/service/s3"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FakeS3 struct {
|
||||||
|
Storage map[string]*object
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFakeS3() *FakeS3 {
|
||||||
|
return &FakeS3{Storage: map[string]*object{}}
|
||||||
|
}
|
||||||
|
|
||||||
|
type object struct {
|
||||||
|
key string
|
||||||
|
fileName string
|
||||||
|
body io.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *FakeS3) Upload(key, fileName string, body io.Reader) error {
|
||||||
|
s.Storage[key] = &object{
|
||||||
|
key: key,
|
||||||
|
fileName: fileName,
|
||||||
|
body: body,
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *FakeS3) GetDownloadURL(key string, fileName string) (string, error) {
|
||||||
|
if o, ok := s.Storage[key]; ok {
|
||||||
|
return fmt.Sprintf("http://%s/%s", o.key, fileName), nil
|
||||||
|
}
|
||||||
|
return "", awserr.New(s3.ErrCodeNoSuchKey, "no such object", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *FakeS3) Delete(key string) error {
|
||||||
|
delete(s.Storage, key)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
52
pkg/simple/client/s3/fake/fakes3_test.go
Normal file
52
pkg/simple/client/s3/fake/fakes3_test.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package fake
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFakeS3(t *testing.T) {
|
||||||
|
s3 := NewFakeS3()
|
||||||
|
key := "hello"
|
||||||
|
fileName := "world"
|
||||||
|
err := s3.Upload(key, fileName, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
o, ok := s3.storage["hello"]
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("should have hello object")
|
||||||
|
}
|
||||||
|
if o.key != key || o.fileName != fileName {
|
||||||
|
t.Fatalf("key should be %s, fileName should be %s", key, fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
url, err := s3.GetDownloadURL(key, fileName+"1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if url != fmt.Sprintf("http://%s/%s", key, fileName+"1") {
|
||||||
|
t.Fatalf("url should be %s", fmt.Sprintf("http://%s/%s", key, fileName+"1"))
|
||||||
|
}
|
||||||
|
|
||||||
|
url, err = s3.GetDownloadURL(key, fileName+"2")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if url != fmt.Sprintf("http://%s/%s", key, fileName+"2") {
|
||||||
|
t.Fatalf("url should be %s", fmt.Sprintf("http://%s/%s", key, fileName+"2"))
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s3.Delete(key)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
_, ok = s3.storage["hello"]
|
||||||
|
if ok {
|
||||||
|
t.Fatal("should not have hello object")
|
||||||
|
}
|
||||||
|
err = s3.Delete(key)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,15 +2,13 @@ package s3
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
// Upload uploads a object to storage and returns object location if succeeded
|
// Upload uploads a object to storage and returns object location if succeeded
|
||||||
Upload(key string, body io.Reader) (string, error)
|
Upload(key, fileName string, body io.Reader) error
|
||||||
|
|
||||||
// Get retrieves and object's downloadable location if succeeded
|
GetDownloadURL(key string, fileName string) (string, error)
|
||||||
Get(key string, fileName string, expire time.Duration) (string, error)
|
|
||||||
|
|
||||||
// Delete deletes an object by its key
|
// Delete deletes an object by its key
|
||||||
Delete(key string) error
|
Delete(key string) error
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
package s3
|
package s3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"code.cloudfoundry.org/bytefmt"
|
||||||
|
"fmt"
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
"github.com/aws/aws-sdk-go/service/s3"
|
"github.com/aws/aws-sdk-go/service/s3"
|
||||||
|
"github.com/aws/aws-sdk-go/service/s3/s3manager"
|
||||||
"io"
|
"io"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
"time"
|
"time"
|
||||||
@@ -16,16 +19,38 @@ type Client struct {
|
|||||||
bucket string
|
bucket string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Client) Upload(key string, body io.Reader) (string, error) {
|
func (s *Client) Upload(key, fileName string, body io.Reader) error {
|
||||||
panic("implement me")
|
uploader := s3manager.NewUploader(s.s3Session, func(uploader *s3manager.Uploader) {
|
||||||
|
uploader.PartSize = 5 * bytefmt.MEGABYTE
|
||||||
|
uploader.LeavePartsOnError = true
|
||||||
|
})
|
||||||
|
_, err := uploader.Upload(&s3manager.UploadInput{
|
||||||
|
Bucket: aws.String(s.bucket),
|
||||||
|
Key: aws.String(key),
|
||||||
|
Body: body,
|
||||||
|
ContentDisposition: aws.String(fmt.Sprintf("attachment; filename=\"%s\"", fileName)),
|
||||||
|
})
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Client) Get(key string, fileName string, expire time.Duration) (string, error) {
|
func (s *Client) GetDownloadURL(key string, fileName string) (string, error) {
|
||||||
panic("implement me")
|
req, _ := s.s3Client.GetObjectRequest(&s3.GetObjectInput{
|
||||||
|
Bucket: aws.String(s.bucket),
|
||||||
|
Key: aws.String(key),
|
||||||
|
ResponseContentDisposition: aws.String(fmt.Sprintf("attachment; filename=\"%s\"", fileName)),
|
||||||
|
})
|
||||||
|
return req.Presign(5 * time.Minute)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Client) Delete(key string) error {
|
func (s *Client) Delete(key string) error {
|
||||||
panic("implement me")
|
_, err := s.s3Client.DeleteObject(
|
||||||
|
&s3.DeleteObjectInput{Bucket: aws.String(s.bucket),
|
||||||
|
Key: aws.String(key),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewS3Client(options *Options) (Interface, error) {
|
func NewS3Client(options *Options) (Interface, error) {
|
||||||
@@ -55,7 +80,6 @@ func NewS3Client(options *Options) (Interface, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Client) Client() *s3.S3 {
|
func (s *Client) Client() *s3.S3 {
|
||||||
|
|
||||||
return s.s3Client
|
return s.s3Client
|
||||||
}
|
}
|
||||||
func (s *Client) Session() *session.Session {
|
func (s *Client) Session() *session.Session {
|
||||||
|
|||||||
@@ -1,8 +1,68 @@
|
|||||||
package sonarqube
|
package sonarqube
|
||||||
|
|
||||||
type Interface interface {
|
import (
|
||||||
//
|
sonargo "github.com/kubesphere/sonargo/sonar"
|
||||||
GetIssues()
|
"k8s.io/klog"
|
||||||
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
|
)
|
||||||
|
|
||||||
//
|
type SonarInterface interface {
|
||||||
|
GetSonarResultsByTaskIds(taskId ...string) ([]*SonarStatus, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type sonarQube struct {
|
||||||
|
client *sonargo.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
SonarAnalysisActionClass = "hudson.plugins.sonar.action.SonarAnalysisAction"
|
||||||
|
SonarMetricKeys = "alert_status,quality_gate_details,bugs,new_bugs,reliability_rating,new_reliability_rating,vulnerabilities,new_vulnerabilities,security_rating,new_security_rating,code_smells,new_code_smells,sqale_rating,new_maintainability_rating,sqale_index,new_technical_debt,coverage,new_coverage,new_lines_to_cover,tests,duplicated_lines_density,new_duplicated_lines_density,duplicated_blocks,ncloc,ncloc_language_distribution,projects,new_lines"
|
||||||
|
SonarAdditionalFields = "metrics,periods"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SonarStatus struct {
|
||||||
|
Measures *sonargo.MeasuresComponentObject `json:"measures,omitempty"`
|
||||||
|
Issues *sonargo.IssuesSearchObject `json:"issues,omitempty"`
|
||||||
|
GeneralAction *devops.GeneralAction `json:"generalAction,omitempty"`
|
||||||
|
Task *sonargo.CeTaskObject `json:"task,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sonarQube) GetSonarResultsByTaskIds(taskIds ...string) ([]*SonarStatus, error) {
|
||||||
|
sonarStatuses := make([]*SonarStatus, 0)
|
||||||
|
for _, taskId := range taskIds {
|
||||||
|
sonarStatus := &SonarStatus{}
|
||||||
|
taskOptions := &sonargo.CeTaskOption{
|
||||||
|
Id: taskId,
|
||||||
|
}
|
||||||
|
ceTask, _, err := s.client.Ce.Task(taskOptions)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("get sonar task error [%+v]", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
sonarStatus.Task = ceTask
|
||||||
|
measuresComponentOption := &sonargo.MeasuresComponentOption{
|
||||||
|
Component: ceTask.Task.ComponentKey,
|
||||||
|
AdditionalFields: SonarAdditionalFields,
|
||||||
|
MetricKeys: SonarMetricKeys,
|
||||||
|
}
|
||||||
|
measures, _, err := s.client.Measures.Component(measuresComponentOption)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("get sonar task error [%+v]", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
sonarStatus.Measures = measures
|
||||||
|
|
||||||
|
issuesSearchOption := &sonargo.IssuesSearchOption{
|
||||||
|
AdditionalFields: "_all",
|
||||||
|
ComponentKeys: ceTask.Task.ComponentKey,
|
||||||
|
Resolved: "false",
|
||||||
|
Ps: "10",
|
||||||
|
S: "FILE_LINE",
|
||||||
|
Facets: "severities,types",
|
||||||
|
}
|
||||||
|
issuesSearch, _, err := s.client.Issues.Search(issuesSearchOption)
|
||||||
|
sonarStatus.Issues = issuesSearch
|
||||||
|
sonarStatuses = append(sonarStatuses, sonarStatus)
|
||||||
|
}
|
||||||
|
return sonarStatuses, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user