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:
@@ -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.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
}
|
||||
@@ -1,633 +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 (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_NoScmPipelineConfig(t *testing.T) {
|
||||
inputs := []*NoScmPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
DisableConcurrent: true,
|
||||
},
|
||||
}
|
||||
for _, input := range inputs {
|
||||
outputString, err := createPipelineConfigXml(input)
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
output, err := parsePipelineConfigXml(outputString)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(input, output) {
|
||||
t.Fatalf("input [%+v] output [%+v] should equal ", input, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_NoScmPipelineConfig_Discarder(t *testing.T) {
|
||||
inputs := []*NoScmPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
Discarder: &DiscarderProperty{
|
||||
"3", "5",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
Discarder: &DiscarderProperty{
|
||||
"3", "",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
Discarder: &DiscarderProperty{
|
||||
"", "21321",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
Discarder: &DiscarderProperty{
|
||||
"", "",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, input := range inputs {
|
||||
outputString, err := createPipelineConfigXml(input)
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
output, err := parsePipelineConfigXml(outputString)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(input, output) {
|
||||
t.Fatalf("input [%+v] output [%+v] should equal ", input, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_NoScmPipelineConfig_Param(t *testing.T) {
|
||||
inputs := []*NoScmPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
Parameters: &Parameters{
|
||||
&Parameter{
|
||||
Name: "d",
|
||||
DefaultValue: "a\nb",
|
||||
Type: "choice",
|
||||
Description: "fortest",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
Parameters: &Parameters{
|
||||
&Parameter{
|
||||
Name: "a",
|
||||
DefaultValue: "abc",
|
||||
Type: "string",
|
||||
Description: "fortest",
|
||||
},
|
||||
&Parameter{
|
||||
Name: "b",
|
||||
DefaultValue: "false",
|
||||
Type: "boolean",
|
||||
Description: "fortest",
|
||||
},
|
||||
&Parameter{
|
||||
Name: "c",
|
||||
DefaultValue: "password \n aaa",
|
||||
Type: "text",
|
||||
Description: "fortest",
|
||||
},
|
||||
&Parameter{
|
||||
Name: "d",
|
||||
DefaultValue: "a\nb",
|
||||
Type: "choice",
|
||||
Description: "fortest",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, input := range inputs {
|
||||
outputString, err := createPipelineConfigXml(input)
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
output, err := parsePipelineConfigXml(outputString)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(input, output) {
|
||||
t.Fatalf("input [%+v] output [%+v] should equal ", input, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_NoScmPipelineConfig_Trigger(t *testing.T) {
|
||||
inputs := []*NoScmPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
TimerTrigger: &TimerTrigger{
|
||||
Cron: "1 1 1 * * *",
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
RemoteTrigger: &RemoteTrigger{
|
||||
Token: "abc",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
Jenkinsfile: "node{echo 'hello'}",
|
||||
TimerTrigger: &TimerTrigger{
|
||||
Cron: "1 1 1 * * *",
|
||||
},
|
||||
RemoteTrigger: &RemoteTrigger{
|
||||
Token: "abc",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, input := range inputs {
|
||||
outputString, err := createPipelineConfigXml(input)
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
output, err := parsePipelineConfigXml(outputString)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(input, output) {
|
||||
t.Fatalf("input [%+v] output [%+v] should equal ", input, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_MultiBranchPipelineConfig(t *testing.T) {
|
||||
|
||||
inputs := []*MultiBranchPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "git",
|
||||
GitSource: &GitSource{},
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "github",
|
||||
GitHubSource: &GithubSource{},
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "single_svn",
|
||||
SingleSvnSource: &SingleSvnSource{},
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "svn",
|
||||
SvnSource: &SvnSource{},
|
||||
},
|
||||
}
|
||||
for _, input := range inputs {
|
||||
outputString, err := createMultiBranchPipelineConfigXml("", input)
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
output, err := parseMultiBranchPipelineConfigXml(outputString)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(input, output) {
|
||||
t.Fatalf("input [%+v] output [%+v] should equal ", input, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_MultiBranchPipelineConfig_Discarder(t *testing.T) {
|
||||
|
||||
inputs := []*MultiBranchPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "git",
|
||||
Discarder: &DiscarderProperty{
|
||||
DaysToKeep: "1",
|
||||
NumToKeep: "2",
|
||||
},
|
||||
GitSource: &GitSource{},
|
||||
},
|
||||
}
|
||||
for _, input := range inputs {
|
||||
outputString, err := createMultiBranchPipelineConfigXml("", input)
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
output, err := parseMultiBranchPipelineConfigXml(outputString)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(input, output) {
|
||||
t.Fatalf("input [%+v] output [%+v] should equal ", input, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_MultiBranchPipelineConfig_TimerTrigger(t *testing.T) {
|
||||
inputs := []*MultiBranchPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "git",
|
||||
TimerTrigger: &TimerTrigger{
|
||||
Interval: "12345566",
|
||||
},
|
||||
GitSource: &GitSource{},
|
||||
},
|
||||
}
|
||||
for _, input := range inputs {
|
||||
outputString, err := createMultiBranchPipelineConfigXml("", input)
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
output, err := parseMultiBranchPipelineConfigXml(outputString)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(input, output) {
|
||||
t.Fatalf("input [%+v] output [%+v] should equal ", input, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_MultiBranchPipelineConfig_Source(t *testing.T) {
|
||||
|
||||
inputs := []*MultiBranchPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "git",
|
||||
TimerTrigger: &TimerTrigger{
|
||||
Interval: "12345566",
|
||||
},
|
||||
GitSource: &GitSource{
|
||||
Url: "https://github.com/kubesphere/devops",
|
||||
CredentialId: "git",
|
||||
DiscoverBranches: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "github",
|
||||
TimerTrigger: &TimerTrigger{
|
||||
Interval: "12345566",
|
||||
},
|
||||
GitHubSource: &GithubSource{
|
||||
Owner: "kubesphere",
|
||||
Repo: "devops",
|
||||
CredentialId: "github",
|
||||
ApiUri: "https://api.github.com",
|
||||
DiscoverBranches: 1,
|
||||
DiscoverPRFromOrigin: 2,
|
||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
||||
Strategy: 1,
|
||||
Trust: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "bitbucket_server",
|
||||
TimerTrigger: &TimerTrigger{
|
||||
Interval: "12345566",
|
||||
},
|
||||
BitbucketServerSource: &BitbucketServerSource{
|
||||
Owner: "kubesphere",
|
||||
Repo: "devops",
|
||||
CredentialId: "github",
|
||||
ApiUri: "https://api.github.com",
|
||||
DiscoverBranches: 1,
|
||||
DiscoverPRFromOrigin: 2,
|
||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
||||
Strategy: 1,
|
||||
Trust: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "svn",
|
||||
TimerTrigger: &TimerTrigger{
|
||||
Interval: "12345566",
|
||||
},
|
||||
SvnSource: &SvnSource{
|
||||
Remote: "https://api.svn.com/bcd",
|
||||
CredentialId: "svn",
|
||||
Excludes: "truck",
|
||||
Includes: "tag/*",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "single_svn",
|
||||
TimerTrigger: &TimerTrigger{
|
||||
Interval: "12345566",
|
||||
},
|
||||
SingleSvnSource: &SingleSvnSource{
|
||||
Remote: "https://api.svn.com/bcd",
|
||||
CredentialId: "svn",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, input := range inputs {
|
||||
outputString, err := createMultiBranchPipelineConfigXml("", input)
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
output, err := parseMultiBranchPipelineConfigXml(outputString)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(input, output) {
|
||||
t.Fatalf("input [%+v] output [%+v] should equal ", input, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_MultiBranchPipelineCloneConfig(t *testing.T) {
|
||||
|
||||
inputs := []*MultiBranchPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "git",
|
||||
GitSource: &GitSource{
|
||||
Url: "https://github.com/kubesphere/devops",
|
||||
CredentialId: "git",
|
||||
DiscoverBranches: true,
|
||||
CloneOption: &GitCloneOption{
|
||||
Shallow: false,
|
||||
Depth: 3,
|
||||
Timeout: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "github",
|
||||
GitHubSource: &GithubSource{
|
||||
Owner: "kubesphere",
|
||||
Repo: "devops",
|
||||
CredentialId: "github",
|
||||
ApiUri: "https://api.github.com",
|
||||
DiscoverBranches: 1,
|
||||
DiscoverPRFromOrigin: 2,
|
||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
||||
Strategy: 1,
|
||||
Trust: 1,
|
||||
},
|
||||
CloneOption: &GitCloneOption{
|
||||
Shallow: false,
|
||||
Depth: 3,
|
||||
Timeout: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, input := range inputs {
|
||||
outputString, err := createMultiBranchPipelineConfigXml("", input)
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
output, err := parseMultiBranchPipelineConfigXml(outputString)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(input, output) {
|
||||
t.Fatalf("input [%+v] output [%+v] should equal ", input, output)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Test_MultiBranchPipelineRegexFilter(t *testing.T) {
|
||||
|
||||
inputs := []*MultiBranchPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "git",
|
||||
GitSource: &GitSource{
|
||||
Url: "https://github.com/kubesphere/devops",
|
||||
CredentialId: "git",
|
||||
DiscoverBranches: true,
|
||||
RegexFilter: ".*",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "github",
|
||||
GitHubSource: &GithubSource{
|
||||
Owner: "kubesphere",
|
||||
Repo: "devops",
|
||||
CredentialId: "github",
|
||||
ApiUri: "https://api.github.com",
|
||||
DiscoverBranches: 1,
|
||||
DiscoverPRFromOrigin: 2,
|
||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
||||
Strategy: 1,
|
||||
Trust: 1,
|
||||
},
|
||||
RegexFilter: ".*",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, input := range inputs {
|
||||
outputString, err := createMultiBranchPipelineConfigXml("", input)
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
output, err := parseMultiBranchPipelineConfigXml(outputString)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(input, output) {
|
||||
t.Fatalf("input [%+v] output [%+v] should equal ", input, output)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Test_MultiBranchPipelineMultibranchTrigger(t *testing.T) {
|
||||
|
||||
inputs := []*MultiBranchPipeline{
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "github",
|
||||
GitHubSource: &GithubSource{
|
||||
Owner: "kubesphere",
|
||||
Repo: "devops",
|
||||
CredentialId: "github",
|
||||
ApiUri: "https://api.github.com",
|
||||
DiscoverBranches: 1,
|
||||
DiscoverPRFromOrigin: 2,
|
||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
||||
Strategy: 1,
|
||||
Trust: 1,
|
||||
},
|
||||
RegexFilter: ".*",
|
||||
},
|
||||
MultiBranchJobTrigger: &MultiBranchJobTrigger{
|
||||
CreateActionJobsToTrigger: "abc",
|
||||
DeleteActionJobsToTrigger: "ddd",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "github",
|
||||
GitHubSource: &GithubSource{
|
||||
Owner: "kubesphere",
|
||||
Repo: "devops",
|
||||
CredentialId: "github",
|
||||
ApiUri: "https://api.github.com",
|
||||
DiscoverBranches: 1,
|
||||
DiscoverPRFromOrigin: 2,
|
||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
||||
Strategy: 1,
|
||||
Trust: 1,
|
||||
},
|
||||
RegexFilter: ".*",
|
||||
},
|
||||
MultiBranchJobTrigger: &MultiBranchJobTrigger{
|
||||
CreateActionJobsToTrigger: "abc",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "",
|
||||
Description: "for test",
|
||||
ScriptPath: "Jenkinsfile",
|
||||
SourceType: "github",
|
||||
GitHubSource: &GithubSource{
|
||||
Owner: "kubesphere",
|
||||
Repo: "devops",
|
||||
CredentialId: "github",
|
||||
ApiUri: "https://api.github.com",
|
||||
DiscoverBranches: 1,
|
||||
DiscoverPRFromOrigin: 2,
|
||||
DiscoverPRFromForks: &DiscoverPRFromForks{
|
||||
Strategy: 1,
|
||||
Trust: 1,
|
||||
},
|
||||
RegexFilter: ".*",
|
||||
},
|
||||
MultiBranchJobTrigger: &MultiBranchJobTrigger{
|
||||
DeleteActionJobsToTrigger: "ddd",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, input := range inputs {
|
||||
outputString, err := createMultiBranchPipelineConfigXml("", input)
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
output, err := parseMultiBranchPipelineConfigXml(outputString)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("should not get error %+v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(input, output) {
|
||||
t.Fatalf("input [%+v] output [%+v] should equal ", input, output)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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"
|
||||
)
|
||||
Reference in New Issue
Block a user