-
Notifications
You must be signed in to change notification settings - Fork 196
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add "cloud" command to odigos cli for login and logout (#727)
- Loading branch information
Showing
6 changed files
with
278 additions
and
4 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/google/uuid" | ||
"github.com/keyval-dev/odigos/cli/cmd/resources" | ||
"github.com/keyval-dev/odigos/cli/pkg/kube" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func verifyOdigosCloudApiKey(apikey string) error { | ||
_, err := uuid.Parse(apikey) | ||
if err != nil { | ||
return fmt.Errorf("invalid apikey format. expected uuid format") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// cloudCmd represents the cloud command | ||
var cloudCmd = &cobra.Command{ | ||
Use: "cloud", | ||
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() | ||
|
||
ns, err := resources.GetOdigosNamespace(client, ctx) | ||
if resources.IsErrNoOdigosNamespaceFound(err) { | ||
fmt.Println("\033[31mERROR\033[0m no odigos installation found in the current cluster. use \"odigos install\" to install odigos in the cluster or check that kubeconfig is pointing to the correct cluster.") | ||
os.Exit(1) | ||
} else if err != nil { | ||
fmt.Printf("\033[31mERROR\033[0m Failed to check if Odigos is already installed: %s\n", err) | ||
os.Exit(1) | ||
} | ||
|
||
isOdigosCloud, err := resources.IsOdigosCloud(ctx, client, ns) | ||
if err != nil { | ||
fmt.Println("Odigos cloud failed - unable to read the current Odigos cloud configuration.") | ||
os.Exit(1) | ||
} | ||
|
||
if isOdigosCloud { | ||
fmt.Println("Odigos cloud is currently enabled") | ||
} else { | ||
fmt.Println(`Odigos cloud is currently disabled. | ||
To enable odigos cloud run 'odigos cloud login'`) | ||
} | ||
}, | ||
} | ||
|
||
func init() { | ||
rootCmd.AddCommand(cloudCmd) | ||
} |
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 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,127 @@ | ||
package cmd | ||
|
||
import ( | ||
"bufio" | ||
"context" | ||
"fmt" | ||
"os" | ||
"strconv" | ||
|
||
"github.com/keyval-dev/odigos/cli/cmd/resources" | ||
"github.com/keyval-dev/odigos/cli/pkg/kube" | ||
"github.com/keyval-dev/odigos/cli/pkg/labels" | ||
"github.com/keyval-dev/odigos/cli/pkg/log" | ||
"github.com/spf13/cobra" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/types" | ||
) | ||
|
||
// This function requires knowledge of which objects should be updated once the odigos cloud secret is updated. | ||
// It is not very generic, but it is the best we can do for now. | ||
func restartPodsAfterCloudLogin(ctx context.Context, client *kube.Client, ns string, configVersion int) error { | ||
|
||
configVersionStr := strconv.Itoa(configVersion) | ||
patch := fmt.Sprintf(`{"spec":{"template":{"metadata":{"annotations":{"%s":"%s"}}}}}`, labels.OdigosSystemConfigLabelKey, configVersionStr) | ||
|
||
_, err := client.AppsV1().Deployments(ns).Patch(ctx, resources.KeyvalProxyDeploymentName, types.StrategicMergePatchType, []byte(patch), metav1.PatchOptions{}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
_, err = client.AppsV1().Deployments(ns).Patch(ctx, resources.OwnTelemetryCollectorDeploymentName, types.StrategicMergePatchType, []byte(patch), metav1.PatchOptions{}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// 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() | ||
|
||
ns, err := resources.GetOdigosNamespace(client, ctx) | ||
if resources.IsErrNoOdigosNamespaceFound(err) { | ||
fmt.Println("\033[31mERROR\033[0m no odigos installation found in the current cluster. use \"odigos install\" to install odigos in the cluster or check that kubeconfig is pointing to the correct cluster.") | ||
os.Exit(1) | ||
} else if err != nil { | ||
fmt.Printf("\033[31mERROR\033[0m Failed to check if Odigos is already installed: %s\n", err) | ||
os.Exit(1) | ||
} | ||
|
||
config, err := resources.GetCurrentConfig(ctx, client, ns) | ||
if err != nil { | ||
fmt.Println("Odigos cloud login failed - unable to read the current Odigos configuration.") | ||
os.Exit(1) | ||
} | ||
config.Spec.ConfigVersion += 1 | ||
|
||
if odigosCloudApiKeyFlag == "" { | ||
fmt.Println("Enter your odigos cloud api-key. You can find it here: https://app.keyval.io/settings/api-keys") | ||
fmt.Print("api-key: ") | ||
scanner := bufio.NewScanner(os.Stdin) | ||
scanner.Scan() | ||
odigosCloudApiKeyFlag = scanner.Text() | ||
} | ||
|
||
err = verifyOdigosCloudApiKey(odigosCloudApiKeyFlag) | ||
if err != nil { | ||
fmt.Println("Odigos cloud login failed - invalid api-key format.") | ||
os.Exit(1) | ||
} | ||
|
||
isPrevOdigosCloud, err := resources.IsOdigosCloud(ctx, client, ns) | ||
if err != nil { | ||
fmt.Println("Odigos cloud login failed - unable to read the current Odigos cloud configuration.") | ||
os.Exit(1) | ||
} | ||
|
||
resourceManagers := resources.CreateResourceManagers(client, ns, true, &odigosCloudApiKeyFlag, &config.Spec) | ||
err = resources.ApplyResourceManagers(ctx, client, resourceManagers, "Updating") | ||
if err != nil { | ||
fmt.Println("Odigos cloud login failed - unable to apply Odigos resources.") | ||
os.Exit(1) | ||
} | ||
err = resources.DeleteOldOdigosSystemObjects(ctx, client, ns, config) | ||
if err != nil { | ||
fmt.Println("Odigos cloud login failed - unable to cleanup old Odigos resources.") | ||
os.Exit(1) | ||
} | ||
|
||
if isPrevOdigosCloud { | ||
l := log.Print("Restarting relevant pods ...") | ||
err := restartPodsAfterCloudLogin(ctx, client, ns, config.Spec.ConfigVersion) | ||
if err != nil { | ||
l.Error(err) | ||
} | ||
l.Success() | ||
} | ||
} | ||
|
||
// loginCmd represents the login command | ||
var loginCmd = &cobra.Command{ | ||
Use: "login", | ||
Short: "Login to Odigos cloud", | ||
Long: `Connect this Odigos installation to your odigos cloud account.`, | ||
Run: updateApiKey, | ||
} | ||
|
||
// loginCmd represents the login command | ||
var updateCmd = &cobra.Command{ | ||
Use: "update", | ||
Short: "Update your Odigos Cloud api-key", | ||
Long: `Use this command to update your Odigos Cloud api-key.`, | ||
Run: updateApiKey, | ||
} | ||
|
||
func init() { | ||
cloudCmd.AddCommand(loginCmd) | ||
cloudCmd.AddCommand(updateCmd) | ||
|
||
loginCmd.Flags().StringVarP(&odigosCloudApiKeyFlag, "api-key", "k", "", "api key for odigos cloud") | ||
updateCmd.Flags().StringVarP(&odigosCloudApiKeyFlag, "api-key", "k", "", "api key for odigos cloud") | ||
} |
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,79 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/keyval-dev/odigos/cli/cmd/resources" | ||
"github.com/keyval-dev/odigos/cli/pkg/confirm" | ||
"github.com/keyval-dev/odigos/cli/pkg/kube" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
// logoutCmd represents the logout command | ||
var logoutCmd = &cobra.Command{ | ||
Use: "logout", | ||
Short: "Logout from Odigos cloud", | ||
Long: `Disconnect this Odigos installation from your odigos cloud account. | ||
After running this command, you will no longer be able to control and monitor this Odigos installation from Odigos cloud. | ||
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() | ||
|
||
ns, err := resources.GetOdigosNamespace(client, ctx) | ||
if resources.IsErrNoOdigosNamespaceFound(err) { | ||
fmt.Println("\033[31mERROR\033[0m no odigos installation found in the current cluster. use \"odigos install\" to install odigos in the cluster or check that kubeconfig is pointing to the correct cluster.") | ||
os.Exit(1) | ||
} else if err != nil { | ||
fmt.Printf("\033[31mERROR\033[0m Failed to check if Odigos is already installed: %s\n", err) | ||
os.Exit(1) | ||
} | ||
|
||
isOdigosCloud, err := resources.IsOdigosCloud(ctx, client, ns) | ||
if err != nil { | ||
fmt.Println("Odigos cloud logout failed - unable to read the current Odigos cloud configuration.") | ||
os.Exit(1) | ||
} | ||
if !isOdigosCloud { | ||
fmt.Println("The current odigos installation is not connected to Odigos cloud.") | ||
os.Exit(1) | ||
} | ||
|
||
fmt.Println("About to logout from Odigos cloud. You can still manager your Odigos installation locally with 'odigos ui'.") | ||
confirmed, err := confirm.Ask("Are you sure?") | ||
if err != nil || !confirmed { | ||
fmt.Println("Aborting odigos cloud logout") | ||
return | ||
} | ||
|
||
config, err := resources.GetCurrentConfig(ctx, client, ns) | ||
if err != nil { | ||
fmt.Println("Odigos cloud logout failed - unable to read the current Odigos configuration.") | ||
os.Exit(1) | ||
} | ||
config.Spec.ConfigVersion += 1 | ||
|
||
emptyApiKey := "" | ||
resourceManagers := resources.CreateResourceManagers(client, ns, false, &emptyApiKey, &config.Spec) | ||
err = resources.ApplyResourceManagers(ctx, client, resourceManagers, "Updating") | ||
if err != nil { | ||
fmt.Println("Odigos cloud logout failed - unable to apply Odigos resources.") | ||
os.Exit(1) | ||
} | ||
err = resources.DeleteOldOdigosSystemObjects(ctx, client, ns, config) | ||
if err != nil { | ||
fmt.Println("Odigos cloud logout failed - unable to cleanup old Odigos resources.") | ||
os.Exit(1) | ||
} | ||
}, | ||
} | ||
|
||
func init() { | ||
cloudCmd.AddCommand(logoutCmd) | ||
} |
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 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