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"
|
||||
"k8s.io/klog"
|
||||
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/openpitrix"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/s3"
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
|
||||
type KubeSphereControllerManagerOptions struct {
|
||||
KubernetesOptions *k8s.KubernetesOptions
|
||||
DevopsOptions *devops.Options
|
||||
DevopsOptions *jenkins.Options
|
||||
S3Options *s3.Options
|
||||
OpenPitrixOptions *openpitrix.Options
|
||||
|
||||
@@ -27,7 +27,7 @@ type KubeSphereControllerManagerOptions struct {
|
||||
func NewKubeSphereControllerManagerOptions() *KubeSphereControllerManagerOptions {
|
||||
s := &KubeSphereControllerManagerOptions{
|
||||
KubernetesOptions: k8s.NewKubernetesOptions(),
|
||||
DevopsOptions: devops.NewDevopsOptions(),
|
||||
DevopsOptions: jenkins.NewDevopsOptions(),
|
||||
S3Options: s3.NewS3Options(),
|
||||
OpenPitrixOptions: openpitrix.NewOpenPitrixOptions(),
|
||||
LeaderElection: &leaderelection.LeaderElectionConfig{
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
cliflag "k8s.io/component-base/cli/flag"
|
||||
"k8s.io/klog"
|
||||
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"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
|
||||
@@ -21,7 +21,7 @@ type ServerRunOptions struct {
|
||||
ConfigFile string
|
||||
GenericServerRunOptions *genericoptions.ServerRunOptions
|
||||
KubernetesOptions *k8s.KubernetesOptions
|
||||
DevopsOptions *devops.Options
|
||||
DevopsOptions *jenkins.Options
|
||||
SonarQubeOptions *sonarqube.Options
|
||||
ServiceMeshOptions *servicemesh.Options
|
||||
MySQLOptions *mysql.Options
|
||||
@@ -36,7 +36,7 @@ func NewServerRunOptions() *ServerRunOptions {
|
||||
s := ServerRunOptions{
|
||||
GenericServerRunOptions: genericoptions.NewServerRunOptions(),
|
||||
KubernetesOptions: k8s.NewKubernetesOptions(),
|
||||
DevopsOptions: devops.NewDevopsOptions(),
|
||||
DevopsOptions: jenkins.NewDevopsOptions(),
|
||||
SonarQubeOptions: sonarqube.NewSonarQubeOptions(),
|
||||
ServiceMeshOptions: servicemesh.NewServiceMeshOptions(),
|
||||
MySQLOptions: mysql.NewMySQLOptions(),
|
||||
|
||||
2
go.mod
2
go.mod
@@ -99,7 +99,7 @@ require (
|
||||
k8s.io/component-base v0.17.0
|
||||
k8s.io/klog v1.0.0
|
||||
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
|
||||
openpitrix.io/iam v0.1.0 // indirect
|
||||
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/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
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/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||
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/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
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/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
||||
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/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/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/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
|
||||
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/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/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/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
|
||||
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/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
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/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
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/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
||||
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/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw=
|
||||
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/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-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/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
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/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/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/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
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/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/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/go.mod h1:4L/zQOBkEf4pArQJ+CMk1/5xjA30B5oyWv+Bzb44DOw=
|
||||
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/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/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/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||
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-tools v0.2.4 h1:la1h46EzElvWefWLqfsXrnsO3lZjpkI0asTpX6h8PLA=
|
||||
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/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/go.mod h1:ToQrwSC3s8Xf/lADdZp3Mktcql9CG0UAmdJG9th5i0w=
|
||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||
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,9 +70,8 @@ type FluentBitList struct {
|
||||
Items []FluentBit `json:"items"`
|
||||
}
|
||||
|
||||
|
||||
type FluentbitOutputsResult struct {
|
||||
Status int `json:"status" description:"response status"`
|
||||
Error string `json:"error,omitempty" description:"debug information"`
|
||||
Status int `json:"status" description:"response status"`
|
||||
Error string `json:"error,omitempty" description:"debug information"`
|
||||
Outputs []OutputPlugin `json:"outputs,omitempty" description:"array of fluent bit output plugins"`
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package devops
|
||||
package v1alpha2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -19,19 +19,19 @@ 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"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||
"kubesphere.io/kubesphere/pkg/utils/reflectutils"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func GetDevOpsProjectMembersHandler(request *restful.Request, resp *restful.Response) {
|
||||
func (h ProjectPipelineHandler) GetDevOpsProjectMembersHandler(request *restful.Request, resp *restful.Response) {
|
||||
|
||||
projectId := request.PathParameter("devops")
|
||||
username := request.HeaderParameter(constants.UserNameHeader)
|
||||
|
||||
err := devops.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
|
||||
err := h.projectOperator.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
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))
|
||||
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 {
|
||||
klog.Errorf("%+v", err)
|
||||
@@ -54,19 +54,19 @@ func GetDevOpsProjectMembersHandler(request *restful.Request, resp *restful.Resp
|
||||
return
|
||||
}
|
||||
|
||||
func GetDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Response) {
|
||||
func (h ProjectPipelineHandler) GetDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Response) {
|
||||
|
||||
projectId := request.PathParameter("devops")
|
||||
username := request.HeaderParameter(constants.UserNameHeader)
|
||||
member := request.PathParameter("member")
|
||||
|
||||
err := devops.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
|
||||
err := h.projectOperator.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||
return
|
||||
}
|
||||
project, err := devops.GetProjectMember(projectId, member)
|
||||
project, err := h.projectMemberOperator.GetProjectMember(projectId, member)
|
||||
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
@@ -78,11 +78,11 @@ func GetDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Respo
|
||||
return
|
||||
}
|
||||
|
||||
func AddDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Response) {
|
||||
func (h ProjectPipelineHandler) AddDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Response) {
|
||||
|
||||
projectId := request.PathParameter("devops")
|
||||
username := request.HeaderParameter(constants.UserNameHeader)
|
||||
member := &devops.DevOpsProjectMembership{}
|
||||
member := &devops.ProjectMembership{}
|
||||
err := request.ReadEntity(&member)
|
||||
if err != nil {
|
||||
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)
|
||||
return
|
||||
}
|
||||
|
||||
err = devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
|
||||
err = h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||
return
|
||||
}
|
||||
project, err := devops.AddProjectMember(projectId, username, member)
|
||||
|
||||
member.GrantBy = username
|
||||
project, err := h.projectMemberOperator.AddProjectMember(projectId, member)
|
||||
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
@@ -121,11 +122,11 @@ func AddDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Respo
|
||||
return
|
||||
}
|
||||
|
||||
func UpdateDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Response) {
|
||||
func (h ProjectPipelineHandler) UpdateDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Response) {
|
||||
|
||||
projectId := request.PathParameter("devops")
|
||||
username := request.HeaderParameter(constants.UserNameHeader)
|
||||
member := &devops.DevOpsProjectMembership{}
|
||||
member := &devops.ProjectMembership{}
|
||||
err := request.ReadEntity(&member)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
@@ -153,13 +154,13 @@ func UpdateDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Re
|
||||
return
|
||||
}
|
||||
|
||||
err = devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
|
||||
err = h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||
return
|
||||
}
|
||||
project, err := devops.UpdateProjectMember(projectId, username, member)
|
||||
project, err := h.projectMemberOperator.UpdateProjectMember(projectId, member)
|
||||
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
@@ -171,19 +172,19 @@ func UpdateDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Re
|
||||
return
|
||||
}
|
||||
|
||||
func DeleteDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Response) {
|
||||
func (h ProjectPipelineHandler) DeleteDevOpsProjectMemberHandler(request *restful.Request, resp *restful.Response) {
|
||||
|
||||
projectId := request.PathParameter("devops")
|
||||
username := request.HeaderParameter(constants.UserNameHeader)
|
||||
member := request.PathParameter("member")
|
||||
|
||||
err := devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
|
||||
err := h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||
return
|
||||
}
|
||||
username, err = devops.DeleteProjectMember(projectId, member)
|
||||
username, err = h.projectMemberOperator.DeleteProjectMember(projectId, member)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
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.
|
||||
*/
|
||||
|
||||
package devops
|
||||
package v1alpha2
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/devops"
|
||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func GetDevOpsProjectHandler(request *restful.Request, resp *restful.Response) {
|
||||
func (h ProjectPipelineHandler) GetDevOpsProjectHandler(request *restful.Request, resp *restful.Response) {
|
||||
|
||||
projectId := request.PathParameter("devops")
|
||||
username := request.HeaderParameter(constants.UserNameHeader)
|
||||
|
||||
err := devops.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
|
||||
err := h.projectOperator.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||
return
|
||||
}
|
||||
project, err := devops.GetProject(projectId)
|
||||
project, err := h.projectOperator.GetProject(projectId)
|
||||
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
@@ -46,7 +46,7 @@ func GetDevOpsProjectHandler(request *restful.Request, resp *restful.Response) {
|
||||
return
|
||||
}
|
||||
|
||||
func UpdateProjectHandler(request *restful.Request, resp *restful.Response) {
|
||||
func (h ProjectPipelineHandler) UpdateProjectHandler(request *restful.Request, resp *restful.Response) {
|
||||
|
||||
projectId := request.PathParameter("devops")
|
||||
username := request.HeaderParameter(constants.UserNameHeader)
|
||||
@@ -58,13 +58,13 @@ func UpdateProjectHandler(request *restful.Request, resp *restful.Response) {
|
||||
return
|
||||
}
|
||||
project.ProjectId = projectId
|
||||
err = devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
|
||||
err = h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||
return
|
||||
}
|
||||
project, err = devops.UpdateProject(project)
|
||||
project, err = h.projectOperator.UpdateProject(project)
|
||||
|
||||
if err != nil {
|
||||
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.
|
||||
*/
|
||||
|
||||
package devops
|
||||
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"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func CreateDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.Response) {
|
||||
func (h ProjectPipelineHandler) CreateDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.Response) {
|
||||
|
||||
projectId := request.PathParameter("devops")
|
||||
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)
|
||||
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 {
|
||||
klog.Errorf("%+v", err)
|
||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||
return
|
||||
}
|
||||
pipelineName, err := devops.CreateProjectPipeline(projectId, pipeline)
|
||||
pipelineName, err := h.projectPipelineOperator.CreateProjectPipeline(projectId, pipeline)
|
||||
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
@@ -53,18 +53,18 @@ func CreateDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.
|
||||
return
|
||||
}
|
||||
|
||||
func DeleteDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.Response) {
|
||||
func (h ProjectPipelineHandler) DeleteDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.Response) {
|
||||
projectId := request.PathParameter("devops")
|
||||
username := request.HeaderParameter(constants.UserNameHeader)
|
||||
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 {
|
||||
klog.Errorf("%+v", err)
|
||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||
return
|
||||
}
|
||||
pipelineName, err := devops.DeleteProjectPipeline(projectId, pipelineId)
|
||||
pipelineName, err := h.projectPipelineOperator.DeleteProjectPipeline(projectId, pipelineId)
|
||||
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
@@ -78,7 +78,7 @@ func DeleteDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.
|
||||
return
|
||||
}
|
||||
|
||||
func UpdateDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.Response) {
|
||||
func (h ProjectPipelineHandler) UpdateDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.Response) {
|
||||
|
||||
projectId := request.PathParameter("devops")
|
||||
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)
|
||||
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 {
|
||||
klog.Errorf("%+v", err)
|
||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||
return
|
||||
}
|
||||
pipelineName, err := devops.UpdateProjectPipeline(projectId, pipelineId, pipeline)
|
||||
pipelineName, err := h.projectPipelineOperator.UpdateProjectPipeline(projectId, pipelineId, pipeline)
|
||||
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
@@ -110,19 +110,19 @@ func UpdateDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.
|
||||
return
|
||||
}
|
||||
|
||||
func GetDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.Response) {
|
||||
func (h ProjectPipelineHandler) GetDevOpsProjectPipelineConfigHandler(request *restful.Request, resp *restful.Response) {
|
||||
|
||||
projectId := request.PathParameter("devops")
|
||||
username := request.HeaderParameter(constants.UserNameHeader)
|
||||
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 {
|
||||
klog.Errorf("%+v", err)
|
||||
errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp)
|
||||
return
|
||||
}
|
||||
pipeline, err := devops.GetProjectPipeline(projectId, pipelineId)
|
||||
pipeline, err := h.projectPipelineOperator.GetProjectPipelineConfig(projectId, pipelineId)
|
||||
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
@@ -133,42 +133,3 @@ func GetDevOpsProjectPipelineHandler(request *restful.Request, resp *restful.Res
|
||||
resp.WriteAsJson(pipeline)
|
||||
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 (
|
||||
"code.cloudfoundry.org/bytefmt"
|
||||
@@ -11,7 +11,11 @@ import (
|
||||
"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")
|
||||
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 {
|
||||
klog.Errorf("%+v", err)
|
||||
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")
|
||||
name := req.PathParameter("s2ibinary")
|
||||
fileName := req.PathParameter("file")
|
||||
url, err := devops.DownloadS2iBinary(ns, name, fileName)
|
||||
url, err := h.s2iUploader.DownloadS2iBinary(ns, name, fileName)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
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/klog"
|
||||
"kubesphere.io/kubesphere/pkg/api"
|
||||
devopsv1alpha2 "kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
|
||||
loggingv1alpha2 "kubesphere.io/kubesphere/pkg/api/logging/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/logging"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
@@ -184,45 +183,6 @@ func (h *tenantHandler) DeleteNamespace(req *restful.Request, resp *restful.Resp
|
||||
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) {
|
||||
projectId := req.PathParameter("devops")
|
||||
workspace := req.PathParameter("workspace")
|
||||
@@ -235,7 +195,7 @@ func (h *tenantHandler) DeleteDevopsProject(req *restful.Request, resp *restful.
|
||||
return
|
||||
}
|
||||
|
||||
err = tenant.DeleteDevOpsProject(projectId, username)
|
||||
err = h.tenant.DeleteDevOpsProject(projectId, username)
|
||||
|
||||
if err != nil {
|
||||
api.HandleInternalError(resp, err)
|
||||
@@ -245,30 +205,6 @@ func (h *tenantHandler) DeleteDevopsProject(req *restful.Request, resp *restful.
|
||||
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) {
|
||||
namespace := req.PathParameter("namespace")
|
||||
username := req.HeaderParameter(constants.UserNameHeader)
|
||||
@@ -283,21 +219,6 @@ func (h *tenantHandler) ListNamespaceRules(req *restful.Request, resp *restful.R
|
||||
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) {
|
||||
operation := req.QueryParameter("operation")
|
||||
req, err := h.regenerateLoggingRequest(req)
|
||||
|
||||
@@ -103,7 +103,7 @@ func AddToContainer(c *restful.Container) error {
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
|
||||
|
||||
ws.Route(ws.GET("/workspaces/{workspace}/devops").
|
||||
To(handler.ListDevopsProjects).
|
||||
To(handler.ListDevOpsProjectsHandler).
|
||||
Param(ws.PathParameter("workspace", "workspace name")).
|
||||
Param(ws.QueryParameter(params.PagingParam, "page").
|
||||
Required(false).
|
||||
@@ -115,7 +115,7 @@ func AddToContainer(c *restful.Container) error {
|
||||
Doc("List devops projects for the current user").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
|
||||
ws.Route(ws.GET("/workspaces/{workspace}/members/{member}/devops").
|
||||
To(handler.ListDevopsProjects).
|
||||
To(handler.ListDevOpsProjectsHandler).
|
||||
Param(ws.PathParameter("workspace", "workspace name")).
|
||||
Param(ws.PathParameter("member", "workspace member's username")).
|
||||
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").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
|
||||
ws.Route(ws.GET("/devopscount").
|
||||
To(handler.GetDevOpsProjectsCount).
|
||||
To(handler.GetDevOpsProjectsCountHandler).
|
||||
Returns(http.StatusOK, api.StatusOK, struct {
|
||||
Count uint32 `json:"count"`
|
||||
}{}).
|
||||
Doc("Get the devops projects count for the member").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
|
||||
ws.Route(ws.POST("/workspaces/{workspace}/devops").
|
||||
To(handler.CreateDevopsProject).
|
||||
To(handler.CreateDevOpsProjectHandler).
|
||||
Param(ws.PathParameter("workspace", "workspace name")).
|
||||
Doc("Create a devops project in the specified workspace").
|
||||
Reads(devopsv1alpha2.DevOpsProject{}).
|
||||
|
||||
@@ -1,43 +1,43 @@
|
||||
package v1alpha2
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/gorilla/websocket"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/models/terminal"
|
||||
"net/http"
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/gorilla/websocket"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/models/terminal"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
// Allow connections from any Origin
|
||||
CheckOrigin: func(r *http.Request) bool { return true },
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
// Allow connections from any Origin
|
||||
CheckOrigin: func(r *http.Request) bool { return true },
|
||||
}
|
||||
|
||||
type terminalHandler struct {
|
||||
terminaler terminal.Interface
|
||||
terminaler terminal.Interface
|
||||
}
|
||||
|
||||
func newTerminalHandler(client kubernetes.Interface, config *rest.Config) *terminalHandler {
|
||||
return &terminalHandler{
|
||||
terminaler: terminal.NewTerminaler(client, config),
|
||||
}
|
||||
return &terminalHandler{
|
||||
terminaler: terminal.NewTerminaler(client, config),
|
||||
}
|
||||
}
|
||||
|
||||
func (t *terminalHandler) handleTerminalSession(request *restful.Request, response *restful.Response) {
|
||||
namespace := request.PathParameter("namespace")
|
||||
podName := request.PathParameter("pod")
|
||||
containerName := request.QueryParameter("container")
|
||||
shell := request.QueryParameter("shell")
|
||||
namespace := request.PathParameter("namespace")
|
||||
podName := request.PathParameter("pod")
|
||||
containerName := request.QueryParameter("container")
|
||||
shell := request.QueryParameter("shell")
|
||||
|
||||
conn, err := upgrader.Upgrade(response.ResponseWriter, request.Request, nil)
|
||||
if err != nil {
|
||||
klog.Warning(err)
|
||||
return
|
||||
}
|
||||
conn, err := upgrader.Upgrade(response.ResponseWriter, request.Request, nil)
|
||||
if err != nil {
|
||||
klog.Warning(err)
|
||||
return
|
||||
}
|
||||
|
||||
t.terminaler.HandleSession(shell, namespace, podName, containerName, conn)
|
||||
}
|
||||
t.terminaler.HandleSession(shell, namespace, podName, containerName, conn)
|
||||
}
|
||||
|
||||
@@ -14,13 +14,7 @@ limitations under the License.
|
||||
package devops
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"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"
|
||||
)
|
||||
|
||||
@@ -67,298 +61,3 @@ const (
|
||||
const (
|
||||
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
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/devops/fake"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_parseCronJobTime(t *testing.T) {
|
||||
type Except struct {
|
||||
Last string
|
||||
Next string
|
||||
const baseUrl = "http://127.0.0.1/kapis/devops.kubesphere.io/v1alpha2/"
|
||||
|
||||
func TestGetNodesDetail(t *testing.T) {
|
||||
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 {
|
||||
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"}},
|
||||
NodeSteps := []devops.NodeSteps{
|
||||
{
|
||||
DisplayName: "Deploy to Kubernetes",
|
||||
ID: "1",
|
||||
Result: "SUCCESS",
|
||||
},
|
||||
}
|
||||
|
||||
for _, item := range Items {
|
||||
last, next, err := parseCronJobTime(item.Input)
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
fakeData["project1-pipeline1-run1"] = PipelineRunNodes
|
||||
fakeData["project1-pipeline1-run1-1"] = NodeSteps
|
||||
fakeData["project1-pipeline1-run1-2"] = NodeSteps
|
||||
fakeData["project1-pipeline1-run1-3"] = NodeSteps
|
||||
|
||||
if last != item.Expected.Last {
|
||||
t.Errorf("got %#v, expected %#v", last, item.Expected.Last)
|
||||
}
|
||||
devopsClient := fake.NewFakeDevops(fakeData)
|
||||
|
||||
if next != item.Expected.Next {
|
||||
t.Errorf("got %#v, expected %#v", next, item.Expected.Next)
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
for _, v := range nodesDetails {
|
||||
if v.Steps[0].ID == "" {
|
||||
t.Fatalf("Can not get any step.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetBranchNodesDetail(t *testing.T) {
|
||||
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
|
||||
|
||||
import "kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||
|
||||
const (
|
||||
DevOpsProjectMembershipTableName = "project_membership"
|
||||
DevOpsProjectMembershipUsernameColumn = "project_membership.username"
|
||||
DevOpsProjectMembershipProjectIdColumn = "project_membership.project_id"
|
||||
DevOpsProjectMembershipRoleColumn = "project_membership.role"
|
||||
ProjectMembershipTableName = "project_membership"
|
||||
ProjectMembershipUsernameColumn = "project_membership.username"
|
||||
ProjectMembershipProjectIdColumn = "project_membership.project_id"
|
||||
ProjectMembershipRoleColumn = "project_membership.role"
|
||||
)
|
||||
|
||||
type DevOpsProjectMembership 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"`
|
||||
}
|
||||
var ProjectMembershipColumns = GetColumnsFromStruct(&devops.ProjectMembership{})
|
||||
|
||||
var DevOpsProjectMembershipColumns = GetColumnsFromStruct(&DevOpsProjectMembership{})
|
||||
|
||||
func NewDevOpsProjectMemberShip(username, projectId, role, grantBy string) *DevOpsProjectMembership {
|
||||
return &DevOpsProjectMembership{
|
||||
func NewDevOpsProjectMemberShip(username, projectId, role, grantBy string) *devops.ProjectMembership {
|
||||
return &devops.ProjectMembership{
|
||||
Username: username,
|
||||
ProjectId: projectId,
|
||||
Role: role,
|
||||
|
||||
@@ -18,59 +18,6 @@ import (
|
||||
"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 (
|
||||
ProjectCredentialTableName = "project_credential"
|
||||
ProjectCredentialIdColumn = "credential_id"
|
||||
@@ -78,13 +25,6 @@ const (
|
||||
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 {
|
||||
ProjectId string `json:"project_id"`
|
||||
CredentialId string `json:"credential_id"`
|
||||
|
||||
@@ -15,389 +15,209 @@ package devops
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
"github.com/asaskevich/govalidator"
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/gocraft/dbr"
|
||||
"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/gojenkins"
|
||||
"kubesphere.io/kubesphere/pkg/gojenkins/utils"
|
||||
cs "kubesphere.io/kubesphere/pkg/simple/client"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func CreateProjectCredential(projectId, username string, credentialRequest *JenkinsCredential) (string, error) {
|
||||
devops, err := cs.ClientSets().Devops()
|
||||
if err != nil {
|
||||
return "", restful.NewError(http.StatusServiceUnavailable, err.Error())
|
||||
type ProjectCredentialOperator interface {
|
||||
CreateProjectCredential(projectId, username string, credentialRequest *devops.Credential) (string, error)
|
||||
UpdateProjectCredential(projectId, credentialId string, credentialRequest *devops.Credential) (string, error)
|
||||
DeleteProjectCredential(projectId, credentialId string) (string, error)
|
||||
GetProjectCredential(projectId, credentialId, getContent string) (*devops.Credential, error)
|
||||
GetProjectCredentials(projectId string) ([]*devops.Credential, error)
|
||||
}
|
||||
|
||||
type projectCredentialOperator struct {
|
||||
devopsClient devops.Interface
|
||||
db *mysql.Database
|
||||
}
|
||||
|
||||
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 {
|
||||
case devops.CredentialTypeUsernamePassword:
|
||||
if credentialRequest.UsernamePasswordCredential == nil {
|
||||
err := fmt.Errorf("usename_password should not be nil")
|
||||
klog.Error(err)
|
||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
case devops.CredentialTypeSsh:
|
||||
if credentialRequest.SshCredential == nil {
|
||||
err := fmt.Errorf("ssh should not be nil")
|
||||
klog.Error(err)
|
||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
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 {
|
||||
klog.Errorf("%+v", err)
|
||||
return "", err
|
||||
}
|
||||
err = o.insertCredentialToDb(projectId, *credentialId, credentialRequest.Domain, username)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return "", err
|
||||
}
|
||||
return *credentialId, nil
|
||||
|
||||
jenkinsClient := devops.Jenkins()
|
||||
}
|
||||
|
||||
err = checkJenkinsCredentialExists(projectId, credentialRequest.Domain, credentialRequest.Id)
|
||||
func (o *projectCredentialOperator) UpdateProjectCredential(projectId, credentialId string, credentialRequest *devops.Credential) (string, error) {
|
||||
|
||||
credential, err := o.devopsClient.GetCredentialInProject(projectId,
|
||||
credentialId, false)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return "", err
|
||||
}
|
||||
switch credential.Type {
|
||||
case devops.CredentialTypeUsernamePassword:
|
||||
if credentialRequest.UsernamePasswordCredential == nil {
|
||||
err := fmt.Errorf("usename_password should not be nil")
|
||||
klog.Error(err)
|
||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
case devops.CredentialTypeSsh:
|
||||
if credentialRequest.SshCredential == nil {
|
||||
err := fmt.Errorf("ssh should not be nil")
|
||||
klog.Error(err)
|
||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
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())
|
||||
}
|
||||
credentialRequest.Id = credentialId
|
||||
_, err = o.devopsClient.UpdateCredentialInProject(projectId, credentialRequest)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
return credentialId, nil
|
||||
|
||||
}
|
||||
|
||||
func (o *projectCredentialOperator) DeleteProjectCredential(projectId, credentialId string) (string, error) {
|
||||
|
||||
_, err := o.devopsClient.GetCredentialInProject(projectId,
|
||||
credentialId, false)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
switch credentialRequest.Type {
|
||||
case CredentialTypeUsernamePassword:
|
||||
if credentialRequest.UsernamePasswordCredential == nil {
|
||||
err := fmt.Errorf("usename_password should not be nil")
|
||||
klog.Error(err)
|
||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
credentialId, err := jenkinsClient.CreateUsernamePasswordCredentialInFolder(credentialRequest.Domain,
|
||||
credentialRequest.Id,
|
||||
credentialRequest.UsernamePasswordCredential.Username,
|
||||
credentialRequest.UsernamePasswordCredential.Password,
|
||||
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 "", err
|
||||
}
|
||||
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 UpdateProjectCredential(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()
|
||||
|
||||
jenkinsCredential, err := jenkinsClient.GetCredentialInFolder(credentialRequest.Domain,
|
||||
credentialId,
|
||||
projectId)
|
||||
id, err := o.devopsClient.DeleteCredentialInProject(projectId, credentialId)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
||||
}
|
||||
credentialType := CredentialTypeMap[jenkinsCredential.TypeName]
|
||||
switch credentialType {
|
||||
case CredentialTypeUsernamePassword:
|
||||
if credentialRequest.UsernamePasswordCredential == nil {
|
||||
err := fmt.Errorf("usename_password should not be nil")
|
||||
klog.Error(err)
|
||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
credentialId, err := jenkinsClient.UpdateUsernamePasswordCredentialInFolder(credentialRequest.Domain,
|
||||
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 {
|
||||
err := fmt.Errorf("ssh should not be nil")
|
||||
klog.Error(err)
|
||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
credentialId, err := jenkinsClient.UpdateSshCredentialInFolder(credentialRequest.Domain,
|
||||
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 {
|
||||
err := fmt.Errorf("secret_text should not be nil")
|
||||
klog.Error(err)
|
||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
credentialId, err := jenkinsClient.UpdateSecretTextCredentialInFolder(credentialRequest.Domain,
|
||||
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 {
|
||||
err := fmt.Errorf("kubeconfig should not be nil")
|
||||
klog.Error(err)
|
||||
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:
|
||||
err := fmt.Errorf("error unsupport credential type")
|
||||
klog.Errorf("%+v", err)
|
||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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 {
|
||||
klog.Errorf("%+v", err)
|
||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
||||
}
|
||||
|
||||
id, err := jenkinsClient.DeleteCredentialInFolder(credentialRequest.Domain, credentialId, projectId)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
||||
return "", err
|
||||
}
|
||||
|
||||
deleteConditions := append(make([]dbr.Builder, 0), db.Eq(ProjectCredentialProjectIdColumn, projectId))
|
||||
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()
|
||||
if err != nil && err != db.ErrNotFound {
|
||||
klog.Errorf("%+v", err)
|
||||
return "", restful.NewError(http.StatusInternalServerError, err.Error())
|
||||
return "", err
|
||||
}
|
||||
return *id, nil
|
||||
|
||||
}
|
||||
|
||||
func GetProjectCredential(projectId, credentialId, domain, getContent string) (*JenkinsCredential, error) {
|
||||
devops, err := cs.ClientSets().Devops()
|
||||
if err != nil {
|
||||
return nil, restful.NewError(http.StatusServiceUnavailable, err.Error())
|
||||
}
|
||||
jenkinsClient := devops.Jenkins()
|
||||
func (o *projectCredentialOperator) GetProjectCredential(projectId, credentialId, getContent string) (*devops.Credential, error) {
|
||||
|
||||
dbClient, err := cs.ClientSets().MySQL()
|
||||
if err != nil {
|
||||
return nil, restful.NewError(http.StatusServiceUnavailable, err.Error())
|
||||
content := false
|
||||
if getContent != "" {
|
||||
content = true
|
||||
}
|
||||
jenkinsResponse, err := jenkinsClient.GetCredentialInFolder(domain,
|
||||
credential, err := o.devopsClient.GetCredentialInProject(projectId,
|
||||
credentialId,
|
||||
projectId)
|
||||
content)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
projectCredential := &ProjectCredential{}
|
||||
err = dbClient.Select(ProjectCredentialColumns...).
|
||||
err = o.db.Select(ProjectCredentialColumns...).
|
||||
From(ProjectCredentialTableName).Where(
|
||||
db.And(db.Eq(ProjectCredentialProjectIdColumn, projectId),
|
||||
db.Eq(ProjectCredentialIdColumn, credentialId),
|
||||
db.Eq(ProjectCredentialDomainColumn, jenkinsResponse.Domain))).LoadOne(projectCredential)
|
||||
db.Eq(ProjectCredentialDomainColumn, credential.Domain))).LoadOne(projectCredential)
|
||||
|
||||
if err != nil && err != db.ErrNotFound {
|
||||
klog.Errorf("%+v", err)
|
||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
response := formatCredentialResponse(jenkinsResponse, 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
|
||||
}
|
||||
}
|
||||
response := formatCredentialResponse(credential, projectCredential)
|
||||
return response, nil
|
||||
|
||||
}
|
||||
|
||||
func GetProjectCredentials(projectId, domain string) ([]*JenkinsCredential, error) {
|
||||
devops, err := cs.ClientSets().Devops()
|
||||
if err != nil {
|
||||
return nil, restful.NewError(http.StatusServiceUnavailable, err.Error())
|
||||
}
|
||||
jenkinsClient := devops.Jenkins()
|
||||
func (o *projectCredentialOperator) GetProjectCredentials(projectId string) ([]*devops.Credential, error) {
|
||||
|
||||
dbClient, err := cs.ClientSets().MySQL()
|
||||
if err != nil {
|
||||
return nil, restful.NewError(http.StatusServiceUnavailable, err.Error())
|
||||
}
|
||||
jenkinsCredentialResponses, err := jenkinsClient.GetCredentialsInFolder(domain, projectId)
|
||||
credentialResponses, err := o.devopsClient.GetCredentialsInProject(projectId)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
||||
return nil, err
|
||||
}
|
||||
selectCondition := db.Eq(ProjectCredentialProjectIdColumn, projectId)
|
||||
if !govalidator.IsNull(domain) {
|
||||
selectCondition = db.And(selectCondition, db.Eq(ProjectCredentialDomainColumn, domain))
|
||||
}
|
||||
projectCredentials := make([]*ProjectCredential, 0)
|
||||
_, err = dbClient.Select(ProjectCredentialColumns...).
|
||||
_, err = o.db.Select(ProjectCredentialColumns...).
|
||||
From(ProjectCredentialTableName).Where(selectCondition).Load(&projectCredentials)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
response := formatCredentialsResponse(jenkinsCredentialResponses, projectCredentials)
|
||||
response := formatCredentialsResponse(credentialResponses, projectCredentials)
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func insertCredentialToDb(projectId, credentialId, domain, username string) error {
|
||||
dbClient, err := cs.ClientSets().MySQL()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (o *projectCredentialOperator) insertCredentialToDb(projectId, credentialId, domain, username string) error {
|
||||
|
||||
projectCredential := NewProjectCredential(projectId, credentialId, domain, username)
|
||||
_, err = dbClient.InsertInto(ProjectCredentialTableName).Columns(ProjectCredentialColumns...).
|
||||
_, err := o.db.InsertInto(ProjectCredentialTableName).Columns(ProjectCredentialColumns...).
|
||||
Record(projectCredential).Exec()
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
@@ -406,41 +226,19 @@ func insertCredentialToDb(projectId, credentialId, domain, username string) erro
|
||||
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(
|
||||
jenkinsCredentialResponse *gojenkins.CredentialResponse,
|
||||
dbCredentialResponse *ProjectCredential) *JenkinsCredential {
|
||||
response := &JenkinsCredential{}
|
||||
response.Id = jenkinsCredentialResponse.Id
|
||||
response.Description = jenkinsCredentialResponse.Description
|
||||
response.DisplayName = jenkinsCredentialResponse.DisplayName
|
||||
if jenkinsCredentialResponse.Fingerprint != nil && jenkinsCredentialResponse.Fingerprint.Hash != "" {
|
||||
credentialResponse *devops.Credential,
|
||||
dbCredentialResponse *ProjectCredential) *devops.Credential {
|
||||
response := &devops.Credential{}
|
||||
response.Id = credentialResponse.Id
|
||||
response.Description = credentialResponse.Description
|
||||
response.DisplayName = credentialResponse.DisplayName
|
||||
if credentialResponse.Fingerprint != nil && credentialResponse.Fingerprint.Hash != "" {
|
||||
response.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"`
|
||||
Name string `json:"name,omitempty" description:"pipeline full name"`
|
||||
Ranges struct {
|
||||
Ranges []*struct {
|
||||
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:"usage,omitempty" description:"all usage of Credential"`
|
||||
}{}
|
||||
response.Fingerprint.FileName = jenkinsCredentialResponse.Fingerprint.FileName
|
||||
response.Fingerprint.Hash = jenkinsCredentialResponse.Fingerprint.Hash
|
||||
for _, usage := range jenkinsCredentialResponse.Fingerprint.Usage {
|
||||
response.Fingerprint.FileName = credentialResponse.Fingerprint.FileName
|
||||
response.Fingerprint.Hash = credentialResponse.Fingerprint.Hash
|
||||
for _, usage := range credentialResponse.Fingerprint.Usage {
|
||||
response.Fingerprint.Usage = append(response.Fingerprint.Usage, usage)
|
||||
}
|
||||
}
|
||||
response.Domain = jenkinsCredentialResponse.Domain
|
||||
response.Domain = credentialResponse.Domain
|
||||
|
||||
if dbCredentialResponse != nil {
|
||||
response.CreateTime = &dbCredentialResponse.CreateTime
|
||||
response.Creator = dbCredentialResponse.Creator
|
||||
}
|
||||
|
||||
credentialType, ok := CredentialTypeMap[jenkinsCredentialResponse.TypeName]
|
||||
credentialType, ok := devops.CredentialTypeMap[credentialResponse.Type]
|
||||
if ok {
|
||||
response.Type = credentialType
|
||||
return response
|
||||
}
|
||||
response.Type = jenkinsCredentialResponse.TypeName
|
||||
response.Type = credentialResponse.Type
|
||||
return response
|
||||
}
|
||||
|
||||
func formatCredentialsResponse(jenkinsCredentialsResponse []*gojenkins.CredentialResponse,
|
||||
projectCredentials []*ProjectCredential) []*JenkinsCredential {
|
||||
responseSlice := make([]*JenkinsCredential, 0)
|
||||
for _, jenkinsCredential := range jenkinsCredentialsResponse {
|
||||
func formatCredentialsResponse(credentialsResponse []*devops.Credential,
|
||||
projectCredentials []*ProjectCredential) []*devops.Credential {
|
||||
responseSlice := make([]*devops.Credential, 0)
|
||||
for _, credential := range credentialsResponse {
|
||||
var dbCredential *ProjectCredential = nil
|
||||
for _, projectCredential := range projectCredentials {
|
||||
if projectCredential.CredentialId == jenkinsCredential.Id &&
|
||||
projectCredential.Domain == jenkinsCredential.Domain {
|
||||
if projectCredential.CredentialId == credential.Id &&
|
||||
projectCredential.Domain == credential.Domain {
|
||||
dbCredential = projectCredential
|
||||
}
|
||||
}
|
||||
responseSlice = append(responseSlice, formatCredentialResponse(jenkinsCredential, dbCredential))
|
||||
responseSlice = append(responseSlice, formatCredentialResponse(credential, dbCredential))
|
||||
}
|
||||
return responseSlice
|
||||
}
|
||||
|
||||
@@ -14,23 +14,37 @@ limitations under the License.
|
||||
package devops
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/asaskevich/govalidator"
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/gocraft/dbr"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
|
||||
"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"
|
||||
)
|
||||
|
||||
func GetProject(projectId string) (*v1alpha2.DevOpsProject, error) {
|
||||
dbconn, err := cs.ClientSets().MySQL()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
type ProjectOperator interface {
|
||||
GetProject(projectId string) (*v1alpha2.DevOpsProject, error)
|
||||
UpdateProject(project *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, error)
|
||||
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{}
|
||||
err = dbconn.Select(DevOpsProjectColumns...).
|
||||
err := o.db.Select(DevOpsProjectColumns...).
|
||||
From(DevOpsProjectTableName).
|
||||
Where(db.Eq(DevOpsProjectIdColumn, projectId)).
|
||||
LoadOne(project)
|
||||
@@ -46,13 +60,9 @@ func GetProject(projectId string) (*v1alpha2.DevOpsProject, error) {
|
||||
return project, nil
|
||||
}
|
||||
|
||||
func UpdateProject(project *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, error) {
|
||||
dbconn, err := cs.ClientSets().MySQL()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func (o *projectOperator) UpdateProject(project *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, error) {
|
||||
|
||||
query := dbconn.Update(DevOpsProjectTableName)
|
||||
query := o.db.Update(DevOpsProjectTableName)
|
||||
if !govalidator.IsNull(project.Description) {
|
||||
query.Set(DevOpsProjectDescriptionColumn, project.Description)
|
||||
}
|
||||
@@ -73,7 +83,7 @@ func UpdateProject(project *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, er
|
||||
}
|
||||
}
|
||||
newProject := &v1alpha2.DevOpsProject{}
|
||||
err = dbconn.Select(DevOpsProjectColumns...).
|
||||
err := o.db.Select(DevOpsProjectColumns...).
|
||||
From(DevOpsProjectTableName).
|
||||
Where(db.Eq(DevOpsProjectIdColumn, project.ProjectId)).
|
||||
LoadOne(newProject)
|
||||
@@ -83,3 +93,22 @@ func UpdateProject(project *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, er
|
||||
}
|
||||
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 (
|
||||
"fmt"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
|
||||
"net/http"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/gocraft/dbr"
|
||||
"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/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) {
|
||||
dbconn, err := cs.ClientSets().MySQL()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
type ProjectMemberOperator interface {
|
||||
GetProjectMembers(projectId string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error)
|
||||
GetProjectMember(projectId, username string) (*devops.ProjectMembership, error)
|
||||
AddProjectMember(projectId string, membership *devops.ProjectMembership) (*devops.ProjectMembership, error)
|
||||
UpdateProjectMember(projectId string, membership *devops.ProjectMembership) (*devops.ProjectMembership, error)
|
||||
DeleteProjectMember(projectId, username string) (string, error)
|
||||
}
|
||||
type projectMemberOperator struct {
|
||||
db *mysql.Database
|
||||
projectMemberOperator devops.ProjectMemberOperator
|
||||
}
|
||||
|
||||
func NewProjectMemberOperator(devopsClient devops.ProjectMemberOperator, dbClient *mysql.Database) ProjectMemberOperator {
|
||||
return &projectMemberOperator{
|
||||
db: dbClient,
|
||||
projectMemberOperator: devopsClient,
|
||||
}
|
||||
memberships := make([]*DevOpsProjectMembership, 0)
|
||||
}
|
||||
|
||||
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
|
||||
sqconditions = append(sqconditions, db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId))
|
||||
sqconditions = append(sqconditions, db.Eq(ProjectMembershipProjectIdColumn, projectId))
|
||||
if keyword := conditions.Match["keyword"]; keyword != "" {
|
||||
sqconditions = append(sqconditions, db.Like(DevOpsProjectMembershipUsernameColumn, keyword))
|
||||
sqconditions = append(sqconditions, db.Like(ProjectMembershipUsernameColumn, keyword))
|
||||
}
|
||||
query := dbconn.Select(DevOpsProjectMembershipColumns...).
|
||||
From(DevOpsProjectMembershipTableName)
|
||||
query := *o.db.Select(ProjectMembershipColumns...).
|
||||
From(ProjectMembershipTableName)
|
||||
switch orderBy {
|
||||
case "name":
|
||||
if reverse {
|
||||
query.OrderDesc(DevOpsProjectMembershipUsernameColumn)
|
||||
query.OrderDesc(ProjectMembershipUsernameColumn)
|
||||
} else {
|
||||
query.OrderAsc(DevOpsProjectMembershipUsernameColumn)
|
||||
query.OrderAsc(ProjectMembershipUsernameColumn)
|
||||
}
|
||||
default:
|
||||
if reverse {
|
||||
query.OrderDesc(DevOpsProjectMembershipRoleColumn)
|
||||
query.OrderDesc(ProjectMembershipRoleColumn)
|
||||
} else {
|
||||
query.OrderAsc(DevOpsProjectMembershipRoleColumn)
|
||||
query.OrderAsc(ProjectMembershipRoleColumn)
|
||||
}
|
||||
}
|
||||
query.Limit(uint64(limit))
|
||||
@@ -61,7 +76,7 @@ func GetProjectMembers(projectId string, conditions *params.Conditions, orderBy
|
||||
} else {
|
||||
query.Where(sqconditions[0])
|
||||
}
|
||||
_, err = query.Load(&memberships)
|
||||
_, err := query.Load(&memberships)
|
||||
if err != nil && err != dbr.ErrNotFound {
|
||||
klog.Errorf("%+v", err)
|
||||
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
|
||||
}
|
||||
|
||||
func GetProjectMember(projectId, username string) (*DevOpsProjectMembership, error) {
|
||||
dbconn, err := cs.ClientSets().MySQL()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func (o *projectMemberOperator) GetProjectMember(projectId, username string) (*devops.ProjectMembership, error) {
|
||||
|
||||
member := &DevOpsProjectMembership{}
|
||||
err = dbconn.Select(DevOpsProjectMembershipColumns...).
|
||||
From(DevOpsProjectMembershipTableName).
|
||||
Where(db.And(db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId),
|
||||
db.Eq(DevOpsProjectMembershipUsernameColumn, username))).
|
||||
member := &devops.ProjectMembership{}
|
||||
err := o.db.Select(ProjectMembershipColumns...).
|
||||
From(ProjectMembershipTableName).
|
||||
Where(db.And(db.Eq(ProjectMembershipProjectIdColumn, projectId),
|
||||
db.Eq(ProjectMembershipUsernameColumn, username))).
|
||||
LoadOne(&member)
|
||||
if err != nil && err != dbr.ErrNotFound {
|
||||
klog.Errorf("%+v", err)
|
||||
@@ -102,31 +113,17 @@ func GetProjectMember(projectId, username string) (*DevOpsProjectMembership, err
|
||||
return member, nil
|
||||
}
|
||||
|
||||
func AddProjectMember(projectId, operator string, member *DevOpsProjectMembership) (*DevOpsProjectMembership, 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())
|
||||
}
|
||||
func (o *projectMemberOperator) AddProjectMember(projectId string, membership *devops.ProjectMembership) (*devops.ProjectMembership, error) {
|
||||
|
||||
membership := &DevOpsProjectMembership{}
|
||||
err = dbconn.Select(DevOpsProjectMembershipColumns...).
|
||||
From(DevOpsProjectMembershipTableName).
|
||||
dbmembership := &devops.ProjectMembership{}
|
||||
err := o.db.Select(ProjectMembershipColumns...).
|
||||
From(ProjectMembershipTableName).
|
||||
Where(db.And(
|
||||
db.Eq(DevOpsProjectMembershipUsernameColumn, member.Username),
|
||||
db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId))).LoadOne(membership)
|
||||
db.Eq(ProjectMembershipUsernameColumn, membership.Username),
|
||||
db.Eq(ProjectMembershipProjectIdColumn, projectId))).LoadOne(dbmembership)
|
||||
// if user could be founded in db, user have been added to project
|
||||
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)
|
||||
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())
|
||||
}
|
||||
|
||||
globalRole, err := jenkinsClient.GetGlobalRole(JenkinsAllUserRoleName)
|
||||
_, err = o.projectMemberOperator.AddProjectMember(membership)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
||||
return nil, err
|
||||
}
|
||||
if globalRole == nil {
|
||||
_, err := jenkinsClient.AddGlobalRole(JenkinsAllUserRoleName, gojenkins.GlobalPermissionIds{
|
||||
GlobalRead: true,
|
||||
}, true)
|
||||
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...).
|
||||
projectMembership := NewDevOpsProjectMemberShip(membership.Username, projectId, membership.Role, membership.GrantBy)
|
||||
_, err = o.db.
|
||||
InsertInto(ProjectMembershipTableName).
|
||||
Columns(ProjectMembershipColumns...).
|
||||
Record(projectMembership).Exec()
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
err = projectRole.UnAssignRole(member.Username)
|
||||
_, err = o.projectMemberOperator.DeleteProjectMember(membership)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
||||
}
|
||||
err = pipelineRole.UnAssignRole(member.Username)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
||||
return nil, err
|
||||
}
|
||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return projectMembership, nil
|
||||
}
|
||||
|
||||
func UpdateProjectMember(projectId, operator string, member *DevOpsProjectMembership) (*DevOpsProjectMembership, 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
|
||||
}
|
||||
func (o *projectMemberOperator) UpdateProjectMember(projectId string, membership *devops.ProjectMembership) (*devops.ProjectMembership, error) {
|
||||
|
||||
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())
|
||||
}
|
||||
|
||||
oldMembership := &DevOpsProjectMembership{}
|
||||
err = dbconn.Select(DevOpsProjectMembershipColumns...).
|
||||
From(DevOpsProjectMembershipTableName).
|
||||
oldMembership := &devops.ProjectMembership{}
|
||||
err := o.db.Select(ProjectMembershipColumns...).
|
||||
From(ProjectMembershipTableName).
|
||||
Where(db.And(
|
||||
db.Eq(DevOpsProjectMembershipUsernameColumn, member.Username),
|
||||
db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId),
|
||||
db.Eq(ProjectMembershipUsernameColumn, membership.Username),
|
||||
db.Eq(ProjectMembershipProjectIdColumn, projectId),
|
||||
)).LoadOne(oldMembership)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
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 {
|
||||
klog.Errorf("%+v", err)
|
||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = oldProjectRole.UnAssignRole(member.Username)
|
||||
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).
|
||||
_, err = o.db.Update(ProjectMembershipTableName).
|
||||
Set(ProjectMembershipRoleColumn, membership.Role).
|
||||
Where(db.And(
|
||||
db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId),
|
||||
db.Eq(DevOpsProjectMembershipUsernameColumn, member.Username),
|
||||
db.Eq(ProjectMembershipProjectIdColumn, projectId),
|
||||
db.Eq(ProjectMembershipUsernameColumn, membership.Username),
|
||||
)).Exec()
|
||||
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
responseMembership := &DevOpsProjectMembership{}
|
||||
err = dbconn.Select(DevOpsProjectMembershipColumns...).
|
||||
From(DevOpsProjectMembershipTableName).
|
||||
responseMembership := &devops.ProjectMembership{}
|
||||
err = o.db.Select(ProjectMembershipColumns...).
|
||||
From(ProjectMembershipTableName).
|
||||
Where(db.And(
|
||||
db.Eq(DevOpsProjectMembershipUsernameColumn, member.Username),
|
||||
db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId),
|
||||
db.Eq(ProjectMembershipUsernameColumn, membership.Username),
|
||||
db.Eq(ProjectMembershipProjectIdColumn, projectId),
|
||||
)).LoadOne(responseMembership)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
@@ -299,25 +200,14 @@ func UpdateProjectMember(projectId, operator string, member *DevOpsProjectMember
|
||||
return responseMembership, nil
|
||||
}
|
||||
|
||||
func DeleteProjectMember(projectId, username string) (string, error) {
|
||||
dbconn, err := cs.ClientSets().MySQL()
|
||||
if err != nil {
|
||||
return "", restful.NewError(http.StatusServiceUnavailable, err.Error())
|
||||
}
|
||||
func (o *projectMemberOperator) DeleteProjectMember(projectId, username string) (string, error) {
|
||||
|
||||
devops, err := cs.ClientSets().Devops()
|
||||
if err != nil {
|
||||
return "", restful.NewError(http.StatusServiceUnavailable, err.Error())
|
||||
}
|
||||
|
||||
jenkinsClient := devops.Jenkins()
|
||||
|
||||
oldMembership := &DevOpsProjectMembership{}
|
||||
err = dbconn.Select(DevOpsProjectMembershipColumns...).
|
||||
From(DevOpsProjectMembershipTableName).
|
||||
oldMembership := &devops.ProjectMembership{}
|
||||
err := o.db.Select(ProjectMembershipColumns...).
|
||||
From(ProjectMembershipTableName).
|
||||
Where(db.And(
|
||||
db.Eq(DevOpsProjectMembershipUsernameColumn, username),
|
||||
db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId),
|
||||
db.Eq(ProjectMembershipUsernameColumn, username),
|
||||
db.Eq(ProjectMembershipProjectIdColumn, projectId),
|
||||
)).LoadOne(oldMembership)
|
||||
if err != nil {
|
||||
if err != db.ErrNotFound {
|
||||
@@ -329,12 +219,12 @@ func DeleteProjectMember(projectId, username string) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if oldMembership.Role == ProjectOwner {
|
||||
count, err := dbconn.Select(DevOpsProjectMembershipProjectIdColumn).
|
||||
From(DevOpsProjectMembershipTableName).
|
||||
if oldMembership.Role == devops.ProjectOwner {
|
||||
count, err := o.db.Select(ProjectMembershipProjectIdColumn).
|
||||
From(ProjectMembershipTableName).
|
||||
Where(db.And(
|
||||
db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId),
|
||||
db.Eq(DevOpsProjectMembershipRoleColumn, ProjectOwner))).Count()
|
||||
db.Eq(ProjectMembershipProjectIdColumn, projectId),
|
||||
db.Eq(ProjectMembershipRoleColumn, devops.ProjectOwner))).Count()
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
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 {
|
||||
klog.Errorf("%+v", err)
|
||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
||||
}
|
||||
err = oldProjectRole.UnAssignRole(username)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
||||
klog.Error(err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
oldPipelineRole, err := jenkinsClient.GetProjectRole(GetPipelineRoleName(projectId, oldMembership.Role))
|
||||
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).
|
||||
_, err = o.db.DeleteFrom(ProjectMembershipTableName).
|
||||
Where(db.And(
|
||||
db.Eq(DevOpsProjectMembershipProjectIdColumn, projectId),
|
||||
db.Eq(DevOpsProjectMembershipUsernameColumn, username),
|
||||
db.Eq(ProjectMembershipProjectIdColumn, projectId),
|
||||
db.Eq(ProjectMembershipUsernameColumn, username),
|
||||
)).Exec()
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
|
||||
@@ -17,295 +17,49 @@ import (
|
||||
"fmt"
|
||||
"github.com/emicklei/go-restful"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/gojenkins/utils"
|
||||
cs "kubesphere.io/kubesphere/pkg/simple/client"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func CreateProjectPipeline(projectId string, pipeline *ProjectPipeline) (string, error) {
|
||||
devops, err := cs.ClientSets().Devops()
|
||||
if err != nil {
|
||||
return "", restful.NewError(http.StatusServiceUnavailable, err.Error())
|
||||
type ProjectPipelineOperator interface {
|
||||
CreateProjectPipeline(projectId string, pipeline *devops.ProjectPipeline) (string, error)
|
||||
DeleteProjectPipeline(projectId string, pipelineId string) (string, error)
|
||||
UpdateProjectPipeline(projectId, pipelineId string, pipeline *devops.ProjectPipeline) (string, error)
|
||||
GetProjectPipelineConfig(projectId, pipelineId string) (*devops.ProjectPipeline, error)
|
||||
}
|
||||
type projectPipelineOperator struct {
|
||||
pipelineOperator devops.ProjectPipelineOperator
|
||||
}
|
||||
|
||||
func NewProjectPipelineOperator(devopsClient devops.ProjectPipelineOperator) ProjectPipelineOperator {
|
||||
return &projectPipelineOperator{
|
||||
pipelineOperator: devopsClient,
|
||||
}
|
||||
jenkinsClient := devops.Jenkins()
|
||||
}
|
||||
|
||||
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 {
|
||||
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(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
|
||||
|
||||
case devops.NoScmPipelineType:
|
||||
pipeline.Pipeline.Name = pipelineId
|
||||
case devops.MultiBranchPipelineType:
|
||||
pipeline.MultiBranchPipeline.Name = pipelineId
|
||||
default:
|
||||
err := fmt.Errorf("error unsupport job type")
|
||||
err := fmt.Errorf("error unsupport pipeline type")
|
||||
klog.Errorf("%+v", err)
|
||||
return "", restful.NewError(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
return o.pipelineOperator.UpdateProjectPipeline(projectId, pipeline)
|
||||
}
|
||||
|
||||
func DeleteProjectPipeline(projectId string, pipelineId string) (string, error) {
|
||||
devops, err := cs.ClientSets().Devops()
|
||||
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
|
||||
func (o *projectPipelineOperator) GetProjectPipelineConfig(projectId, pipelineId string) (*devops.ProjectPipeline, error) {
|
||||
return o.pipelineOperator.GetProjectPipelineConfig(projectId, pipelineId)
|
||||
}
|
||||
|
||||
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 (
|
||||
"code.cloudfoundry.org/bytefmt"
|
||||
"fmt"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
awsS3 "github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/emicklei/go-restful"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/util/retry"
|
||||
@@ -10,7 +12,6 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
"kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/s3"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
@@ -22,9 +23,9 @@ const (
|
||||
)
|
||||
|
||||
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 {
|
||||
@@ -33,6 +34,14 @@ type s2iBinaryUploader struct {
|
||||
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) {
|
||||
binFile, err := fileHeader.Open()
|
||||
if err != nil {
|
||||
@@ -75,58 +84,35 @@ func (s *s2iBinaryUploader) UploadS2iBinary(namespace, name, md5 string, fileHea
|
||||
copy.Spec.FileName = fileHeader.Filename
|
||||
copy.Spec.DownloadURL = fmt.Sprintf(GetS2iBinaryURL, namespace, name, copy.Spec.FileName)
|
||||
|
||||
/*
|
||||
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)
|
||||
err = s.s3Client.Upload(fmt.Sprintf("%s-%s", namespace, name), copy.Spec.FileName, binFile)
|
||||
if err != nil {
|
||||
if aerr, ok := err.(awserr.Error); ok {
|
||||
switch aerr.Code() {
|
||||
case awsS3.ErrCodeNoSuchBucket:
|
||||
klog.Error(err)
|
||||
_, serr := s.SetS2iBinaryStatusWithRetry(copy, origin.Status.Phase)
|
||||
if serr != nil {
|
||||
klog.Error(serr)
|
||||
}
|
||||
return nil, err
|
||||
default:
|
||||
klog.Error(err)
|
||||
_, serr := s.SetS2iBinaryStatusWithRetry(copy, v1alpha1.StatusUploadFailed)
|
||||
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)),
|
||||
})
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if aerr, ok := err.(awserr.Error); ok {
|
||||
switch aerr.Code() {
|
||||
case s3.ErrCodeNoSuchBucket:
|
||||
klog.Error(err)
|
||||
_, serr := SetS2iBinaryStatusWithRetry(copy, origin.Status.Phase)
|
||||
if serr != nil {
|
||||
klog.Error(serr)
|
||||
}
|
||||
return nil, err
|
||||
default:
|
||||
klog.Error(err)
|
||||
_, serr := SetS2iBinaryStatusWithRetry(copy, v1alpha1.StatusUploadFailed)
|
||||
if serr != nil {
|
||||
klog.Error(serr)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
*/
|
||||
if copy.Spec.UploadTimeStamp == nil {
|
||||
copy.Spec.UploadTimeStamp = new(metav1.Time)
|
||||
}
|
||||
*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 {
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
@@ -159,22 +145,7 @@ func (s *s2iBinaryUploader) DownloadS2iBinary(namespace, name, fileName string)
|
||||
klog.Error(err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
/*
|
||||
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
|
||||
|
||||
return s.s3Client.GetDownloadURL(fmt.Sprintf("%s-%s", namespace, name), fileName)
|
||||
}
|
||||
|
||||
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 err 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 {
|
||||
klog.Error(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()
|
||||
|
||||
_, err = devopsDb.DeleteFrom(devops.DevOpsProjectMembershipTableName).
|
||||
_, err = devopsDb.DeleteFrom(devops.ProjectMembershipTableName).
|
||||
Where(db.And(
|
||||
db.Eq(devops.DevOpsProjectMembershipUsernameColumn, username),
|
||||
db.Eq(devops.ProjectMembershipUsernameColumn, username),
|
||||
)).Exec()
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
|
||||
@@ -64,4 +64,4 @@ func objectsToInterfaces(objs []runtime.Object) []interface{} {
|
||||
res = append(res, obj)
|
||||
}
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,75 +1,75 @@
|
||||
package namespace
|
||||
|
||||
import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/api"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/query"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
|
||||
"strings"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/informers"
|
||||
"kubesphere.io/kubesphere/pkg/api"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/query"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type namespaceGetter struct {
|
||||
informers informers.SharedInformerFactory
|
||||
informers informers.SharedInformerFactory
|
||||
}
|
||||
|
||||
func NewNamespaceGetter(informers informers.SharedInformerFactory) v1alpha3.Interface {
|
||||
return &namespaceGetter{informers:informers}
|
||||
return &namespaceGetter{informers: informers}
|
||||
}
|
||||
|
||||
func (n namespaceGetter) Get(_, name string) (runtime.Object, error) {
|
||||
return n.informers.Core().V1().Namespaces().Lister().Get(name)
|
||||
return n.informers.Core().V1().Namespaces().Lister().Get(name)
|
||||
}
|
||||
|
||||
func (n namespaceGetter) List(_ string, query *query.Query) (*api.ListResult, error) {
|
||||
ns, err := n.informers.Core().V1().Namespaces().Lister().List(labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ns, err := n.informers.Core().V1().Namespaces().Lister().List(labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []runtime.Object
|
||||
for _, item := range ns {
|
||||
result = append(result, item)
|
||||
}
|
||||
var result []runtime.Object
|
||||
for _, item := range ns {
|
||||
result = append(result, item)
|
||||
}
|
||||
|
||||
return v1alpha3.DefaultList(result, query, n.compare, n.filter), nil
|
||||
return v1alpha3.DefaultList(result, query, n.compare, n.filter), nil
|
||||
}
|
||||
|
||||
func (n namespaceGetter) filter(item runtime.Object, filter query.Filter) bool {
|
||||
namespace, ok := item.(*v1.Namespace)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
namespace, ok := item.(*v1.Namespace)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
switch filter.Field {
|
||||
case query.FieldName:
|
||||
return query.ComparableString(namespace.Name).Contains(filter.Value)
|
||||
case query.FieldStatus:
|
||||
return query.ComparableString(namespace.Status.Phase).Compare(filter.Value) == 0
|
||||
default:
|
||||
return false
|
||||
}
|
||||
switch filter.Field {
|
||||
case query.FieldName:
|
||||
return query.ComparableString(namespace.Name).Contains(filter.Value)
|
||||
case query.FieldStatus:
|
||||
return query.ComparableString(namespace.Status.Phase).Compare(filter.Value) == 0
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (n namespaceGetter) compare(left runtime.Object, right runtime.Object, field query.Field) bool {
|
||||
leftNs, ok := left.(*v1.Namespace)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
leftNs, ok := left.(*v1.Namespace)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
rightNs, ok := right.(*v1.Namespace)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
rightNs, ok := right.(*v1.Namespace)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
switch field {
|
||||
case query.FieldName:
|
||||
return strings.Compare(leftNs.Name, rightNs.Name) > 0
|
||||
case query.FieldCreationTimeStamp:
|
||||
return leftNs.CreationTimestamp.After(rightNs.CreationTimestamp.Time)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
switch field {
|
||||
case query.FieldName:
|
||||
return strings.Compare(leftNs.Name, rightNs.Name) > 0
|
||||
case query.FieldCreationTimeStamp:
|
||||
return leftNs.CreationTimestamp.After(rightNs.CreationTimestamp.Time)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,35 +24,40 @@ import (
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
|
||||
"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/devops"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam"
|
||||
"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"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type DevOpsProjectRoleResponse struct {
|
||||
ProjectRole *gojenkins.ProjectRole
|
||||
Err error
|
||||
type DevOpsProjectOperator interface {
|
||||
ListDevOpsProjects(workspace, username string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, 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
|
||||
db *mysql.Database
|
||||
dsProject dsClient.ProjectOperator
|
||||
}
|
||||
|
||||
dbconn, err := cs.ClientSets().MySQL()
|
||||
if err != nil {
|
||||
if _, ok := err.(cs.ClientSetNotEnabledError); ok {
|
||||
klog.V(4).Info("devops client is not enable")
|
||||
return nil, err
|
||||
}
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
func newProjectOperator(operator devops.ProjectOperator, db *mysql.Database, client dsClient.ProjectOperator) DevOpsProjectOperator {
|
||||
return &devopsProjectOperator{
|
||||
ksProjectOperator: operator,
|
||||
db: db,
|
||||
dsProject: client,
|
||||
}
|
||||
}
|
||||
|
||||
query := dbconn.Select(devops.GetColumnsFromStructWithPrefix(devops.DevOpsProjectTableName, v1alpha2.DevOpsProject{})...).
|
||||
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)
|
||||
var sqconditions []dbr.Builder
|
||||
|
||||
@@ -61,11 +66,11 @@ func ListDevopsProjects(workspace, username string, conditions *params.Condition
|
||||
switch username {
|
||||
case devops.KS_ADMIN:
|
||||
default:
|
||||
onCondition := fmt.Sprintf("%s = %s", devops.DevOpsProjectMembershipProjectIdColumn, devops.DevOpsProjectIdColumn)
|
||||
query.Join(devops.DevOpsProjectMembershipTableName, onCondition)
|
||||
sqconditions = append(sqconditions, db.Eq(devops.DevOpsProjectMembershipUsernameColumn, username))
|
||||
onCondition := fmt.Sprintf("%s = %s", devops.ProjectMembershipProjectIdColumn, devops.DevOpsProjectIdColumn)
|
||||
query.Join(devops.ProjectMembershipTableName, onCondition)
|
||||
sqconditions = append(sqconditions, db.Eq(devops.ProjectMembershipUsernameColumn, username))
|
||||
sqconditions = append(sqconditions, db.Eq(
|
||||
devops.DevOpsProjectMembershipTableName+"."+devops.StatusColumn, devops.StatusActive))
|
||||
devops.ProjectMembershipTableName+"."+devops.StatusColumn, devops.StatusActive))
|
||||
}
|
||||
|
||||
sqconditions = append(sqconditions, db.Eq(
|
||||
@@ -95,7 +100,7 @@ func ListDevopsProjects(workspace, username string, conditions *params.Condition
|
||||
}
|
||||
query.Limit(uint64(limit))
|
||||
query.Offset(uint64(offset))
|
||||
_, err = query.Load(&projects)
|
||||
_, err := query.Load(&projects)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
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
|
||||
}
|
||||
|
||||
func GetDevOpsProjectsCount(username string) (uint32, error) {
|
||||
dbconn, err := cs.ClientSets().MySQL()
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return 0, err
|
||||
}
|
||||
func (o *devopsProjectOperator) GetDevOpsProjectsCount(username string) (uint32, error) {
|
||||
|
||||
query := dbconn.Select(devops.GetColumnsFromStructWithPrefix(devops.DevOpsProjectTableName, v1alpha2.DevOpsProject{})...).
|
||||
query := o.db.Select(devops.GetColumnsFromStructWithPrefix(devops.DevOpsProjectTableName, v1alpha2.DevOpsProject{})...).
|
||||
From(devops.DevOpsProjectTableName)
|
||||
var sqconditions []dbr.Builder
|
||||
|
||||
if username != devops.KS_ADMIN {
|
||||
onCondition := fmt.Sprintf("%s = %s", devops.DevOpsProjectMembershipProjectIdColumn, devops.DevOpsProjectIdColumn)
|
||||
query.Join(devops.DevOpsProjectMembershipTableName, onCondition)
|
||||
sqconditions = append(sqconditions, db.Eq(devops.DevOpsProjectMembershipUsernameColumn, username))
|
||||
onCondition := fmt.Sprintf("%s = %s", devops.ProjectMembershipProjectIdColumn, devops.DevOpsProjectIdColumn)
|
||||
query.Join(devops.ProjectMembershipTableName, onCondition)
|
||||
sqconditions = append(sqconditions, db.Eq(devops.ProjectMembershipUsernameColumn, username))
|
||||
sqconditions = append(sqconditions, db.Eq(
|
||||
devops.DevOpsProjectMembershipTableName+"."+devops.StatusColumn, devops.StatusActive))
|
||||
devops.ProjectMembershipTableName+"."+devops.StatusColumn, devops.StatusActive))
|
||||
}
|
||||
|
||||
sqconditions = append(sqconditions, db.Eq(
|
||||
@@ -146,171 +146,61 @@ func GetDevOpsProjectsCount(username string) (uint32, error) {
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func DeleteDevOpsProject(projectId, username string) error {
|
||||
err := devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
|
||||
func (o *devopsProjectOperator) DeleteDevOpsProject(projectId, username string) error {
|
||||
err := o.ksProjectOperator.CheckProjectUserInRole(username, projectId, []string{dsClient.ProjectOwner})
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return restful.NewError(http.StatusForbidden, err.Error())
|
||||
}
|
||||
|
||||
dp, err := cs.ClientSets().Devops()
|
||||
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...)
|
||||
err = o.dsProject.DeleteDevOpsProject(projectId)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
||||
return err
|
||||
}
|
||||
_, err = devopsdb.DeleteFrom(devops.DevOpsProjectMembershipTableName).
|
||||
Where(db.Eq(devops.DevOpsProjectMembershipProjectIdColumn, projectId)).Exec()
|
||||
_, err = o.db.DeleteFrom(devops.ProjectMembershipTableName).
|
||||
Where(db.Eq(devops.ProjectMembershipProjectIdColumn, projectId)).Exec()
|
||||
if err != nil {
|
||||
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).
|
||||
Where(db.Eq(devops.DevOpsProjectIdColumn, projectId)).Exec()
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
||||
return err
|
||||
}
|
||||
project := &v1alpha2.DevOpsProject{}
|
||||
err = devopsdb.Select(devops.DevOpsProjectColumns...).
|
||||
err = o.db.Select(devops.DevOpsProjectColumns...).
|
||||
From(devops.DevOpsProjectTableName).
|
||||
Where(db.Eq(devops.DevOpsProjectIdColumn, projectId)).
|
||||
LoadOne(project)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func 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())
|
||||
}
|
||||
func (o *devopsProjectOperator) CreateDevOpsProject(username string, workspace string, req *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, error) {
|
||||
|
||||
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 {
|
||||
klog.Errorf("%+v", err)
|
||||
return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error())
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
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).
|
||||
_, err = o.db.InsertInto(devops.DevOpsProjectTableName).
|
||||
Columns(devops.DevOpsProjectColumns...).Record(project).Exec()
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
|
||||
projectMembership := devops.NewDevOpsProjectMemberShip(username, project.ProjectId, devops.ProjectOwner, username)
|
||||
_, err = devopsdb.InsertInto(devops.DevOpsProjectMembershipTableName).
|
||||
Columns(devops.DevOpsProjectMembershipColumns...).Record(projectMembership).Exec()
|
||||
projectMembership := devops.NewDevOpsProjectMemberShip(username, project.ProjectId, dsClient.ProjectOwner, username)
|
||||
_, err = o.db.InsertInto(devops.ProjectMembershipTableName).
|
||||
Columns(devops.ProjectMembershipColumns...).Record(projectMembership).Exec()
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
|
||||
@@ -318,8 +208,9 @@ func CreateDevopsProject(username string, workspace string, req *v1alpha2.DevOps
|
||||
return project, nil
|
||||
}
|
||||
|
||||
func GetUserDevopsSimpleRules(username, projectId string) ([]iam.SimpleRule, error) {
|
||||
role, err := devops.GetProjectUserRole(username, projectId)
|
||||
func (o *devopsProjectOperator) GetUserDevOpsSimpleRules(username, projectId string) ([]iam.SimpleRule, error) {
|
||||
|
||||
role, err := o.getProjectUserRole(username, projectId)
|
||||
if err != nil {
|
||||
klog.Errorf("%+v", err)
|
||||
return nil, restful.NewError(http.StatusForbidden, err.Error())
|
||||
@@ -327,6 +218,24 @@ func GetUserDevopsSimpleRules(username, projectId string) ([]iam.SimpleRule, err
|
||||
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 {
|
||||
var rules []iam.SimpleRule
|
||||
|
||||
|
||||
@@ -36,11 +36,14 @@ type Interface interface {
|
||||
DescribeWorkspace(username, workspace string) (*v1alpha1.Workspace, 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)
|
||||
GetWorkspace(workspace string) (*v1alpha1.Workspace, error)
|
||||
DevOpsProjectOperator
|
||||
}
|
||||
|
||||
type tenantOperator struct {
|
||||
workspaces WorkspaceInterface
|
||||
namespaces NamespaceInterface
|
||||
DevOpsProjectOperator
|
||||
}
|
||||
|
||||
func (t *tenantOperator) DeleteNamespace(workspace, namespace string) error {
|
||||
@@ -101,7 +104,7 @@ func (t *tenantOperator) appendAnnotations(username string, workspace *v1alpha1.
|
||||
if err == nil {
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
||||
func (t *tenantOperator) GetWorkspace(workspace string) (*v1alpha1.Workspace, error) {
|
||||
return t.workspaces.GetWorkspace(workspace)
|
||||
}
|
||||
|
||||
@@ -145,12 +145,12 @@ type terminaler struct {
|
||||
}
|
||||
|
||||
func NewTerminaler(client kubernetes.Interface, config *rest.Config) Interface {
|
||||
return &terminaler{client:client, config:config}
|
||||
return &terminaler{client: client, config: config}
|
||||
}
|
||||
|
||||
// startProcess is called by handleAttach
|
||||
// Executed cmd in the container specified in request and connects it up with the ptyHandler (a session)
|
||||
func (t *terminaler)startProcess(namespace, podName, containerName string, cmd []string, ptyHandler PtyHandler) error {
|
||||
func (t *terminaler) startProcess(namespace, podName, containerName string, cmd []string, ptyHandler PtyHandler) error {
|
||||
req := t.client.CoreV1().RESTClient().Post().
|
||||
Resource("pods").
|
||||
Name(podName).
|
||||
@@ -194,7 +194,7 @@ func isValidShell(validShells []string, shell string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *terminaler)HandleSession(shell, namespace, podName, containerName string, conn *websocket.Conn) {
|
||||
func (t *terminaler) HandleSession(shell, namespace, podName, containerName string, conn *websocket.Conn) {
|
||||
var err error
|
||||
validShells := []string{"sh", "bash"}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/alerting"
|
||||
"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/k8s"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/kubesphere"
|
||||
@@ -159,7 +159,7 @@ var (
|
||||
|
||||
type Config struct {
|
||||
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"`
|
||||
KubernetesOptions *k8s.KubernetesOptions `json:"kubernetes,omitempty" yaml:"kubernetes,omitempty" mapstructure:"kubernetes"`
|
||||
ServiceMeshOptions *servicemesh.Options `json:"servicemesh,omitempty" yaml:"servicemesh,omitempty" mapstructure:"servicemesh"`
|
||||
@@ -182,7 +182,7 @@ type Config struct {
|
||||
func newConfig() *Config {
|
||||
return &Config{
|
||||
MySQLOptions: mysql.NewMySQLOptions(),
|
||||
DevopsOptions: devops.NewDevopsOptions(),
|
||||
DevopsOptions: jenkins.NewDevopsOptions(),
|
||||
SonarQubeOptions: sonarqube.NewSonarQubeOptions(),
|
||||
KubernetesOptions: k8s.NewKubernetesOptions(),
|
||||
ServiceMeshOptions: servicemesh.NewServiceMeshOptions(),
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"io/ioutil"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/alerting"
|
||||
"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/k8s"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/kubesphere"
|
||||
@@ -34,7 +34,7 @@ func newTestConfig() *Config {
|
||||
MaxOpenConnections: 20,
|
||||
MaxConnectionLifeTime: time.Duration(10) * time.Second,
|
||||
},
|
||||
DevopsOptions: &devops.Options{
|
||||
DevopsOptions: &jenkins.Options{
|
||||
Host: "http://ks-devops.kubesphere-devops-system.svc",
|
||||
Username: "jenkins",
|
||||
Password: "kubesphere",
|
||||
|
||||
@@ -47,3 +47,11 @@ func ParseSvcErr(err error, resp *restful.Response) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
2
pkg/simple/client/cache/cache.go
vendored
2
pkg/simple/client/cache/cache.go
vendored
@@ -20,4 +20,4 @@ type Interface interface {
|
||||
|
||||
// Expires updates object's expiration time, return err if key doesn't exist
|
||||
Expire(key string, duration time.Duration) error
|
||||
}
|
||||
}
|
||||
|
||||
20
pkg/simple/client/cache/simple_cache.go
vendored
20
pkg/simple/client/cache/simple_cache.go
vendored
@@ -3,38 +3,38 @@ package cache
|
||||
import "time"
|
||||
|
||||
type simpleObject struct {
|
||||
value string
|
||||
expire time.Time
|
||||
value string
|
||||
expire time.Time
|
||||
}
|
||||
|
||||
type SimpleCache struct {
|
||||
store map[string]simpleObject
|
||||
store map[string]simpleObject
|
||||
}
|
||||
|
||||
func NewSimpleCache() Interface {
|
||||
return &SimpleCache{store: make(map[string]simpleObject)}
|
||||
return &SimpleCache{store: make(map[string]simpleObject)}
|
||||
}
|
||||
|
||||
func (s *SimpleCache) Keys(pattern string) ([]string, error) {
|
||||
panic("implement me")
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (s *SimpleCache) Set(key string, value string, duration time.Duration) error {
|
||||
panic("implement me")
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (s *SimpleCache) Del(key string) error {
|
||||
panic("implement me")
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (s *SimpleCache) Get(key string) (string, error) {
|
||||
return "", nil
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (s *SimpleCache) Exists(key string) (bool, error) {
|
||||
panic("implement me")
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (s *SimpleCache) Expire(key string, duration time.Duration) error {
|
||||
panic("implement me")
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
type Job struct {
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
GetProjectRole(roleName string)
|
||||
ProjectPipelineOperator
|
||||
}
|
||||
|
||||
@@ -12,14 +12,15 @@
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package gojenkins
|
||||
package jenkins
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"github.com/emicklei/go-restful"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
@@ -31,26 +32,26 @@ const (
|
||||
)
|
||||
|
||||
type Build struct {
|
||||
Raw *BuildResponse
|
||||
Raw *devops.Build
|
||||
Job *Job
|
||||
Jenkins *Jenkins
|
||||
Base string
|
||||
Depth int
|
||||
}
|
||||
|
||||
type parameter struct {
|
||||
type Parameter struct {
|
||||
Name string
|
||||
Value string
|
||||
}
|
||||
|
||||
type branch struct {
|
||||
type Branch struct {
|
||||
SHA1 string `json:",omitempty"`
|
||||
Name string `json:",omitempty"`
|
||||
}
|
||||
|
||||
type BuildRevision struct {
|
||||
SHA1 string `json:"SHA1,omitempty"`
|
||||
Branch []branch `json:"branch,omitempty"`
|
||||
Branch []Branch `json:"Branch,omitempty"`
|
||||
}
|
||||
|
||||
type Builds struct {
|
||||
@@ -66,7 +67,7 @@ type Culprit struct {
|
||||
}
|
||||
|
||||
type GeneralObj struct {
|
||||
Parameters []parameter `json:"parameters,omitempty"`
|
||||
Parameters []Parameter `json:"parameters,omitempty"`
|
||||
Causes []map[string]interface{} `json:"causes,omitempty"`
|
||||
BuildsByBranchName map[string]Builds `json:"buildsByBranchName,omitempty"`
|
||||
LastBuiltRevision *BuildRevision `json:"lastBuiltRevision,omitempty"`
|
||||
@@ -114,7 +115,7 @@ type TestResult struct {
|
||||
}
|
||||
|
||||
type BuildResponse struct {
|
||||
Actions []GeneralObj
|
||||
Actions []devops.GeneralAction
|
||||
Artifacts []struct {
|
||||
DisplayPath string `json:"displayPath"`
|
||||
FileName string `json:"fileName"`
|
||||
@@ -146,22 +147,21 @@ type BuildResponse struct {
|
||||
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"`
|
||||
MavenArtifacts interface{} `json:"mavenArtifacts"`
|
||||
MavenVersionUsed string `json:"mavenVersionUsed"`
|
||||
FingerPrint []FingerPrintResponse
|
||||
Culprits []devops.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"`
|
||||
MavenArtifacts interface{} `json:"mavenArtifacts"`
|
||||
MavenVersionUsed string `json:"mavenVersionUsed"`
|
||||
Runs []struct {
|
||||
Number int64
|
||||
URL string
|
||||
@@ -169,14 +169,10 @@ type BuildResponse struct {
|
||||
}
|
||||
|
||||
// Builds
|
||||
func (b *Build) Info() *BuildResponse {
|
||||
func (b *Build) Info() *devops.Build {
|
||||
return b.Raw
|
||||
}
|
||||
|
||||
func (b *Build) GetActions() []GeneralObj {
|
||||
return b.Raw.Actions
|
||||
}
|
||||
|
||||
func (b *Build) GetUrl() string {
|
||||
return b.Raw.URL
|
||||
}
|
||||
@@ -188,23 +184,6 @@ func (b *Build) GetResult() string {
|
||||
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) {
|
||||
if b.IsRunning() {
|
||||
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")
|
||||
}
|
||||
|
||||
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) {
|
||||
var envVars struct {
|
||||
EnvMap map[string]string `json:"envMap"`
|
||||
@@ -286,31 +256,6 @@ func (b *Build) GetDownstreamBuilds() ([]*Build, error) {
|
||||
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) {
|
||||
causes, err := b.GetCauses()
|
||||
if err != nil {
|
||||
@@ -356,22 +301,6 @@ func (b *Build) GetUpstreamBuild() (*Build, error) {
|
||||
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) {
|
||||
|
||||
url := b.Base + "/testReport"
|
||||
@@ -395,24 +324,6 @@ func (b *Build) GetDuration() int64 {
|
||||
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 {
|
||||
vcs := b.Raw.ChangeSet.Kind
|
||||
if vcs == Git {
|
||||
@@ -456,7 +367,7 @@ func (b *Build) PauseToggle() error {
|
||||
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
|
||||
func (b *Build) Poll(options ...interface{}) (int, error) {
|
||||
depth := "-1"
|
||||
@@ -484,3 +395,20 @@ func (b *Build) Poll(options ...interface{}) (int, error) {
|
||||
}
|
||||
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 (
|
||||
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.
|
||||
*/
|
||||
|
||||
package devops
|
||||
package jenkins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/gojenkins"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@@ -25,13 +24,13 @@ const (
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
jenkinsClient *gojenkins.Jenkins
|
||||
jenkinsClient *Jenkins
|
||||
}
|
||||
|
||||
func NewDevopsClient(options *Options) (*Client, error) {
|
||||
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()
|
||||
if err != nil {
|
||||
klog.Errorf("failed to connecto to jenkins role, %+v", err)
|
||||
@@ -49,7 +48,7 @@ func NewDevopsClient(options *Options) (*Client, error) {
|
||||
return &d, nil
|
||||
}
|
||||
|
||||
func (c *Client) Jenkins() *gojenkins.Jenkins {
|
||||
func (c *Client) Jenkins() *Jenkins {
|
||||
return c.jenkinsClient
|
||||
}
|
||||
|
||||
@@ -71,14 +70,14 @@ func (c *Client) initializeJenkins() error {
|
||||
|
||||
// Jenkins uninitialized, create global role
|
||||
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 {
|
||||
klog.Error(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 {
|
||||
klog.Error(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
|
||||
// under the License.
|
||||
|
||||
package gojenkins
|
||||
package jenkins
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@@ -33,8 +33,6 @@ type FolderResponse struct {
|
||||
Name string `json:"name"`
|
||||
URL string `json:"url"`
|
||||
Jobs []InnerJob `json:"jobs"`
|
||||
PrimaryView *ViewData `json:"primaryView"`
|
||||
Views []ViewData `json:"views"`
|
||||
}
|
||||
|
||||
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
|
||||
// under the License.
|
||||
|
||||
package gojenkins
|
||||
package jenkins
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||
"net/url"
|
||||
"path"
|
||||
"strconv"
|
||||
@@ -60,7 +61,7 @@ type ParameterDefinition struct {
|
||||
|
||||
type JobResponse struct {
|
||||
Class string `json:"_class"`
|
||||
Actions []GeneralObj
|
||||
Actions []devops.GeneralAction
|
||||
Buildable bool `json:"buildable"`
|
||||
Builds []JobBuild
|
||||
Color string `json:"color"`
|
||||
@@ -96,8 +97,6 @@ type JobResponse struct {
|
||||
UpstreamProjects []InnerJob `json:"upstreamProjects"`
|
||||
URL string `json:"url"`
|
||||
Jobs []InnerJob `json:"jobs"`
|
||||
PrimaryView *ViewData `json:"primaryView"`
|
||||
Views []ViewData `json:"views"`
|
||||
}
|
||||
|
||||
func (j *Job) parentBase() string {
|
||||
@@ -123,7 +122,7 @@ func (j *Job) GetDetails() *JobResponse {
|
||||
}
|
||||
|
||||
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()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -153,7 +152,7 @@ func (j *Job) getBuildByType(buildType string) (*Build, error) {
|
||||
Jenkins: j.Jenkins,
|
||||
Depth: 1,
|
||||
Job: j,
|
||||
Raw: new(BuildResponse),
|
||||
Raw: new(devops.Build),
|
||||
Base: j.Base + "/" + number}
|
||||
status, err := build.Poll()
|
||||
if err != nil {
|
||||
@@ -212,10 +211,6 @@ func (j *Job) GetAllBuildStatus() ([]JobBuildStatus, error) {
|
||||
return buildsResp.Builds, nil
|
||||
}
|
||||
|
||||
func (j *Job) GetSubJobsMetadata() []InnerJob {
|
||||
return j.Raw.SubJobs
|
||||
}
|
||||
|
||||
func (j *Job) GetUpstreamJobsMetadata() []InnerJob {
|
||||
return j.Raw.UpstreamProjects
|
||||
}
|
||||
@@ -224,18 +219,6 @@ func (j *Job) GetDownstreamJobsMetadata() []InnerJob {
|
||||
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 {
|
||||
return j.Raw.Jobs
|
||||
}
|
||||
@@ -519,11 +502,3 @@ func (j *Job) Poll() (int, error) {
|
||||
}
|
||||
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 (
|
||||
"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 @@
|
||||
/*
|
||||
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 jenkins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/beevik/etree"
|
||||
"github.com/kubesphere/sonargo/sonar"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/gojenkins"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||
"strconv"
|
||||
"strings"
|
||||
"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 {
|
||||
lines := strings.Split(config, "\n")
|
||||
lines[0] = strings.Replace(lines[0], oldVersion, targetVersion, -1)
|
||||
@@ -181,7 +16,7 @@ func replaceXmlVersion(config, oldVersion, targetVersion string) string {
|
||||
return output
|
||||
}
|
||||
|
||||
func createPipelineConfigXml(pipeline *NoScmPipeline) (string, error) {
|
||||
func createPipelineConfigXml(pipeline *devops.NoScmPipeline) (string, error) {
|
||||
doc := etree.NewDocument()
|
||||
xmlString := `<?xml version='1.0' encoding='UTF-8'?>
|
||||
<flow-definition plugin="workflow-job">
|
||||
@@ -215,7 +50,7 @@ func createPipelineConfigXml(pipeline *NoScmPipeline) (string, error) {
|
||||
strategy.CreateElement("artifactNumToKeep").SetText("-1")
|
||||
}
|
||||
if pipeline.Parameters != nil {
|
||||
pipeline.Parameters.appendToEtree(properties)
|
||||
appendParametersToEtree(properties, pipeline.Parameters)
|
||||
}
|
||||
|
||||
if pipeline.TimerTrigger != nil {
|
||||
@@ -247,8 +82,8 @@ func createPipelineConfigXml(pipeline *NoScmPipeline) (string, error) {
|
||||
return replaceXmlVersion(stringXml, "1.0", "1.1"), err
|
||||
}
|
||||
|
||||
func parsePipelineConfigXml(config string) (*NoScmPipeline, error) {
|
||||
pipeline := &NoScmPipeline{}
|
||||
func parsePipelineConfigXml(config string) (*devops.NoScmPipeline, error) {
|
||||
pipeline := &devops.NoScmPipeline{}
|
||||
config = replaceXmlVersion(config, "1.1", "1.0")
|
||||
doc := etree.NewDocument()
|
||||
err := doc.ReadFromString(config)
|
||||
@@ -271,13 +106,13 @@ func parsePipelineConfigXml(config string) (*NoScmPipeline, error) {
|
||||
strategy := properties.
|
||||
SelectElement("jenkins.model.BuildDiscarderProperty").
|
||||
SelectElement("strategy")
|
||||
pipeline.Discarder = &DiscarderProperty{
|
||||
pipeline.Discarder = &devops.DiscarderProperty{
|
||||
DaysToKeep: strategy.SelectElement("daysToKeep").Text(),
|
||||
NumToKeep: strategy.SelectElement("numToKeep").Text(),
|
||||
}
|
||||
}
|
||||
pipeline.Parameters = &Parameters{}
|
||||
pipeline.Parameters = pipeline.Parameters.fromEtree(properties)
|
||||
pipeline.Parameters = &devops.Parameters{}
|
||||
pipeline.Parameters = getParametersfromEtree(properties)
|
||||
if len(*pipeline.Parameters) == 0 {
|
||||
pipeline.Parameters = nil
|
||||
}
|
||||
@@ -287,13 +122,13 @@ func parsePipelineConfigXml(config string) (*NoScmPipeline, error) {
|
||||
"org.jenkinsci.plugins.workflow.job.properties.PipelineTriggersJobProperty"); triggerProperty != nil {
|
||||
triggers := triggerProperty.SelectElement("triggers")
|
||||
if timerTrigger := triggers.SelectElement("hudson.triggers.TimerTrigger"); timerTrigger != nil {
|
||||
pipeline.TimerTrigger = &TimerTrigger{
|
||||
pipeline.TimerTrigger = &devops.TimerTrigger{
|
||||
Cron: timerTrigger.SelectElement("spec").Text(),
|
||||
}
|
||||
}
|
||||
}
|
||||
if authToken := flow.SelectElement("authToken"); authToken != nil {
|
||||
pipeline.RemoteTrigger = &RemoteTrigger{
|
||||
pipeline.RemoteTrigger = &devops.RemoteTrigger{
|
||||
Token: authToken.Text(),
|
||||
}
|
||||
}
|
||||
@@ -305,11 +140,11 @@ func parsePipelineConfigXml(config string) (*NoScmPipeline, error) {
|
||||
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").
|
||||
CreateElement("parameterDefinitions")
|
||||
for _, parameter := range *s {
|
||||
for className, typeName := range ParameterTypeMap {
|
||||
for _, parameter := range *parameters {
|
||||
for className, typeName := range devops.ParameterTypeMap {
|
||||
if typeName == parameter.Type {
|
||||
paramDefine := parameterDefinitions.CreateElement(className)
|
||||
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 {
|
||||
params := parametersProperty.SelectElement("parameterDefinitions").ChildElements()
|
||||
if *s == nil {
|
||||
*s = make([]*Parameter, 0)
|
||||
}
|
||||
for _, param := range params {
|
||||
switch param.Tag {
|
||||
case "hudson.model.StringParameterDefinition":
|
||||
*s = append(*s, &Parameter{
|
||||
parameters = append(parameters, &devops.Parameter{
|
||||
Name: param.SelectElement("name").Text(),
|
||||
Description: param.SelectElement("description").Text(),
|
||||
DefaultValue: param.SelectElement("defaultValue").Text(),
|
||||
Type: ParameterTypeMap["hudson.model.StringParameterDefinition"],
|
||||
Type: devops.ParameterTypeMap["hudson.model.StringParameterDefinition"],
|
||||
})
|
||||
case "hudson.model.BooleanParameterDefinition":
|
||||
*s = append(*s, &Parameter{
|
||||
parameters = append(parameters, &devops.Parameter{
|
||||
Name: param.SelectElement("name").Text(),
|
||||
Description: param.SelectElement("description").Text(),
|
||||
DefaultValue: param.SelectElement("defaultValue").Text(),
|
||||
Type: ParameterTypeMap["hudson.model.BooleanParameterDefinition"],
|
||||
Type: devops.ParameterTypeMap["hudson.model.BooleanParameterDefinition"],
|
||||
})
|
||||
case "hudson.model.TextParameterDefinition":
|
||||
*s = append(*s, &Parameter{
|
||||
parameters = append(parameters, &devops.Parameter{
|
||||
Name: param.SelectElement("name").Text(),
|
||||
Description: param.SelectElement("description").Text(),
|
||||
DefaultValue: param.SelectElement("defaultValue").Text(),
|
||||
Type: ParameterTypeMap["hudson.model.TextParameterDefinition"],
|
||||
Type: devops.ParameterTypeMap["hudson.model.TextParameterDefinition"],
|
||||
})
|
||||
case "hudson.model.FileParameterDefinition":
|
||||
*s = append(*s, &Parameter{
|
||||
parameters = append(parameters, &devops.Parameter{
|
||||
Name: param.SelectElement("name").Text(),
|
||||
Description: param.SelectElement("description").Text(),
|
||||
Type: ParameterTypeMap["hudson.model.FileParameterDefinition"],
|
||||
Type: devops.ParameterTypeMap["hudson.model.FileParameterDefinition"],
|
||||
})
|
||||
case "hudson.model.PasswordParameterDefinition":
|
||||
*s = append(*s, &Parameter{
|
||||
parameters = append(parameters, &devops.Parameter{
|
||||
Name: param.SelectElement("name").Text(),
|
||||
Description: param.SelectElement("description").Text(),
|
||||
DefaultValue: param.SelectElement("name").Text(),
|
||||
Type: ParameterTypeMap["hudson.model.PasswordParameterDefinition"],
|
||||
Type: devops.ParameterTypeMap["hudson.model.PasswordParameterDefinition"],
|
||||
})
|
||||
case "hudson.model.ChoiceParameterDefinition":
|
||||
choiceParameter := &Parameter{
|
||||
choiceParameter := &devops.Parameter{
|
||||
Name: param.SelectElement("name").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")
|
||||
for _, choice := range choices {
|
||||
choiceParameter.DefaultValue += fmt.Sprintf("%s\n", choice.Text())
|
||||
}
|
||||
choiceParameter.DefaultValue = strings.TrimSpace(choiceParameter.DefaultValue)
|
||||
*s = append(*s, choiceParameter)
|
||||
parameters = append(parameters, choiceParameter)
|
||||
default:
|
||||
*s = append(*s, &Parameter{
|
||||
parameters = append(parameters, &devops.Parameter{
|
||||
Name: param.SelectElement("name").Text(),
|
||||
Description: param.SelectElement("description").Text(),
|
||||
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("plugin", "git")
|
||||
source.CreateElement("id").SetText(s.ScmId)
|
||||
source.CreateElement("remote").SetText(s.Url)
|
||||
if s.CredentialId != "" {
|
||||
source.CreateElement("credentialsId").SetText(s.CredentialId)
|
||||
source.CreateElement("id").SetText(gitSource.ScmId)
|
||||
source.CreateElement("remote").SetText(gitSource.Url)
|
||||
if gitSource.CredentialId != "" {
|
||||
source.CreateElement("credentialsId").SetText(gitSource.CredentialId)
|
||||
}
|
||||
traits := source.CreateElement("traits")
|
||||
if s.DiscoverBranches {
|
||||
if gitSource.DiscoverBranches {
|
||||
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.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("honorRefspec").SetText(strconv.FormatBool(true))
|
||||
cloneExtension.CreateElement("reference")
|
||||
if s.CloneOption.Timeout >= 0 {
|
||||
cloneExtension.CreateElement("timeout").SetText(strconv.Itoa(s.CloneOption.Timeout))
|
||||
if gitSource.CloneOption.Timeout >= 0 {
|
||||
cloneExtension.CreateElement("timeout").SetText(strconv.Itoa(gitSource.CloneOption.Timeout))
|
||||
} else {
|
||||
cloneExtension.CreateElement("timeout").SetText(strconv.Itoa(10))
|
||||
}
|
||||
|
||||
if s.CloneOption.Depth >= 0 {
|
||||
cloneExtension.CreateElement("depth").SetText(strconv.Itoa(s.CloneOption.Depth))
|
||||
if gitSource.CloneOption.Depth >= 0 {
|
||||
cloneExtension.CreateElement("depth").SetText(strconv.Itoa(gitSource.CloneOption.Depth))
|
||||
} else {
|
||||
cloneExtension.CreateElement("depth").SetText(strconv.Itoa(1))
|
||||
}
|
||||
}
|
||||
|
||||
if s.RegexFilter != "" {
|
||||
if gitSource.RegexFilter != "" {
|
||||
regexTraits := traits.CreateElement("jenkins.scm.impl.trait.RegexSCMHeadFilterTrait")
|
||||
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 {
|
||||
s.CredentialId = credential.Text()
|
||||
gitSource.CredentialId = credential.Text()
|
||||
}
|
||||
if remote := source.SelectElement("remote"); remote != nil {
|
||||
s.Url = remote.Text()
|
||||
gitSource.Url = remote.Text()
|
||||
}
|
||||
|
||||
traits := source.SelectElement("traits")
|
||||
if branchDiscoverTrait := traits.SelectElement(
|
||||
"jenkins.plugins.git.traits.BranchDiscoveryTrait"); branchDiscoverTrait != nil {
|
||||
s.DiscoverBranches = true
|
||||
gitSource.DiscoverBranches = true
|
||||
}
|
||||
if cloneTrait := traits.SelectElement(
|
||||
"jenkins.plugins.git.traits.CloneOptionTrait"); cloneTrait != nil {
|
||||
if cloneExtension := cloneTrait.SelectElement(
|
||||
"extension"); cloneExtension != nil {
|
||||
s.CloneOption = &GitCloneOption{}
|
||||
gitSource.CloneOption = &devops.GitCloneOption{}
|
||||
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 {
|
||||
s.CloneOption.Timeout = int(value)
|
||||
gitSource.CloneOption.Timeout = int(value)
|
||||
}
|
||||
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(
|
||||
"jenkins.scm.impl.trait.RegexSCMHeadFilterTrait"); regexTrait != 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 {
|
||||
s.CredentialId = credential.Text()
|
||||
githubSource.CredentialId = credential.Text()
|
||||
}
|
||||
if repoOwner := source.SelectElement("repoOwner"); repoOwner != nil {
|
||||
s.Owner = repoOwner.Text()
|
||||
githubSource.Owner = repoOwner.Text()
|
||||
}
|
||||
if repository := source.SelectElement("repository"); repository != nil {
|
||||
s.Repo = repository.Text()
|
||||
githubSource.Repo = repository.Text()
|
||||
}
|
||||
if apiUri := source.SelectElement("apiUri"); apiUri != nil {
|
||||
s.ApiUri = apiUri.Text()
|
||||
githubSource.ApiUri = apiUri.Text()
|
||||
}
|
||||
traits := source.SelectElement("traits")
|
||||
if branchDiscoverTrait := traits.SelectElement(
|
||||
"org.jenkinsci.plugins.github__branch__source.BranchDiscoveryTrait"); branchDiscoverTrait != nil {
|
||||
strategyId, _ := strconv.Atoi(branchDiscoverTrait.SelectElement("strategyId").Text())
|
||||
s.DiscoverBranches = strategyId
|
||||
githubSource.DiscoverBranches = strategyId
|
||||
}
|
||||
if originPRDiscoverTrait := traits.SelectElement(
|
||||
"org.jenkinsci.plugins.github__branch__source.OriginPullRequestDiscoveryTrait"); originPRDiscoverTrait != nil {
|
||||
strategyId, _ := strconv.Atoi(originPRDiscoverTrait.SelectElement("strategyId").Text())
|
||||
s.DiscoverPRFromOrigin = strategyId
|
||||
githubSource.DiscoverPRFromOrigin = strategyId
|
||||
}
|
||||
if forkPRDiscoverTrait := traits.SelectElement(
|
||||
"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, "$")
|
||||
switch trust[1] {
|
||||
case "TrustContributors":
|
||||
s.DiscoverPRFromForks = &DiscoverPRFromForks{
|
||||
githubSource.DiscoverPRFromForks = &devops.DiscoverPRFromForks{
|
||||
Strategy: strategyId,
|
||||
Trust: 1,
|
||||
}
|
||||
case "TrustEveryone":
|
||||
s.DiscoverPRFromForks = &DiscoverPRFromForks{
|
||||
githubSource.DiscoverPRFromForks = &devops.DiscoverPRFromForks{
|
||||
Strategy: strategyId,
|
||||
Trust: 2,
|
||||
}
|
||||
case "TrustPermission":
|
||||
s.DiscoverPRFromForks = &DiscoverPRFromForks{
|
||||
githubSource.DiscoverPRFromForks = &devops.DiscoverPRFromForks{
|
||||
Strategy: strategyId,
|
||||
Trust: 3,
|
||||
}
|
||||
case "TrustNobody":
|
||||
s.DiscoverPRFromForks = &DiscoverPRFromForks{
|
||||
githubSource.DiscoverPRFromForks = &devops.DiscoverPRFromForks{
|
||||
Strategy: strategyId,
|
||||
Trust: 4,
|
||||
}
|
||||
@@ -536,15 +369,15 @@ func (s *GithubSource) fromEtree(source *etree.Element) *GithubSource {
|
||||
"jenkins.plugins.git.traits.CloneOptionTrait"); cloneTrait != nil {
|
||||
if cloneExtension := cloneTrait.SelectElement(
|
||||
"extension"); cloneExtension != nil {
|
||||
s.CloneOption = &GitCloneOption{}
|
||||
githubSource.CloneOption = &devops.GitCloneOption{}
|
||||
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 {
|
||||
s.CloneOption.Timeout = int(value)
|
||||
githubSource.CloneOption.Timeout = int(value)
|
||||
}
|
||||
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(
|
||||
"jenkins.scm.impl.trait.RegexSCMHeadFilterTrait"); regexTrait != 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("plugin", "github-branch-source")
|
||||
source.CreateElement("id").SetText(s.ScmId)
|
||||
source.CreateElement("credentialsId").SetText(s.CredentialId)
|
||||
source.CreateElement("repoOwner").SetText(s.Owner)
|
||||
source.CreateElement("repository").SetText(s.Repo)
|
||||
if s.ApiUri != "" {
|
||||
source.CreateElement("apiUri").SetText(s.ApiUri)
|
||||
source.CreateElement("id").SetText(githubSource.ScmId)
|
||||
source.CreateElement("credentialsId").SetText(githubSource.CredentialId)
|
||||
source.CreateElement("repoOwner").SetText(githubSource.Owner)
|
||||
source.CreateElement("repository").SetText(githubSource.Repo)
|
||||
if githubSource.ApiUri != "" {
|
||||
source.CreateElement("apiUri").SetText(githubSource.ApiUri)
|
||||
}
|
||||
traits := source.CreateElement("traits")
|
||||
if s.DiscoverBranches != 0 {
|
||||
if githubSource.DiscoverBranches != 0 {
|
||||
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").
|
||||
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.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$"
|
||||
switch s.DiscoverPRFromForks.Trust {
|
||||
switch githubSource.DiscoverPRFromForks.Trust {
|
||||
case 1:
|
||||
trustClass += "TrustContributors"
|
||||
case 2:
|
||||
@@ -595,34 +428,35 @@ func (s *GithubSource) appendToEtree(source *etree.Element) *GithubSource {
|
||||
}
|
||||
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.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("honorRefspec").SetText(strconv.FormatBool(true))
|
||||
cloneExtension.CreateElement("reference")
|
||||
if s.CloneOption.Timeout >= 0 {
|
||||
cloneExtension.CreateElement("timeout").SetText(strconv.Itoa(s.CloneOption.Timeout))
|
||||
if githubSource.CloneOption.Timeout >= 0 {
|
||||
cloneExtension.CreateElement("timeout").SetText(strconv.Itoa(githubSource.CloneOption.Timeout))
|
||||
} else {
|
||||
cloneExtension.CreateElement("timeout").SetText(strconv.Itoa(10))
|
||||
}
|
||||
|
||||
if s.CloneOption.Depth >= 0 {
|
||||
cloneExtension.CreateElement("depth").SetText(strconv.Itoa(s.CloneOption.Depth))
|
||||
if githubSource.CloneOption.Depth >= 0 {
|
||||
cloneExtension.CreateElement("depth").SetText(strconv.Itoa(githubSource.CloneOption.Depth))
|
||||
} else {
|
||||
cloneExtension.CreateElement("depth").SetText(strconv.Itoa(1))
|
||||
}
|
||||
}
|
||||
if s.RegexFilter != "" {
|
||||
if githubSource.RegexFilter != "" {
|
||||
regexTraits := traits.CreateElement("jenkins.scm.impl.trait.RegexSCMHeadFilterTrait")
|
||||
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 {
|
||||
s.CredentialId = credential.Text()
|
||||
}
|
||||
@@ -653,17 +487,17 @@ func (s *BitbucketServerSource) fromEtree(source *etree.Element) *BitbucketServe
|
||||
trust := strings.Split(trustClass, "$")
|
||||
switch trust[1] {
|
||||
case "TrustEveryone":
|
||||
s.DiscoverPRFromForks = &DiscoverPRFromForks{
|
||||
s.DiscoverPRFromForks = &devops.DiscoverPRFromForks{
|
||||
Strategy: strategyId,
|
||||
Trust: 1,
|
||||
}
|
||||
case "TrustTeamForks":
|
||||
s.DiscoverPRFromForks = &DiscoverPRFromForks{
|
||||
s.DiscoverPRFromForks = &devops.DiscoverPRFromForks{
|
||||
Strategy: strategyId,
|
||||
Trust: 2,
|
||||
}
|
||||
case "TrustNobody":
|
||||
s.DiscoverPRFromForks = &DiscoverPRFromForks{
|
||||
s.DiscoverPRFromForks = &devops.DiscoverPRFromForks{
|
||||
Strategy: strategyId,
|
||||
Trust: 3,
|
||||
}
|
||||
@@ -672,7 +506,7 @@ func (s *BitbucketServerSource) fromEtree(source *etree.Element) *BitbucketServe
|
||||
"jenkins.plugins.git.traits.CloneOptionTrait"); cloneTrait != nil {
|
||||
if cloneExtension := cloneTrait.SelectElement(
|
||||
"extension"); cloneExtension != nil {
|
||||
s.CloneOption = &GitCloneOption{}
|
||||
s.CloneOption = &devops.GitCloneOption{}
|
||||
if value, err := strconv.ParseBool(cloneExtension.SelectElement("shallow").Text()); err == nil {
|
||||
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("plugin", "cloudbees-bitbucket-branch-source")
|
||||
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.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 {
|
||||
s.Remote = remote.Text()
|
||||
}
|
||||
@@ -772,10 +607,10 @@ func (s *SvnSource) fromEtree(source *etree.Element) *SvnSource {
|
||||
if excludes := source.SelectElement("excludes"); excludes != nil {
|
||||
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("plugin", "subversion")
|
||||
source.CreateElement("id").SetText(s.ScmId)
|
||||
@@ -791,10 +626,11 @@ func (s *SvnSource) appendToEtree(source *etree.Element) *SvnSource {
|
||||
if 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 locations := scm.SelectElement("locations"); locations != 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("plugin", "scm-api")
|
||||
@@ -843,26 +679,27 @@ func (s *SingleSvnSource) appendToEtree(source *etree.Element) *SingleSvnSource
|
||||
source.CreateElement("filterChangelog").SetText("false")
|
||||
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.CreateAttr("plugin", "multibranch-action-triggers")
|
||||
triggerProperty.CreateElement("createActionJobsToTrigger").SetText(s.CreateActionJobsToTrigger)
|
||||
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")
|
||||
if triggerProperty != nil {
|
||||
s.CreateActionJobsToTrigger = triggerProperty.SelectElement("createActionJobsToTrigger").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()
|
||||
xmlString := `
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
@@ -896,7 +733,7 @@ func createMultiBranchPipelineConfigXml(projectName string, pipeline *MultiBranc
|
||||
|
||||
if pipeline.MultiBranchJobTrigger != nil {
|
||||
properties := project.SelectElement("properties")
|
||||
pipeline.MultiBranchJobTrigger.appendToEtree(properties)
|
||||
appendMultiBranchJobTriggerToEtree(properties, pipeline.MultiBranchJobTrigger)
|
||||
}
|
||||
|
||||
if pipeline.Discarder != nil {
|
||||
@@ -939,27 +776,15 @@ func createMultiBranchPipelineConfigXml(projectName string, pipeline *MultiBranc
|
||||
|
||||
switch pipeline.SourceType {
|
||||
case "git":
|
||||
gitDefine := pipeline.GitSource
|
||||
gitDefine.ScmId = projectName + pipeline.Name
|
||||
gitDefine.appendToEtree(source)
|
||||
appendGitSourceToEtree(source, pipeline.GitSource)
|
||||
case "github":
|
||||
githubDefine := pipeline.GitHubSource
|
||||
githubDefine.ScmId = projectName + pipeline.Name
|
||||
githubDefine.appendToEtree(source)
|
||||
appendGithubSourceToEtree(source, pipeline.GitHubSource)
|
||||
case "svn":
|
||||
svnDefine := pipeline.SvnSource
|
||||
svnDefine.ScmId = projectName + pipeline.Name
|
||||
svnDefine.appendToEtree(source)
|
||||
|
||||
appendSvnSourceToEtree(source, pipeline.SvnSource)
|
||||
case "single_svn":
|
||||
singSvnDefine := pipeline.SingleSvnSource
|
||||
singSvnDefine.ScmId = projectName + pipeline.Name
|
||||
singSvnDefine.appendToEtree(source)
|
||||
|
||||
appendSingleSvnSourceToEtree(source, pipeline.SingleSvnSource)
|
||||
case "bitbucket_server":
|
||||
bitbucketServerDefine := pipeline.BitbucketServerSource
|
||||
bitbucketServerDefine.ScmId = projectName + pipeline.Name
|
||||
bitbucketServerDefine.appendToEtree(source)
|
||||
appendBitbucketServerSourceToEtree(source, pipeline.BitbucketServerSource)
|
||||
|
||||
default:
|
||||
return "", fmt.Errorf("unsupport source type")
|
||||
@@ -977,8 +802,8 @@ func createMultiBranchPipelineConfigXml(projectName string, pipeline *MultiBranc
|
||||
return replaceXmlVersion(stringXml, "1.0", "1.1"), err
|
||||
}
|
||||
|
||||
func parseMultiBranchPipelineConfigXml(config string) (*MultiBranchPipeline, error) {
|
||||
pipeline := &MultiBranchPipeline{}
|
||||
func parseMultiBranchPipelineConfigXml(config string) (*devops.MultiBranchPipeline, error) {
|
||||
pipeline := &devops.MultiBranchPipeline{}
|
||||
config = replaceXmlVersion(config, "1.1", "1.0")
|
||||
doc := etree.NewDocument()
|
||||
err := doc.ReadFromString(config)
|
||||
@@ -992,15 +817,13 @@ func parseMultiBranchPipelineConfigXml(config string) (*MultiBranchPipeline, err
|
||||
if properties := project.SelectElement("properties"); properties != nil {
|
||||
if multibranchTrigger := properties.SelectElement(
|
||||
"org.jenkinsci.plugins.workflow.multibranch.PipelineTriggerProperty"); multibranchTrigger != nil {
|
||||
trigger := &MultiBranchJobTrigger{}
|
||||
trigger.fromEtree(properties)
|
||||
pipeline.MultiBranchJobTrigger = trigger
|
||||
pipeline.MultiBranchJobTrigger = getMultiBranchJobTriggerfromEtree(properties)
|
||||
}
|
||||
}
|
||||
pipeline.Description = project.SelectElement("description").Text()
|
||||
|
||||
if discarder := project.SelectElement("orphanedItemStrategy"); discarder != nil {
|
||||
pipeline.Discarder = &DiscarderProperty{
|
||||
pipeline.Discarder = &devops.DiscarderProperty{
|
||||
DaysToKeep: discarder.SelectElement("daysToKeep").Text(),
|
||||
NumToKeep: discarder.SelectElement("numToKeep").Text(),
|
||||
}
|
||||
@@ -1008,7 +831,7 @@ func parseMultiBranchPipelineConfigXml(config string) (*MultiBranchPipeline, err
|
||||
if triggers := project.SelectElement("triggers"); triggers != nil {
|
||||
if timerTrigger := triggers.SelectElement(
|
||||
"com.cloudbees.hudson.plugins.folder.computed.PeriodicFolderTrigger"); timerTrigger != nil {
|
||||
pipeline.TimerTrigger = &TimerTrigger{
|
||||
pipeline.TimerTrigger = &devops.TimerTrigger{
|
||||
Interval: timerTrigger.SelectElement("interval").Text(),
|
||||
}
|
||||
}
|
||||
@@ -1020,33 +843,23 @@ func parseMultiBranchPipelineConfigXml(config string) (*MultiBranchPipeline, err
|
||||
source := branchSource.SelectElement("source")
|
||||
switch source.SelectAttr("class").Value {
|
||||
case "org.jenkinsci.plugins.github_branch_source.GitHubSCMSource":
|
||||
githubSource := &GithubSource{}
|
||||
githubSource.fromEtree(source)
|
||||
pipeline.GitHubSource = githubSource
|
||||
pipeline.GitHubSource = getGithubSourcefromEtree(source)
|
||||
pipeline.SourceType = "github"
|
||||
case "com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMSource":
|
||||
bitbucketServerSource := &BitbucketServerSource{}
|
||||
bitbucketServerSource.fromEtree(source)
|
||||
pipeline.BitbucketServerSource = bitbucketServerSource
|
||||
pipeline.BitbucketServerSource = getBitbucketServerSourceFromEtree(source)
|
||||
pipeline.SourceType = "bitbucket_server"
|
||||
|
||||
case "jenkins.plugins.git.GitSCMSource":
|
||||
gitSource := &GitSource{}
|
||||
gitSource.fromEtree(source)
|
||||
pipeline.SourceType = "git"
|
||||
pipeline.GitSource = gitSource
|
||||
pipeline.GitSource = getGitSourcefromEtree(source)
|
||||
|
||||
case "jenkins.scm.impl.SingleSCMSource":
|
||||
singleSvnSource := &SingleSvnSource{}
|
||||
singleSvnSource.fromEtree(source)
|
||||
pipeline.SourceType = "single_svn"
|
||||
pipeline.SingleSvnSource = singleSvnSource
|
||||
pipeline.SingleSvnSource = getSingleSvnSourceFromEtree(source)
|
||||
|
||||
case "jenkins.scm.impl.subversion.SubversionSCMSource":
|
||||
svnSource := &SvnSource{}
|
||||
svnSource.fromEtree(source)
|
||||
pipeline.SourceType = "svn"
|
||||
pipeline.SvnSource = svnSource
|
||||
pipeline.SvnSource = getSvnSourcefromEtree(source)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1078,55 +891,3 @@ func toCrontab(millis int64) string {
|
||||
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 @@
|
||||
/*
|
||||
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 jenkins
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_NoScmPipelineConfig(t *testing.T) {
|
||||
inputs := []*NoScmPipeline{
|
||||
inputs := []*devops.NoScmPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
@@ -54,12 +42,12 @@ func Test_NoScmPipelineConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_NoScmPipelineConfig_Discarder(t *testing.T) {
|
||||
inputs := []*NoScmPipeline{
|
||||
inputs := []*devops.NoScmPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
Discarder: &DiscarderProperty{
|
||||
Discarder: &devops.DiscarderProperty{
|
||||
"3", "5",
|
||||
},
|
||||
},
|
||||
@@ -67,7 +55,7 @@ func Test_NoScmPipelineConfig_Discarder(t *testing.T) {
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
Discarder: &DiscarderProperty{
|
||||
Discarder: &devops.DiscarderProperty{
|
||||
"3", "",
|
||||
},
|
||||
},
|
||||
@@ -75,7 +63,7 @@ func Test_NoScmPipelineConfig_Discarder(t *testing.T) {
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
Discarder: &DiscarderProperty{
|
||||
Discarder: &devops.DiscarderProperty{
|
||||
"", "21321",
|
||||
},
|
||||
},
|
||||
@@ -83,7 +71,7 @@ func Test_NoScmPipelineConfig_Discarder(t *testing.T) {
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
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) {
|
||||
inputs := []*NoScmPipeline{
|
||||
inputs := []*devops.NoScmPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
Parameters: &Parameters{
|
||||
&Parameter{
|
||||
Parameters: &devops.Parameters{
|
||||
&devops.Parameter{
|
||||
Name: "d",
|
||||
DefaultValue: "a\nb",
|
||||
Type: "choice",
|
||||
@@ -123,26 +111,26 @@ func Test_NoScmPipelineConfig_Param(t *testing.T) {
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
Parameters: &Parameters{
|
||||
&Parameter{
|
||||
Parameters: &devops.Parameters{
|
||||
&devops.Parameter{
|
||||
Name: "a",
|
||||
DefaultValue: "abc",
|
||||
Type: "string",
|
||||
Description: "fortest",
|
||||
},
|
||||
&Parameter{
|
||||
&devops.Parameter{
|
||||
Name: "b",
|
||||
DefaultValue: "false",
|
||||
Type: "boolean",
|
||||
Description: "fortest",
|
||||
},
|
||||
&Parameter{
|
||||
&devops.Parameter{
|
||||
Name: "c",
|
||||
DefaultValue: "password \n aaa",
|
||||
Type: "text",
|
||||
Description: "fortest",
|
||||
},
|
||||
&Parameter{
|
||||
&devops.Parameter{
|
||||
Name: "d",
|
||||
DefaultValue: "a\nb",
|
||||
Type: "choice",
|
||||
@@ -168,12 +156,12 @@ func Test_NoScmPipelineConfig_Param(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_NoScmPipelineConfig_Trigger(t *testing.T) {
|
||||
inputs := []*NoScmPipeline{
|
||||
inputs := []*devops.NoScmPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
TimerTrigger: &TimerTrigger{
|
||||
TimerTrigger: &devops.TimerTrigger{
|
||||
Cron: "1 1 1 * * *",
|
||||
},
|
||||
},
|
||||
@@ -182,7 +170,7 @@ func Test_NoScmPipelineConfig_Trigger(t *testing.T) {
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
RemoteTrigger: &RemoteTrigger{
|
||||
RemoteTrigger: &devops.RemoteTrigger{
|
||||
Token: "abc",
|
||||
},
|
||||
},
|
||||
@@ -190,10 +178,10 @@ func Test_NoScmPipelineConfig_Trigger(t *testing.T) {
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
TimerTrigger: &TimerTrigger{
|
||||
TimerTrigger: &devops.TimerTrigger{
|
||||
Cron: "1 1 1 * * *",
|
||||
},
|
||||
RemoteTrigger: &RemoteTrigger{
|
||||
RemoteTrigger: &devops.RemoteTrigger{
|
||||
Token: "abc",
|
||||
},
|
||||
},
|
||||
@@ -217,34 +205,34 @@ func Test_NoScmPipelineConfig_Trigger(t *testing.T) {
|
||||
|
||||
func Test_MultiBranchPipelineConfig(t *testing.T) {
|
||||
|
||||
inputs := []*MultiBranchPipeline{
|
||||
inputs := []*devops.MultiBranchPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "git",
|
||||
GitSource: &GitSource{},
|
||||
GitSource: &devops.GitSource{},
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "github",
|
||||
GitHubSource: &GithubSource{},
|
||||
GitHubSource: &devops.GithubSource{},
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "single_svn",
|
||||
SingleSvnSource: &SingleSvnSource{},
|
||||
SingleSvnSource: &devops.SingleSvnSource{},
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "svn",
|
||||
SvnSource: &SvnSource{},
|
||||
SvnSource: &devops.SvnSource{},
|
||||
},
|
||||
}
|
||||
for _, input := range inputs {
|
||||
@@ -265,17 +253,17 @@ func Test_MultiBranchPipelineConfig(t *testing.T) {
|
||||
|
||||
func Test_MultiBranchPipelineConfig_Discarder(t *testing.T) {
|
||||
|
||||
inputs := []*MultiBranchPipeline{
|
||||
inputs := []*devops.MultiBranchPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "git",
|
||||
Discarder: &DiscarderProperty{
|
||||
Discarder: &devops.DiscarderProperty{
|
||||
DaysToKeep: "1",
|
||||
NumToKeep: "2",
|
||||
},
|
||||
GitSource: &GitSource{},
|
||||
GitSource: &devops.GitSource{},
|
||||
},
|
||||
}
|
||||
for _, input := range inputs {
|
||||
@@ -295,16 +283,16 @@ func Test_MultiBranchPipelineConfig_Discarder(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_MultiBranchPipelineConfig_TimerTrigger(t *testing.T) {
|
||||
inputs := []*MultiBranchPipeline{
|
||||
inputs := []*devops.MultiBranchPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "git",
|
||||
TimerTrigger: &TimerTrigger{
|
||||
TimerTrigger: &devops.TimerTrigger{
|
||||
Interval: "12345566",
|
||||
},
|
||||
GitSource: &GitSource{},
|
||||
GitSource: &devops.GitSource{},
|
||||
},
|
||||
}
|
||||
for _, input := range inputs {
|
||||
@@ -325,16 +313,16 @@ func Test_MultiBranchPipelineConfig_TimerTrigger(t *testing.T) {
|
||||
|
||||
func Test_MultiBranchPipelineConfig_Source(t *testing.T) {
|
||||
|
||||
inputs := []*MultiBranchPipeline{
|
||||
inputs := []*devops.MultiBranchPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "git",
|
||||
TimerTrigger: &TimerTrigger{
|
||||
TimerTrigger: &devops.TimerTrigger{
|
||||
Interval: "12345566",
|
||||
},
|
||||
GitSource: &GitSource{
|
||||
GitSource: &devops.GitSource{
|
||||
Url: "https://github.com/kubesphere/devops",
|
||||
CredentialId: "git",
|
||||
DiscoverBranches: true,
|
||||
@@ -345,17 +333,17 @@ func Test_MultiBranchPipelineConfig_Source(t *testing.T) {
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "github",
|
||||
TimerTrigger: &TimerTrigger{
|
||||
TimerTrigger: &devops.TimerTrigger{
|
||||
Interval: "12345566",
|
||||
},
|
||||
GitHubSource: &GithubSource{
|
||||
GitHubSource: &devops.GithubSource{
|
||||
Owner: "kubesphere",
|
||||
Repo: "devops",
|
||||
CredentialId: "github",
|
||||
ApiUri: "https://api.github.com",
|
||||
DiscoverBranches: 1,
|
||||
DiscoverPRFromOrigin: 2,
|
||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
||||
DiscoverPRFromForks: &devops.DiscoverPRFromForks{
|
||||
Strategy: 1,
|
||||
Trust: 1,
|
||||
},
|
||||
@@ -366,17 +354,17 @@ func Test_MultiBranchPipelineConfig_Source(t *testing.T) {
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "bitbucket_server",
|
||||
TimerTrigger: &TimerTrigger{
|
||||
TimerTrigger: &devops.TimerTrigger{
|
||||
Interval: "12345566",
|
||||
},
|
||||
BitbucketServerSource: &BitbucketServerSource{
|
||||
BitbucketServerSource: &devops.BitbucketServerSource{
|
||||
Owner: "kubesphere",
|
||||
Repo: "devops",
|
||||
CredentialId: "github",
|
||||
ApiUri: "https://api.github.com",
|
||||
DiscoverBranches: 1,
|
||||
DiscoverPRFromOrigin: 2,
|
||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
||||
DiscoverPRFromForks: &devops.DiscoverPRFromForks{
|
||||
Strategy: 1,
|
||||
Trust: 1,
|
||||
},
|
||||
@@ -388,10 +376,10 @@ func Test_MultiBranchPipelineConfig_Source(t *testing.T) {
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "svn",
|
||||
TimerTrigger: &TimerTrigger{
|
||||
TimerTrigger: &devops.TimerTrigger{
|
||||
Interval: "12345566",
|
||||
},
|
||||
SvnSource: &SvnSource{
|
||||
SvnSource: &devops.SvnSource{
|
||||
Remote: "https://api.svn.com/bcd",
|
||||
CredentialId: "svn",
|
||||
Excludes: "truck",
|
||||
@@ -403,10 +391,10 @@ func Test_MultiBranchPipelineConfig_Source(t *testing.T) {
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "single_svn",
|
||||
TimerTrigger: &TimerTrigger{
|
||||
TimerTrigger: &devops.TimerTrigger{
|
||||
Interval: "12345566",
|
||||
},
|
||||
SingleSvnSource: &SingleSvnSource{
|
||||
SingleSvnSource: &devops.SingleSvnSource{
|
||||
Remote: "https://api.svn.com/bcd",
|
||||
CredentialId: "svn",
|
||||
},
|
||||
@@ -431,17 +419,17 @@ func Test_MultiBranchPipelineConfig_Source(t *testing.T) {
|
||||
|
||||
func Test_MultiBranchPipelineCloneConfig(t *testing.T) {
|
||||
|
||||
inputs := []*MultiBranchPipeline{
|
||||
inputs := []*devops.MultiBranchPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "git",
|
||||
GitSource: &GitSource{
|
||||
GitSource: &devops.GitSource{
|
||||
Url: "https://github.com/kubesphere/devops",
|
||||
CredentialId: "git",
|
||||
DiscoverBranches: true,
|
||||
CloneOption: &GitCloneOption{
|
||||
CloneOption: &devops.GitCloneOption{
|
||||
Shallow: false,
|
||||
Depth: 3,
|
||||
Timeout: 20,
|
||||
@@ -453,18 +441,18 @@ func Test_MultiBranchPipelineCloneConfig(t *testing.T) {
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "github",
|
||||
GitHubSource: &GithubSource{
|
||||
GitHubSource: &devops.GithubSource{
|
||||
Owner: "kubesphere",
|
||||
Repo: "devops",
|
||||
CredentialId: "github",
|
||||
ApiUri: "https://api.github.com",
|
||||
DiscoverBranches: 1,
|
||||
DiscoverPRFromOrigin: 2,
|
||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
||||
DiscoverPRFromForks: &devops.DiscoverPRFromForks{
|
||||
Strategy: 1,
|
||||
Trust: 1,
|
||||
},
|
||||
CloneOption: &GitCloneOption{
|
||||
CloneOption: &devops.GitCloneOption{
|
||||
Shallow: false,
|
||||
Depth: 3,
|
||||
Timeout: 20,
|
||||
@@ -492,13 +480,13 @@ func Test_MultiBranchPipelineCloneConfig(t *testing.T) {
|
||||
|
||||
func Test_MultiBranchPipelineRegexFilter(t *testing.T) {
|
||||
|
||||
inputs := []*MultiBranchPipeline{
|
||||
inputs := []*devops.MultiBranchPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "git",
|
||||
GitSource: &GitSource{
|
||||
GitSource: &devops.GitSource{
|
||||
Url: "https://github.com/kubesphere/devops",
|
||||
CredentialId: "git",
|
||||
DiscoverBranches: true,
|
||||
@@ -510,14 +498,14 @@ func Test_MultiBranchPipelineRegexFilter(t *testing.T) {
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "github",
|
||||
GitHubSource: &GithubSource{
|
||||
GitHubSource: &devops.GithubSource{
|
||||
Owner: "kubesphere",
|
||||
Repo: "devops",
|
||||
CredentialId: "github",
|
||||
ApiUri: "https://api.github.com",
|
||||
DiscoverBranches: 1,
|
||||
DiscoverPRFromOrigin: 2,
|
||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
||||
DiscoverPRFromForks: &devops.DiscoverPRFromForks{
|
||||
Strategy: 1,
|
||||
Trust: 1,
|
||||
},
|
||||
@@ -545,26 +533,26 @@ func Test_MultiBranchPipelineRegexFilter(t *testing.T) {
|
||||
|
||||
func Test_MultiBranchPipelineMultibranchTrigger(t *testing.T) {
|
||||
|
||||
inputs := []*MultiBranchPipeline{
|
||||
inputs := []*devops.MultiBranchPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "github",
|
||||
GitHubSource: &GithubSource{
|
||||
GitHubSource: &devops.GithubSource{
|
||||
Owner: "kubesphere",
|
||||
Repo: "devops",
|
||||
CredentialId: "github",
|
||||
ApiUri: "https://api.github.com",
|
||||
DiscoverBranches: 1,
|
||||
DiscoverPRFromOrigin: 2,
|
||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
||||
DiscoverPRFromForks: &devops.DiscoverPRFromForks{
|
||||
Strategy: 1,
|
||||
Trust: 1,
|
||||
},
|
||||
RegexFilter: ".*",
|
||||
},
|
||||
MultiBranchJobTrigger: &MultiBranchJobTrigger{
|
||||
MultiBranchJobTrigger: &devops.MultiBranchJobTrigger{
|
||||
CreateActionJobsToTrigger: "abc",
|
||||
DeleteActionJobsToTrigger: "ddd",
|
||||
},
|
||||
@@ -574,20 +562,20 @@ func Test_MultiBranchPipelineMultibranchTrigger(t *testing.T) {
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "github",
|
||||
GitHubSource: &GithubSource{
|
||||
GitHubSource: &devops.GithubSource{
|
||||
Owner: "kubesphere",
|
||||
Repo: "devops",
|
||||
CredentialId: "github",
|
||||
ApiUri: "https://api.github.com",
|
||||
DiscoverBranches: 1,
|
||||
DiscoverPRFromOrigin: 2,
|
||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
||||
DiscoverPRFromForks: &devops.DiscoverPRFromForks{
|
||||
Strategy: 1,
|
||||
Trust: 1,
|
||||
},
|
||||
RegexFilter: ".*",
|
||||
},
|
||||
MultiBranchJobTrigger: &MultiBranchJobTrigger{
|
||||
MultiBranchJobTrigger: &devops.MultiBranchJobTrigger{
|
||||
CreateActionJobsToTrigger: "abc",
|
||||
},
|
||||
},
|
||||
@@ -596,20 +584,20 @@ func Test_MultiBranchPipelineMultibranchTrigger(t *testing.T) {
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "github",
|
||||
GitHubSource: &GithubSource{
|
||||
GitHubSource: &devops.GithubSource{
|
||||
Owner: "kubesphere",
|
||||
Repo: "devops",
|
||||
CredentialId: "github",
|
||||
ApiUri: "https://api.github.com",
|
||||
DiscoverBranches: 1,
|
||||
DiscoverPRFromOrigin: 2,
|
||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
||||
DiscoverPRFromForks: &devops.DiscoverPRFromForks{
|
||||
Strategy: 1,
|
||||
Trust: 1,
|
||||
},
|
||||
RegexFilter: ".*",
|
||||
},
|
||||
MultiBranchJobTrigger: &MultiBranchJobTrigger{
|
||||
MultiBranchJobTrigger: &devops.MultiBranchJobTrigger{
|
||||
DeleteActionJobsToTrigger: "ddd",
|
||||
},
|
||||
},
|
||||
@@ -11,7 +11,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package gojenkins
|
||||
package jenkins
|
||||
|
||||
import (
|
||||
"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
|
||||
// under the License.
|
||||
|
||||
package gojenkins
|
||||
package jenkins
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -1,4 +1,4 @@
|
||||
package gojenkins
|
||||
package jenkins
|
||||
|
||||
import (
|
||||
"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
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type PipelineList struct {
|
||||
Items []Pipeline `json:"items"`
|
||||
Total int `json:"total_count"`
|
||||
}
|
||||
|
||||
// GetPipeline & SearchPipelines
|
||||
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." `
|
||||
@@ -85,7 +79,7 @@ type Pipeline struct {
|
||||
}
|
||||
|
||||
// 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."`
|
||||
Links struct {
|
||||
PrevRun struct {
|
||||
@@ -316,7 +310,7 @@ type OrgRepo struct {
|
||||
}
|
||||
|
||||
// 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."`
|
||||
Links struct {
|
||||
Parent struct {
|
||||
@@ -390,7 +384,7 @@ type StopPipe struct {
|
||||
}
|
||||
|
||||
// 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."`
|
||||
Links struct {
|
||||
Parent struct {
|
||||
@@ -468,7 +462,7 @@ type Artifacts struct {
|
||||
}
|
||||
|
||||
// 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."`
|
||||
Links struct {
|
||||
Self struct {
|
||||
@@ -598,7 +592,7 @@ type RunPayload struct {
|
||||
} `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."`
|
||||
Links struct {
|
||||
Parent struct {
|
||||
@@ -1108,22 +1102,18 @@ type NodesDetail struct {
|
||||
Actions []interface{} `json:"actions,omitempty" description:"the list of all actions"`
|
||||
DisplayDescription interface{} `json:"displayDescription,omitempty" description:"display description"`
|
||||
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"`
|
||||
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"`
|
||||
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"`
|
||||
CauseOfBlockage interface{} `json:"causeOfBlockage,omitempty" description:"the cause of blockage"`
|
||||
Edges []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."`
|
||||
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"`
|
||||
Restartable bool `json:"restartable,omitempty" description:"restartable or not"`
|
||||
Steps []NodeSteps `json:"steps,omitempty" description:"steps"`
|
||||
Edges []interface{} `json:"edges,omitempty" description:"edges"`
|
||||
FirstParent interface{} `json:"firstParent,omitempty" description:"first parent"`
|
||||
Restartable bool `json:"restartable,omitempty" description:"restartable or not"`
|
||||
Steps []NodeSteps `json:"steps,omitempty" description:"steps"`
|
||||
}
|
||||
|
||||
type NodesStepsIndex struct {
|
||||
@@ -1145,3 +1135,65 @@ type Input struct {
|
||||
Parameters []interface{} `json:"parameters,omitempty" description:"the parameters of check action"`
|
||||
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"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/cache"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/devops/jenkins"
|
||||
esclient "kubesphere.io/kubesphere/pkg/simple/client/elasticsearch"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/kubesphere"
|
||||
@@ -22,7 +23,7 @@ type ClientSetOptions struct {
|
||||
mySQLOptions *mysql.Options
|
||||
redisOptions *cache.Options
|
||||
kubernetesOptions *k8s.KubernetesOptions
|
||||
devopsOptions *devops.Options
|
||||
devopsOptions *jenkins.Options
|
||||
sonarqubeOptions *sonarqube.Options
|
||||
ldapOptions *ldap.Options
|
||||
s3Options *s3.Options
|
||||
@@ -38,7 +39,7 @@ func NewClientSetOptions() *ClientSetOptions {
|
||||
redisOptions: cache.NewRedisOptions(),
|
||||
kubernetesOptions: k8s.NewKubernetesOptions(),
|
||||
ldapOptions: ldap.NewLdapOptions(),
|
||||
devopsOptions: devops.NewDevopsOptions(),
|
||||
devopsOptions: jenkins.NewDevopsOptions(),
|
||||
sonarqubeOptions: sonarqube.NewSonarQubeOptions(),
|
||||
s3Options: s3.NewS3Options(),
|
||||
openPitrixOptions: openpitrix.NewOpenPitrixOptions(),
|
||||
@@ -63,7 +64,7 @@ func (c *ClientSetOptions) SetKubernetesOptions(options *k8s.KubernetesOptions)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ClientSetOptions) SetDevopsOptions(options *devops.Options) *ClientSetOptions {
|
||||
func (c *ClientSetOptions) SetDevopsOptions(options *jenkins.Options) *ClientSetOptions {
|
||||
c.devopsOptions = options
|
||||
return c
|
||||
}
|
||||
@@ -114,7 +115,7 @@ type ClientSet struct {
|
||||
|
||||
k8sClient k8s.Client
|
||||
ldapClient *ldap.Client
|
||||
devopsClient *devops.Client
|
||||
devopsClient *jenkins.Client
|
||||
sonarQubeClient *sonarqube.Client
|
||||
redisClient cache.Interface
|
||||
s3Client s3.Interface
|
||||
@@ -194,27 +195,28 @@ func (cs *ClientSet) Cache() (cache.Interface, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *ClientSet) Devops() (*devops.Client, error) {
|
||||
var err error
|
||||
|
||||
if cs.csoptions.devopsOptions == nil || cs.csoptions.devopsOptions.Host == "" {
|
||||
return nil, ErrClientSetNotEnabled
|
||||
}
|
||||
|
||||
if cs.devopsClient != nil {
|
||||
return cs.devopsClient, nil
|
||||
} else {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
if cs.devopsClient == nil {
|
||||
cs.devopsClient, err = devops.NewDevopsClient(cs.csoptions.devopsOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return cs.devopsClient, nil
|
||||
}
|
||||
func (cs *ClientSet) Devops() (devops.Interface, error) {
|
||||
//var err error
|
||||
//
|
||||
//if cs.csoptions.devopsOptions == nil || cs.csoptions.devopsOptions.Host == "" {
|
||||
// return nil, ErrClientSetNotEnabled
|
||||
//}
|
||||
//
|
||||
//if cs.devopsClient != nil {
|
||||
// return cs.devopsClient, nil
|
||||
//} else {
|
||||
// mutex.Lock()
|
||||
// defer mutex.Unlock()
|
||||
//
|
||||
// if cs.devopsClient == nil {
|
||||
// cs.devopsClient, err = jenkins.NewDevopsClient(cs.csoptions.devopsOptions)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// }
|
||||
// return cs.devopsClient, nil
|
||||
//}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (cs *ClientSet) SonarQube() (*sonarqube.Client, error) {
|
||||
|
||||
@@ -1,39 +1,32 @@
|
||||
package monitoring
|
||||
|
||||
|
||||
type ClusterQuery struct {
|
||||
|
||||
}
|
||||
|
||||
type ClusterMetrics struct {
|
||||
|
||||
}
|
||||
|
||||
type WorkspaceQuery struct {
|
||||
|
||||
}
|
||||
|
||||
type WorkspaceMetrics struct {
|
||||
|
||||
}
|
||||
|
||||
type NamespaceQuery struct {
|
||||
|
||||
}
|
||||
|
||||
type NamespaceMetrics struct {
|
||||
|
||||
}
|
||||
|
||||
// Interface defines all the abstract behaviors of monitoring
|
||||
type Interface interface {
|
||||
|
||||
// Get
|
||||
GetClusterMetrics(query ClusterQuery) ClusterMetrics
|
||||
// Get
|
||||
GetClusterMetrics(query ClusterQuery) ClusterMetrics
|
||||
|
||||
//
|
||||
GetWorkspaceMetrics(query WorkspaceQuery) WorkspaceMetrics
|
||||
//
|
||||
GetWorkspaceMetrics(query WorkspaceQuery) WorkspaceMetrics
|
||||
|
||||
//
|
||||
GetNamespaceMetrics(query NamespaceQuery) NamespaceMetrics
|
||||
//
|
||||
GetNamespaceMetrics(query NamespaceQuery) NamespaceMetrics
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
package monitoring
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// prometheus implements monitoring interface backed by Prometheus
|
||||
type prometheus struct {
|
||||
options *Options
|
||||
client *http.Client
|
||||
options *Options
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
func NewPrometheus(options *Options) Interface {
|
||||
return &prometheus{
|
||||
options:options,
|
||||
client: &http.Client{ Timeout: 10 * time.Second },
|
||||
}
|
||||
return &prometheus{
|
||||
options: options,
|
||||
client: &http.Client{Timeout: 10 * time.Second},
|
||||
}
|
||||
}
|
||||
|
||||
func (p prometheus) GetClusterMetrics(query ClusterQuery) ClusterMetrics {
|
||||
panic("implement me")
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (p prometheus) GetWorkspaceMetrics(query WorkspaceQuery) WorkspaceMetrics {
|
||||
panic("implement me")
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (p prometheus) GetNamespaceMetrics(query NamespaceQuery) NamespaceMetrics {
|
||||
panic("implement me")
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
package monitoring
|
||||
|
||||
import (
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
Endpoint string `json:"endpoint,omitempty" yaml:"endpoint"`
|
||||
SecondaryEndpoint string `json:"secondaryEndpoint,omitempty" yaml:"secondaryEndpoint"`
|
||||
Endpoint string `json:"endpoint,omitempty" yaml:"endpoint"`
|
||||
SecondaryEndpoint string `json:"secondaryEndpoint,omitempty" yaml:"secondaryEndpoint"`
|
||||
}
|
||||
|
||||
func NewPrometheusOptions() *Options {
|
||||
return &Options{
|
||||
Endpoint: "",
|
||||
SecondaryEndpoint: "",
|
||||
}
|
||||
return &Options{
|
||||
Endpoint: "",
|
||||
SecondaryEndpoint: "",
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Options) Validate() []error {
|
||||
var errs []error
|
||||
return errs
|
||||
var errs []error
|
||||
return errs
|
||||
}
|
||||
|
||||
func (s *Options) ApplyTo(options *Options) {
|
||||
if s.Endpoint != "" {
|
||||
options.Endpoint = s.Endpoint
|
||||
}
|
||||
if s.Endpoint != "" {
|
||||
options.Endpoint = s.Endpoint
|
||||
}
|
||||
|
||||
if s.SecondaryEndpoint != "" {
|
||||
options.SecondaryEndpoint = s.SecondaryEndpoint
|
||||
}
|
||||
if s.SecondaryEndpoint != "" {
|
||||
options.SecondaryEndpoint = s.SecondaryEndpoint
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Options) AddFlags(fs *pflag.FlagSet, c *Options) {
|
||||
fs.StringVar(&s.Endpoint, "prometheus-endpoint", c.Endpoint, ""+
|
||||
"Prometheus service endpoint which stores KubeSphere monitoring data, if left "+
|
||||
"blank, will use builtin metrics-server as data source.")
|
||||
fs.StringVar(&s.Endpoint, "prometheus-endpoint", c.Endpoint, ""+
|
||||
"Prometheus service endpoint which stores KubeSphere monitoring data, if left "+
|
||||
"blank, will use builtin metrics-server as data source.")
|
||||
|
||||
fs.StringVar(&s.SecondaryEndpoint, "prometheus-secondary-endpoint", c.SecondaryEndpoint, ""+
|
||||
"Prometheus secondary service endpoint, if left empty and endpoint is set, will use endpoint instead.")
|
||||
fs.StringVar(&s.SecondaryEndpoint, "prometheus-secondary-endpoint", c.SecondaryEndpoint, ""+
|
||||
"Prometheus secondary service endpoint, if left empty and endpoint is set, will use endpoint instead.")
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
|
||||
type Client struct {
|
||||
client *http.Client
|
||||
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 (
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Interface interface {
|
||||
// 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
|
||||
Get(key string, fileName string, expire time.Duration) (string, error)
|
||||
GetDownloadURL(key string, fileName string) (string, error)
|
||||
|
||||
// Delete deletes an object by its key
|
||||
Delete(key string) error
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package s3
|
||||
|
||||
import (
|
||||
"code.cloudfoundry.org/bytefmt"
|
||||
"fmt"
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/aws/aws-sdk-go/service/s3/s3manager"
|
||||
"io"
|
||||
"k8s.io/klog"
|
||||
"time"
|
||||
@@ -16,16 +19,38 @@ type Client struct {
|
||||
bucket string
|
||||
}
|
||||
|
||||
func (s *Client) Upload(key string, body io.Reader) (string, error) {
|
||||
panic("implement me")
|
||||
func (s *Client) Upload(key, fileName string, body io.Reader) error {
|
||||
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) {
|
||||
panic("implement me")
|
||||
func (s *Client) GetDownloadURL(key string, fileName string) (string, error) {
|
||||
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 {
|
||||
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) {
|
||||
@@ -55,7 +80,6 @@ func NewS3Client(options *Options) (Interface, error) {
|
||||
}
|
||||
|
||||
func (s *Client) Client() *s3.S3 {
|
||||
|
||||
return s.s3Client
|
||||
}
|
||||
func (s *Client) Session() *session.Session {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user