-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Validate cluster and machine objects
- Loading branch information
1 parent
029a374
commit cc879bc
Showing
10 changed files
with
761 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
clusterctl/testdata/validate-cluster-no-args-invalid-flag.golden
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
Error: unknown flag: --invalid-flag | ||
Usage: | ||
clusterctl validate cluster [flags] | ||
|
||
Flags: | ||
--cluster string The name of the kubeconfig cluster to use | ||
-h, --help help for cluster | ||
--kubeconfig string The file path of the kubeconfig file for the cluster to validate.. If not specified, $KUBECONFIG environment variable or ${HOME}/.kube/config is used. | ||
-n, --namespace string If present, the namespace scope for this CLI request | ||
--user string The name of the kubeconfig user to use | ||
|
||
Global Flags: | ||
--alsologtostderr log to standard error as well as files | ||
--log-flush-frequency duration Maximum number of seconds between log flushes (default 5s) | ||
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0) | ||
--log_dir string If non-empty, write log files in this directory | ||
--logtostderr log to standard error instead of files (default true) | ||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2) | ||
-v, --v Level log level for V logs | ||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging | ||
|
||
unknown flag: --invalid-flag |
3 changes: 3 additions & 0 deletions
3
clusterctl/validation/testdata/fail-to-validate-cluster-object.golden
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Validating Cluster API objects in namespace "validate-cluster-api-object-output" | ||
Checking cluster object "test-cluster"... FAIL | ||
[CreateError]: Failed to create cluster |
6 changes: 6 additions & 0 deletions
6
clusterctl/validation/testdata/fail-to-validate-machine-objects-with-errors.golden
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
Validating Cluster API objects in namespace "validate-cluster-api-object-output" | ||
Checking cluster object "test-cluster"... PASS | ||
Checking machine object "test-machine1"... FAIL | ||
[CreateError]: Failed to create machine | ||
Checking machine object "test-machine2"... FAIL | ||
The corresponding node is missing. |
6 changes: 6 additions & 0 deletions
6
clusterctl/validation/testdata/fail-to-validate-machine-objects-with-noderef-errors.golden
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
Validating Cluster API objects in namespace "validate-cluster-api-object-output" | ||
Checking cluster object "test-cluster"... PASS | ||
Checking machine object "test-machine1"... FAIL | ||
The corresponding node "test-node-not-ready" is not ready. | ||
Checking machine object "test-machine2"... FAIL | ||
The corresponding node "test-node-not-exist" is not found: nodes "test-node-not-exist" not found |
4 changes: 4 additions & 0 deletions
4
clusterctl/validation/testdata/validate-cluster-api-object-output-pass.golden
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Validating Cluster API objects in namespace "validate-cluster-api-object-output" | ||
Checking cluster object "test-cluster"... PASS | ||
Checking machine object "test-machine1"... PASS | ||
Checking machine object "test-machine2"... PASS |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
/* | ||
Copyright 2018 The Kubernetes Authors. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package validation | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
|
||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/client-go/kubernetes" | ||
"sigs.k8s.io/cluster-api/pkg/apis/cluster/common" | ||
"sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha1" | ||
"sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset" | ||
"sigs.k8s.io/cluster-api/pkg/controller/noderefutil" | ||
) | ||
|
||
func ValidateClusterAPIObjects(w io.Writer, clusterApiClient *clientset.Clientset, k8sClient kubernetes.Interface, clusterName string, namespace string) error { | ||
fmt.Fprintf(w, "Validating Cluster API objects in namespace %q\n", namespace) | ||
|
||
cluster, err := getClusterObject(clusterApiClient, clusterName, namespace) | ||
if err != nil { | ||
return err | ||
} | ||
if err := validateClusterObject(w, cluster); err != nil { | ||
return err | ||
} | ||
|
||
machines, err := clusterApiClient.ClusterV1alpha1().Machines(namespace).List(meta_v1.ListOptions{}) | ||
if err != nil { | ||
return fmt.Errorf("failed to get the machines from the apiserver in namespace %q: %v", namespace, err) | ||
} | ||
|
||
return validateMachineObjects(w, machines, k8sClient) | ||
} | ||
|
||
func getClusterObject(clusterApiClient *clientset.Clientset, clusterName string, namespace string) (*v1alpha1.Cluster, error) { | ||
if clusterName != "" { | ||
cluster, err := clusterApiClient.ClusterV1alpha1().Clusters(namespace).Get(clusterName, meta_v1.GetOptions{}) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get the cluster %q from the apiserver in namespace %q: %v", clusterName, namespace, err) | ||
} | ||
return cluster, nil | ||
} | ||
|
||
clusters, err := clusterApiClient.ClusterV1alpha1().Clusters(namespace).List(meta_v1.ListOptions{}) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get the clusters from the apiserver in namespace %q: %v", namespace, err) | ||
} | ||
if numOfClusters := len(clusters.Items); numOfClusters == 0 { | ||
return nil, fmt.Errorf("fail: No cluster exists in namespace %q.", namespace) | ||
} else if numOfClusters > 1 { | ||
return nil, fmt.Errorf("fail: There is more than one cluster in namespace %q. Please specify --cluster-name.", namespace) | ||
} | ||
return &clusters.Items[0], nil | ||
} | ||
|
||
func validateClusterObject(w io.Writer, cluster *v1alpha1.Cluster) error { | ||
fmt.Fprintf(w, "Checking cluster object %q... ", cluster.Name) | ||
if cluster.Status.ErrorReason != "" || cluster.Status.ErrorMessage != "" { | ||
fmt.Fprintf(w, "FAIL\n") | ||
fmt.Fprintf(w, "\t[%v]: %s\n", cluster.Status.ErrorReason, cluster.Status.ErrorMessage) | ||
return fmt.Errorf("Cluster %q failed the validation.", cluster.Name) | ||
} | ||
fmt.Fprintf(w, "PASS\n") | ||
return nil | ||
} | ||
|
||
func validateMachineObjects(w io.Writer, machines *v1alpha1.MachineList, k8sClient kubernetes.Interface) error { | ||
pass := true | ||
for _, machine := range machines.Items { | ||
if (!validateMachineObject(w, machine, k8sClient)) { | ||
pass = false | ||
} | ||
} | ||
if !pass { | ||
return fmt.Errorf("Machine objects failed the validation.") | ||
} | ||
return nil | ||
} | ||
|
||
func validateMachineObject(w io.Writer, machine v1alpha1.Machine, k8sClient kubernetes.Interface) bool { | ||
fmt.Fprintf(w, "Checking machine object %q... ", machine.Name) | ||
if machine.Status.ErrorReason != nil || machine.Status.ErrorMessage != nil { | ||
var reason common.MachineStatusError = "" | ||
if machine.Status.ErrorReason != nil { | ||
reason = *machine.Status.ErrorReason | ||
} | ||
var message string = "" | ||
if machine.Status.ErrorMessage != nil { | ||
message = *machine.Status.ErrorMessage | ||
} | ||
fmt.Fprintf(w, "FAIL\n") | ||
fmt.Fprintf(w, "\t[%v]: %s\n", reason, message) | ||
return false | ||
} | ||
if machine.Status.NodeRef == nil { | ||
fmt.Fprintf(w, "FAIL\n") | ||
fmt.Fprintf(w, "\tThe corresponding node is missing.\n") | ||
return false | ||
} | ||
err := validateReferredNode(w, machine.Status.NodeRef.Name, k8sClient) | ||
if err != nil { | ||
fmt.Fprintf(w, "FAIL\n") | ||
fmt.Fprintf(w, "\t%v\n", err) | ||
return false | ||
} | ||
fmt.Fprintf(w, "PASS\n") | ||
return true | ||
} | ||
|
||
func validateReferredNode(w io.Writer, nodeName string, k8sClient kubernetes.Interface) error { | ||
node, err := k8sClient.CoreV1().Nodes().Get(nodeName, meta_v1.GetOptions{}) | ||
if err != nil { | ||
return fmt.Errorf("The corresponding node %q is not found: %v", nodeName, err) | ||
} | ||
if !noderefutil.IsNodeReady(node) { | ||
return fmt.Errorf("The corresponding node %q is not ready.", nodeName) | ||
} | ||
return nil | ||
} |
Oops, something went wrong.