diff --git a/pkg/apis/devops/v1alpha2/register.go b/pkg/apis/devops/v1alpha2/register.go index 9d7a9da1a..6544c1611 100644 --- a/pkg/apis/devops/v1alpha2/register.go +++ b/pkg/apis/devops/v1alpha2/register.go @@ -48,32 +48,32 @@ func addWebService(c *restful.Container) error { Doc("get devops project"). Metadata(restfulspec.KeyOpenAPITags, tags). Param(webservice.PathParameter("devops", "projectId")). - Returns(http.StatusOK, "success", &devops.DevOpsProject{}). - Writes(&devops.DevOpsProject{})) + Returns(http.StatusOK, "success", devops.DevOpsProject{}). + Writes(devops.DevOpsProject{})) webservice.Route(webservice.PATCH("/devops/{devops}"). To(devopsapi.UpdateProjectHandler). Doc("get devops project"). Metadata(restfulspec.KeyOpenAPITags, tags). Param(webservice.PathParameter("devops", "projectId")). - Returns(http.StatusOK, "success", &devops.DevOpsProject{}). - Writes(&devops.DevOpsProject{})) + Returns(http.StatusOK, "success", devops.DevOpsProject{}). + Writes(devops.DevOpsProject{})) webservice.Route(webservice.GET("/devops/{devops}/defaultroles"). To(devopsapi.GetDevOpsProjectDefaultRoles). Doc("get devops project defaultroles"). Metadata(restfulspec.KeyOpenAPITags, tags). Param(webservice.PathParameter("devops", "projectId")). - Returns(http.StatusOK, "success", &devops.DefaultRoles). - Writes(&devops.DefaultRoles)) + Returns(http.StatusOK, "success", []devops.Role{}). + Writes([]devops.Role{})) webservice.Route(webservice.GET("/devops/{devops}/members"). To(devopsapi.GetDevOpsProjectMembersHandler). Doc("get devops project members"). Metadata(restfulspec.KeyOpenAPITags, tags). Param(webservice.PathParameter("devops", "projectId")). - Returns(http.StatusOK, "success", []*devops.DevOpsProjectMembership{}). - Writes([]*devops.DevOpsProjectMembership{})) + Returns(http.StatusOK, "success", []devops.DevOpsProjectMembership{}). + Writes([]devops.DevOpsProjectMembership{})) webservice.Route(webservice.GET("/devops/{devops}/members/{members}"). To(devopsapi.GetDevOpsProjectMemberHandler). @@ -81,32 +81,53 @@ func addWebService(c *restful.Container) error { Metadata(restfulspec.KeyOpenAPITags, tags). Param(webservice.PathParameter("devops", "projectId")). Param(webservice.PathParameter("members", "username")). - Returns(http.StatusOK, "success", []*devops.DevOpsProjectMembership{}). - Writes(&devops.DevOpsProjectMembership{})) + Returns(http.StatusOK, "success", devops.DevOpsProjectMembership{}). + Writes(devops.DevOpsProjectMembership{})) webservice.Route(webservice.POST("/devops/{devops}/members"). To(devopsapi.AddDevOpsProjectMemberHandler). Doc("add devops project members"). Metadata(restfulspec.KeyOpenAPITags, tags). Param(webservice.PathParameter("devops", "projectId")). - Returns(http.StatusOK, "success", &devops.DevOpsProjectMembership{}). - Writes(&devops.DevOpsProjectMembership{})) + Returns(http.StatusOK, "success", devops.DevOpsProjectMembership{}). + Writes(devops.DevOpsProjectMembership{})) + + webservice.Route(webservice.PATCH("/devops/{devops}/members/{members}"). + To(devopsapi.UpdateDevOpsProjectMemberHandler). + Doc("update devops project members"). + Metadata(restfulspec.KeyOpenAPITags, tags). + Param(webservice.PathParameter("devops", "projectId")). + Param(webservice.PathParameter("members", "username")). + Reads(devops.DevOpsProjectMembership{}). + Writes(devops.DevOpsProjectMembership{})) + + webservice.Route(webservice.DELETE("/devops/{devops}/members/{members}"). + To(devopsapi.DeleteDevOpsProjectMemberHandler). + Doc("delete devops project members"). + Metadata(restfulspec.KeyOpenAPITags, tags). + Param(webservice.PathParameter("devops", "projectId")). + Param(webservice.PathParameter("members", "username")). + Writes(devops.DevOpsProjectMembership{})) + webservice.Route(webservice.POST("/devops/{devops}/pipelines"). To(devopsapi.CreateDevOpsProjectPipelineHandler). Doc("add devops project pipeline"). Param(webservice.PathParameter("devops", "projectId")). - Returns(http.StatusOK, "success", &devops.ProjectPipeline{}). - Writes(&devops.ProjectPipeline{}). - Reads(&devops.ProjectPipeline{})) + Metadata(restfulspec.KeyOpenAPITags, tags). + Returns(http.StatusOK, "success", devops.ProjectPipeline{}). + Writes(devops.ProjectPipeline{}). + Reads(devops.ProjectPipeline{})) + webservice.Route(webservice.PUT("/devops/{devops}/pipelines/{pipelines}"). To(devopsapi.UpdateDevOpsProjectPipelineHandler). Doc("update devops project pipeline"). Param(webservice.PathParameter("devops", "projectId")). Param(webservice.PathParameter("pipelines", "pipelineId")). Metadata(restfulspec.KeyOpenAPITags, tags). - Returns(http.StatusOK, "success", &devops.ProjectPipeline{}). - Writes(&devops.ProjectPipeline{}). - Reads(&devops.ProjectPipeline{})) + Returns(http.StatusOK, "success", devops.ProjectPipeline{}). + Writes(devops.ProjectPipeline{}). + Reads(devops.ProjectPipeline{})) + webservice.Route(webservice.GET("/devops/{devops}/pipelines/{pipelines}/config"). To(devopsapi.GetDevOpsProjectPipelineHandler). Doc("get devops project pipeline config"). @@ -115,6 +136,7 @@ func addWebService(c *restful.Container) error { Param(webservice.PathParameter("pipelines", "pipelineId")). Returns(http.StatusOK, "ok", devops.ProjectPipeline{}). Writes(devops.ProjectPipeline{})) + webservice.Route(webservice.GET("/devops/{devops}/pipelines/{pipelines}/sonarStatus"). To(devopsapi.GetPipelineSonarStatusHandler). Doc("get devops project pipeline sonarStatus"). @@ -123,6 +145,7 @@ func addWebService(c *restful.Container) error { Param(webservice.PathParameter("pipelines", "pipelineId")). Returns(http.StatusOK, "ok", []devops.SonarStatus{}). Writes([]devops.SonarStatus{})) + webservice.Route(webservice.GET("/devops/{devops}/pipelines/{pipelines}/branches/{branches}/sonarStatus"). To(devopsapi.GetMultiBranchesPipelineSonarStatusHandler). Doc("get devops project pipeline sonarStatus"). @@ -132,26 +155,63 @@ func addWebService(c *restful.Container) error { Param(webservice.PathParameter("branches", "branchName")). Returns(http.StatusOK, "ok", []devops.SonarStatus{}). Writes([]devops.SonarStatus{})) + webservice.Route(webservice.DELETE("/devops/{devops}/pipelines/{pipelines}"). To(devopsapi.DeleteDevOpsProjectPipelineHandler). Doc("delete devops project pipeline"). - Metadata(restfulspec.KeyOpenAPITags, tags)) + Metadata(restfulspec.KeyOpenAPITags, tags). + Param(webservice.PathParameter("devops", "projectId")). + Param(webservice.PathParameter("pipelines", "pipelineId"))) + webservice.Route(webservice.PUT("/devops/{devops}/pipelines"). To(devopsapi.CreateDevOpsProjectPipelineHandler). - Doc("add devops project pipeline"). + Doc("update devops project pipeline"). + Param(webservice.PathParameter("devops", "projectId")). Metadata(restfulspec.KeyOpenAPITags, tags). Reads(devops.ProjectPipeline{})) - webservice.Route(webservice.PATCH("/devops/{devops}/members/{members}"). - To(devopsapi.UpdateDevOpsProjectMemberHandler). - Doc("update devops project members"). + webservice.Route(webservice.POST("/devops/{devops}/credentials"). + To(devopsapi.CreateDevOpsProjectCredentialHandler). + Doc("add project credential pipeline"). Metadata(restfulspec.KeyOpenAPITags, tags). - Writes(&devops.DevOpsProjectMembership{})) - webservice.Route(webservice.DELETE("/devops/{devops}/members/{members}"). - To(devopsapi.DeleteDevOpsProjectMemberHandler). - Doc("delete devops project members"). + Param(webservice.PathParameter("devops", "projectId")). + Reads(devops.JenkinsCredential{})) + + webservice.Route(webservice.PUT("/devops/{devops}/credentials/{credentials}"). + To(devopsapi.UpdateDevOpsProjectCredentialHandler). + Doc("update project credential pipeline"). Metadata(restfulspec.KeyOpenAPITags, tags). - Writes(&devops.DevOpsProjectMembership{})) + Param(webservice.PathParameter("devops", "projectId")). + Param(webservice.PathParameter("credentials", "credentialId")). + Reads(devops.JenkinsCredential{})) + + webservice.Route(webservice.DELETE("/devops/{devops}/credentials/{credentials}"). + To(devopsapi.DeleteDevOpsProjectCredentialHandler). + Doc("delete project credential pipeline"). + Metadata(restfulspec.KeyOpenAPITags, tags). + Param(webservice.PathParameter("devops", "projectId")). + Param(webservice.PathParameter("credentials", "credentialId"))) + + webservice.Route(webservice.GET("/devops/{devops}/credentials/{credentials}"). + To(devopsapi.GetDevOpsProjectCredentialHandler). + Doc("get project credential pipeline"). + Metadata(restfulspec.KeyOpenAPITags, tags). + Param(webservice.PathParameter("devops", "projectId")). + Param(webservice.PathParameter("credentials", "credentialId")). + Param(webservice.QueryParameter("content", "getContent")). + Param(webservice.QueryParameter("domain", "credentialDomain")). + Returns(http.StatusOK, "success", devops.JenkinsCredential{}). + Reads(devops.JenkinsCredential{})) + + webservice.Route(webservice.GET("/devops/{devops}/credentials"). + To(devopsapi.GetDevOpsProjectCredentialsHandler). + Doc("get project credential pipeline"). + Metadata(restfulspec.KeyOpenAPITags, tags). + Param(webservice.PathParameter("devops", "projectId")). + Param(webservice.PathParameter("credentials", "credentialId")). + Param(webservice.QueryParameter("domain", "credentialDomain")). + Returns(http.StatusOK, "success", []devops.JenkinsCredential{}). + Reads([]devops.JenkinsCredential{})) // match Jenkisn api "/blue/rest/organizations/jenkins/pipelines/{projectName}/{pipelineName}" webservice.Route(webservice.GET("/devops/{projectName}/pipelines/{pipelineName}"). diff --git a/pkg/apiserver/devops/project_credential.go b/pkg/apiserver/devops/project_credential.go new file mode 100644 index 000000000..a40d07b08 --- /dev/null +++ b/pkg/apiserver/devops/project_credential.go @@ -0,0 +1,152 @@ +package devops + +import ( + "github.com/emicklei/go-restful" + "github.com/golang/glog" + "kubesphere.io/kubesphere/pkg/constants" + "kubesphere.io/kubesphere/pkg/errors" + "kubesphere.io/kubesphere/pkg/models/devops" + "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 { + glog.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 { + glog.Errorf("%+v", err) + errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp) + return + } + credentialId, err := devops.CreateProjectCredential(projectId, username, credential) + + if err != nil { + glog.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("credentials") + var credential *devops.JenkinsCredential + err := request.ReadEntity(&credential) + if err != nil { + glog.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 { + glog.Errorf("%+v", err) + errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp) + return + } + credentialId, err = devops.UpdateProjectCredential(projectId, credentialId, credential) + + if err != nil { + glog.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("credentials") + var credential *devops.JenkinsCredential + err := request.ReadEntity(&credential) + if err != nil { + glog.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 { + glog.Errorf("%+v", err) + errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp) + return + } + credentialId, err = devops.DeleteProjectCredential(projectId, credentialId, credential) + + if err != nil { + glog.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("credentials") + getContent := request.QueryParameter("content") + domain := request.QueryParameter("domain") + + err := devops.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner, devops.ProjectMaintainer}) + if err != nil { + glog.Errorf("%+v", err) + errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp) + return + } + response, err := devops.GetProjectCredential(projectId, credentialId, domain, getContent) + + if err != nil { + glog.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 { + glog.Errorf("%+v", err) + errors.ParseSvcErr(restful.NewError(http.StatusForbidden, err.Error()), resp) + return + } + jenkinsCredentials, err := devops.GetProjectCredentials(projectId, domain) + if err != nil { + glog.Errorf("%+v", err) + errors.ParseSvcErr(err, resp) + return + } + resp.WriteAsJson(jenkinsCredentials) + return +} diff --git a/pkg/models/devops/project_credential.go b/pkg/models/devops/project_credential.go new file mode 100644 index 000000000..4d3710ec1 --- /dev/null +++ b/pkg/models/devops/project_credential.go @@ -0,0 +1,112 @@ +package devops + +import ( + "github.com/asaskevich/govalidator" + "time" +) + +const ( + CredentialTypeUsernamePassword = "username_password" + CredentialTypeSsh = "ssh" + CredentialTypeSecretText = "secret_text" + CredentialTypeKubeConfig = "kubeconfig" +) + +type JenkinsCredential struct { + Id string `json:"id"` + Type string `json:"type"` + DisplayName string `json:"display_name"` + Fingerprint *struct { + FileName string `json:"file_name,omitempty"` + Hash string `json:"hash,omitempty"` + Usage []*struct { + Name string `json:"name,omitempty"` + Ranges struct { + Ranges []*struct { + Start int `json:"start"` + End int `json:"end"` + } `json:"ranges"` + } `json:"ranges"` + } `json:"usage,omitempty"` + } `json:"fingerprint,omitempty"` + Description string `json:"description"` + Domain string `json:"domain"` + CreateTime *time.Time `json:"create_time,omitempty"` + Creator string `json:"creator,omitempty"` + UsernamePasswordCredential *UsernamePasswordCredential `json:"username_password"` + SshCredential *SshCredential `json:"ssh"` + SecretTextCredential *SecretTextCredential `json:"secret_text"` + KubeconfigCredential *KubeconfigCredential `json:"kubeconfig"` +} + +type UsernamePasswordCredential struct { + Id string `json:"id"` + Username string `json:"username"` + Password string `json:"password,omitempty"` + Description string `json:"description"` +} + +type SshCredential struct { + Id string `json:"id"` + Username string `json:"username"` + Passphrase string `json:"passphrase"` + PrivateKey string `json:"private_key" mapstructure:"private_key"` + Description string `json:"description"` +} + +type SecretTextCredential struct { + Id string `json:"id"` + Secret string `json:"secret"` + Description string `json:"description"` +} + +type KubeconfigCredential struct { + Id string `json:"id"` + Content string `json:"content"` + Description string `json:"description"` +} + +type DeleteCredentialRequest struct { + Domain string `json:"domain"` +} + +type CopySshCredentialRequest struct { + Id string `json:"id"` +} + +const ( + ProjectCredentialTableName = "project_credential" + ProjectCredentialIdColumn = "credential_id" + ProjectCredentialDomainColumn = "domain" + 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"` + Domain string `json:"domain"` + Creator string `json:"creator"` + CreateTime time.Time `json:"create_time"` +} + +var ProjectCredentialColumns = GetColumnsFromStruct(&ProjectCredential{}) + +func NewProjectCredential(projectId, credentialId, domain, creator string) *ProjectCredential { + if govalidator.IsNull(domain) { + domain = "_" + } + return &ProjectCredential{ + ProjectId: projectId, + CredentialId: credentialId, + Domain: domain, + Creator: creator, + CreateTime: time.Now(), + } +} diff --git a/pkg/models/devops/project_credential_handler.go b/pkg/models/devops/project_credential_handler.go new file mode 100644 index 000000000..de55e52f6 --- /dev/null +++ b/pkg/models/devops/project_credential_handler.go @@ -0,0 +1,468 @@ +package devops + +import ( + "fmt" + "github.com/PuerkitoBio/goquery" + "github.com/asaskevich/govalidator" + "github.com/emicklei/go-restful" + "github.com/gocraft/dbr" + "github.com/golang/glog" + + "kubesphere.io/kubesphere/pkg/db" + "kubesphere.io/kubesphere/pkg/gojenkins" + "kubesphere.io/kubesphere/pkg/gojenkins/utils" + "kubesphere.io/kubesphere/pkg/simple/client/admin_jenkins" + "kubesphere.io/kubesphere/pkg/simple/client/devops_mysql" + "net/http" + "strings" +) + +func CreateProjectCredential(projectId, username string, credentialRequest *JenkinsCredential) (string, error) { + jenkinsClient := admin_jenkins.Client() + switch credentialRequest.Type { + case CredentialTypeUsernamePassword: + err := checkJenkinsCredentialExists(projectId, credentialRequest.Domain, credentialRequest.UsernamePasswordCredential.Id) + if err != nil { + glog.Errorf("%+v", err) + return "", err + } + if credentialRequest.UsernamePasswordCredential == nil { + err := fmt.Errorf("usename_password should not be nil") + glog.Error(err) + return "", restful.NewError(http.StatusBadRequest, err.Error()) + } + credentialId, err := jenkinsClient.CreateUsernamePasswordCredentialInFolder(credentialRequest.Domain, + credentialRequest.UsernamePasswordCredential.Id, + credentialRequest.UsernamePasswordCredential.Username, + credentialRequest.UsernamePasswordCredential.Password, + credentialRequest.UsernamePasswordCredential.Description, + projectId) + if err != nil { + glog.Errorf("%+v", err) + return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error()) + } + err = insertCredentialToDb(projectId, *credentialId, credentialRequest.Domain, username) + if err != nil { + glog.Errorf("%+v", err) + return "", err + } + return *credentialId, nil + case CredentialTypeSsh: + err := checkJenkinsCredentialExists(projectId, credentialRequest.Domain, credentialRequest.SshCredential.Id) + if err != nil { + glog.Errorf("%+v", err) + return "", err + } + if credentialRequest.SshCredential == nil { + err := fmt.Errorf("ssh should not be nil") + glog.Error(err) + return "", restful.NewError(http.StatusBadRequest, err.Error()) + } + credentialId, err := jenkinsClient.CreateSshCredentialInFolder(credentialRequest.Domain, + credentialRequest.SshCredential.Id, + credentialRequest.SshCredential.Username, + credentialRequest.SshCredential.Passphrase, + credentialRequest.SshCredential.PrivateKey, + credentialRequest.SshCredential.Description, + projectId) + if err != nil { + glog.Errorf("%+v", err) + return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error()) + } + + err = insertCredentialToDb(projectId, *credentialId, credentialRequest.Domain, username) + if err != nil { + glog.Errorf("%+v", err) + return "", restful.NewError(http.StatusInternalServerError, err.Error()) + } + return *credentialId, nil + case CredentialTypeSecretText: + err := checkJenkinsCredentialExists(projectId, credentialRequest.Domain, credentialRequest.SecretTextCredential.Id) + if err != nil { + glog.Errorf("%+v", err) + return "", err + } + if credentialRequest.SecretTextCredential == nil { + err := fmt.Errorf("secret_text should not be nil") + glog.Error(err) + return "", restful.NewError(http.StatusBadRequest, err.Error()) + } + + credentialId, err := jenkinsClient.CreateSecretTextCredentialInFolder(credentialRequest.Domain, + credentialRequest.SecretTextCredential.Id, + credentialRequest.SecretTextCredential.Secret, + credentialRequest.SecretTextCredential.Description, + projectId) + if err != nil { + glog.Errorf("%+v", err) + return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error()) + } + + err = insertCredentialToDb(projectId, *credentialId, credentialRequest.Domain, username) + if err != nil { + glog.Errorf("%+v", err) + return "", restful.NewError(http.StatusInternalServerError, err.Error()) + } + return *credentialId, nil + case CredentialTypeKubeConfig: + err := checkJenkinsCredentialExists(projectId, credentialRequest.Domain, credentialRequest.KubeconfigCredential.Id) + if err != nil { + glog.Errorf("%+v", err) + return "", err + } + if credentialRequest.KubeconfigCredential == nil { + err := fmt.Errorf("kubeconfig should not be nil") + glog.Error(err) + return "", restful.NewError(http.StatusBadRequest, err.Error()) + } + credentialId, err := jenkinsClient.CreateKubeconfigCredentialInFolder(credentialRequest.Domain, + credentialRequest.KubeconfigCredential.Id, + credentialRequest.KubeconfigCredential.Content, + credentialRequest.KubeconfigCredential.Description, + projectId) + if err != nil { + glog.Errorf("%+v", err) + return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error()) + } + err = insertCredentialToDb(projectId, *credentialId, credentialRequest.Domain, username) + if err != nil { + glog.Errorf("%+v", err) + return "", restful.NewError(http.StatusInternalServerError, err.Error()) + } + return *credentialId, nil + default: + err := fmt.Errorf("error unsupport credential type") + glog.Errorf("%+v", err) + return "", restful.NewError(http.StatusBadRequest, err.Error()) + + } + +} + +func UpdateProjectCredential(projectId, credentialId string, credentialRequest *JenkinsCredential) (string, error) { + jenkinsClient := admin_jenkins.Client() + jenkinsCredential, err := jenkinsClient.GetCredentialInFolder(credentialRequest.Domain, + credentialId, + projectId) + if err != nil { + glog.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") + glog.Error(err) + return "", restful.NewError(http.StatusBadRequest, err.Error()) + } + credentialId, err := jenkinsClient.UpdateUsernamePasswordCredentialInFolder(credentialRequest.Domain, + credentialId, + credentialRequest.UsernamePasswordCredential.Username, + credentialRequest.UsernamePasswordCredential.Password, + credentialRequest.UsernamePasswordCredential.Description, + projectId) + if err != nil { + glog.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") + glog.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.SshCredential.Description, + projectId) + if err != nil { + glog.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") + glog.Error(err) + return "", restful.NewError(http.StatusBadRequest, err.Error()) + } + credentialId, err := jenkinsClient.UpdateSecretTextCredentialInFolder(credentialRequest.Domain, + credentialId, + credentialRequest.SecretTextCredential.Secret, + credentialRequest.SecretTextCredential.Description, + projectId) + if err != nil { + glog.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") + glog.Error(err) + return "", restful.NewError(http.StatusBadRequest, err.Error()) + } + credentialId, err := jenkinsClient.UpdateKubeconfigCredentialInFolder(credentialRequest.Domain, + credentialId, + credentialRequest.KubeconfigCredential.Content, + credentialRequest.KubeconfigCredential.Description, + projectId) + if err != nil { + glog.Errorf("%+v", err) + return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error()) + } + return *credentialId, nil + default: + err := fmt.Errorf("error unsupport credential type") + glog.Errorf("%+v", err) + return "", restful.NewError(http.StatusBadRequest, err.Error()) + + } + +} + +func DeleteProjectCredential(projectId, credentialId string, credentialRequest *JenkinsCredential) (string, error) { + jenkinsClient := admin_jenkins.Client() + dbClient := devops_mysql.OpenDatabase() + _, err := jenkinsClient.GetCredentialInFolder(credentialRequest.Domain, + credentialId, + projectId) + if err != nil { + glog.Errorf("%+v", err) + return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error()) + } + id, err := jenkinsClient.DeleteCredentialInFolder(credentialRequest.Domain, credentialId, projectId) + if err != nil { + glog.Errorf("%+v", err) + return "", restful.NewError(utils.GetJenkinsStatusCode(err), err.Error()) + } + + 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, "_")) + } + + _, err = dbClient.DeleteFrom(ProjectCredentialTableName). + Where(db.And(deleteConditions...)).Exec() + if err != nil && err != db.ErrNotFound { + glog.Errorf("%+v", err) + return "", restful.NewError(http.StatusInternalServerError, err.Error()) + } + return *id, nil + +} + +func GetProjectCredential(projectId, credentialId, domain, getContent string) (*JenkinsCredential, error) { + jenkinsClient := admin_jenkins.Client() + dbClient := devops_mysql.OpenDatabase() + jenkinsResponse, err := jenkinsClient.GetCredentialInFolder(domain, + credentialId, + projectId) + if err != nil { + glog.Errorf("%+v", err) + return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error()) + } + + projectCredential := &ProjectCredential{} + err = dbClient.Select(ProjectCredentialColumns...). + From(ProjectCredentialTableName).Where( + db.And(db.Eq(ProjectCredentialProjectIdColumn, projectId), + db.Eq(ProjectCredentialIdColumn, credentialId), + db.Eq(ProjectCredentialDomainColumn, jenkinsResponse.Domain))).LoadOne(projectCredential) + + if err != nil && err != db.ErrNotFound { + glog.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 { + glog.Errorf("%+v", err) + return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error()) + } + stringReader := strings.NewReader(stringBody) + doc, err := goquery.NewDocumentFromReader(stringReader) + if err != nil { + glog.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 + }) + + doc.Find("input[name*=id][type=text]").Each(func(i int, selection *goquery.Selection) { + value, _ := selection.Attr("value") + content.Id = value + }) + doc.Find("input[name*=description]").Each(func(i int, selection *goquery.Selection) { + value, _ := selection.Attr("value") + content.Description = 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 + }) + + doc.Find("input[name*=id][type=text]").Each(func(i int, selection *goquery.Selection) { + value, _ := selection.Attr("value") + content.Id = value + }) + doc.Find("input[name*=description]").Each(func(i int, selection *goquery.Selection) { + value, _ := selection.Attr("value") + content.Description = 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("input[name*=id][type=text]").Each(func(i int, selection *goquery.Selection) { + value, _ := selection.Attr("value") + content.Id = value + }) + doc.Find("input[name*=description]").Each(func(i int, selection *goquery.Selection) { + value, _ := selection.Attr("value") + content.Description = value + }) + doc.Find("textarea[name*=privateKey]").Each(func(i int, selection *goquery.Selection) { + value := selection.Text() + content.PrivateKey = value + }) + response.SshCredential = content + } + } + return response, nil + +} + +func GetProjectCredentials(projectId, domain string) ([]*JenkinsCredential, error) { + jenkinsClient := admin_jenkins.Client() + dbClient := devops_mysql.OpenDatabase() + jenkinsCredentialResponses, err := jenkinsClient.GetCredentialsInFolder(domain, projectId) + if err != nil { + glog.Errorf("%+v", err) + return nil, restful.NewError(utils.GetJenkinsStatusCode(err), err.Error()) + } + 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...). + From(ProjectCredentialTableName).Where(selectCondition).Load(&projectCredentials) + if err != nil { + glog.Errorf("%+v", err) + return nil, restful.NewError(http.StatusInternalServerError, err.Error()) + } + response := formatCredentialsResponse(jenkinsCredentialResponses, projectCredentials) + return response, nil +} + +func insertCredentialToDb(projectId, credentialId, domain, username string) error { + dbClient := devops_mysql.OpenDatabase() + projectCredential := NewProjectCredential(projectId, credentialId, domain, username) + _, err := dbClient.InsertInto(ProjectCredentialTableName).Columns(ProjectCredentialColumns...). + Record(projectCredential).Exec() + if err != nil { + glog.Errorf("%+v", err) + return restful.NewError(http.StatusInternalServerError, err.Error()) + } + return nil +} + +func checkJenkinsCredentialExists(projectId, domain, credentialId string) error { + jenkinsClient := admin_jenkins.Client() + credential, err := jenkinsClient.GetCredentialInFolder(domain, credentialId, projectId) + if credential != nil { + err := fmt.Errorf("credential id [%s] has been used", credential.Id) + glog.Warning(err.Error()) + return restful.NewError(http.StatusConflict, err.Error()) + } + if err != nil && utils.GetJenkinsStatusCode(err) != http.StatusNotFound { + glog.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 != "" { + response.Fingerprint = &struct { + FileName string `json:"file_name,omitempty"` + Hash string `json:"hash,omitempty"` + Usage []*struct { + Name string `json:"name,omitempty"` + Ranges struct { + Ranges []*struct { + Start int `json:"start"` + End int `json:"end"` + } `json:"ranges"` + } `json:"ranges"` + } `json:"usage,omitempty"` + }{} + response.Fingerprint.FileName = jenkinsCredentialResponse.Fingerprint.FileName + response.Fingerprint.Hash = jenkinsCredentialResponse.Fingerprint.Hash + for _, usage := range jenkinsCredentialResponse.Fingerprint.Usage { + response.Fingerprint.Usage = append(response.Fingerprint.Usage, usage) + } + } + response.Domain = jenkinsCredentialResponse.Domain + + if dbCredentialResponse != nil { + response.CreateTime = &dbCredentialResponse.CreateTime + response.Creator = dbCredentialResponse.Creator + } + + credentialType, ok := CredentialTypeMap[jenkinsCredentialResponse.TypeName] + if ok { + response.Type = credentialType + return response + } + response.Type = jenkinsCredentialResponse.TypeName + return response +} + +func formatCredentialsResponse(jenkinsCredentialsResponse []*gojenkins.CredentialResponse, + projectCredentials []*ProjectCredential) []*JenkinsCredential { + responseSlice := make([]*JenkinsCredential, 0) + for _, jenkinsCredential := range jenkinsCredentialsResponse { + var dbCredential *ProjectCredential = nil + for _, projectCredential := range projectCredentials { + if projectCredential.CredentialId == jenkinsCredential.Id && + projectCredential.Domain == jenkinsCredential.Domain { + dbCredential = projectCredential + } + } + responseSlice = append(responseSlice, formatCredentialResponse(jenkinsCredential, dbCredential)) + } + return responseSlice +}