Skip to content

Commit

Permalink
Add PersistentPreRun to the root CLI cmd to set the kube client and c…
Browse files Browse the repository at this point in the history
…luster details once for all commands (#1759)

Add `PersistentPreRun` which will be inherited by all sub-commands of
the root command.
Perform a client initialzation in that function and set the cluster kind
and k8s version as well - so they can be used by all commands. Both the
kube client and the cluster details are set on the command context and
can be used by all the commands.
The helper function from k8sutils `GetKubernetesVersion` can't be used
outside of the cluster by the CLI since it as using a rest client which
states:

> // InClusterConfig returns a config object which uses the service
account
// kubernetes gives to pods. It's intended for clients that expect to be
// running inside a pod running on kubernetes. It will return
ErrNotInCluster
// if called from a process not running in a kubernetes environment.
func InClusterConfig() (*Config, error) {

Hence, removing the use of this function from the CLI, and using the k8s
version which was calculated in the `PersistentPreRun` function.
Before this change `odigos upgrade` resulted in errors such as:

> Syncing customresourcedefinitionsDeleteOldOdigosSystemObjects failed
to get k8s version, proceeding.. :unable to load in-cluster
configuration, KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must
be defined ✔
Syncing deploymentsDeleteOldOdigosSystemObjects failed to get k8s
version, proceeding.. :unable to load in-cluster configuration,
KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined ✔
Syncing daemonsetsDeleteOldOdigosSystemObjects failed to get k8s
version, proceeding.. :unable to load in-cluster
  • Loading branch information
RonFed authored Nov 17, 2024
1 parent 6d3f571 commit 148a184
Show file tree
Hide file tree
Showing 19 changed files with 217 additions and 135 deletions.
7 changes: 2 additions & 5 deletions cli/cmd/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/google/uuid"
"github.com/odigos-io/odigos/cli/cmd/resources"
"github.com/odigos-io/odigos/cli/cmd/resources/odigospro"
"github.com/odigos-io/odigos/cli/pkg/kube"
cmdcontext "github.com/odigos-io/odigos/cli/pkg/cmd_context"
"github.com/odigos-io/odigos/common"
"github.com/spf13/cobra"
)
Expand All @@ -27,11 +27,8 @@ var cloudCmd = &cobra.Command{
Short: "Manage odigos cloud",
Long: `Used to interact with odigos managed service.`,
Run: func(cmd *cobra.Command, args []string) {
client, err := kube.CreateClient(cmd)
if err != nil {
kube.PrintClientErrorAndExit(err)
}
ctx := cmd.Context()
client := cmdcontext.KubeClientFromContextOrExit(ctx)

ns, err := resources.GetOdigosNamespace(client, ctx)
if resources.IsErrNoOdigosNamespaceFound(err) {
Expand Down
27 changes: 8 additions & 19 deletions cli/cmd/describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/odigos-io/odigos/cli/cmd/resources"
"github.com/odigos-io/odigos/cli/pkg/kube"
cmdcontext "github.com/odigos-io/odigos/cli/pkg/cmd_context"
"github.com/odigos-io/odigos/k8sutils/pkg/describe"
"github.com/spf13/cobra"
)
Expand All @@ -21,12 +22,8 @@ var describeCmd = &cobra.Command{
Short: "Show details on odigos deployment",
Long: `Print detailed description odigos deployment, which can be used to troubleshoot issues`,
Run: func(cmd *cobra.Command, args []string) {

client, err := kube.CreateClient(cmd)
if err != nil {
kube.PrintClientErrorAndExit(err)
}
ctx := cmd.Context()
client := cmdcontext.KubeClientFromContextOrExit(ctx)

odigosNs, err := resources.GetOdigosNamespace(client, ctx)
if err != nil {
Expand Down Expand Up @@ -66,11 +63,9 @@ var describeSourceDeploymentCmd = &cobra.Command{
Aliases: []string{"deploy", "deployments", "deploy.apps", "deployment.apps", "deployments.apps"},
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
client, err := kube.CreateClient(cmd)
if err != nil {
kube.PrintClientErrorAndExit(err)
}
ctx := cmd.Context()
client := cmdcontext.KubeClientFromContextOrExit(ctx)

name := args[0]
ns := cmd.Flag("namespace").Value.String()

Expand All @@ -96,12 +91,9 @@ var describeSourceDaemonSetCmd = &cobra.Command{
Aliases: []string{"ds", "daemonsets", "ds.apps", "daemonset.apps", "daemonsets.apps"},
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
client, err := kube.CreateClient(cmd)
if err != nil {
kube.PrintClientErrorAndExit(err)
}

ctx := cmd.Context()
client := cmdcontext.KubeClientFromContextOrExit(ctx)

name := args[0]
ns := cmd.Flag("namespace").Value.String()

Expand All @@ -127,12 +119,9 @@ var describeSourceStatefulSetCmd = &cobra.Command{
Aliases: []string{"sts", "statefulsets", "sts.apps", "statefulset.apps", "statefulsets.apps"},
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
client, err := kube.CreateClient(cmd)
if err != nil {
kube.PrintClientErrorAndExit(err)
}

ctx := cmd.Context()
client := cmdcontext.KubeClientFromContextOrExit(ctx)

name := args[0]
ns := cmd.Flag("namespace").Value.String()

Expand Down
8 changes: 3 additions & 5 deletions cli/cmd/diagnose.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"github.com/odigos-io/odigos/cli/cmd/diagnose_util"
"github.com/odigos-io/odigos/cli/pkg/kube"
cmdcontext "github.com/odigos-io/odigos/cli/pkg/cmd_context"
"github.com/spf13/cobra"
"io"
"os"
Expand All @@ -32,12 +33,9 @@ var diagnoseCmd = &cobra.Command{
Long: `Diagnose Client Cluster to identify issues and resolve them. This command is useful for troubleshooting and debugging.`,
Run: func(cmd *cobra.Command, args []string) {
ctx := cmd.Context()
client, err := kube.CreateClient(cmd)
if err != nil {
kube.PrintClientErrorAndExit(err)
}
client := cmdcontext.KubeClientFromContextOrExit(ctx)

err = startDiagnose(ctx, client)
err := startDiagnose(ctx, client)
if err != nil {
fmt.Printf("The diagnose script crashed on: %v\n", err)
}
Expand Down
38 changes: 12 additions & 26 deletions cli/cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package cmd

import (
"context"
"errors"
"fmt"
"os"
"time"
Expand All @@ -21,10 +20,11 @@ import (
"github.com/odigos-io/odigos/cli/cmd/resources"
"github.com/odigos-io/odigos/cli/pkg/kube"
"github.com/odigos-io/odigos/cli/pkg/log"
cmdcontext "github.com/odigos-io/odigos/cli/pkg/cmd_context"

"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/version"
"k8s.io/apimachinery/pkg/util/wait"
)

Expand All @@ -47,12 +47,6 @@ var (
imagePrefix string
)

var (
// minK8SVersionForInstallation is the minimum Kubernetes version required for Odigos installation
// this value must be in sync with the one defined in the kubeVersion field in Chart.yaml
minK8SVersionForInstallation = version.MustParse("v1.20.15-0")
)

type ResourceCreationFunc func(ctx context.Context, cmd *cobra.Command, client *kube.Client, ns string) error

// installCmd represents the install command
Expand All @@ -62,12 +56,8 @@ var installCmd = &cobra.Command{
Long: `Install Odigos in your kubernetes cluster.
This command will install k8s components that will auto-instrument your applications with OpenTelemetry and send traces, metrics and logs to any telemetry backend`,
Run: func(cmd *cobra.Command, args []string) {

client, err := kube.CreateClient(cmd)
if err != nil {
kube.PrintClientErrorAndExit(err)
}
ctx := cmd.Context()
client := cmdcontext.KubeClientFromContextOrExit(ctx)
ns := cmd.Flag("namespace").Value.String()

// Check if Odigos already installed
Expand All @@ -78,24 +68,20 @@ This command will install k8s components that will auto-instrument your applicat
}

// Check if the cluster meets the minimum requirements
kc := cmd.Flag("kubeconfig").Value.String()
details, err := autodetect.DetectK8SClusterDetails(ctx, kc, client)
if !errors.Is(err, autodetect.ErrCannotDetectClusterKind) {
autodetect.CurrentKubernetesVersion.Kind = details.Kind
fmt.Printf("Detected cluster: Kubernetes kind: %s\n", details.Kind)
} else {
clusterKind := cmdcontext.ClusterKindFromContext(ctx)
if clusterKind == autodetect.KindUnknown {
fmt.Println("Unknown Kubernetes cluster detected, proceeding with installation")
} else {
fmt.Printf("Detected cluster: Kubernetes kind: %s\n", clusterKind)
}

if !errors.Is(err, autodetect.ErrCannotDetectK8sVersion) {
autodetect.CurrentKubernetesVersion.Version = details.K8SVersion
if details.K8SVersion.LessThan(minK8SVersionForInstallation) {
fmt.Printf("\033[31mERROR\033[0m Odigos requires Kubernetes version %s or higher but found %s, aborting\n", minK8SVersionForInstallation.String(), details.K8SVersion.String())
k8sVersion := cmdcontext.K8SVersionFromContext(ctx)
if k8sVersion != nil {
if k8sVersion.LessThan(k8sconsts.MinK8SVersionForInstallation) {
fmt.Printf("\033[31mERROR\033[0m Odigos requires Kubernetes version %s or higher but found %s, aborting\n", k8sconsts.MinK8SVersionForInstallation.String(), k8sVersion.String())
os.Exit(1)
}
fmt.Printf("Detected cluster: Kubernetes version: %s\n", details.K8SVersion.String())
} else {
fmt.Println("Unknown Kubernetes version detected, proceeding with installation")
fmt.Printf("Detected cluster: Kubernetes version: %s\n", k8sVersion.String())
}

var odigosProToken string
Expand Down
6 changes: 2 additions & 4 deletions cli/cmd/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/odigos-io/odigos/cli/cmd/resources"
"github.com/odigos-io/odigos/cli/cmd/resources/odigospro"
cmdcontext "github.com/odigos-io/odigos/cli/pkg/cmd_context"
"github.com/odigos-io/odigos/cli/pkg/kube"
"github.com/odigos-io/odigos/cli/pkg/labels"
"github.com/odigos-io/odigos/cli/pkg/log"
Expand Down Expand Up @@ -46,11 +47,8 @@ func restartPodsAfterCloudLogin(ctx context.Context, client *kube.Client, ns str

// both login and update trigger this function.
func updateApiKey(cmd *cobra.Command, args []string) {
client, err := kube.CreateClient(cmd)
if err != nil {
kube.PrintClientErrorAndExit(err)
}
ctx := cmd.Context()
client := cmdcontext.KubeClientFromContextOrExit(ctx)

ns, err := resources.GetOdigosNamespace(client, ctx)
if resources.IsErrNoOdigosNamespaceFound(err) {
Expand Down
7 changes: 2 additions & 5 deletions cli/cmd/logout.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (

"github.com/odigos-io/odigos/cli/cmd/resources"
"github.com/odigos-io/odigos/cli/cmd/resources/odigospro"
cmdcontext "github.com/odigos-io/odigos/cli/pkg/cmd_context"
"github.com/odigos-io/odigos/cli/pkg/confirm"
"github.com/odigos-io/odigos/cli/pkg/kube"
"github.com/odigos-io/odigos/common"
"github.com/odigos-io/odigos/k8sutils/pkg/getters"
"github.com/spf13/cobra"
Expand All @@ -23,11 +23,8 @@ var logoutCmd = &cobra.Command{
You can run 'odigos ui' to manage your Odigos installation locally.
`,
Run: func(cmd *cobra.Command, args []string) {
client, err := kube.CreateClient(cmd)
if err != nil {
kube.PrintClientErrorAndExit(err)
}
ctx := cmd.Context()
client := cmdcontext.KubeClientFromContextOrExit(ctx)

ns, err := resources.GetOdigosNamespace(client, ctx)
if resources.IsErrNoOdigosNamespaceFound(err) {
Expand Down
17 changes: 4 additions & 13 deletions cli/cmd/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (

"github.com/odigos-io/odigos/cli/cmd/resources"
"github.com/odigos-io/odigos/cli/cmd/resources/odigospro"
"github.com/odigos-io/odigos/cli/pkg/kube"
cmdcontext "github.com/odigos-io/odigos/cli/pkg/cmd_context"
"github.com/odigos-io/odigos/common"
"github.com/odigos-io/odigos/k8sutils/pkg/getters"
"github.com/spf13/cobra"
Expand All @@ -17,11 +17,8 @@ var profileCmd = &cobra.Command{
Short: "Manage odigos profiles",
Long: `Odigos profiles are used to apply some specific preset configuration to the odigos installation`,
Run: func(cmd *cobra.Command, args []string) {
client, err := kube.CreateClient(cmd)
if err != nil {
kube.PrintClientErrorAndExit(err)
}
ctx := cmd.Context()
client := cmdcontext.KubeClientFromContextOrExit(ctx)

ns, err := resources.GetOdigosNamespace(client, ctx)
if resources.IsErrNoOdigosNamespaceFound(err) {
Expand Down Expand Up @@ -78,11 +75,8 @@ var addProfileCmd = &cobra.Command{
Long: `Add a profile by its name to the current Odigos installation.`,
Args: cobra.ExactArgs(1), // Ensure exactly one argument is passed (the profile name)
Run: func(cmd *cobra.Command, args []string) {
client, err := kube.CreateClient(cmd)
if err != nil {
kube.PrintClientErrorAndExit(err)
}
ctx := cmd.Context()
client := cmdcontext.KubeClientFromContextOrExit(ctx)

ns, err := resources.GetOdigosNamespace(client, ctx)
if resources.IsErrNoOdigosNamespaceFound(err) {
Expand Down Expand Up @@ -164,11 +158,8 @@ var removeProfileCmd = &cobra.Command{
Long: `Remove a profile by its name from the current Odigos installation.`,
Args: cobra.ExactArgs(1), // Ensure exactly one argument is passed (the profile name)
Run: func(cmd *cobra.Command, args []string) {
client, err := kube.CreateClient(cmd)
if err != nil {
kube.PrintClientErrorAndExit(err)
}
ctx := cmd.Context()
client := cmdcontext.KubeClientFromContextOrExit(ctx)

ns, err := resources.GetOdigosNamespace(client, ctx)
if resources.IsErrNoOdigosNamespaceFound(err) {
Expand Down
4 changes: 3 additions & 1 deletion cli/cmd/resources/applyresources.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/odigos-io/odigos/api/odigos/v1alpha1"
"github.com/odigos-io/odigos/cli/cmd/resources/resourcemanager"
cmdcontext "github.com/odigos-io/odigos/cli/pkg/cmd_context"
"github.com/odigos-io/odigos/cli/pkg/kube"
"github.com/odigos-io/odigos/cli/pkg/log"
"github.com/odigos-io/odigos/common"
Expand All @@ -30,9 +31,10 @@ func ApplyResourceManagers(ctx context.Context, client *kube.Client, resourceMan

func DeleteOldOdigosSystemObjects(ctx context.Context, client *kube.Client, ns string, config *common.OdigosConfiguration) error {
resources := kube.GetManagedResources(ns)
k8sVersion := cmdcontext.K8SVersionFromContext(ctx)
for _, resource := range resources {
l := log.Print(fmt.Sprintf("Syncing %s", resource.Resource.Resource))
err := client.DeleteOldOdigosSystemObjects(ctx, resource, config.ConfigVersion)
err := client.DeleteOldOdigosSystemObjects(ctx, resource, config.ConfigVersion, k8sVersion)
if err != nil {
l.Error(err)
os.Exit(1)
Expand Down
20 changes: 14 additions & 6 deletions cli/cmd/resources/odiglet.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"k8s.io/apimachinery/pkg/api/resource"

"github.com/odigos-io/odigos/cli/pkg/autodetect"
cmdcontext "github.com/odigos-io/odigos/cli/pkg/cmd_context"

"github.com/odigos-io/odigos/cli/cmd/resources/odigospro"
"github.com/odigos-io/odigos/cli/cmd/resources/resourcemanager"
Expand Down Expand Up @@ -416,7 +417,7 @@ func NewResourceQuota(ns string) *corev1.ResourceQuota {
}
}

func NewOdigletDaemonSet(ns string, version string, imagePrefix string, imageName string, odigosTier common.OdigosTier, openshiftEnabled bool, goAutoIncludeCodeAttributes bool) *appsv1.DaemonSet {
func NewOdigletDaemonSet(ns string, version string, imagePrefix string, imageName string, odigosTier common.OdigosTier, openshiftEnabled bool, goAutoIncludeCodeAttributes bool, clusterDetails *autodetect.ClusterDetails) *appsv1.DaemonSet {

dynamicEnv := []corev1.EnvVar{}
if odigosTier == common.CloudOdigosTier {
Expand All @@ -434,7 +435,7 @@ func NewOdigletDaemonSet(ns string, version string, imagePrefix string, imageNam

odigosSeLinuxHostVolumes := []corev1.Volume{}
odigosSeLinuxHostVolumeMounts := []corev1.VolumeMount{}
if openshiftEnabled || autodetect.CurrentKubernetesVersion.Kind == autodetect.KindOpenShift {
if openshiftEnabled || clusterDetails.Kind == autodetect.KindOpenShift {
odigosSeLinuxHostVolumes = append(odigosSeLinuxHostVolumes, selinuxHostVolumes()...)
odigosSeLinuxHostVolumeMounts = append(odigosSeLinuxHostVolumeMounts, selinuxHostVolumeMounts()...)
}
Expand All @@ -452,7 +453,8 @@ func NewOdigletDaemonSet(ns string, version string, imagePrefix string, imageNam
rollingUpdate := &appsv1.RollingUpdateDaemonSet{
MaxUnavailable: &maxUnavailable,
}
if autodetect.CurrentKubernetesVersion.Version != nil && autodetect.CurrentKubernetesVersion.Version.AtLeast(k8sversion.MustParse("v1.22")) {
k8sversionInCluster := clusterDetails.K8SVersion
if k8sversionInCluster != nil && k8sversionInCluster.AtLeast(k8sversion.MustParse("v1.22")) {
maxSurge := intstr.FromInt(0)
rollingUpdate.MaxSurge = &maxSurge
}
Expand Down Expand Up @@ -725,14 +727,16 @@ func (a *odigletResourceManager) InstallFromScratch(ctx context.Context) error {
NewOdigletClusterRoleBinding(a.ns),
}

clusterKind := cmdcontext.ClusterKindFromContext(ctx)

// if openshift is enabled, we need to create additional SCC cluster role binding first
if a.config.OpenshiftEnabled || autodetect.CurrentKubernetesVersion.Kind == autodetect.KindOpenShift {
if a.config.OpenshiftEnabled || clusterKind == autodetect.KindOpenShift {
resources = append(resources, NewSCCRoleBinding(a.ns))
resources = append(resources, NewSCClusterRoleBinding(a.ns))
}

// if gke, create resource quota
if autodetect.CurrentKubernetesVersion.Kind == autodetect.KindGKE {
if clusterKind == autodetect.KindGKE {
resources = append(resources, NewResourceQuota(a.ns))
}

Expand All @@ -747,7 +751,11 @@ func (a *odigletResourceManager) InstallFromScratch(ctx context.Context) error {

// before creating the daemonset, we need to create the service account, cluster role and cluster role binding
resources = append(resources,
NewOdigletDaemonSet(a.ns, a.odigosVersion, a.config.ImagePrefix, odigletImage, a.odigosTier, a.config.OpenshiftEnabled, goAutoIncludeCodeAttributes))
NewOdigletDaemonSet(a.ns, a.odigosVersion, a.config.ImagePrefix, odigletImage, a.odigosTier, a.config.OpenshiftEnabled, goAutoIncludeCodeAttributes,
&autodetect.ClusterDetails{
Kind: clusterKind,
K8SVersion: cmdcontext.K8SVersionFromContext(ctx),
}))

return a.client.ApplyResources(ctx, a.config.ConfigVersion, resources)
}
Loading

0 comments on commit 148a184

Please sign in to comment.