Skip to content

Commit a2b23ae

Browse files
authored
pb installer, uninstaller, show values and list (#80)
1 parent ca8242f commit a2b23ae

File tree

13 files changed

+1188
-582
lines changed

13 files changed

+1188
-582
lines changed

cmd/cluster.go

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
// Copyright (c) 2024 Parseable, Inc
2+
//
3+
// This program is free software: you can redistribute it and/or modify
4+
// it under the terms of the GNU Affero General Public License as published by
5+
// the Free Software Foundation, either version 3 of the License, or
6+
// (at your option) any later version.
7+
//
8+
// This program is distributed in the hope that it will be useful
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
// GNU Affero General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU Affero General Public License
14+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
16+
package cmd
17+
18+
import (
19+
"context"
20+
"fmt"
21+
"log"
22+
"os"
23+
"pb/pkg/common"
24+
"pb/pkg/helm"
25+
"pb/pkg/installer"
26+
27+
"github.com/olekukonko/tablewriter"
28+
"github.com/spf13/cobra"
29+
"gopkg.in/yaml.v2"
30+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31+
"k8s.io/client-go/kubernetes"
32+
)
33+
34+
var verbose bool
35+
36+
var InstallOssCmd = &cobra.Command{
37+
Use: "install",
38+
Short: "Deploy Parseable",
39+
Example: "pb cluster install",
40+
Run: func(cmd *cobra.Command, _ []string) {
41+
// Add verbose flag
42+
cmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "Enable verbose logging")
43+
installer.Installer(verbose)
44+
},
45+
}
46+
47+
// ListOssCmd lists the Parseable OSS servers
48+
var ListOssCmd = &cobra.Command{
49+
Use: "list",
50+
Short: "List available Parseable servers",
51+
Example: "pb list",
52+
Run: func(_ *cobra.Command, _ []string) {
53+
_, err := common.PromptK8sContext()
54+
if err != nil {
55+
log.Fatalf("Failed to prompt for kubernetes context: %v", err)
56+
}
57+
58+
// Read the installer data from the ConfigMap
59+
entries, err := common.ReadInstallerConfigMap()
60+
if err != nil {
61+
log.Fatalf("Failed to list servers: %v", err)
62+
}
63+
64+
// Check if there are no entries
65+
if len(entries) == 0 {
66+
fmt.Println("No clusters found.")
67+
return
68+
}
69+
70+
// Display the entries in a table format
71+
table := tablewriter.NewWriter(os.Stdout)
72+
table.SetHeader([]string{"Name", "Namespace", "Version", "Status"})
73+
74+
for _, entry := range entries {
75+
table.Append([]string{entry.Name, entry.Namespace, entry.Version, entry.Status})
76+
}
77+
78+
table.Render()
79+
},
80+
}
81+
82+
// ShowValuesCmd lists the Parseable OSS servers
83+
var ShowValuesCmd = &cobra.Command{
84+
Use: "show values",
85+
Short: "Show values available in Parseable servers",
86+
Example: "pb show values",
87+
Run: func(_ *cobra.Command, _ []string) {
88+
_, err := common.PromptK8sContext()
89+
if err != nil {
90+
log.Fatalf("Failed to prompt for Kubernetes context: %v", err)
91+
}
92+
93+
// Read the installer data from the ConfigMap
94+
entries, err := common.ReadInstallerConfigMap()
95+
if err != nil {
96+
log.Fatalf("Failed to list OSS servers: %v", err)
97+
}
98+
99+
// Check if there are no entries
100+
if len(entries) == 0 {
101+
fmt.Println("No OSS servers found.")
102+
return
103+
}
104+
105+
// Prompt user to select a cluster
106+
selectedCluster, err := common.PromptClusterSelection(entries)
107+
if err != nil {
108+
log.Fatalf("Failed to select a cluster: %v", err)
109+
}
110+
111+
values, err := helm.GetReleaseValues(selectedCluster.Name, selectedCluster.Namespace)
112+
if err != nil {
113+
log.Fatalf("Failed to get values for release: %v", err)
114+
}
115+
116+
// Marshal values to YAML for nice formatting
117+
yamlOutput, err := yaml.Marshal(values)
118+
if err != nil {
119+
log.Fatalf("Failed to marshal values to YAML: %v", err)
120+
}
121+
122+
// Print the YAML output
123+
fmt.Println(string(yamlOutput))
124+
125+
// Print instructions for fetching secret values
126+
fmt.Printf("\nTo get secret values of the Parseable cluster, run the following command:\n")
127+
fmt.Printf("kubectl get secret -n %s parseable-env-secret -o jsonpath='{.data}' | jq -r 'to_entries[] | \"\\(.key): \\(.value | @base64d)\"'\n", selectedCluster.Namespace)
128+
},
129+
}
130+
131+
// UninstallOssCmd removes Parseable OSS servers
132+
var UninstallOssCmd = &cobra.Command{
133+
Use: "uninstall",
134+
Short: "Uninstall Parseable servers",
135+
Example: "pb uninstall",
136+
Run: func(_ *cobra.Command, _ []string) {
137+
_, err := common.PromptK8sContext()
138+
if err != nil {
139+
log.Fatalf("Failed to prompt for Kubernetes context: %v", err)
140+
}
141+
142+
// Read the installer data from the ConfigMap
143+
entries, err := common.ReadInstallerConfigMap()
144+
if err != nil {
145+
log.Fatalf("Failed to fetch OSS servers: %v", err)
146+
}
147+
148+
// Check if there are no entries
149+
if len(entries) == 0 {
150+
fmt.Println(common.Yellow + "\nNo Parseable OSS servers found to uninstall.")
151+
return
152+
}
153+
154+
// Prompt user to select a cluster
155+
selectedCluster, err := common.PromptClusterSelection(entries)
156+
if err != nil {
157+
log.Fatalf("Failed to select a cluster: %v", err)
158+
}
159+
160+
// Display a warning banner
161+
fmt.Println("\n────────────────────────────────────────────────────────────────────────────")
162+
fmt.Println("⚠️ Deleting this cluster will not delete any data on object storage.")
163+
fmt.Println(" This operation will clean up the Parseable deployment on Kubernetes.")
164+
fmt.Println("────────────────────────────────────────────────────────────────────────────")
165+
166+
// Confirm uninstallation
167+
fmt.Printf("\nYou have selected to uninstall the cluster '%s' in namespace '%s'.\n", selectedCluster.Name, selectedCluster.Namespace)
168+
if !common.PromptConfirmation(fmt.Sprintf("Do you want to proceed with uninstalling '%s'?", selectedCluster.Name)) {
169+
fmt.Println(common.Yellow + "Uninstall operation canceled.")
170+
return
171+
}
172+
173+
//Perform uninstallation
174+
if err := uninstallCluster(selectedCluster); err != nil {
175+
log.Fatalf("Failed to uninstall cluster: %v", err)
176+
}
177+
178+
// Remove entry from ConfigMap
179+
if err := common.RemoveInstallerEntry(selectedCluster.Name); err != nil {
180+
log.Fatalf("Failed to remove entry from ConfigMap: %v", err)
181+
}
182+
183+
// Delete secret
184+
if err := deleteSecret(selectedCluster.Namespace, "parseable-env-secret"); err != nil {
185+
log.Printf("Warning: Failed to delete secret 'parseable-env-secret': %v", err)
186+
} else {
187+
fmt.Println(common.Green + "Secret 'parseable-env-secret' deleted successfully." + common.Reset)
188+
}
189+
190+
fmt.Println(common.Green + "Uninstallation completed successfully." + common.Reset)
191+
},
192+
}
193+
194+
func uninstallCluster(entry common.InstallerEntry) error {
195+
helmApp := helm.Helm{
196+
ReleaseName: entry.Name,
197+
Namespace: entry.Namespace,
198+
RepoName: "parseable",
199+
RepoURL: "https://charts.parseable.com",
200+
ChartName: "parseable",
201+
Version: entry.Version,
202+
}
203+
204+
fmt.Println(common.Yellow + "Starting uninstallation process..." + common.Reset)
205+
206+
spinner := common.CreateDeploymentSpinner(fmt.Sprintf("Uninstalling Parseable OSS '%s'...", entry.Name))
207+
spinner.Start()
208+
209+
_, err := helm.Uninstall(helmApp, false)
210+
spinner.Stop()
211+
212+
if err != nil {
213+
return fmt.Errorf("failed to uninstall Parseable OSS: %v", err)
214+
}
215+
216+
fmt.Printf(common.Green+"Successfully uninstalled '%s' from namespace '%s'.\n"+common.Reset, entry.Name, entry.Namespace)
217+
return nil
218+
}
219+
220+
func deleteSecret(namespace, secretName string) error {
221+
config, err := common.LoadKubeConfig()
222+
if err != nil {
223+
return fmt.Errorf("failed to create Kubernetes client: %v", err)
224+
}
225+
226+
clientset, err := kubernetes.NewForConfig(config)
227+
if err != nil {
228+
return fmt.Errorf("failed to create Kubernetes client: %w", err)
229+
}
230+
231+
err = clientset.CoreV1().Secrets(namespace).Delete(context.TODO(), "parseable-env-secret", metav1.DeleteOptions{})
232+
if err != nil {
233+
return fmt.Errorf("failed to delete secret '%s': %v", secretName, err)
234+
}
235+
236+
return nil
237+
}

0 commit comments

Comments
 (0)