diff --git a/apis/management.cattle.io/v3/k8s_defaults.go b/apis/management.cattle.io/v3/k8s_defaults.go index 60af85d2..cfa3da78 100644 --- a/apis/management.cattle.io/v3/k8s_defaults.go +++ b/apis/management.cattle.io/v3/k8s_defaults.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + projectv3 "github.com/rancher/types/apis/project.cattle.io/v3" "github.com/rancher/types/image" ) @@ -53,18 +54,21 @@ var ( // ToolsSystemImages default images for alert, pipeline, logging ToolsSystemImages = struct { AlertSystemImages AlertSystemImages - PipelineSystemImages PipelineSystemImages + PipelineSystemImages projectv3.PipelineSystemImages LoggingSystemImages LoggingSystemImages }{ AlertSystemImages: AlertSystemImages{ AlertManager: m("prom/alertmanager:v0.11.0"), AlertManagerHelper: m("rancher/alertmanager-helper:v0.0.2"), }, - PipelineSystemImages: PipelineSystemImages{ - Jenkins: m("jenkins/jenkins:2.107-slim"), + PipelineSystemImages: projectv3.PipelineSystemImages{ + Jenkins: m("rancher/pipeline-jenkins-server:v0.1.0"), JenkinsJnlp: m("jenkins/jnlp-slave:3.10-1-alpine"), AlpineGit: m("alpine/git:1.0.4"), - PluginsDocker: m("plugins/docker:17.12"), + PluginsDocker: m("rancher/pipeline-docker-publish:v0.2.0"), + Minio: m("minio/minio:RELEASE.2018-05-25T19-49-13Z"), + Registry: m("registry:2"), + KubeApply: m("rancher/pipeline-kube-apply:v0.2.0"), }, LoggingSystemImages: LoggingSystemImages{ Fluentd: m("rancher/fluentd:v0.1.10"), diff --git a/apis/management.cattle.io/v3/pipeline_types.go b/apis/management.cattle.io/v3/pipeline_types.go deleted file mode 100644 index 58c26727..00000000 --- a/apis/management.cattle.io/v3/pipeline_types.go +++ /dev/null @@ -1,274 +0,0 @@ -package v3 - -import ( - "github.com/rancher/norman/condition" - "github.com/rancher/norman/types" - "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -type PipelineConditionType string - -const ( - PipelineExecutionConditonProvisioned condition.Cond = "Provisioned" - PipelineExecutionConditionCompleted condition.Cond = "Completed" -) - -type ClusterPipeline struct { - types.Namespaced - - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec ClusterPipelineSpec `json:"spec"` - Status ClusterPipelineStatus `json:"status"` -} - -type Pipeline struct { - types.Namespaced - - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - ProjectName string `json:"projectName" yaml:"projectName" norman:"required,type=reference[project]"` - - Spec PipelineSpec `json:"spec"` - Status PipelineStatus `json:"status"` -} - -type PipelineExecution struct { - types.Namespaced - - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - ProjectName string `json:"projectName" yaml:"projectName" norman:"required,type=reference[project]"` - - Spec PipelineExecutionSpec `json:"spec"` - Status PipelineExecutionStatus `json:"status"` -} - -type PipelineExecutionLog struct { - types.Namespaced - - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - ProjectName string `json:"projectName" yaml:"projectName" norman:"required,type=reference[project]"` - - Spec PipelineExecutionLogSpec `json:"spec"` -} - -type SourceCodeCredential struct { - types.Namespaced - - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec SourceCodeCredentialSpec `json:"spec"` - Status SourceCodeCredentialStatus `json:"status"` -} - -type SourceCodeRepository struct { - types.Namespaced - - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec SourceCodeRepositorySpec `json:"spec"` - Status SourceCodeRepositoryStatus `json:"status"` -} - -type ClusterPipelineSpec struct { - ClusterName string `json:"clusterName" norman:"type=reference[cluster]"` - Deploy bool `json:"deploy"` - GithubConfig *GithubClusterConfig `json:"githubConfig,omitempty"` -} - -type ClusterPipelineStatus struct { -} - -type GithubClusterConfig struct { - TLS bool `json:"tls,omitempty"` - Host string `json:"host,omitempty"` - ClientID string `json:"clientId,omitempty"` - ClientSecret string `json:"clientSecret,omitempty"` - RedirectURL string `json:"redirectUrl,omitempty"` -} - -type PipelineStatus struct { - PipelineState string `json:"pipelineState,omitempty" norman:"required,options=active|inactive,default=active"` - NextRun int `json:"nextRun" yaml:"nextRun,omitempty" norman:"default=1,min=1"` - LastExecutionID string `json:"lastExecutionId,omitempty" yaml:"lastExecutionId,omitempty"` - LastRunState string `json:"lastRunState,omitempty" yaml:"lastRunState,omitempty"` - LastStarted string `json:"lastStarted,omitempty" yaml:"lastStarted,omitempty"` - NextStart string `json:"nextStart,omitempty" yaml:"nextStart,omitempty"` - WebHookID string `json:"webhookId,omitempty" yaml:"webhookId,omitempty"` - Token string `json:"token,omitempty" yaml:"token,omitempty" norman:"writeOnly,noupdate"` - SourceCodeCredential *SourceCodeCredential `json:"sourceCodeCredential,omitempty" yaml:"sourceCodeCredential,omitempty"` -} - -type PipelineSpec struct { - DisplayName string `json:"displayName,omitempty" yaml:"displayName,omitempty"` - TriggerWebhookPush bool `json:"triggerWebhookPush,omitempty" yaml:"triggerWebhookPush,omitempty"` - TriggerWebhookPr bool `json:"triggerWebhookPr,omitempty" yaml:"triggerWebhookPr,omitempty"` - TriggerWebhookTag bool `json:"triggerWebhookTag,omitempty" yaml:"triggerWebhookTag,omitempty"` - TriggerCronTimezone string `json:"triggerCronTimezone,omitempty" yaml:"triggerCronTimezone,omitempty"` - TriggerCronExpression string `json:"triggerCronExpression,omitempty" yaml:"triggerCronExpression,omitempty"` - - Stages []Stage `json:"stages,omitempty" yaml:"stages,omitempty"` - - Templates map[string]string `json:"templates,omitempty" yaml:"templates,omitempty"` -} - -type PipelineCondition struct { - // Type of cluster condition. - Type PipelineConditionType `json:"type"` - // Status of the condition, one of True, False, Unknown. - Status v1.ConditionStatus `json:"status"` - // The last time this condition was updated. - LastUpdateTime string `json:"lastUpdateTime,omitempty"` - // Last time the condition transitioned from one status to another. - LastTransitionTime string `json:"lastTransitionTime,omitempty"` - // The reason for the condition's last transition. - Reason string `json:"reason,omitempty"` - // Human-readable message indicating details about last transition - Message string `json:"message,omitempty"` -} - -type Stage struct { - Name string `json:"name,omitempty" yaml:"name,omitempty" norman:"required"` - Steps []Step `json:"steps,omitempty" yaml:"steps,omitempty" norman:"required"` -} - -type Step struct { - SourceCodeConfig *SourceCodeConfig `json:"sourceCodeConfig,omitempty" yaml:"sourceCodeConfig,omitempty"` - RunScriptConfig *RunScriptConfig `json:"runScriptConfig,omitempty" yaml:"runScriptConfig,omitempty"` - PublishImageConfig *PublishImageConfig `json:"publishImageConfig,omitempty" yaml:"publishImageConfig,omitempty"` - //Step timeout in minutes - Timeout int `json:"timeout,omitempty" yaml:"timeout,omitempty"` -} - -type SourceCodeConfig struct { - URL string `json:"url,omitempty" yaml:"url,omitempty" norman:"required"` - Branch string `json:"branch,omitempty" yaml:"branch,omitempty" ` - BranchCondition string `json:"branchCondition,omitempty" yaml:"branchCondition,omitempty" norman:"options=only|except|all"` - SourceCodeCredentialName string `json:"sourceCodeCredentialName,omitempty" yaml:"sourceCodeCredentialName,omitempty" norman:"type=reference[sourceCodeCredential]"` -} - -type RunScriptConfig struct { - Image string `json:"image,omitempty" yaml:"image,omitempty" norman:"required"` - IsShell bool `json:"isShell,omitempty" yaml:"isShell,omitempty"` - ShellScript string `json:"shellScript,omitempty" yaml:"shellScript,omitempty"` - Entrypoint string `json:"entrypoint,omitempty" yaml:"enrtypoint,omitempty"` - Command string `json:"command,omitempty" yaml:"command,omitempty"` - Env []string `json:"env,omitempty" yaml:"env,omitempty"` -} - -type PublishImageConfig struct { - DockerfilePath string `json:"dockerfilePath,omittempty" yaml:"dockerfilePath,omitempty" norman:"required,default=./Dockerfile"` - BuildContext string `json:"buildContext,omitempty" yaml:"buildContext,omitempty" norman:"required,default=."` - Tag string `json:"tag,omitempty" yaml:"tag,omitempty" norman:"required,default=${CICD_GIT_REPOSITORY_NAME}:${CICD_GIT_BRANCH}"` -} - -type PipelineExecutionSpec struct { - PipelineName string `json:"pipelineName" norman:"required,type=reference[pipeline]"` - Run int `json:"run,omitempty" norman:"required,min=1"` - TriggeredBy string `json:"triggeredBy,omitempty" norman:"required,options=user|cron|webhook"` - TriggerUserName string `json:"triggerUserName,omitempty" norman:"type=reference[user]"` - Pipeline Pipeline `json:"pipeline,omitempty" norman:"required"` -} - -type PipelineExecutionStatus struct { - Conditions []PipelineCondition `json:"conditions,omitempty"` - - Commit string `json:"commit,omitempty"` - ExecutionState string `json:"executionState,omitempty"` - Started string `json:"started,omitempty"` - Ended string `json:"ended,omitempty"` - Stages []StageStatus `json:"stages,omitempty"` - EnvVars map[string]string `json:"envVars,omitempty"` -} - -type StageStatus struct { - State string `json:"state,omitempty"` - Started string `json:"started,omitempty"` - Ended string `json:"ended,omitempty"` - Steps []StepStatus `json:"steps,omitempty"` -} - -type StepStatus struct { - State string `json:"state,omitempty"` - Started string `json:"started,omitempty"` - Ended string `json:"ended,omitempty"` -} - -type SourceCodeCredentialSpec struct { - ClusterName string `json:"clusterName" norman:"required,type=reference[cluster]"` - SourceCodeType string `json:"sourceCodeType,omitempty" norman:"required,options=github"` - UserName string `json:"userName" norman:"required,type=reference[user]"` - DisplayName string `json:"displayName,omitempty" norman:"required"` - AvatarURL string `json:"avatarUrl,omitempty"` - HTMLURL string `json:"htmlUrl,omitempty"` - LoginName string `json:"loginName,omitempty"` - AccessToken string `json:"accessToken,omitempty" norman:"writeOnly,noupdate"` -} - -type SourceCodeCredentialStatus struct { -} - -type SourceCodeRepositorySpec struct { - ClusterName string `json:"clusterName" norman:"required,type=reference[cluster]"` - SourceCodeType string `json:"sourceCodeType,omitempty" norman:"required,options=github"` - UserName string `json:"userName" norman:"required,type=reference[user]"` - SourceCodeCredentialName string `json:"sourceCodeCredentialName,omitempty" norman:"required,type=reference[sourceCodeCredential]"` - URL string `json:"url,omitempty"` - Permissions RepoPerm `json:"permissions,omitempty"` - Language string `json:"language,omitempty"` - DefaultBranch string `json:"defaultBranch,omitempty"` -} - -type SourceCodeRepositoryStatus struct { -} - -type RepoPerm struct { - Pull bool `json:"pull,omitempty"` - Push bool `json:"push,omitempty"` - Admin bool `json:"admin,omitempty"` -} - -type PipelineExecutionLogSpec struct { - PipelineExecutionName string `json:"pipelineExecutionName,omitempty" norman:"type=reference[pipelineExecution]"` - Stage int `json:"stage,omitempty" norman:"min=1"` - Step int `json:"step,omitempty" norman:"min=1"` - Line int `json:"line,omitempty"` - Message string `json:"message,omitempty"` -} - -type RunPipelineInput struct { - Branch string `json:"branch,omitempty"` -} - -type AuthAppInput struct { - InheritGlobal bool `json:"inheritGlobal,omitempty"` - SourceCodeType string `json:"sourceCodeType,omitempty" norman:"type=string,required"` - RedirectURL string `json:"redirectUrl,omitempty" norman:"type=string"` - TLS bool `json:"tls,omitempty"` - Host string `json:"host,omitempty"` - ClientID string `json:"clientId,omitempty" norman:"type=string,required"` - ClientSecret string `json:"clientSecret,omitempty" norman:"type=string,required"` - Code string `json:"code,omitempty" norman:"type=string,required"` -} - -type AuthUserInput struct { - SourceCodeType string `json:"sourceCodeType,omitempty" norman:"type=string,required"` - RedirectURL string `json:"redirectUrl,omitempty" norman:"type=string"` - Code string `json:"code,omitempty" norman:"type=string,required"` -} - -type PipelineSystemImages struct { - Jenkins string `json:"jenkins,omitempty"` - JenkinsJnlp string `json:"jenkinsJnlp,omitempty"` - AlpineGit string `json:"alpineGit,omitempty"` - PluginsDocker string `json:"pluginsDocker,omitempty"` -} diff --git a/apis/management.cattle.io/v3/schema/schema.go b/apis/management.cattle.io/v3/schema/schema.go index 1e6c76d7..12bea36b 100644 --- a/apis/management.cattle.io/v3/schema/schema.go +++ b/apis/management.cattle.io/v3/schema/schema.go @@ -34,7 +34,6 @@ var ( Init(globalTypes). Init(rkeTypes). Init(alertTypes). - Init(pipelineTypes). Init(composeType). Init(resourceQuotaTemplateTypes) @@ -535,65 +534,6 @@ func alertTypes(schema *types.Schemas) *types.Schemas { } -func pipelineTypes(schema *types.Schemas) *types.Schemas { - return schema. - AddMapperForType(&Version, v3.ClusterPipeline{}). - AddMapperForType(&Version, v3.Pipeline{}, - &m.Embed{Field: "status"}, - m.DisplayName{}). - AddMapperForType(&Version, v3.PipelineExecution{}, - &m.Embed{Field: "status"}). - AddMapperForType(&Version, v3.SourceCodeCredential{}). - AddMapperForType(&Version, v3.SourceCodeRepository{}). - AddMapperForType(&Version, v3.PipelineExecutionLog{}). - MustImport(&Version, v3.AuthAppInput{}). - MustImport(&Version, v3.AuthUserInput{}). - MustImport(&Version, v3.RunPipelineInput{}). - MustImportAndCustomize(&Version, v3.ClusterPipeline{}, func(schema *types.Schema) { - schema.ResourceActions = map[string]types.Action{ - "deploy": {}, - "destroy": {}, - "authapp": { - Input: "authAppInput", - Output: "clusterPipeline", - }, - "revokeapp": {}, - "authuser": { - Input: "authUserInput", - Output: "sourceCodeCredential", - }, - } - }). - MustImportAndCustomize(&Version, v3.Pipeline{}, func(schema *types.Schema) { - schema.ResourceActions = map[string]types.Action{ - "activate": {}, - "deactivate": {}, - "run": { - Input: "runPipelineInput", - }, - } - }). - MustImportAndCustomize(&Version, v3.PipelineExecution{}, func(schema *types.Schema) { - schema.ResourceActions = map[string]types.Action{ - "stop": {}, - "rerun": {}, - } - }). - MustImport(&Version, v3.PipelineExecutionLog{}). - MustImportAndCustomize(&Version, v3.SourceCodeCredential{}, func(schema *types.Schema) { - delete(schema.ResourceFields, "namespaceId") - schema.ResourceMethods = []string{http.MethodGet, http.MethodDelete} - schema.ResourceActions = map[string]types.Action{ - "refreshrepos": {}, - } - }). - MustImportAndCustomize(&Version, v3.SourceCodeRepository{}, func(schema *types.Schema) { - schema.ResourceMethods = []string{http.MethodGet, http.MethodDelete} - delete(schema.ResourceFields, "namespaceId") - }) - -} - func composeType(schemas *types.Schemas) *types.Schemas { return schemas.MustImport(&Version, v3.ComposeConfig{}) } diff --git a/apis/project.cattle.io/v3/pipeline_types.go b/apis/project.cattle.io/v3/pipeline_types.go new file mode 100644 index 00000000..1056c4c9 --- /dev/null +++ b/apis/project.cattle.io/v3/pipeline_types.go @@ -0,0 +1,406 @@ +package v3 + +import ( + "github.com/pkg/errors" + "github.com/rancher/norman/condition" + "github.com/rancher/norman/types" + "github.com/rancher/norman/types/convert" + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type PipelineConditionType string + +const ( + PipelineExecutionConditionProvisioned condition.Cond = "Provisioned" + PipelineExecutionConditionInitialized condition.Cond = "Initialized" + PipelineExecutionConditionBuilt condition.Cond = "Built" +) + +type SourceCodeProvider struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + ProjectName string `json:"projectName" norman:"type=reference[project]"` + Type string `json:"type" norman:"options=github|gitlab"` +} + +type OauthProvider struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + SourceCodeProvider `json:",inline"` + + RedirectURL string `json:"redirectUrl"` +} + +type GithubProvider struct { + OauthProvider `json:",inline"` +} + +type GitlabProvider struct { + OauthProvider `json:",inline"` +} + +type SourceCodeProviderConfig struct { + types.Namespaced + + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + ProjectName string `json:"projectName" norman:"required,type=reference[project]"` + Type string `json:"type" norman:"noupdate,options=github|gitlab"` + Enabled bool `json:"enabled,omitempty"` +} + +type GithubPipelineConfig struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + SourceCodeProviderConfig `json:",inline" mapstructure:",squash"` + + Hostname string `json:"hostname,omitempty" norman:"default=github.com" norman:"noupdate"` + TLS bool `json:"tls,omitempty" norman:"notnullable,default=true" norman:"noupdate"` + ClientID string `json:"clientId,omitempty" norman:"noupdate"` + ClientSecret string `json:"clientSecret,omitempty" norman:"noupdate,type=password"` + Inherit bool `json:"inherit,omitempty" norman:"noupdate"` +} + +type GitlabPipelineConfig struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + SourceCodeProviderConfig `json:",inline" mapstructure:",squash"` + + Hostname string `json:"hostname,omitempty" norman:"default=gitlab.com" norman:"noupdate"` + TLS bool `json:"tls,omitempty" norman:"notnullable,default=true" norman:"noupdate"` + ClientID string `json:"clientId,omitempty" norman:"noupdate"` + ClientSecret string `json:"clientSecret,omitempty" norman:"noupdate,type=password"` + RedirectURL string `json:"redirectUrl,omitempty" norman:"noupdate"` +} + +type Pipeline struct { + types.Namespaced + + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec PipelineSpec `json:"spec"` + Status PipelineStatus `json:"status"` +} + +type PipelineExecution struct { + types.Namespaced + + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec PipelineExecutionSpec `json:"spec"` + Status PipelineExecutionStatus `json:"status"` +} + +type PipelineSetting struct { + types.Namespaced + + ProjectName string `json:"projectName" norman:"type=reference[project]"` + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Value string `json:"value" norman:"required"` + Default string `json:"default" norman:"nocreate,noupdate"` + Customized bool `json:"customized" norman:"nocreate,noupdate"` +} + +type SourceCodeCredential struct { + types.Namespaced + + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec SourceCodeCredentialSpec `json:"spec"` + Status SourceCodeCredentialStatus `json:"status"` +} + +type SourceCodeRepository struct { + types.Namespaced + + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec SourceCodeRepositorySpec `json:"spec"` + Status SourceCodeRepositoryStatus `json:"status"` +} + +type PipelineStatus struct { + PipelineState string `json:"pipelineState,omitempty" norman:"required,options=active|inactive,default=active"` + NextRun int `json:"nextRun" yaml:"nextRun,omitempty" norman:"default=1,min=1"` + LastExecutionID string `json:"lastExecutionId,omitempty" yaml:"lastExecutionId,omitempty"` + LastRunState string `json:"lastRunState,omitempty" yaml:"lastRunState,omitempty"` + LastStarted string `json:"lastStarted,omitempty" yaml:"lastStarted,omitempty"` + NextStart string `json:"nextStart,omitempty" yaml:"nextStart,omitempty"` + WebHookID string `json:"webhookId,omitempty" yaml:"webhookId,omitempty"` + Token string `json:"token,omitempty" yaml:"token,omitempty" norman:"writeOnly,noupdate"` + SourceCodeCredential *SourceCodeCredential `json:"sourceCodeCredential,omitempty" yaml:"sourceCodeCredential,omitempty"` +} + +type PipelineSpec struct { + ProjectName string `json:"projectName" yaml:"projectName" norman:"required,type=reference[project]"` + + DisplayName string `json:"displayName,omitempty" yaml:"displayName,omitempty"` + TriggerWebhookPush bool `json:"triggerWebhookPush,omitempty" yaml:"triggerWebhookPush,omitempty"` + TriggerWebhookPr bool `json:"triggerWebhookPr,omitempty" yaml:"triggerWebhookPr,omitempty"` + TriggerWebhookTag bool `json:"triggerWebhookTag,omitempty" yaml:"triggerWebhookTag,omitempty"` + + RepositoryURL string `json:"repositoryUrl,omitempty" yaml:"repositoryUrl,omitempty"` + SourceCodeCredentialName string `json:"sourceCodeCredentialName,omitempty" yaml:"sourceCodeCredentialName,omitempty" norman:"type=reference[sourceCodeCredential]"` +} + +type PipelineConfig struct { + Stages []Stage `json:"stages,omitempty" yaml:"stages,omitempty"` + + Timeout int `json:"timeout,omitempty" yaml:"timeout,omitempty"` + Branch *Constraint `json:"branch,omitempty" yaml:"branch,omitempty"` +} + +type PipelineCondition struct { + // Type of cluster condition. + Type PipelineConditionType `json:"type"` + // Status of the condition, one of True, False, Unknown. + Status v1.ConditionStatus `json:"status"` + // The last time this condition was updated. + LastUpdateTime string `json:"lastUpdateTime,omitempty"` + // Last time the condition transitioned from one status to another. + LastTransitionTime string `json:"lastTransitionTime,omitempty"` + // The reason for the condition's last transition. + Reason string `json:"reason,omitempty"` + // Human-readable message indicating details about last transition + Message string `json:"message,omitempty"` +} + +type Stage struct { + Name string `json:"name,omitempty" yaml:"name,omitempty" norman:"required"` + Steps []Step `json:"steps,omitempty" yaml:"steps,omitempty" norman:"required"` + + When *Constraints `json:"when,omitempty" yaml:"when,omitempty"` +} + +type Step struct { + SourceCodeConfig *SourceCodeConfig `json:"sourceCodeConfig,omitempty" yaml:"sourceCodeConfig,omitempty"` + RunScriptConfig *RunScriptConfig `json:"runScriptConfig,omitempty" yaml:"runScriptConfig,omitempty"` + PublishImageConfig *PublishImageConfig `json:"publishImageConfig,omitempty" yaml:"publishImageConfig,omitempty"` + ApplyYamlConfig *ApplyYamlConfig `json:"applyYamlConfig,omitempty" yaml:"applyYamlConfig,omitempty"` + + Env map[string]string `json:"env,omitempty" yaml:"env,omitempty"` + EnvFrom []EnvFrom `json:"envFrom,omitempty" yaml:"envFrom,omitempty"` + Privileged bool `json:"privileged,omitempty" yaml:"privileged,omitempty"` + When *Constraints `json:"when,omitempty" yaml:"when,omitempty"` +} + +type Constraints struct { + Branch *Constraint `json:"branch,omitempty" yaml:"branch,omitempty"` + Event *Constraint `json:"event,omitempty" yaml:"event,omitempty"` +} + +type Constraint struct { + Include []string `json:"include,omitempty" yaml:"include,omitempty"` + Exclude []string `json:"exclude,omitempty" yaml:"exclude,omitempty"` +} + +type SourceCodeConfig struct { +} + +type RunScriptConfig struct { + Image string `json:"image,omitempty" yaml:"image,omitempty" norman:"required"` + ShellScript string `json:"shellScript,omitempty" yaml:"shellScript,omitempty"` +} + +type PublishImageConfig struct { + DockerfilePath string `json:"dockerfilePath,omittempty" yaml:"dockerfilePath,omitempty" norman:"required,default=./Dockerfile"` + BuildContext string `json:"buildContext,omitempty" yaml:"buildContext,omitempty" norman:"required,default=."` + Tag string `json:"tag,omitempty" yaml:"tag,omitempty" norman:"required,default=${CICD_GIT_REPOSITORY_NAME}:${CICD_GIT_BRANCH}"` + PushRemote bool `json:"pushRemote,omitempty" yaml:"pushRemote,omitempty"` + Registry string `json:"registry,omitempty" yaml:"registry,omitempty"` +} + +type ApplyYamlConfig struct { + Path string `json:"path,omitempty" yaml:"path,omitempty"` + Content string `json:"content,omitempty" yaml:"content,omitempty"` + Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"` +} + +type PipelineExecutionSpec struct { + ProjectName string `json:"projectName" yaml:"projectName" norman:"required,type=reference[project]"` + + PipelineName string `json:"pipelineName" norman:"required,type=reference[pipeline]"` + PipelineConfig PipelineConfig `json:"pipelineConfig,omitempty" norman:"required"` + RepositoryURL string `json:"repositoryUrl,omitempty"` + Run int `json:"run,omitempty" norman:"required,min=1"` + TriggeredBy string `json:"triggeredBy,omitempty" norman:"required,options=user|cron|webhook"` + TriggerUserName string `json:"triggerUserName,omitempty" norman:"type=reference[user]"` + Commit string `json:"commit,omitempty"` + Event string `json:"event,omitempty"` + Branch string `json:"branch,omitempty"` + Ref string `json:"ref,omitempty"` + HTMLLink string `json:"htmlLink,omitempty"` + Title string `json:"title,omitempty"` + Message string `json:"message,omitempty"` + Author string `json:"author,omitempty"` + AvatarURL string `json:"avatarUrl,omitempty"` + Email string `json:"email,omitempty"` +} + +type PipelineExecutionStatus struct { + Conditions []PipelineCondition `json:"conditions,omitempty"` + + ExecutionState string `json:"executionState,omitempty"` + Started string `json:"started,omitempty"` + Ended string `json:"ended,omitempty"` + Stages []StageStatus `json:"stages,omitempty"` +} + +type StageStatus struct { + State string `json:"state,omitempty"` + Started string `json:"started,omitempty"` + Ended string `json:"ended,omitempty"` + Steps []StepStatus `json:"steps,omitempty"` +} + +type StepStatus struct { + State string `json:"state,omitempty"` + Started string `json:"started,omitempty"` + Ended string `json:"ended,omitempty"` +} + +type SourceCodeCredentialSpec struct { + ProjectName string `json:"projectName" norman:"type=reference[project]"` + SourceCodeType string `json:"sourceCodeType,omitempty" norman:"required,options=github|gitlab"` + UserName string `json:"userName" norman:"required,type=reference[user]"` + DisplayName string `json:"displayName,omitempty" norman:"required"` + AvatarURL string `json:"avatarUrl,omitempty"` + HTMLURL string `json:"htmlUrl,omitempty"` + LoginName string `json:"loginName,omitempty"` + GitLoginName string `json:"gitLoginName,omitempty"` + AccessToken string `json:"accessToken,omitempty" norman:"writeOnly,noupdate"` +} + +type SourceCodeCredentialStatus struct { + Logout bool `json:"logout,omitempty"` +} + +type SourceCodeRepositorySpec struct { + ProjectName string `json:"projectName" norman:"type=reference[project]"` + SourceCodeType string `json:"sourceCodeType,omitempty" norman:"required,options=github|gitlab"` + UserName string `json:"userName" norman:"required,type=reference[user]"` + SourceCodeCredentialName string `json:"sourceCodeCredentialName,omitempty" norman:"required,type=reference[sourceCodeCredential]"` + URL string `json:"url,omitempty"` + Permissions RepoPerm `json:"permissions,omitempty"` + Language string `json:"language,omitempty"` + DefaultBranch string `json:"defaultBranch,omitempty"` +} + +type SourceCodeRepositoryStatus struct { +} + +type RepoPerm struct { + Pull bool `json:"pull,omitempty"` + Push bool `json:"push,omitempty"` + Admin bool `json:"admin,omitempty"` +} + +type RunPipelineInput struct { + Branch string `json:"branch,omitempty"` +} + +type AuthAppInput struct { + InheritGlobal bool `json:"inheritGlobal,omitempty"` + SourceCodeType string `json:"sourceCodeType,omitempty" norman:"type=string,required,options=github|gitlab"` + RedirectURL string `json:"redirectUrl,omitempty" norman:"type=string"` + TLS bool `json:"tls,omitempty"` + Host string `json:"host,omitempty"` + ClientID string `json:"clientId,omitempty" norman:"type=string,required"` + ClientSecret string `json:"clientSecret,omitempty" norman:"type=string,required"` + Code string `json:"code,omitempty" norman:"type=string,required"` +} + +type AuthUserInput struct { + SourceCodeType string `json:"sourceCodeType,omitempty" norman:"type=string,required,options=github|gitlab"` + RedirectURL string `json:"redirectUrl,omitempty" norman:"type=string"` + Code string `json:"code,omitempty" norman:"type=string,required"` +} + +type PushPipelineConfigInput struct { + Configs map[string]PipelineConfig `json:"configs,omitempty"` +} + +type PipelineSystemImages struct { + Jenkins string `json:"jenkins,omitempty"` + JenkinsJnlp string `json:"jenkinsJnlp,omitempty"` + AlpineGit string `json:"alpineGit,omitempty"` + PluginsDocker string `json:"pluginsDocker,omitempty"` + Minio string `json:"minio,omitempty"` + Registry string `json:"registry,omitempty"` + KubeApply string `json:"kubeApply,omitempty"` +} + +type GithubPipelineConfigApplyInput struct { + InheritAuth bool `json:"inheritAuth,omitempty"` + GithubConfig GithubPipelineConfig `json:"githubConfig, omitempty"` + Code string `json:"code,omitempty"` +} + +type GithubLoginInput struct { + Code string `json:"code,omitempty" norman:"type=string,required"` +} + +type GitlabPipelineConfigApplyInput struct { + GitlabConfig GitlabPipelineConfig `json:"gitlabConfig, omitempty"` + Code string `json:"code,omitempty"` +} + +type GitlabLoginInput struct { + Code string `json:"code,omitempty" norman:"type=string,required"` +} + +type EnvFrom struct { + SourceName string `json:"sourceName,omitempty" yaml:"sourceName,omitempty" norman:"type=string,required"` + SourceKey string `json:"sourceKey,omitempty" yaml:"sourceKey,omitempty" norman:"type=string,required"` + TargetKey string `json:"targetKey,omitempty" yaml:"targetKey,omitempty"` +} + +// UnmarshalYAML unmarshals the constraint. +// So as to support yaml syntax including: +// branch: dev, branch: ["dev","hotfix"], branch: {include:[],exclude:[]} +func (c *Constraint) UnmarshalYAML(unmarshal func(interface{}) error) error { + var out1 = struct { + Include stringorslice + Exclude stringorslice + }{} + + var out2 stringorslice + + unmarshal(&out1) + unmarshal(&out2) + + c.Exclude = out1.Exclude + c.Include = append( + out1.Include, + out2..., + ) + return nil +} + +type stringorslice []string + +// UnmarshalYAML implements the Unmarshaller interface. +func (s *stringorslice) UnmarshalYAML(unmarshal func(interface{}) error) error { + var stringType string + if err := unmarshal(&stringType); err == nil { + *s = []string{stringType} + return nil + } + + var sliceType []interface{} + if err := unmarshal(&sliceType); err == nil { + *s = convert.ToStringSlice(sliceType) + return nil + } + + return errors.New("Failed to unmarshal stringorslice") +} diff --git a/apis/project.cattle.io/v3/schema/schema.go b/apis/project.cattle.io/v3/schema/schema.go index e4395ce7..47257af5 100644 --- a/apis/project.cattle.io/v3/schema/schema.go +++ b/apis/project.cattle.io/v3/schema/schema.go @@ -41,7 +41,8 @@ var ( Init(cronJobTypes). Init(podTemplateSpecTypes). Init(workloadTypes). - Init(appTypes) + Init(appTypes). + Init(pipelineTypes) ) func configMapTypes(schemas *types.Schemas) *types.Schemas { @@ -781,3 +782,112 @@ func NewWorkloadTypeMapper() types.Mapper { &m.AnnotationField{Field: "publicEndpoints", List: true}, } } + +func pipelineTypes(schema *types.Schemas) *types.Schemas { + return schema. + AddMapperForType(&Version, v3.SourceCodeProviderConfig{}). + AddMapperForType(&Version, v3.Pipeline{}, + &m.Embed{Field: "status"}, + m.DisplayName{}). + AddMapperForType(&Version, v3.PipelineExecution{}, + &m.Embed{Field: "status"}). + AddMapperForType(&Version, v3.SourceCodeCredential{}, + &m.Embed{Field: "status"}). + AddMapperForType(&Version, v3.SourceCodeRepository{}). + MustImport(&Version, v3.AuthAppInput{}). + MustImport(&Version, v3.AuthUserInput{}). + MustImport(&Version, v3.RunPipelineInput{}). + MustImport(&Version, v3.PushPipelineConfigInput{}). + MustImport(&Version, v3.GithubPipelineConfigApplyInput{}). + MustImport(&Version, v3.GithubLoginInput{}). + MustImport(&Version, v3.GitlabPipelineConfigApplyInput{}). + MustImport(&Version, v3.GitlabLoginInput{}). + MustImportAndCustomize(&Version, v3.SourceCodeProvider{}, func(schema *types.Schema) { + schema.CollectionMethods = []string{http.MethodGet} + }). + MustImportAndCustomize(&Version, v3.GithubProvider{}, func(schema *types.Schema) { + schema.BaseType = "sourceCodeProvider" + schema.ResourceActions = map[string]types.Action{ + "login": { + Input: "githubLoginInput", + Output: "sourceCodeCredential", + }, + } + schema.CollectionMethods = []string{} + schema.ResourceMethods = []string{http.MethodGet} + }). + MustImportAndCustomize(&Version, v3.GitlabProvider{}, func(schema *types.Schema) { + schema.BaseType = "sourceCodeProvider" + schema.ResourceActions = map[string]types.Action{ + "login": { + Input: "gitlabLoginInput", + Output: "sourceCodeCredential", + }, + } + schema.CollectionMethods = []string{} + schema.ResourceMethods = []string{http.MethodGet} + }). + //Github Integration Config + MustImportAndCustomize(&Version, v3.SourceCodeProviderConfig{}, func(schema *types.Schema) { + schema.CollectionMethods = []string{http.MethodGet} + }). + MustImportAndCustomize(&Version, v3.GithubPipelineConfig{}, func(schema *types.Schema) { + schema.BaseType = "sourceCodeProviderConfig" + schema.ResourceActions = map[string]types.Action{ + "disable": {}, + "testAndApply": { + Input: "githubPipelineConfigApplyInput", + }, + } + schema.CollectionMethods = []string{} + schema.ResourceMethods = []string{http.MethodGet, http.MethodPut} + }). + MustImportAndCustomize(&Version, v3.GitlabPipelineConfig{}, func(schema *types.Schema) { + schema.BaseType = "sourceCodeProviderConfig" + schema.ResourceActions = map[string]types.Action{ + "disable": {}, + "testAndApply": { + Input: "gitlabPipelineConfigApplyInput", + }, + } + schema.CollectionMethods = []string{} + schema.ResourceMethods = []string{http.MethodGet, http.MethodPut} + }). + MustImportAndCustomize(&Version, v3.Pipeline{}, func(schema *types.Schema) { + schema.ResourceActions = map[string]types.Action{ + "activate": {}, + "deactivate": {}, + "run": { + Input: "runPipelineInput", + }, + "pushconfig": { + Input: "pushPipelineConfigInput", + }, + } + }). + MustImportAndCustomize(&Version, v3.PipelineExecution{}, func(schema *types.Schema) { + schema.ResourceActions = map[string]types.Action{ + "stop": {}, + "rerun": {}, + } + }). + MustImportAndCustomize(&Version, v3.PipelineSetting{}, func(schema *types.Schema) { + schema.MustCustomizeField("name", func(f types.Field) types.Field { + f.Required = true + return f + }) + }). + MustImportAndCustomize(&Version, v3.SourceCodeCredential{}, func(schema *types.Schema) { + delete(schema.ResourceFields, "namespaceId") + schema.ResourceMethods = []string{http.MethodGet, http.MethodDelete} + schema.ResourceActions = map[string]types.Action{ + "refreshrepos": {}, + "logout": {}, + } + }). + MustImportAndCustomize(&Version, v3.SourceCodeRepository{}, func(schema *types.Schema) { + delete(schema.ResourceFields, "namespaceId") + schema.ResourceMethods = []string{http.MethodGet, http.MethodDelete} + }) + +} diff --git a/mapper/namespace_reference.go b/mapper/namespace_reference.go index f36be7bb..f6b8db10 100644 --- a/mapper/namespace_reference.go +++ b/mapper/namespace_reference.go @@ -20,6 +20,10 @@ func (n *NamespaceReference) FromInternal(data map[string]interface{}) { if ok { for _, path := range n.fields { convert.Transform(data, path, func(input interface{}) interface{} { + parts := strings.SplitN(convert.ToString(input), ":", 2) + if len(parts) == 2 { + return input + } return fmt.Sprintf("%s:%v", namespaceID, input) }) } @@ -27,13 +31,17 @@ func (n *NamespaceReference) FromInternal(data map[string]interface{}) { } func (n *NamespaceReference) ToInternal(data map[string]interface{}) error { + namespaceID, ok := data["namespaceId"] + if !ok { + return nil + } for _, path := range n.fields { convert.Transform(data, path, func(input interface{}) interface{} { parts := strings.SplitN(convert.ToString(input), ":", 2) - if len(parts) == 2 { + if len(parts) == 2 && (parts[0] == namespaceID) { return parts[1] } - return parts[0] + return input }) } diff --git a/status/status.go b/status/status.go index fe79eaa0..465f38a8 100644 --- a/status/status.go +++ b/status/status.go @@ -31,6 +31,7 @@ var transitioningMap = map[string]string{ "AddonDeploy": "provisioning", "AgentDeployed": "provisioning", "BackingNamespaceCreated": "configuring", + "Built": "building", "CertsGenerated": "provisioning", "ConfigOK": "configuring", "Created": "creating",