Files
deploy/cmd/cd/commands/admin/redis_initial_password.go
zeekayandHanzo Dev 1ab6e799c1 cd: the module is github.com/hanzoai/cd, where it is actually hosted
go.mod still declared `module github.com/hanzoai/deploy` after the repo was
renamed. A Go module path is not cosmetic — it is the resolvable location. So
`go get github.com/hanzoai/cd` could not work, and anything importing this
module had to spell a name that no longer exists at that address. The build log
of v3.6.0 is where it surfaced: the compiler was still emitting
github.com/hanzoai/deploy/cmd/cd/commands.

3541 import paths across 690 .go, 19 .proto, 4 .yaml, 3 .sh, 2 .mod, Procfile
and Makefile. Plus the 62 ghcr.io/hanzoai/deploy image references, moved to
ghcr.io/hanzoai/cd to match hanzo.yml's build target — a distinct string from
the module path, replaced separately so neither could clobber the other.

go mod tidy clean, CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build ./... clean.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-28 21:16:24 -07:00

97 lines
3.2 KiB
Go

package admin
import (
"context"
"crypto/rand"
"fmt"
"math/big"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"github.com/hanzoai/cd/common"
"github.com/hanzoai/cd/pkg/apis/application/v1alpha1"
"github.com/hanzoai/cd/util/cli"
"github.com/hanzoai/cd/util/errors"
)
func generateRandomPassword() (string, error) {
const initialPasswordLength = 16
const letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"
randBytes := make([]byte, initialPasswordLength)
for i := range initialPasswordLength {
num, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters))))
if err != nil {
return "", err
}
randBytes[i] = letters[num.Int64()]
}
initialPassword := string(randBytes)
return initialPassword, nil
}
// NewRedisInitialPasswordCommand defines a new command to ensure Hanzo CD Redis password secret exists.
func NewRedisInitialPasswordCommand() *cobra.Command {
var clientConfig clientcmd.ClientConfig
command := cobra.Command{
Use: "redis-initial-password",
Short: "Ensure the Redis password exists, creating a new one if necessary.",
Run: func(_ *cobra.Command, _ []string) {
namespace, _, err := clientConfig.Namespace()
errors.CheckError(err)
// redisInitialCredentials is the kubernetes secret containing
// the redis password
redisInitialCredentials := common.RedisInitialCredentials
// redisInitialCredentialsKey is the key in the redisInitialCredentials
// secret which maps to the redis password
redisInitialCredentialsKey := common.RedisInitialCredentialsKey
fmt.Printf("Checking for initial Redis password in secret %s/%s at key %s. \n", namespace, redisInitialCredentials, redisInitialCredentialsKey)
config, err := clientConfig.ClientConfig()
errors.CheckError(err)
errors.CheckError(v1alpha1.SetK8SConfigDefaults(config))
kubeClientset := kubernetes.NewForConfigOrDie(config)
randomPassword, err := generateRandomPassword()
errors.CheckError(err)
data := map[string][]byte{
redisInitialCredentialsKey: []byte(randomPassword),
}
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: redisInitialCredentials,
Namespace: namespace,
},
Data: data,
Type: corev1.SecretTypeOpaque,
}
_, err = kubeClientset.CoreV1().Secrets(namespace).Create(context.Background(), secret, metav1.CreateOptions{})
if err != nil && !apierrors.IsAlreadyExists(err) {
errors.CheckError(err)
}
fmt.Printf("Hanzo CD Redis secret state confirmed: secret name %s.\n", redisInitialCredentials)
secret, err = kubeClientset.CoreV1().Secrets(namespace).Get(context.Background(), redisInitialCredentials, metav1.GetOptions{})
errors.CheckError(err)
if _, ok := secret.Data[redisInitialCredentialsKey]; ok {
fmt.Println("Password secret is configured properly.")
} else {
errors.Fatal(errors.ErrorGeneric, fmt.Sprintf("key %s doesn't exist in secret %s. \n", redisInitialCredentialsKey, redisInitialCredentials))
}
},
}
clientConfig = cli.AddKubectlFlagsToCmd(&command)
return &command
}