Skip to content

Commit

Permalink
review fix
Browse files Browse the repository at this point in the history
  • Loading branch information
wangzhen127 committed Jun 28, 2018
1 parent 1f0391d commit 5ef8f64
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 118 deletions.
31 changes: 9 additions & 22 deletions clusterctl/cmd/validate_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,14 @@ import (
"os"

"github.com/spf13/cobra"
"k8s.io/api/core/v1"
tcmd "k8s.io/client-go/tools/clientcmd"
"sigs.k8s.io/cluster-api/clusterctl/validation"
"sigs.k8s.io/cluster-api/pkg/clientcmd"
"sigs.k8s.io/cluster-api/pkg/util"
)

type ValidateClusterOptions struct {
ClusterName string
Namespace string
Kubeconfig string
Kubeconfig string
KubeconfigOverrides tcmd.ConfigOverrides
}

var vco = &ValidateClusterOptions{}
Expand All @@ -49,35 +47,24 @@ var validateClusterCmd = &cobra.Command{
}

func init() {
validateClusterCmd.Flags().StringVarP(
&vco.ClusterName, "cluster-name", "", "",
"The name of the cluster to be validated. This can be omitted if there is only one cluster being managed in the given namespace.")
validateClusterCmd.Flags().StringVarP(
&vco.Namespace, "namespace", "n", v1.NamespaceDefault,
"If present, validate the cluster in the specified namespace.")
validateClusterCmd.Flags().StringVarP(
&vco.Kubeconfig, "kubeconfig", "", "",
"The file path of the kubeconfig file for Cluster API management stack. If not specified, $KUBECONFIG environment variable or ${HOME}/.kube/config is used.")
// BindContextFlags will bind the flags cluster, namespace, and user
tcmd.BindContextFlags(&do.KubeconfigOverrides.Context, validateClusterCmd.Flags(), tcmd.RecommendedContextOverrideFlags(""))
validateCmd.AddCommand(validateClusterCmd)
}

func RunValidateCluster() error {
kubeconfig := vco.Kubeconfig
if kubeconfig == "" {
kubeconfig = os.Getenv("KUBECONFIG")
if kubeconfig == "" {
kubeconfig = util.GetDefaultKubeConfigPath()
}
}
client, err := clientcmd.NewClusterApiClientForDefaultSearchPath(kubeconfig, clientcmd.NewConfigOverrides())
client, err := clientcmd.NewClusterApiClientForDefaultSearchPath(vco.Kubeconfig, vco.KubeconfigOverrides)
if err != nil {
return fmt.Errorf("Failed to create client for talking to the apiserver: %v", err)
return fmt.Errorf("failed to create client for talking to the apiserver: %v", err)
}

if err = validation.ValidateClusterAPIObjects(client, vco.ClusterName, vco.Namespace); err != nil {
if err = validation.ValidateClusterAPIObjects(os.Stdout, client, vco.KubeconfigOverrides.Context.Cluster, vco.KubeconfigOverrides.Context.Namespace); err != nil {
return err
}

// TODO(wangzhen127): Also validate the cluster in addition to the cluster API objects.
// TODO(wangzhen127): Also validate the cluster in addition to the cluster API objects. https://github.com/kubernetes-sigs/cluster-api/issues/168
return nil
}
1 change: 1 addition & 0 deletions clusterctl/main_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ func TestEmptyAndInvalidArgs(t *testing.T) {
{"delete cluster with no arguments with invalid flag", []string{"delete", "cluster", "--invalid-flag"}, 1, "delete-cluster-no-args-invalid-flag.golden"},
{"validate with no arguments", []string{"validate"}, 0, "validate-no-args.golden"},
{"validate with no arguments with invalid flag", []string{"validate", "--invalid-flag"}, 1, "validate-no-args-invalid-flag.golden"},
{"validate cluster with no arguments with invalid flag", []string{"validate", "cluster", "--invalid-flag"}, 1, "validate-cluster-no-args-invalid-flag.golden"},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
Expand Down
22 changes: 22 additions & 0 deletions clusterctl/testdata/validate-cluster-no-args-invalid-flag.golden
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 Cluster API management stack. 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
80 changes: 43 additions & 37 deletions clusterctl/validation/validate_cluster_api_objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,30 @@ package validation

import (
"fmt"
"io"

meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"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"
)

func ValidateClusterAPIObjects(client *clientset.Clientset, clusterName string, namespace string) error {
fmt.Printf("Validating cluster API objects in namespace %q.\n", namespace)
func ValidateClusterAPIObjects(w io.Writer, client *clientset.Clientset, clusterName string, namespace string) error {
fmt.Fprintf(w,"Validating cluster API objects in namespace %q\n", namespace)

cluster, err := getClusterObject(client, clusterName, namespace)
if err != nil {
return err
}
if err := validateClusterObject(cluster); err != nil {
if err := validateClusterObject(w, cluster); err != nil {
return err
}

machines, err := client.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 fmt.Errorf("failed to get the machines from the apiserver in namespace %q: %v", namespace, err)
}
if err = validateMachineObjects(machines); err != nil {
if err = validateMachineObjects(w, machines); err != nil {
return err
}

Expand All @@ -51,62 +52,67 @@ func getClusterObject(client *clientset.Clientset, clusterName string, namespace
if clusterName != "" {
cluster, err := client.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 nil, fmt.Errorf("failed to get the cluster %q from the apiserver in namespace %q: %v", clusterName, namespace, err)
}
return cluster, nil
}

clusters, err := client.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)
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)
return nil, fmt.Errorf("fail: No cluster exists in namespace %q.", namespace)
} else if numOfClusters > 1 {
return nil, fmt.Errorf("Fail: There are more than one cluster in namespace %q. Please specify --cluster-name.", namespace)
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(cluster *v1alpha1.Cluster) error {
fmt.Printf("Checking cluster object %q... ", cluster.Name)
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.Printf("FAIL\n")
fmt.Printf("\t[%v]: %s\n", cluster.Status.ErrorReason, cluster.Status.ErrorMessage)
return fmt.Errorf("Failed to validate the cluster %q.", cluster.Name)
fmt.Fprintf(w,"FAIL\n")
fmt.Fprintf(w,"\t[%v]: %s\n", cluster.Status.ErrorReason, cluster.Status.ErrorMessage)
return fmt.Errorf("failed to validate the cluster %q.", cluster.Name)
}
fmt.Printf("PASS\n")
fmt.Fprintf(w,"PASS\n")
return nil
}

func validateMachineObjects(machines *v1alpha1.MachineList) error {
func validateMachineObject(w io.Writer, machine v1alpha1.Machine) 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 does not exist.\n")
return false
}
fmt.Fprintf(w,"PASS\n")
return true
}

func validateMachineObjects(w io.Writer, machines *v1alpha1.MachineList) error {
pass := true
for _, machine := range machines.Items {
fmt.Printf("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.Printf("FAIL\n")
fmt.Printf("\t[%v]: %s\n", reason, message)
pass = false
continue
}
if machine.Status.NodeRef == nil {
fmt.Printf("FAIL\n")
fmt.Printf("\tThe corresponding node does not exist.\n")
if (!validateMachineObject(w, machine)) {
pass = false
continue
}
fmt.Printf("PASS\n")
}
if !pass {
return fmt.Errorf("Failed to validate machine objects.")
return fmt.Errorf("failed to validate some machine object.")
}
return nil
}
Loading

0 comments on commit 5ef8f64

Please sign in to comment.