add kubesphereversion field for cluser.status

Signed-off-by: yuswift <yuswiftli@yunify.com>

adopt reviews from @LinuxSuRen
This commit is contained in:
yuswift
2021-04-07 11:19:26 +08:00
parent 828d2c6d37
commit 3b00fc6d5e
3 changed files with 161 additions and 139 deletions

View File

@@ -1,6 +1,6 @@
--- ---
apiVersion: apiextensions.k8s.io/v1beta1 apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition kind: CustomResourceDefinition
metadata: metadata:
annotations: annotations:
@@ -8,19 +8,6 @@ metadata:
creationTimestamp: null creationTimestamp: null
name: clusters.cluster.kubesphere.io name: clusters.cluster.kubesphere.io
spec: 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 group: cluster.kubesphere.io
names: names:
kind: Cluster kind: Cluster
@@ -28,20 +15,30 @@ spec:
plural: clusters plural: clusters
singular: cluster singular: cluster
scope: Cluster scope: Cluster
subresources: {} versions:
validation: - 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: openAPIV3Schema:
description: Cluster is the schema for the clusters API description: Cluster is the schema for the clusters API
properties: properties:
apiVersion: apiVersion:
description: 'APIVersion defines the versioned schema of this representation 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'
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 type: string
kind: kind:
description: 'Kind is a string value representing the REST resource this 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'
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 type: string
metadata: metadata:
type: object type: object
@@ -51,42 +48,26 @@ spec:
description: Connection holds info to connect to the member cluster description: Connection holds info to connect to the member cluster
properties: properties:
kubeconfig: kubeconfig:
description: KubeConfig content used to connect to cluster api server 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.
Should provide this field explicitly if connection type is direct.
Will be populated by ks-proxy if connection type is proxy.
format: byte format: byte
type: string type: string
kubernetesAPIEndpoint: kubernetesAPIEndpoint:
description: 'Kubernetes API Server endpoint. Example: https://10.10.0.1:6443 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.'
Should provide this field explicitly if connection type is direct.
Will be populated by ks-apiserver if connection type is proxy.'
type: string type: string
kubernetesAPIServerPort: kubernetesAPIServerPort:
description: KubeAPIServerPort is the port which listens for forwarding description: KubeAPIServerPort is the port which listens for forwarding kube-apiserver traffic Only applicable when connection type is proxy.
kube-apiserver traffic Only applicable when connection type is
proxy.
type: integer type: integer
kubesphereAPIEndpoint: kubesphereAPIEndpoint:
description: 'KubeSphere API Server endpoint. Example: http://10.10.0.11:8080 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.'
Should provide this field explicitly if connection type is direct.
Will be populated by ks-apiserver if connection type is proxy.'
type: string type: string
kubesphereAPIServerPort: kubesphereAPIServerPort:
description: KubeSphereAPIServerPort is the port which listens for description: KubeSphereAPIServerPort is the port which listens for forwarding kubesphere apigateway traffic Only applicable when connection type is proxy.
forwarding kubesphere apigateway traffic Only applicable when
connection type is proxy.
type: integer type: integer
token: token:
description: Token used by agents of member cluster to connect to 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.
host cluster proxy. This field is populated by apiserver only
if connection type is proxy.
type: string type: string
type: type:
description: type defines how host cluster will connect to host 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
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: string
type: object type: object
enable: enable:
@@ -102,13 +83,11 @@ spec:
status: status:
properties: properties:
conditions: conditions:
description: Represents the latest available observations of a cluster's description: Represents the latest available observations of a cluster's current state.
current state.
items: items:
properties: properties:
lastTransitionTime: lastTransitionTime:
description: Last time the condition transitioned from one status description: Last time the condition transitioned from one status to another.
to another.
format: date-time format: date-time
type: string type: string
lastUpdateTime: lastUpdateTime:
@@ -116,8 +95,7 @@ spec:
format: date-time format: date-time
type: string type: string
message: message:
description: A human readable message indicating details about description: A human readable message indicating details about the transition.
the transition.
type: string type: string
reason: reason:
description: The reason for the condition's last transition. description: The reason for the condition's last transition.
@@ -136,35 +114,30 @@ spec:
configz: configz:
additionalProperties: additionalProperties:
type: boolean type: boolean
description: Configz is status of components enabled in the member cluster. description: Configz is status of components enabled in the member cluster. This is synchronized with member cluster every amount of time, like 5 minutes.
This is synchronized with member cluster every amount of time, like
5 minutes.
type: object type: object
kubernetesVersion: kubernetesVersion:
description: GitVersion of the kubernetes cluster, this field is populated description: GitVersion of the kubernetes cluster, this field is populated by cluster controller
by cluster controller type: string
kubesphereVersion:
description: GitVersion of the /kapis/version api response, this field is populated by cluster controller
type: string type: string
nodeCount: nodeCount:
description: Count of the kubernetes cluster nodes This field may not description: Count of the kubernetes cluster nodes This field may not reflect the instant status of the cluster.
reflect the instant status of the cluster.
type: integer type: integer
region: region:
description: Region is the name of the region in which all of the nodes description: Region is the name of the region in which all of the nodes in the cluster exist. e.g. 'us-east1'.
in the cluster exist. e.g. 'us-east1'.
type: string type: string
zones: zones:
description: Zones are the names of availability zones in which the description: Zones are the names of availability zones in which the nodes of the cluster exist, e.g. 'us-east1-a'.
nodes of the cluster exist, e.g. 'us-east1-a'.
items: items:
type: string type: string
type: array type: array
type: object type: object
type: object type: object
version: v1alpha1
versions:
- name: v1alpha1
served: true served: true
storage: true storage: true
subresources: {}
status: status:
acceptedNames: acceptedNames:
kind: "" kind: ""

View File

@@ -136,6 +136,9 @@ type ClusterStatus struct {
// GitVersion of the kubernetes cluster, this field is populated by cluster controller // GitVersion of the kubernetes cluster, this field is populated by cluster controller
KubernetesVersion string `json:"kubernetesVersion,omitempty"` 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 // Count of the kubernetes cluster nodes
// This field may not reflect the instant status of the cluster. // This field may not reflect the instant status of the cluster.
NodeCount int `json:"nodeCount,omitempty"` NodeCount int `json:"nodeCount,omitempty"`

View File

@@ -51,6 +51,7 @@ import (
clusterclient "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/cluster/v1alpha1" clusterclient "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/cluster/v1alpha1"
clusterinformer "kubesphere.io/kubesphere/pkg/client/informers/externalversions/cluster/v1alpha1" clusterinformer "kubesphere.io/kubesphere/pkg/client/informers/externalversions/cluster/v1alpha1"
clusterlister "kubesphere.io/kubesphere/pkg/client/listers/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, // 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 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 // label cluster host cluster if configz["multicluster"]==true
if mc, ok := configz[configzMultiCluster]; ok && mc && c.checkIfClusterIsHostCluster(nodes) { if mc, ok := configz[configzMultiCluster]; ok && mc && c.checkIfClusterIsHostCluster(nodes) {
if cluster.Labels == nil { if cluster.Labels == nil {
@@ -660,6 +668,44 @@ func (c *clusterController) tryToFetchKubeSphereComponents(host string, transpor
return configz, nil 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{}) { func (c *clusterController) addCluster(obj interface{}) {
cluster := obj.(*clusterv1alpha1.Cluster) cluster := obj.(*clusterv1alpha1.Cluster)