From 4194e10396f49c1f169c60ade95f6617edf4ee38 Mon Sep 17 00:00:00 2001 From: Devdatta Kulkarni Date: Wed, 5 Sep 2018 13:45:08 -0500 Subject: [PATCH 1/2] WIP: OpenAPI Spec DO NOT MERGE We analyzed types.go to check its adherence to OpenAPI format. We found that it is violating OpenAPI Spec rules at certain places. This patch fixes those violations by updating types.go. After making the changes we were able to generate OpenAPI Spec correctly. Included files: - kube-openapi-violations.txt: Output showing OpenAPI Spec violations - openapispec.json: Generated OpenAPI Spec We used following tool to analyze and generate OpenAPI Spec: https://github.com/cloud-ark/kubeplus/tree/master/openapi-spec-generator The analysis was performed with the goal of checking the Operator against these guidelines: https://medium.com/@cloudark/kubernetes-operator-development-guidelines-for-improved-usability-222390b00dc4 --- kube-openapi-violations.txt | 24 ++ openapispec.json | 475 +++++++++++++++++++++++++++++++ pkg/apis/mysql/v1alpha1/types.go | 65 +++-- 3 files changed, 544 insertions(+), 20 deletions(-) create mode 100644 kube-openapi-violations.txt create mode 100644 openapispec.json diff --git a/kube-openapi-violations.txt b/kube-openapi-violations.txt new file mode 100644 index 000000000..1c311055c --- /dev/null +++ b/kube-openapi-violations.txt @@ -0,0 +1,24 @@ +Devs-MacBook:openapi-spec-generator devdatta$ ./build-openapi-spec.sh /Users/devdatta/go/src/github.com/oracle/mysql-operator/pkg/apis/mysql/v1alpha1 +2018/09/05 12:15:27 OpenAPI code generation error: Failed executing generator: some packages had errors: +API rule violations exist +exit status 1 +builder.go:28:2: no Go files in /Users/devdatta/go/src/github.com/cloud-ark/kubeplus/openapi-spec-generator/generated +API rule violation: names_match,github.com/cloud-ark/kubeplus/openapi-spec-generator/typedir,BackupCondition,Type +API rule violation: names_match,github.com/cloud-ark/kubeplus/openapi-spec-generator/typedir,BackupCondition,Status +API rule violation: names_match,github.com/cloud-ark/kubeplus/openapi-spec-generator/typedir,BackupCondition,Reason +API rule violation: names_match,github.com/cloud-ark/kubeplus/openapi-spec-generator/typedir,BackupCondition,Message +API rule violation: names_match,github.com/cloud-ark/kubeplus/openapi-spec-generator/typedir,BackupExecutor,MySQLDump +API rule violation: names_match,github.com/cloud-ark/kubeplus/openapi-spec-generator/typedir,BackupStatus,Conditions +API rule violation: names_match,github.com/cloud-ark/kubeplus/openapi-spec-generator/typedir,ClusterCondition,Type +API rule violation: names_match,github.com/cloud-ark/kubeplus/openapi-spec-generator/typedir,ClusterCondition,Status +API rule violation: names_match,github.com/cloud-ark/kubeplus/openapi-spec-generator/typedir,ClusterCondition,Reason +API rule violation: names_match,github.com/cloud-ark/kubeplus/openapi-spec-generator/typedir,ClusterCondition,Message +API rule violation: names_match,github.com/cloud-ark/kubeplus/openapi-spec-generator/typedir,ClusterSpec,BaseServerID +API rule violation: names_match,github.com/cloud-ark/kubeplus/openapi-spec-generator/typedir,ClusterStatus,Conditions +API rule violation: names_match,github.com/cloud-ark/kubeplus/openapi-spec-generator/typedir,RestoreCondition,Type +API rule violation: names_match,github.com/cloud-ark/kubeplus/openapi-spec-generator/typedir,RestoreCondition,Status +API rule violation: names_match,github.com/cloud-ark/kubeplus/openapi-spec-generator/typedir,RestoreCondition,Reason +API rule violation: names_match,github.com/cloud-ark/kubeplus/openapi-spec-generator/typedir,RestoreCondition,Message +API rule violation: names_match,github.com/cloud-ark/kubeplus/openapi-spec-generator/typedir,RestoreStatus,Conditions +FAIL +API rule violation diff --git a/openapispec.json b/openapispec.json new file mode 100644 index 000000000..ece2241dc --- /dev/null +++ b/openapispec.json @@ -0,0 +1,475 @@ +{ + "swagger": "2.0", + "info": { + "title": "OpenAPI Doc Generator", + "version": "0.0.1" + }, + "paths": {}, + "definitions": { + "typedir.Backup": { + "description": "Backup is a backup of a Cluster.", + "required": [ + "spec", + "status" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "spec": { + "$ref": "#/definitions/typedir.BackupSpec" + }, + "status": { + "$ref": "#/definitions/typedir.BackupStatus" + } + } + }, + "typedir.BackupCondition": { + "description": "BackupCondition describes the observed state of a Backup at a certain point.", + "required": [ + "type", + "status" + ], + "properties": { + "message": { + "type": "string" + }, + "reason": { + "description": "\n\tLastTransitionTime metav1.Time `json:\"lastTransitionTime\"`", + "type": "string" + }, + "status": { + "type": "string" + }, + "type": { + "type": "string" + } + } + }, + "typedir.BackupExecutor": { + "description": "BackupExecutor represents the configuration of the tool performing the backup. This includes the tool to use, and, what database and tables should be backed up. The storage of the backup is configured in the relevant Storage configuration.", + "required": [ + "mySQLDump" + ], + "properties": { + "mySQLDump": { + "$ref": "#/definitions/typedir.MySQLDumpBackupExecutor" + } + } + }, + "typedir.BackupList": { + "description": "BackupList is a list of Backups.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/typedir.Backup" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + } + } + }, + "typedir.BackupOutcome": { + "description": "BackupOutcome describes the location of a Backup", + "required": [ + "location" + ], + "properties": { + "location": { + "description": "Location is the Object Storage network location of the Backup.", + "type": "string" + } + } + }, + "typedir.BackupSchedule": { + "description": "BackupSchedule is a backup schedule for a Cluster.", + "required": [ + "spec" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "spec": { + "$ref": "#/definitions/typedir.BackupScheduleSpec" + }, + "status": { + "$ref": "#/definitions/typedir.ScheduleStatus" + } + } + }, + "typedir.BackupScheduleList": { + "description": "BackupScheduleList is a list of BackupSchedules.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/typedir.BackupSchedule" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + } + } + }, + "typedir.BackupScheduleSpec": { + "description": "BackupScheduleSpec defines the specification for a MySQL backup schedule.", + "required": [ + "schedule", + "backupTemplate" + ], + "properties": { + "backupTemplate": { + "description": "BackupTemplate is the specification of the backup structure to get scheduled.", + "$ref": "#/definitions/typedir.BackupSpec" + }, + "schedule": { + "description": "Schedule specifies the cron string used for backup scheduling.", + "type": "string" + } + } + }, + "typedir.BackupSpec": { + "description": "BackupSpec defines the specification for a MySQL backup. This includes what should be backed up, what tool should perform the backup, and, where the backup should be stored.", + "required": [ + "executor", + "storageProvider", + "scheduledMember" + ], + "properties": { + "executor": { + "description": "Executor is the configuration of the tool that will produce the backup, and a definition of what databases and tables to backup.", + "$ref": "#/definitions/typedir.BackupExecutor" + }, + "scheduledMember": { + "description": "Cluster is the Cluster to backup.\n\tCluster *corev1.LocalObjectReference `json:\"cluster\"`\nScheduledMember is the Pod name of the Cluster member on which the Backup will be executed.", + "type": "string" + }, + "storageProvider": { + "description": "StorageProvider configures where and how backups should be stored.", + "$ref": "#/definitions/typedir.StorageProvider" + } + } + }, + "typedir.BackupStatus": { + "description": "BackupStatus captures the current status of a Backup.", + "properties": { + "conditions": { + "description": "\n\t// TimeStarted is the time at which the backup was started.\n\tTimeStarted metav1.Time `json:\"timeStarted\"`\n\t// TimeCompleted is the time at which the backup completed.\n\tTimeCompleted metav1.Time `json:\"timeCompleted\"`", + "type": "array", + "items": { + "$ref": "#/definitions/typedir.BackupCondition" + } + }, + "outcome": { + "description": "Outcome holds the results of a successful backup.", + "$ref": "#/definitions/typedir.BackupOutcome" + } + } + }, + "typedir.Cluster": { + "description": "Cluster represents a cluster spec and associated metadata", + "required": [ + "spec", + "status" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "spec": { + "$ref": "#/definitions/typedir.ClusterSpec" + }, + "status": { + "$ref": "#/definitions/typedir.ClusterStatus" + } + } + }, + "typedir.ClusterCondition": { + "description": "ClusterCondition describes the observed state of a Cluster at a certain point.", + "required": [ + "type", + "status" + ], + "properties": { + "message": { + "type": "string" + }, + "reason": { + "description": "\n\tLastTransitionTime metav1.Time `json:\"lastTransitionTime\"`", + "type": "string" + }, + "status": { + "type": "string" + }, + "type": { + "type": "string" + } + } + }, + "typedir.ClusterList": { + "description": "ClusterList is a placeholder type for a list of MySQL clusters", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/typedir.Cluster" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + } + } + }, + "typedir.ClusterSpec": { + "description": "ClusterSpec defines the attributes a user can specify when creating a cluster", + "required": [ + "version" + ], + "properties": { + "baseServerID": { + "description": "BaseServerID defines the base number used to create unique server_id for MySQL instances in the cluster. Valid range 1 to 4294967286. If omitted in the manifest file (or set to 0) defaultBaseServerID value will be used.", + "type": "integer", + "format": "int64" + }, + "members": { + "description": "Members defines the number of MySQL instances in a cluster", + "type": "integer", + "format": "int32" + }, + "multiMaster": { + "description": "MultiMaster defines the mode of the MySQL cluster. If set to true, all instances will be R/W. If false (the default), only a single instance will be R/W and the rest will be R/O.", + "type": "boolean" + }, + "nodeSelector": { + "description": "NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node's labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "version": { + "description": "Version defines the MySQL Docker image version.", + "type": "string" + } + } + }, + "typedir.ClusterStatus": { + "description": "ClusterStatus defines the current status of a MySQL cluster propagating useful information back to the cluster admin", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "conditions": { + "type": "array", + "items": { + "$ref": "#/definitions/typedir.ClusterCondition" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + } + } + }, + "typedir.Database": { + "description": "Database represents a database to backup.", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + } + } + }, + "typedir.MySQLDumpBackupExecutor": { + "description": "MySQLDumpBackupExecutor executes backups using mysqldump.", + "required": [ + "databases" + ], + "properties": { + "databases": { + "type": "array", + "items": { + "$ref": "#/definitions/typedir.Database" + } + } + } + }, + "typedir.Restore": { + "description": "Restore is a MySQL Operator resource that represents the restoration of backup of a MySQL cluster.", + "required": [ + "spec", + "status" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + }, + "spec": { + "$ref": "#/definitions/typedir.RestoreSpec" + }, + "status": { + "$ref": "#/definitions/typedir.RestoreStatus" + } + } + }, + "typedir.RestoreCondition": { + "description": "RestoreCondition describes the observed state of a Restore at a certain point.", + "required": [ + "type", + "status" + ], + "properties": { + "message": { + "type": "string" + }, + "reason": { + "description": "\n\tLastTransitionTime metav1.Time `json:\"lastTransitionTime\"`", + "type": "string" + }, + "status": { + "type": "string" + }, + "type": { + "type": "string" + } + } + }, + "typedir.RestoreList": { + "description": "RestoreList is a list of Restores.", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources", + "type": "string" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/typedir.Restore" + } + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "type": "string" + } + } + }, + "typedir.RestoreSpec": { + "description": "RestoreSpec defines the specification for a restore of a MySQL backup.", + "required": [ + "scheduledMember" + ], + "properties": { + "scheduledMember": { + "description": "Cluster is a refeference to the Cluster to which the Restore belongs.\n\tCluster *corev1.LocalObjectReference `json:\"cluster\"`\nBackup is a reference to the Backup object to be restored.\n\tBackup *corev1.LocalObjectReference `json:\"backup\"`\nScheduledMember is the Pod name of the Cluster member on which the Restore will be executed.", + "type": "string" + } + } + }, + "typedir.RestoreStatus": { + "description": "RestoreStatus captures the current status of a MySQL restore.", + "properties": { + "conditions": { + "description": "\n\t// TimeStarted is the time at which the restore was started.\n\tTimeStarted metav1.Time `json:\"timeStarted\"`\n\t// TimeCompleted is the time at which the restore completed.\n\tTimeCompleted metav1.Time `json:\"timeCompleted\"`", + "type": "array", + "items": { + "$ref": "#/definitions/typedir.RestoreCondition" + } + } + } + }, + "typedir.S3StorageProvider": { + "description": "S3StorageProvider represents an S3 compatible bucket for storing Backups.", + "required": [ + "region", + "endpoint", + "bucket", + "forcePathStyle" + ], + "properties": { + "bucket": { + "description": "Bucket in which to store the Backup.", + "type": "string" + }, + "endpoint": { + "description": "Endpoint (hostname only or fully qualified URI) of S3 compatible storage service.", + "type": "string" + }, + "forcePathStyle": { + "description": "ForcePathStyle when set to true forces the request to use path-style addressing, i.e., `http://s3.amazonaws.com/BUCKET/KEY`. By default, the S3 client will use virtual hosted bucket addressing when possible (`http://BUCKET.s3.amazonaws.com/KEY`).", + "type": "boolean" + }, + "region": { + "description": "Region in which the S3 compatible bucket is located.", + "type": "string" + } + } + }, + "typedir.ScheduleStatus": { + "description": "ScheduleStatus captures the current state of a MySQL backup schedule." + }, + "typedir.StorageProvider": { + "description": "StorageProvider defines the configuration for storing a Backup in a storage service.", + "required": [ + "s3" + ], + "properties": { + "s3": { + "$ref": "#/definitions/typedir.S3StorageProvider" + } + } + } + } + } \ No newline at end of file diff --git a/pkg/apis/mysql/v1alpha1/types.go b/pkg/apis/mysql/v1alpha1/types.go index 40cb42fb9..21cca7a78 100644 --- a/pkg/apis/mysql/v1alpha1/types.go +++ b/pkg/apis/mysql/v1alpha1/types.go @@ -24,6 +24,7 @@ import ( const MinimumMySQLVersion = "8.0.11" // ClusterSpec defines the attributes a user can specify when creating a cluster +//+k8s:openapi-gen=true type ClusterSpec struct { // Version defines the MySQL Docker image version. Version string `json:"version"` @@ -33,7 +34,7 @@ type ClusterSpec struct { // for MySQL instances in the cluster. Valid range 1 to 4294967286. // If omitted in the manifest file (or set to 0) defaultBaseServerID // value will be used. - BaseServerID uint32 `json:"baseServerId,omitempty"` + BaseServerID uint32 `json:"baseServerID,omitempty"` // MultiMaster defines the mode of the MySQL cluster. If set to true, // all instances will be R/W. If false (the default), only a single instance // will be R/W and the rest will be R/O. @@ -75,25 +76,27 @@ const ( ) // ClusterCondition describes the observed state of a Cluster at a certain point. +//+k8s:openapi-gen=true type ClusterCondition struct { - Type ClusterConditionType - Status corev1.ConditionStatus + Type ClusterConditionType `json:"type"` + Status corev1.ConditionStatus `json:"status"` // +optional - LastTransitionTime metav1.Time + LastTransitionTime metav1.Time `json:"lastTransitionTime"` // +optional - Reason string + Reason string `json:"reason"` // +optional - Message string + Message string `json:"message"` } // ClusterStatus defines the current status of a MySQL cluster // propagating useful information back to the cluster admin +//+k8s:openapi-gen=true type ClusterStatus struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata"` // +optional - Conditions []ClusterCondition + Conditions []ClusterCondition `json:"conditions"` } // +genclient @@ -102,6 +105,7 @@ type ClusterStatus struct { // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // Cluster represents a cluster spec and associated metadata +//+k8s:openapi-gen=true type Cluster struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata"` @@ -113,6 +117,7 @@ type Cluster struct { // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // ClusterList is a placeholder type for a list of MySQL clusters +//+k8s:openapi-gen=true type ClusterList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata"` @@ -121,11 +126,13 @@ type ClusterList struct { } // Database represents a database to backup. +//+k8s:openapi-gen=true type Database struct { Name string `json:"name"` } // MySQLDumpBackupExecutor executes backups using mysqldump. +//+k8s:openapi-gen=true type MySQLDumpBackupExecutor struct { Databases []Database `json:"databases"` } @@ -133,11 +140,13 @@ type MySQLDumpBackupExecutor struct { // BackupExecutor represents the configuration of the tool performing the backup. This includes the tool // to use, and, what database and tables should be backed up. // The storage of the backup is configured in the relevant Storage configuration. +//+k8s:openapi-gen=true type BackupExecutor struct { - MySQLDump *MySQLDumpBackupExecutor `json:"mysqldump"` + MySQLDump *MySQLDumpBackupExecutor `json:"mySQLDump"` } // S3StorageProvider represents an S3 compatible bucket for storing Backups. +//+k8s:openapi-gen=true type S3StorageProvider struct { // Region in which the S3 compatible bucket is located. Region string `json:"region"` @@ -158,12 +167,14 @@ type S3StorageProvider struct { // StorageProvider defines the configuration for storing a Backup in a storage // service. +//+k8s:openapi-gen=true type StorageProvider struct { S3 *S3StorageProvider `json:"s3"` } // BackupSpec defines the specification for a MySQL backup. This includes what should be backed up, // what tool should perform the backup, and, where the backup should be stored. +//+k8s:openapi-gen=true type BackupSpec struct { // Executor is the configuration of the tool that will produce the backup, and a definition of // what databases and tables to backup. @@ -195,24 +206,27 @@ const ( ) // BackupCondition describes the observed state of a Backup at a certain point. +//+k8s:openapi-gen=true type BackupCondition struct { - Type BackupConditionType - Status corev1.ConditionStatus + Type BackupConditionType `json:"type"` + Status corev1.ConditionStatus `json:"status"` // +optional - LastTransitionTime metav1.Time + LastTransitionTime metav1.Time `json:"lastTransitionTime"` // +optional - Reason string + Reason string `json:"reason"` // +optional - Message string + Message string `json:"message"` } // BackupOutcome describes the location of a Backup +//+k8s:openapi-gen=true type BackupOutcome struct { // Location is the Object Storage network location of the Backup. Location string `json:"location"` } // BackupStatus captures the current status of a Backup. +//+k8s:openapi-gen=true type BackupStatus struct { // Outcome holds the results of a successful backup. // +optional @@ -224,7 +238,7 @@ type BackupStatus struct { // +optional TimeCompleted metav1.Time `json:"timeCompleted"` // +optional - Conditions []BackupCondition + Conditions []BackupCondition `json:"conditions"` } // +genclient @@ -233,6 +247,7 @@ type BackupStatus struct { // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // Backup is a backup of a Cluster. +//+k8s:openapi-gen=true type Backup struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata"` @@ -244,6 +259,7 @@ type Backup struct { // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // BackupList is a list of Backups. +//+k8s:openapi-gen=true type BackupList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata"` @@ -252,6 +268,7 @@ type BackupList struct { } // BackupScheduleSpec defines the specification for a MySQL backup schedule. +//+k8s:openapi-gen=true type BackupScheduleSpec struct { // Schedule specifies the cron string used for backup scheduling. Schedule string `json:"schedule"` @@ -262,6 +279,7 @@ type BackupScheduleSpec struct { } // ScheduleStatus captures the current state of a MySQL backup schedule. +//+k8s:openapi-gen=true type ScheduleStatus struct { // LastBackup is the last time a Backup was run for this // backup schedule. @@ -275,6 +293,7 @@ type ScheduleStatus struct { // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // BackupSchedule is a backup schedule for a Cluster. +//+k8s:openapi-gen=true type BackupSchedule struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata"` @@ -286,6 +305,7 @@ type BackupSchedule struct { // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // BackupScheduleList is a list of BackupSchedules. +//+k8s:openapi-gen=true type BackupScheduleList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata"` @@ -311,18 +331,20 @@ const ( ) // RestoreCondition describes the observed state of a Restore at a certain point. +//+k8s:openapi-gen=true type RestoreCondition struct { - Type RestoreConditionType - Status corev1.ConditionStatus + Type RestoreConditionType `json:"type"` + Status corev1.ConditionStatus `json:"status"` // +optional - LastTransitionTime metav1.Time + LastTransitionTime metav1.Time `json:"lastTransitionTime"` // +optional - Reason string + Reason string `json:"reason"` // +optional - Message string + Message string `json:"message"` } // RestoreSpec defines the specification for a restore of a MySQL backup. +//+k8s:openapi-gen=true type RestoreSpec struct { // Cluster is a refeference to the Cluster to which the Restore // belongs. @@ -335,6 +357,7 @@ type RestoreSpec struct { } // RestoreStatus captures the current status of a MySQL restore. +//+k8s:openapi-gen=true type RestoreStatus struct { // TimeStarted is the time at which the restore was started. // +optional @@ -343,7 +366,7 @@ type RestoreStatus struct { // +optional TimeCompleted metav1.Time `json:"timeCompleted"` // +optional - Conditions []RestoreCondition + Conditions []RestoreCondition `json:"conditions"` } // +genclient @@ -353,6 +376,7 @@ type RestoreStatus struct { // Restore is a MySQL Operator resource that represents the restoration of // backup of a MySQL cluster. +//+k8s:openapi-gen=true type Restore struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata"` @@ -364,6 +388,7 @@ type Restore struct { // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // RestoreList is a list of Restores. +//+k8s:openapi-gen=true type RestoreList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata"` From 6b9bc1b479e1e11261f2bd246d444b6d9d01f139 Mon Sep 17 00:00:00 2001 From: Devdatta Kulkarni Date: Wed, 5 Sep 2018 14:04:06 -0500 Subject: [PATCH 2/2] DO NOT MERGE We analyzed types.go to check its adherence to OpenAPI format. We found that it is violating OpenAPI Spec rules at certain places. This patch fixes those violations by updating types.go. After making the changes we were able to generate OpenAPI Spec correctly. Included files: kube-openapi-violations.txt: Output showing OpenAPI Spec violations openapispec.json: Generated OpenAPI Spec We used following tool to analyze and generate OpenAPI Spec: https://github.com/cloud-ark/kubeplus/tree/master/openapi-spec-generator The analysis was performed with the goal of checking the Operator against these guidelines: https://medium.com/@cloudark/kubernetes-operator-development-guidelines-for-improved-usability-222390b00dc4 --- pkg/apis/mysql/v1alpha1/types.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/apis/mysql/v1alpha1/types.go b/pkg/apis/mysql/v1alpha1/types.go index 21cca7a78..9381ce845 100644 --- a/pkg/apis/mysql/v1alpha1/types.go +++ b/pkg/apis/mysql/v1alpha1/types.go @@ -78,7 +78,7 @@ const ( // ClusterCondition describes the observed state of a Cluster at a certain point. //+k8s:openapi-gen=true type ClusterCondition struct { - Type ClusterConditionType `json:"type"` + Type ClusterConditionType `json:"type"` Status corev1.ConditionStatus `json:"status"` // +optional LastTransitionTime metav1.Time `json:"lastTransitionTime"` @@ -208,7 +208,7 @@ const ( // BackupCondition describes the observed state of a Backup at a certain point. //+k8s:openapi-gen=true type BackupCondition struct { - Type BackupConditionType `json:"type"` + Type BackupConditionType `json:"type"` Status corev1.ConditionStatus `json:"status"` // +optional LastTransitionTime metav1.Time `json:"lastTransitionTime"` @@ -333,7 +333,7 @@ const ( // RestoreCondition describes the observed state of a Restore at a certain point. //+k8s:openapi-gen=true type RestoreCondition struct { - Type RestoreConditionType `json:"type"` + Type RestoreConditionType `json:"type"` Status corev1.ConditionStatus `json:"status"` // +optional LastTransitionTime metav1.Time `json:"lastTransitionTime"`