Skip to content

Commit

Permalink
show values, uninstall, list
Browse files Browse the repository at this point in the history
  • Loading branch information
AdheipSingh committed Dec 22, 2024
1 parent 1f22051 commit 1988da9
Show file tree
Hide file tree
Showing 6 changed files with 220 additions and 21 deletions.
14 changes: 14 additions & 0 deletions cmd/list.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
// Copyright (c) 2024 Parseable, Inc
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package cmd

import (
Expand Down
75 changes: 75 additions & 0 deletions cmd/show.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (c) 2024 Parseable, Inc
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package cmd

import (
"fmt"
"log"

"pb/pkg/common"
"pb/pkg/helm"

"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
)

// ShowValuesCmd lists the Parseable OSS servers
var ShowValuesCmd = &cobra.Command{
Use: "values",
Short: "Show values available in Parseable OSS servers",
Example: "pb show values",
Run: func(cmd *cobra.Command, _ []string) {
_, err := common.PromptK8sContext()
if err != nil {
log.Fatalf("Failed to prompt for Kubernetes context: %v", err)
}

// Read the installer data from the ConfigMap
entries, err := common.ReadInstallerConfigMap()
if err != nil {
log.Fatalf("Failed to list OSS servers: %v", err)
}

// Check if there are no entries
if len(entries) == 0 {
fmt.Println("No OSS servers found.")
return
}

// Prompt user to select a cluster
selectedCluster, err := common.PromptClusterSelection(entries)
if err != nil {
log.Fatalf("Failed to select a cluster: %v", err)
}

values, err := helm.GetReleaseValues(selectedCluster.Name, selectedCluster.Namespace)
if err != nil {
log.Fatalf("Failed to get values for release: %v", err)
}

// Marshal values to YAML for nice formatting
yamlOutput, err := yaml.Marshal(values)
if err != nil {
log.Fatalf("Failed to marshal values to YAML: %v", err)
}

// Print the YAML output
fmt.Println(string(yamlOutput))

// Print instructions for fetching secret values
fmt.Printf("\nTo get secret values of the Parseable cluster, run the following command:\n")
fmt.Printf("kubectl get secret -n %s parseable-env-secret -o jsonpath='{.data}' | jq -r 'to_entries[] | \"\\(.key): \\(.value | @base64d)\"'\n", selectedCluster.Namespace)
},
}
44 changes: 42 additions & 2 deletions cmd/uninstaller.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package cmd

import (
"context"
"fmt"
"log"

"pb/pkg/common"
"pb/pkg/helm"

"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)

// UninstallOssCmd removes Parseable OSS servers
Expand Down Expand Up @@ -39,6 +42,12 @@ var UninstallOssCmd = &cobra.Command{
log.Fatalf("Failed to select a cluster: %v", err)
}

// Display a warning banner
fmt.Println("\n────────────────────────────────────────────────────────────────────────────")
fmt.Println("⚠️ Deleting this cluster will not delete any data on object storage.")
fmt.Println(" This operation will clean up the Parseable deployment on Kubernetes.")
fmt.Println("────────────────────────────────────────────────────────────────────────────")

// Confirm uninstallation
fmt.Printf("\nYou have selected to uninstall the cluster '%s' in namespace '%s'.\n", selectedCluster.Name, selectedCluster.Namespace)
if !common.PromptConfirmation(fmt.Sprintf("Do you want to proceed with uninstalling '%s'?", selectedCluster.Name)) {
Expand All @@ -47,8 +56,20 @@ var UninstallOssCmd = &cobra.Command{
}

// Perform uninstallation
if err := uninstallCluster(selectedCluster); err != nil {
log.Fatalf("Failed to uninstall cluster: %v", err)
// if err := uninstallCluster(selectedCluster); err != nil {
// log.Fatalf("Failed to uninstall cluster: %v", err)
// }

// Remove entry from ConfigMap
if err := common.RemoveInstallerEntry(selectedCluster.Name); err != nil {
log.Fatalf("Failed to remove entry from ConfigMap: %v", err)
}

// Delete secret
if err := deleteSecret(selectedCluster.Namespace, "parseable-env-secret"); err != nil {
log.Printf("Warning: Failed to delete secret 'parseable-env-secret': %v", err)
} else {
fmt.Println(common.Green + "Secret 'parseable-env-secret' deleted successfully." + common.Reset)
}

fmt.Println(common.Green + "Uninstallation completed successfully." + common.Reset)
Expand Down Expand Up @@ -80,3 +101,22 @@ func uninstallCluster(entry common.InstallerEntry) error {
fmt.Printf(common.Green+"Successfully uninstalled '%s' from namespace '%s'.\n"+common.Reset, entry.Name, entry.Namespace)
return nil
}

func deleteSecret(namespace, secretName string) error {
config, err := common.LoadKubeConfig()
if err != nil {
return fmt.Errorf("failed to create Kubernetes client: %v", err)
}

clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return fmt.Errorf("failed to create Kubernetes client: %w", err)
}

err = clientset.CoreV1().Secrets(namespace).Delete(context.TODO(), "parseable-env-secret", metav1.DeleteOptions{})
if err != nil {
return fmt.Errorf("failed to delete secret '%s': %v", secretName, err)
}

return nil
}
20 changes: 20 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,23 @@ var list = &cobra.Command{
},
}

var show = &cobra.Command{
Use: "show",
Short: "Show outputs values defined when installing parseable on kubernetes cluster",
Long: "\nshow command is used to get values in parseable.",
PersistentPreRunE: combinedPreRun,
PersistentPostRun: func(cmd *cobra.Command, args []string) {
if os.Getenv("PB_ANALYTICS") == "disable" {
return
}
wg.Add(1)
go func() {
defer wg.Done()
analytics.PostRunAnalytics(cmd, "install", args)
}()
},
}

var uninstall = &cobra.Command{
Use: "uninstall",
Short: "Uninstall parseable on kubernetes cluster",
Expand Down Expand Up @@ -269,6 +286,8 @@ func main() {

uninstall.AddCommand(pb.UninstallOssCmd)

show.AddCommand(pb.ShowValuesCmd)

cli.AddCommand(profile)
cli.AddCommand(query)
cli.AddCommand(stream)
Expand All @@ -281,6 +300,7 @@ func main() {
cli.AddCommand(uninstall)
cli.AddCommand(schema)
cli.AddCommand(list)
cli.AddCommand(show)

// Set as command
pb.VersionCmd.Run = func(_ *cobra.Command, _ []string) {
Expand Down
69 changes: 64 additions & 5 deletions pkg/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ import (
"k8s.io/client-go/tools/clientcmd"
)

const (
configMapName = "parseable-installer"
namespace = "pb-system"
dataKey = "installer-data"
)

// ANSI escape codes for colors
const (
Yellow = "\033[33m"
Expand All @@ -51,11 +57,6 @@ type InstallerEntry struct {

// ReadInstallerConfigMap fetches and parses installer data from a ConfigMap
func ReadInstallerConfigMap() ([]InstallerEntry, error) {
const (
configMapName = "parseable-installer"
namespace = "pb-system"
dataKey = "installer-data"
)

// Load kubeconfig and create a Kubernetes client
config, err := LoadKubeConfig()
Expand Down Expand Up @@ -200,3 +201,61 @@ func CreateDeploymentSpinner(namespace, infoMsg string) *spinner.Spinner {

return s
}
func RemoveInstallerEntry(name string) error {
// Load kubeconfig and create a Kubernetes client
config, err := LoadKubeConfig()
if err != nil {
return fmt.Errorf("failed to load kubeconfig: %w", err)
}

clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return fmt.Errorf("failed to create Kubernetes client: %w", err)
}

// Fetch the ConfigMap
configMap, err := clientset.CoreV1().ConfigMaps(namespace).Get(context.TODO(), configMapName, metav1.GetOptions{})
if err != nil {
return fmt.Errorf("failed to fetch ConfigMap: %v", err)
}

// Log the current data in the ConfigMap

// Assuming the entries are stored as YAML or JSON string, unmarshal them into a slice
var entries []map[string]interface{}
if err := yaml.Unmarshal([]byte(configMap.Data["installer-data"]), &entries); err != nil {
return fmt.Errorf("failed to unmarshal installer data: %w", err)
}

// Find the entry to remove by name
var indexToRemove = -1
for i, entry := range entries {
if entry["name"] == name {
indexToRemove = i
break
}
}

// Check if the entry was found
if indexToRemove == -1 {
return fmt.Errorf("entry '%s' does not exist in ConfigMap", name)
}

// Remove the entry
entries = append(entries[:indexToRemove], entries[indexToRemove+1:]...)

// Marshal the updated entries back into YAML
updatedData, err := yaml.Marshal(entries)
if err != nil {
return fmt.Errorf("failed to marshal updated entries: %w", err)
}
configMap.Data["installer-data"] = string(updatedData)

// Update the ConfigMap in Kubernetes
_, err = clientset.CoreV1().ConfigMaps(namespace).Update(context.TODO(), configMap, metav1.UpdateOptions{})
if err != nil {
return fmt.Errorf("failed to update ConfigMap: %v", err)
}

return nil
}
19 changes: 5 additions & 14 deletions pkg/helm/helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ func ListRelease(releaseName, namespace string) (bool, error) {
return false, nil
}

func GetReleaseValues(chartName, namespace string) (map[string]interface{}, error) {
func GetReleaseValues(releaseName, namespace string) (map[string]interface{}, error) {
settings := cli.New()

// Initialize action configuration
Expand All @@ -266,24 +266,15 @@ func GetReleaseValues(chartName, namespace string) (map[string]interface{}, erro
return nil, err
}

// Create a new List action
client := action.NewList(actionConfig)
// Create a new get action
client := action.NewGet(actionConfig)

// Run the List action to get releases
releases, err := client.Run()
release, err := client.Run(releaseName)
if err != nil {
return nil, err
}

// Iterate over the releases
for _, release := range releases {
// Check if the release's chart name matches the specified chart name
if release.Chart.Name() == chartName {
return release.Chart.Values, nil
}
}

return nil, nil
return release.Config, nil
}

// DeleteRelease deletes a Helm release based on the specified chart name and namespace.
Expand Down

0 comments on commit 1988da9

Please sign in to comment.