Skip to content

Commit

Permalink
show cluster instance name and version in flux check and flux version
Browse files Browse the repository at this point in the history
Signed-off-by: Somtochi Onyekwere <[email protected]>
  • Loading branch information
somtochiama committed Nov 22, 2023
1 parent 2fb132b commit f6c1158
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 31 deletions.
72 changes: 45 additions & 27 deletions cmd/flux/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package main

import (
"context"
"fmt"
"os"
"time"

Expand All @@ -26,6 +27,7 @@ import (
v1 "k8s.io/api/apps/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/fluxcd/pkg/version"
Expand Down Expand Up @@ -80,7 +82,18 @@ func runCheckCmd(cmd *cobra.Command, args []string) error {

fluxCheck()

if !kubernetesCheck(kubernetesConstraints) {
ctx := context.Background()
kubeClient, err := utils.KubeClient(kubeconfigArgs, kubeclientOptions)
if err != nil {
return err
}

cfg, err := utils.KubeConfig(kubeconfigArgs, kubeclientOptions)
if err != nil {
return fmt.Errorf("Kubernetes client initialization failed: %s", err.Error())
}

if !kubernetesCheck(cfg, kubernetesConstraints) {
checkFailed = true
}

Expand All @@ -92,13 +105,18 @@ func runCheckCmd(cmd *cobra.Command, args []string) error {
return nil
}

logger.Actionf("checking cluster version")
if !fluxClusterVersionCheck(ctx, kubeClient) {
checkFailed = true
}

logger.Actionf("checking controllers")
if !componentsCheck() {
if !componentsCheck(ctx, cfg, kubeClient) {
checkFailed = true
}

logger.Actionf("checking crds")
if !crdsCheck() {
if !crdsCheck(ctx, kubeClient) {
checkFailed = true
}

Expand Down Expand Up @@ -129,17 +147,11 @@ func fluxCheck() {
return
}
if latestSv.GreaterThan(curSv) {
logger.Failuref("flux %s <%s (new version is available, please upgrade)", curSv, latestSv)
logger.Failuref("flux %s <%s (new CLI version is available, please upgrade)", curSv, latestSv)
}
}

func kubernetesCheck(constraints []string) bool {
cfg, err := utils.KubeConfig(kubeconfigArgs, kubeclientOptions)
if err != nil {
logger.Failuref("Kubernetes client initialization failed: %s", err.Error())
return false
}

func kubernetesCheck(cfg *rest.Config, constraints []string) bool {
clientSet, err := kubernetes.NewForConfig(cfg)
if err != nil {
logger.Failuref("Kubernetes client initialization failed: %s", err.Error())
Expand Down Expand Up @@ -178,30 +190,20 @@ func kubernetesCheck(constraints []string) bool {
return true
}

func componentsCheck() bool {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
func componentsCheck(ctx context.Context, kubeConfig *rest.Config, kubeClient client.Client) bool {
timeoutCtx, cancel := context.WithTimeout(ctx, rootArgs.timeout)
defer cancel()

kubeConfig, err := utils.KubeConfig(kubeconfigArgs, kubeclientOptions)
if err != nil {
return false
}

statusChecker, err := status.NewStatusChecker(kubeConfig, checkArgs.pollInterval, rootArgs.timeout, logger)
if err != nil {
return false
}

kubeClient, err := utils.KubeClient(kubeconfigArgs, kubeclientOptions)
if err != nil {
return false
}

ok := true
selector := client.MatchingLabels{manifestgen.PartOfLabelKey: manifestgen.PartOfLabelValue}
var list v1.DeploymentList
ns := *kubeconfigArgs.Namespace
if err := kubeClient.List(ctx, &list, client.InNamespace(ns), selector); err == nil {
if err := kubeClient.List(timeoutCtx, &list, client.InNamespace(ns), selector); err == nil {
if len(list.Items) == 0 {
logger.Failuref("no controllers found in the '%s' namespace with the label selector '%s=%s'",
ns, manifestgen.PartOfLabelKey, manifestgen.PartOfLabelValue)
Expand All @@ -222,8 +224,8 @@ func componentsCheck() bool {
return ok
}

func crdsCheck() bool {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
func crdsCheck(ctx context.Context, kubeClient client.Client) bool {
timeoutCtx, cancel := context.WithTimeout(ctx, rootArgs.timeout)
defer cancel()

kubeClient, err := utils.KubeClient(kubeconfigArgs, kubeclientOptions)
Expand All @@ -234,7 +236,7 @@ func crdsCheck() bool {
ok := true
selector := client.MatchingLabels{manifestgen.PartOfLabelKey: manifestgen.PartOfLabelValue}
var list apiextensionsv1.CustomResourceDefinitionList
if err := kubeClient.List(ctx, &list, client.InNamespace(*kubeconfigArgs.Namespace), selector); err == nil {
if err := kubeClient.List(timeoutCtx, &list, client.InNamespace(*kubeconfigArgs.Namespace), selector); err == nil {
if len(list.Items) == 0 {
logger.Failuref("no crds found with the label selector '%s=%s'",
manifestgen.PartOfLabelKey, manifestgen.PartOfLabelValue)
Expand All @@ -253,3 +255,19 @@ func crdsCheck() bool {
}
return ok
}

func fluxClusterVersionCheck(ctx context.Context, kubeClient client.Client) bool {
timeoutCtx, cancel := context.WithTimeout(ctx, rootArgs.timeout)
defer cancel()

distribution, bootstrapped, err := getFluxDistribution(timeoutCtx, kubeClient)
if err != nil {
return false
}

if distribution != "" {
logger.Successf("distribution: %s", distribution)
}
logger.Successf("bootstrapped: %t", bootstrapped)
return true
}
25 changes: 24 additions & 1 deletion cmd/flux/cluster_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ import (

"github.com/manifoldco/promptui"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/fluxcd/flux2/v2/pkg/manifestgen"
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
sourcev1 "github.com/fluxcd/source-controller/api/v1"
)
Expand All @@ -42,6 +44,8 @@ type fluxClusterInfo struct {
bootstrapped bool
// managedBy is the name of the tool being used to manage the installation of Flux.
managedBy string
// partOf indicates which distribution the instance is a part of.
partOf string
// version is the Flux version number in semver format.
version string
}
Expand All @@ -68,7 +72,7 @@ func getFluxClusterInfo(ctx context.Context, c client.Client) (fluxClusterInfo,
return info, err
}

info.version = crdMetadata.Labels["app.kubernetes.io/version"]
info.version = crdMetadata.Labels[manifestgen.VersionLabelKey]

var present bool
for _, l := range bootstrapLabels {
Expand All @@ -83,6 +87,10 @@ func getFluxClusterInfo(ctx context.Context, c client.Client) (fluxClusterInfo,
if manager, ok := crdMetadata.Labels["app.kubernetes.io/managed-by"]; ok {
info.managedBy = manager
}

if partOf, ok := crdMetadata.Labels[manifestgen.PartOfLabelKey]; ok {
info.partOf = partOf
}
return info, nil
}

Expand All @@ -105,6 +113,21 @@ func confirmFluxInstallOverride(info fluxClusterInfo) error {
return err
}

func getFluxDistribution(ctx context.Context, kubeClient client.Client) (string, bool, error) {
clusterInfo, err := getFluxClusterInfo(ctx, kubeClient)
if err != nil {
if !errors.IsNotFound(err) {
return "", false, fmt.Errorf("cluster info unavailable: %w", err)
}
}

distribution := clusterInfo.version
if clusterInfo.partOf != "" {
distribution = fmt.Sprintf("%s-%s", clusterInfo.partOf, clusterInfo.version)
}
return distribution, clusterInfo.bootstrapped, nil
}

func installManagedByFlux(manager string) bool {
return manager == "" || manager == "flux"
}
11 changes: 11 additions & 0 deletions cmd/flux/cluster_info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,17 @@ func Test_getFluxClusterInfo(t *testing.T) {
version: "v2.1.0",
},
},
{
name: "CRD with version and part-of labels",
labels: map[string]string{
"app.kubernetes.io/version": "v2.1.0",
"app.kubernetes.io/part-of": "flux",
},
wantInfo: fluxClusterInfo{
version: "v2.1.0",
partOf: "flux",
},
},
}

for _, tt := range tests {
Expand Down
27 changes: 25 additions & 2 deletions cmd/flux/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ import (
"context"
"encoding/json"
"fmt"
"gopkg.in/yaml.v2"
"strings"

"github.com/google/go-containerregistry/pkg/name"
"github.com/spf13/cobra"
v1 "k8s.io/api/apps/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"

"github.com/fluxcd/flux2/v2/internal/utils"
"github.com/fluxcd/flux2/v2/pkg/manifestgen"
Expand Down Expand Up @@ -55,6 +55,12 @@ type versionFlags struct {

var versionArgs versionFlags

type VersionInfo struct {
Flux string `yaml:"flux"`
Distribution string `yaml:"distribution,omitempty"`
Controller map[string]string `yaml:"controller,inline"`
}

func init() {
versionCmd.Flags().BoolVar(&versionArgs.client, "client", false,
"print only client version")
Expand All @@ -71,15 +77,31 @@ func versionCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()

// VersionInfo struct is used for yaml because we care about the order.
// Without this `distribution` is printed before `flux`.
// Unfortunately, encoding/json doesn't support the inline tag, so the struct can't be used for json.
yamlInfo := &VersionInfo{
Controller: map[string]string{},
}
info := map[string]string{}
info["flux"] = rootArgs.defaults.Version
yamlInfo.Flux = rootArgs.defaults.Version

if !versionArgs.client {
kubeClient, err := utils.KubeClient(kubeconfigArgs, kubeclientOptions)
if err != nil {
return err
}

distribution, _, err := getFluxDistribution(ctx, kubeClient)
if err != nil {
return err
}
if distribution != "" {
info["distribution"] = distribution
yamlInfo.Distribution = distribution
}

selector := client.MatchingLabels{manifestgen.PartOfLabelKey: manifestgen.PartOfLabelValue}
var list v1.DeploymentList
if err := kubeClient.List(ctx, &list, client.InNamespace(*kubeconfigArgs.Namespace), selector); err != nil {
Expand All @@ -97,6 +119,7 @@ func versionCmdRun(cmd *cobra.Command, args []string) error {
return err
}
info[name] = tag
yamlInfo.Controller[name] = tag
}
}
}
Expand All @@ -108,7 +131,7 @@ func versionCmdRun(cmd *cobra.Command, args []string) error {
marshalled, err = json.MarshalIndent(&info, "", " ")
marshalled = append(marshalled, "\n"...)
} else {
marshalled, err = yaml.Marshal(&info)
marshalled, err = yaml.Marshal(&yamlInfo)
}

if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ require (
golang.org/x/crypto v0.15.0
golang.org/x/term v0.14.0
golang.org/x/text v0.14.0
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.28.4
k8s.io/apiextensions-apiserver v0.28.4
k8s.io/apimachinery v0.28.4
Expand Down Expand Up @@ -209,7 +210,6 @@ require (
gopkg.in/evanphx/json-patch.v5 v5.6.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/component-base v0.28.4 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
Expand Down

0 comments on commit f6c1158

Please sign in to comment.