From 3b00fc6d5e7d9b6dd6efac506628c9d2cff00c55 Mon Sep 17 00:00:00 2001 From: yuswift Date: Wed, 7 Apr 2021 11:19:26 +0800 Subject: [PATCH] add kubesphereversion field for cluser.status Signed-off-by: yuswift adopt reviews from @LinuxSuRen --- .../crds/cluster.kubesphere.io_clusters.yaml | 251 ++++++++---------- pkg/apis/cluster/v1alpha1/cluster_types.go | 3 + pkg/controller/cluster/cluster_controller.go | 46 ++++ 3 files changed, 161 insertions(+), 139 deletions(-) diff --git a/config/crds/cluster.kubesphere.io_clusters.yaml b/config/crds/cluster.kubesphere.io_clusters.yaml index 4834fb080..72ce77c2c 100644 --- a/config/crds/cluster.kubesphere.io_clusters.yaml +++ b/config/crds/cluster.kubesphere.io_clusters.yaml @@ -1,6 +1,6 @@ --- -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: @@ -8,19 +8,6 @@ metadata: creationTimestamp: null name: clusters.cluster.kubesphere.io spec: - additionalPrinterColumns: - - JSONPath: .spec.joinFederation - name: Federated - type: boolean - - JSONPath: .spec.provider - name: Provider - type: string - - JSONPath: .spec.enable - name: Active - type: boolean - - JSONPath: .status.kubernetesVersion - name: Version - type: string group: cluster.kubesphere.io names: kind: Cluster @@ -28,143 +15,129 @@ spec: plural: clusters singular: cluster scope: Cluster - subresources: {} - validation: - openAPIV3Schema: - description: Cluster is the schema for the clusters API - 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/sig-architecture/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/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - properties: - connection: - description: Connection holds info to connect to the member cluster - properties: - kubeconfig: - description: KubeConfig content used to connect to cluster api server - Should provide this field explicitly if connection type is direct. - Will be populated by ks-proxy if connection type is proxy. - format: byte - type: string - kubernetesAPIEndpoint: - description: 'Kubernetes API Server endpoint. Example: https://10.10.0.1:6443 - Should provide this field explicitly if connection type is direct. - Will be populated by ks-apiserver if connection type is proxy.' - type: string - kubernetesAPIServerPort: - description: KubeAPIServerPort is the port which listens for forwarding - kube-apiserver traffic Only applicable when connection type is - proxy. - type: integer - kubesphereAPIEndpoint: - description: 'KubeSphere API Server endpoint. Example: http://10.10.0.11:8080 - Should provide this field explicitly if connection type is direct. - Will be populated by ks-apiserver if connection type is proxy.' - type: string - kubesphereAPIServerPort: - description: KubeSphereAPIServerPort is the port which listens for - forwarding kubesphere apigateway traffic Only applicable when - connection type is proxy. - type: integer - token: - description: Token used by agents of member cluster to connect to - host cluster proxy. This field is populated by apiserver only - if connection type is proxy. - type: string - type: - description: type defines how host cluster will connect to host - cluster ConnectionTypeDirect means direct connection, this requires kubeconfig - and kubesphere apiserver endpoint provided ConnectionTypeProxy - means using kubesphere proxy, no kubeconfig or kubesphere apiserver - endpoint required - type: string - type: object - enable: - description: Desired state of the cluster - type: boolean - joinFederation: - description: Join cluster as a kubefed cluster - type: boolean - provider: - description: Provider of the cluster, this field is just for description - type: string - type: object - status: - properties: - conditions: - description: Represents the latest available observations of a cluster's - current state. - items: + versions: + - additionalPrinterColumns: + - jsonPath: .spec.joinFederation + name: Federated + type: boolean + - jsonPath: .spec.provider + name: Provider + type: string + - jsonPath: .spec.enable + name: Active + type: boolean + - jsonPath: .status.kubernetesVersion + name: Version + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: Cluster is the schema for the clusters API + 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/sig-architecture/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/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + connection: + description: Connection holds info to connect to the member cluster properties: - lastTransitionTime: - description: Last time the condition transitioned from one status - to another. - format: date-time + kubeconfig: + description: KubeConfig content used to connect to cluster api server Should provide this field explicitly if connection type is direct. Will be populated by ks-proxy if connection type is proxy. + format: byte type: string - lastUpdateTime: - description: The last time this condition was updated. - format: date-time + kubernetesAPIEndpoint: + description: 'Kubernetes API Server endpoint. Example: https://10.10.0.1:6443 Should provide this field explicitly if connection type is direct. Will be populated by ks-apiserver if connection type is proxy.' type: string - message: - description: A human readable message indicating details about - the transition. + kubernetesAPIServerPort: + description: KubeAPIServerPort is the port which listens for forwarding kube-apiserver traffic Only applicable when connection type is proxy. + type: integer + kubesphereAPIEndpoint: + description: 'KubeSphere API Server endpoint. Example: http://10.10.0.11:8080 Should provide this field explicitly if connection type is direct. Will be populated by ks-apiserver if connection type is proxy.' type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. + kubesphereAPIServerPort: + description: KubeSphereAPIServerPort is the port which listens for forwarding kubesphere apigateway traffic Only applicable when connection type is proxy. + type: integer + token: + description: Token used by agents of member cluster to connect to host cluster proxy. This field is populated by apiserver only if connection type is proxy. type: string type: - description: Type of the condition + description: type defines how host cluster will connect to host cluster ConnectionTypeDirect means direct connection, this requires kubeconfig and kubesphere apiserver endpoint provided ConnectionTypeProxy means using kubesphere proxy, no kubeconfig or kubesphere apiserver endpoint required type: string - required: - - status - - type type: object - type: array - configz: - additionalProperties: + enable: + description: Desired state of the cluster type: boolean - description: Configz is status of components enabled in the member cluster. - This is synchronized with member cluster every amount of time, like - 5 minutes. - type: object - kubernetesVersion: - description: GitVersion of the kubernetes cluster, this field is populated - by cluster controller - type: string - nodeCount: - description: Count of the kubernetes cluster nodes This field may not - reflect the instant status of the cluster. - type: integer - region: - description: Region is the name of the region in which all of the nodes - in the cluster exist. e.g. 'us-east1'. - type: string - zones: - description: Zones are the names of availability zones in which the - nodes of the cluster exist, e.g. 'us-east1-a'. - items: + joinFederation: + description: Join cluster as a kubefed cluster + type: boolean + provider: + description: Provider of the cluster, this field is just for description type: string - type: array - type: object - type: object - version: v1alpha1 - versions: - - name: v1alpha1 + type: object + status: + properties: + conditions: + description: Represents the latest available observations of a cluster's current state. + items: + properties: + lastTransitionTime: + description: Last time the condition transitioned from one status to another. + format: date-time + type: string + lastUpdateTime: + description: The last time this condition was updated. + format: date-time + type: string + message: + description: A human readable message indicating details about the transition. + type: string + reason: + description: The reason for the condition's last transition. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of the condition + type: string + required: + - status + - type + type: object + type: array + configz: + additionalProperties: + type: boolean + description: Configz is status of components enabled in the member cluster. This is synchronized with member cluster every amount of time, like 5 minutes. + type: object + kubernetesVersion: + description: GitVersion of the kubernetes cluster, this field is populated by cluster controller + type: string + kubesphereVersion: + description: GitVersion of the /kapis/version api response, this field is populated by cluster controller + type: string + nodeCount: + description: Count of the kubernetes cluster nodes This field may not reflect the instant status of the cluster. + type: integer + region: + description: Region is the name of the region in which all of the nodes in the cluster exist. e.g. 'us-east1'. + type: string + zones: + description: Zones are the names of availability zones in which the nodes of the cluster exist, e.g. 'us-east1-a'. + items: + type: string + type: array + type: object + type: object served: true storage: true + subresources: {} status: acceptedNames: kind: "" diff --git a/pkg/apis/cluster/v1alpha1/cluster_types.go b/pkg/apis/cluster/v1alpha1/cluster_types.go index 8eb36127f..5d0382f9d 100644 --- a/pkg/apis/cluster/v1alpha1/cluster_types.go +++ b/pkg/apis/cluster/v1alpha1/cluster_types.go @@ -136,6 +136,9 @@ type ClusterStatus struct { // GitVersion of the kubernetes cluster, this field is populated by cluster controller KubernetesVersion string `json:"kubernetesVersion,omitempty"` + // GitVersion of the /kapis/version api response, this field is populated by cluster controller + KubeSphereVersion string `json:"kubeSphereVersion,omitempty"` + // Count of the kubernetes cluster nodes // This field may not reflect the instant status of the cluster. NodeCount int `json:"nodeCount,omitempty"` diff --git a/pkg/controller/cluster/cluster_controller.go b/pkg/controller/cluster/cluster_controller.go index 1b221984d..bce689ed9 100644 --- a/pkg/controller/cluster/cluster_controller.go +++ b/pkg/controller/cluster/cluster_controller.go @@ -51,6 +51,7 @@ import ( clusterclient "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/cluster/v1alpha1" clusterinformer "kubesphere.io/kubesphere/pkg/client/informers/externalversions/cluster/v1alpha1" clusterlister "kubesphere.io/kubesphere/pkg/client/listers/cluster/v1alpha1" + "kubesphere.io/kubesphere/pkg/version" ) // Cluster controller only runs under multicluster mode. Cluster controller is following below steps, @@ -582,6 +583,13 @@ func (c *clusterController) syncCluster(key string) error { cluster.Status.Configz = configz } + v, err := c.tryFetchKubeSphereVersion(clusterDt.config.Host, clusterDt.transport) + if err != nil { + klog.Errorf("failed to get KubeSphere version, err: %#v", err) + } else { + cluster.Status.KubeSphereVersion = v + } + // label cluster host cluster if configz["multicluster"]==true if mc, ok := configz[configzMultiCluster]; ok && mc && c.checkIfClusterIsHostCluster(nodes) { if cluster.Labels == nil { @@ -660,6 +668,44 @@ func (c *clusterController) tryToFetchKubeSphereComponents(host string, transpor return configz, nil } +// +func (c *clusterController) tryFetchKubeSphereVersion(host string, transport http.RoundTripper) (string, error) { + client := http.Client{ + Transport: transport, + Timeout: 5 * time.Second, + } + + response, err := client.Get(fmt.Sprintf(proxyFormat, host, "kapis/version")) + if err != nil { + return "", err + } + + if response.StatusCode != http.StatusOK { + klog.V(4).Infof("Response status code isn't 200.") + return "", fmt.Errorf("response code %d", response.StatusCode) + } + + info := version.Info{} + decoder := json.NewDecoder(response.Body) + err = decoder.Decode(&info) + if err != nil { + return "", err + } + + // currently, we kubesphere v2.1 can not be joined as a member cluster and it will never be reconciled, + // so we don't consider that situation + // for kubesphere v3.0.0, the gitVersion is always v0.0.0, so we return v3.0.0 + if info.GitVersion == "v0.0.0" { + return "v3.0.0", nil + } + + if len(info.GitVersion) == 0 { + return "unknown", nil + } + + return info.GitVersion, nil +} + func (c *clusterController) addCluster(obj interface{}) { cluster := obj.(*clusterv1alpha1.Cluster)