Skip to content

Commit f58b6c6

Browse files
Add mssql server dag config command
Signed-off-by: Neaj Morshad <neaj@appscode.com>
1 parent b43c9c1 commit f58b6c6

File tree

2 files changed

+158
-0
lines changed

2 files changed

+158
-0
lines changed

pkg/cmds/mssql.go

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/*
2+
Copyright AppsCode Inc. and Contributors
3+
4+
Licensed under the AppsCode Community License 1.0.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package cmds
18+
19+
import (
20+
"context"
21+
"fmt"
22+
"os"
23+
24+
"github.com/spf13/cobra"
25+
core "k8s.io/api/core/v1"
26+
kerr "k8s.io/apimachinery/pkg/api/errors"
27+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28+
"k8s.io/client-go/kubernetes"
29+
cmdutil "k8s.io/kubectl/pkg/cmd/util"
30+
"sigs.k8s.io/yaml"
31+
)
32+
33+
// NewCmdMSSQL creates the parent `mssql` command
34+
func NewCmdMSSQL(f cmdutil.Factory) *cobra.Command {
35+
cmd := &cobra.Command{
36+
Use: "mssql",
37+
Short: "MSSQLServer database commands",
38+
Long: "Commands for managing KubeDB MSSQLServer instances.",
39+
Run: func(cmd *cobra.Command, args []string) {
40+
_ = cmd.Help()
41+
},
42+
}
43+
// Add your new command as a subcommand of mssql
44+
cmd.AddCommand(NewCmdDAGConfig(f))
45+
46+
// If you create more mssql commands in the future, add them here.
47+
// For example: cmd.AddCommand(mssql.NewCmdSomeOtherCommand(f))
48+
49+
return cmd
50+
}
51+
52+
// NewCmdDAGConfig creates the `kubectl dba mssql dag-config` command.
53+
func NewCmdDAGConfig(f cmdutil.Factory) *cobra.Command {
54+
var (
55+
namespace string
56+
outputDir string
57+
desLong = `Generates a YAML file with the necessary secrets for setting up a MSSQLServer Distributed Availability Group (DAG) remote replica.`
58+
exampleStr = ` # Generate DAG configuration secrets from MSSQLServer 'ag1' in namespace 'demo' and save to the current directory
59+
kubectl dba mssql dag-config ag1 -n demo
60+
61+
# Generate and save the configuration to a specific directory
62+
kubectl dba mssql dag-config ag1 -n demo --output-dir=/tmp/configs`
63+
)
64+
65+
cmd := &cobra.Command{
66+
Use: "dag-config [mssqlserver-name]",
67+
Short: "Generate Distributed Availability Group configuration from a source MSSQLServer",
68+
Long: desLong,
69+
Example: exampleStr,
70+
Args: cobra.ExactArgs(1),
71+
Run: func(cmd *cobra.Command, args []string) {
72+
mssqlServerName := args[0]
73+
cmdutil.CheckErr(runDAGConfig(f, namespace, outputDir, mssqlServerName))
74+
},
75+
}
76+
77+
cmd.Flags().StringVarP(&namespace, "namespace", "n", "default", "Namespace of the source MSSQLServer")
78+
cmd.Flags().StringVar(&outputDir, "output-dir", ".", "Directory where the configuration YAML file will be saved")
79+
return cmd
80+
}
81+
82+
func runDAGConfig(f cmdutil.Factory, namespace, outputDir, mssqlServerName string) error {
83+
client, err := f.KubernetesClientSet()
84+
if err != nil {
85+
return fmt.Errorf("failed to get kubernetes client: %w", err)
86+
}
87+
88+
fmt.Printf("Generating DAG configuration for MSSQLServer '%s' in namespace '%s'...\n", mssqlServerName, namespace)
89+
90+
yamlBuffer, err := generateMSSQLDAGConfig(client, namespace, mssqlServerName)
91+
if err != nil {
92+
return err
93+
}
94+
95+
if err := os.MkdirAll(outputDir, 0o755); err != nil {
96+
return fmt.Errorf("failed to create output directory '%s': %w", outputDir, err)
97+
}
98+
99+
outputFile := fmt.Sprintf("%s/%s-dag-config.yaml", outputDir, mssqlServerName)
100+
if err := os.WriteFile(outputFile, yamlBuffer, 0o644); err != nil {
101+
return fmt.Errorf("failed to write DAG config to file '%s': %w", outputFile, err)
102+
}
103+
104+
fmt.Printf("✅ Successfully generated DAG configuration.\n")
105+
fmt.Printf(" Apply this file in your remote cluster: kubectl apply -f %s\n", outputFile)
106+
107+
return nil
108+
}
109+
110+
func generateMSSQLDAGConfig(client kubernetes.Interface, namespace, mssqlServerName string) ([]byte, error) {
111+
var finalYAML []byte
112+
secretNames := []string{
113+
fmt.Sprintf("%s-dbm-login", mssqlServerName),
114+
fmt.Sprintf("%s-master-key", mssqlServerName),
115+
fmt.Sprintf("%s-endpoint-cert", mssqlServerName),
116+
}
117+
118+
for _, secretName := range secretNames {
119+
fmt.Printf(" - Fetching secret '%s'...\n", secretName)
120+
secret, err := client.CoreV1().Secrets(namespace).Get(context.TODO(), secretName, metav1.GetOptions{})
121+
if err != nil {
122+
if kerr.IsNotFound(err) {
123+
return nil, fmt.Errorf("required secret '%s' not found in namespace '%s'. Please ensure the source MSSQLServer is running correctly", secretName, namespace)
124+
}
125+
return nil, fmt.Errorf("failed to get secret '%s': %w", secretName, err)
126+
}
127+
cleanedSecret := cleanupSecretForExport(secret)
128+
secretYAML, err := yaml.Marshal(cleanedSecret)
129+
if err != nil {
130+
return nil, fmt.Errorf("failed to marshal secret '%s' to YAML: %w", secretName, err)
131+
}
132+
finalYAML = append(finalYAML, secretYAML...)
133+
finalYAML = append(finalYAML, []byte("---\n")...)
134+
}
135+
return finalYAML, nil
136+
}
137+
138+
func cleanupSecretForExport(secret *core.Secret) *core.Secret {
139+
return &core.Secret{
140+
TypeMeta: metav1.TypeMeta{
141+
APIVersion: core.SchemeGroupVersion.Version,
142+
Kind: "Secret",
143+
},
144+
ObjectMeta: metav1.ObjectMeta{
145+
Name: secret.Name,
146+
Namespace: secret.Namespace,
147+
Labels: secret.Labels,
148+
},
149+
Data: secret.Data,
150+
Type: secret.Type,
151+
}
152+
}

pkg/cmds/root.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,12 @@ func NewKubeDBCommand(in io.Reader, out, err io.Writer) *cobra.Command {
108108
NewCmdGenApb(f),
109109
},
110110
},
111+
{
112+
Message: "MSSQLServer specific commands",
113+
Commands: []*cobra.Command{
114+
NewCmdMSSQL(f),
115+
},
116+
},
111117
{
112118
Message: "Metric related CMDs",
113119
Commands: []*cobra.Command{

0 commit comments

Comments
 (0)