diff --git a/apis/management.cattle.io/v3/compose_types.go b/apis/management.cattle.io/v3/compose_types.go new file mode 100644 index 00000000..d5bd034c --- /dev/null +++ b/apis/management.cattle.io/v3/compose_types.go @@ -0,0 +1,63 @@ +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 GlobalComposeConfig struct { + metav1.TypeMeta `json:",inline"` + // Standard object’s metadata. More info: + // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata + metav1.ObjectMeta `json:"metadata,omitempty"` + // Specification of the desired behavior of the the cluster. More info: + // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status + Spec ComposeSpec `json:"spec,omitempty"` + Status ComposeStatus `json:"status,omitempty"` +} + +type ComposeSpec struct { + RancherCompose string `json:"rancherCompose,omitempty"` +} + +type ComposeStatus struct { + Conditions []ComposeCondition `json:"conditions,omitempty"` +} + +var ( + ComposeConditionExecuted condition.Cond = "Executed" +) + +type ComposeCondition struct { + // Type of cluster condition. + Type string `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 ClusterComposeConfig struct { + types.Namespaced + metav1.TypeMeta `json:",inline"` + // Standard object’s metadata. More info: + // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata + metav1.ObjectMeta `json:"metadata,omitempty"` + // Specification of the desired behavior of the the cluster. More info: + // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status + Spec ClusterComposeSpec `json:"spec,omitempty"` + Status ComposeStatus `json:"status,omitempty"` +} + +type ClusterComposeSpec struct { + ClusterName string `json:"clusterName" norman:"type=reference[cluster]"` + RancherCompose string `json:"rancherCompose,omitempty"` +} diff --git a/apis/management.cattle.io/v3/schema/schema.go b/apis/management.cattle.io/v3/schema/schema.go index f06de328..3e1f2859 100644 --- a/apis/management.cattle.io/v3/schema/schema.go +++ b/apis/management.cattle.io/v3/schema/schema.go @@ -34,7 +34,8 @@ var ( Init(globalTypes). Init(rkeTypes). Init(alertTypes). - Init(pipelineTypes) + Init(pipelineTypes). + Init(composeType) TokenSchemas = factory.Schemas(&Version). Init(tokens) @@ -438,3 +439,8 @@ func pipelineTypes(schema *types.Schemas) *types.Schemas { }) } + +func composeType(schemas *types.Schemas) *types.Schemas { + return schemas.MustImport(&Version, v3.GlobalComposeConfig{}). + MustImport(&Version, v3.ClusterComposeConfig{}) +} diff --git a/apis/project.cattle.io/v3/namespace_compose_types.go b/apis/project.cattle.io/v3/namespace_compose_types.go new file mode 100644 index 00000000..6b06d699 --- /dev/null +++ b/apis/project.cattle.io/v3/namespace_compose_types.go @@ -0,0 +1,49 @@ +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 NamespaceComposeConfig struct { + types.Namespaced + metav1.TypeMeta `json:",inline"` + // Standard object’s metadata. More info: + // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata + metav1.ObjectMeta `json:"metadata,omitempty"` + // Specification of the desired behavior of the the cluster. More info: + // https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status + Spec NamespaceComposeSpec `json:"spec,omitempty"` + Status ComposeStatus `json:"status,omitempty"` +} + +type NamespaceComposeSpec struct { + RancherCompose string `json:"rancherCompose,omitempty"` + ProjectName string `json:"projectName" norman:"type=reference[project]"` + InstallNamespace string `json:"installNamespace,omitempty"` +} + +type ComposeStatus struct { + Conditions []ComposeCondition `json:"conditions,omitempty"` +} + +var ( + ComposeConditionExecuted condition.Cond = "Executed" +) + +type ComposeCondition struct { + // Type of cluster condition. + Type string `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"` +} diff --git a/apis/project.cattle.io/v3/schema/schema.go b/apis/project.cattle.io/v3/schema/schema.go index 1f257f78..6ceaad32 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(podTemplateSpecTypes). Init(workloadTypes). Init(appTypes). - Init(configMapTypes) + Init(configMapTypes). + Init(namespaceComposeType) ) func configMapTypes(schemas *types.Schemas) *types.Schemas { @@ -677,3 +678,7 @@ func NewWorkloadTypeMapper() types.Mapper { &m.AnnotationField{Field: "publicEndpoints", List: true}, } } + +func namespaceComposeType(schemas *types.Schemas) *types.Schemas { + return schemas.MustImport(&Version, v3.NamespaceComposeConfig{}) +} diff --git a/generator/compose_template.go b/generator/compose_template.go new file mode 100644 index 00000000..5a725b0e --- /dev/null +++ b/generator/compose_template.go @@ -0,0 +1,27 @@ +package generator + +var composeTemplate = `package compose + +import ( + clusterClient "github.com/rancher/types/client/cluster/v3" + managementClient "github.com/rancher/types/client/management/v3" + projectClient "github.com/rancher/types/client/project/v3" +) + +type Config struct { + Version string %BACK%yaml:"version,omitempty"%BACK% + + // Management Client + {{range .managementSchemas}} + {{- if . | hasPost }}{{.CodeName}}s map[string]managementClient.{{.CodeName}} %BACK%json:"{{.PluralName}},omitempty" yaml:"{{.PluralName}},omitempty"%BACK% +{{end}}{{end}} + + // Cluster Client + {{range .clusterSchemas}} + {{- if . | hasGet }}{{.CodeName}}s map[string]clusterClient.{{.CodeName}} %BACK%json:"{{.PluralName}},omitempty" yaml:"{{.PluralName}},omitempty"%BACK% +{{end}}{{end}} + + // Project Client + {{range .projectSchemas}} + {{- if . | hasGet }}{{.CodeName}}s map[string]projectClient.{{.CodeName}} %BACK%json:"{{.PluralName}},omitempty" yaml:"{{.PluralName}},omitempty"%BACK% +{{end}}{{end}}}` diff --git a/generator/generator.go b/generator/generator.go index 5253ed66..9718dcdc 100644 --- a/generator/generator.go +++ b/generator/generator.go @@ -5,17 +5,54 @@ import ( "path" "strings" + "net/http" + "os" + "os/exec" + "path/filepath" + "text/template" + "github.com/rancher/norman/generator" "github.com/rancher/norman/types" + "github.com/rancher/norman/types/convert" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/gengo/args" ) var ( basePackage = "github.com/rancher/types" baseCattle = "client" baseK8s = "apis" + baseCompose = "compose" ) +func funcs() template.FuncMap { + return template.FuncMap{ + "capitalize": convert.Capitalize, + "unCapitalize": convert.Uncapitalize, + "upper": strings.ToUpper, + "toLower": strings.ToLower, + "hasGet": hasGet, + "hasPost": hasPost, + } +} + +func hasGet(schema *types.Schema) bool { + return contains(schema.CollectionMethods, http.MethodGet) +} + +func hasPost(schema *types.Schema) bool { + return contains(schema.CollectionMethods, http.MethodPost) +} + +func contains(list []string, needle string) bool { + for _, i := range list { + if i == needle { + return true + } + } + return false +} + func Generate(schemas *types.Schemas) { version := getVersion(schemas) group := strings.Split(version.Group, ".")[0] @@ -28,6 +65,51 @@ func Generate(schemas *types.Schemas) { } } +func GenerateComposeType(projectSchemas *types.Schemas, managementSchemas *types.Schemas, clusterSchemas *types.Schemas) { + if err := generateComposeType(filepath.Join(basePackage, baseCompose), projectSchemas, managementSchemas, clusterSchemas); err != nil { + panic(err) + } +} + +func generateComposeType(baseCompose string, projectSchemas *types.Schemas, managementSchemas *types.Schemas, clusterSchemas *types.Schemas) error { + outputDir := filepath.Join(args.DefaultSourceTree(), baseCompose) + if err := os.MkdirAll(outputDir, 0755); err != nil { + return err + } + filePath := "zz_generated_compose.go" + output, err := os.Create(path.Join(outputDir, filePath)) + if err != nil { + return err + } + defer output.Close() + + typeTemplate, err := template.New("compose.template"). + Funcs(funcs()). + Parse(strings.Replace(composeTemplate, "%BACK%", "`", -1)) + if err != nil { + return err + } + + if err := typeTemplate.Execute(output, map[string]interface{}{ + "managementSchemas": managementSchemas.Schemas(), + "projectSchemas": projectSchemas.Schemas(), + "clusterSchemas": clusterSchemas.Schemas(), + }); err != nil { + return err + } + + return gofmt(args.DefaultSourceTree(), baseCompose) +} + +func gofmt(workDir, pkg string) error { + cmd := exec.Command("goimports", "-w", "-l", "./"+pkg) + cmd.Dir = workDir + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + return cmd.Run() +} + func GenerateNativeTypes(gv schema.GroupVersion, nsObjs []interface{}, objs []interface{}) { version := gv.Version group := gv.Group diff --git a/main.go b/main.go index dc8230e7..cb48fe48 100644 --- a/main.go +++ b/main.go @@ -19,6 +19,7 @@ import ( ) func main() { + generator.GenerateComposeType(projectSchema.Schemas, managementSchema.Schemas, clusterSchema.Schemas) generator.Generate(managementSchema.Schemas) generator.Generate(publicSchema.PublicSchemas) generator.Generate(clusterSchema.Schemas)