Skip to content

Commit

Permalink
Move the server setup to a separate container
Browse files Browse the repository at this point in the history
In the kubernetes world, running the setup as an exec is really dirty as
we can't have it in an operator or helm chart. This commits benefits
from the setup script not needing systemd to run as PID1 to move the
setup in a separate container.
  • Loading branch information
cbosdo committed Nov 25, 2024
1 parent cd4d3cf commit 8d95587
Show file tree
Hide file tree
Showing 10 changed files with 551 additions and 299 deletions.
2 changes: 1 addition & 1 deletion mgradm/cmd/inspect/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func kuberneteInspect(
}

// Get the SCC credentials secret if existing
pullSecret, err := kubernetes.GetSCCSecret(namespace, &types.SCCCredentials{}, kubernetes.ServerApp)
pullSecret, err := kubernetes.GetRegistrySecret(namespace, &types.SCCCredentials{}, kubernetes.ServerApp)
if err != nil {
return err
}
Expand Down
123 changes: 122 additions & 1 deletion mgradm/cmd/install/podman/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ package podman
import (
"errors"
"os/exec"
"path/filepath"
"strconv"
"strings"

"github.com/rs/zerolog"
Expand All @@ -15,6 +17,7 @@ import (
"github.com/uyuni-project/uyuni-tools/mgradm/shared/coco"
"github.com/uyuni-project/uyuni-tools/mgradm/shared/hub"
"github.com/uyuni-project/uyuni-tools/mgradm/shared/podman"
"github.com/uyuni-project/uyuni-tools/mgradm/shared/templates"
adm_utils "github.com/uyuni-project/uyuni-tools/mgradm/shared/utils"
"github.com/uyuni-project/uyuni-tools/shared"
. "github.com/uyuni-project/uyuni-tools/shared/l10n"
Expand Down Expand Up @@ -114,7 +117,7 @@ func installForPodman(

log.Info().Msg(L("Run setup command in the container"))

if err := adm_utils.RunSetup(cnx, &flags.ServerFlags, fqdn, env); err != nil {
if err := runSetup(cnx, &flags.ServerFlags, fqdn, env); err != nil {
if stopErr := systemd.StopService(shared_podman.ServerService); stopErr != nil {
log.Error().Msgf(L("Failed to stop service: %v"), stopErr)
}
Expand Down Expand Up @@ -163,3 +166,121 @@ func installForPodman(
}
return nil
}

const setupName = "setup.sh"

// runSetup execute the setup.
func runSetup(cnx *shared.Connection, flags *adm_utils.ServerFlags, fqdn string, env map[string]string) error {
tmpFolder, cleaner, err := generateSetupScript(&flags.Installation, fqdn, flags.Mirror, env)
if err != nil {
return err
}
defer cleaner()

if err := cnx.Copy(filepath.Join(tmpFolder, setupName), "server:/tmp/setup.sh", "root", "root"); err != nil {
return utils.Errorf(err, L("cannot copy /tmp/setup.sh"))
}

err = adm_utils.ExecCommand(zerolog.InfoLevel, cnx, "/tmp/setup.sh")
if err != nil {
return utils.Errorf(err, L("error running the setup script"))
}
if err := cnx.CopyCaCertificate(fqdn); err != nil {
return utils.Errorf(err, L("failed to add SSL CA certificate to host trusted certificates"))
}

log.Info().Msgf(L("Server set up, login on https://%[1]s with %[2]s user"), fqdn, flags.Installation.Admin.Login)
return nil
}

// generateSetupScript creates a temporary folder with the setup script to execute in the container.
// The script exports all the needed environment variables and calls uyuni's mgr-setup.
func generateSetupScript(
flags *adm_utils.InstallationFlags,
fqdn string,
mirror string,
extraEnv map[string]string,
) (string, func(), error) {
localHostValues := []string{
"localhost",
"127.0.0.1",
"::1",
fqdn,
}

localDB := utils.Contains(localHostValues, flags.DB.Host)

dbHost := flags.DB.Host
reportdbHost := flags.ReportDB.Host

if localDB {
dbHost = "localhost"
if reportdbHost == "" {
reportdbHost = "localhost"
}
}
env := map[string]string{
"UYUNI_FQDN": fqdn,
"MANAGER_USER": flags.DB.User,
"MANAGER_PASS": flags.DB.Password,
"MANAGER_ADMIN_EMAIL": flags.Email,
"MANAGER_MAIL_FROM": flags.EmailFrom,
"MANAGER_ENABLE_TFTP": boolToString(flags.Tftp),
"LOCAL_DB": boolToString(localDB),
"MANAGER_DB_NAME": flags.DB.Name,
"MANAGER_DB_HOST": dbHost,
"MANAGER_DB_PORT": strconv.Itoa(flags.DB.Port),
"MANAGER_DB_PROTOCOL": flags.DB.Protocol,
"REPORT_DB_NAME": flags.ReportDB.Name,
"REPORT_DB_HOST": reportdbHost,
"REPORT_DB_PORT": strconv.Itoa(flags.ReportDB.Port),
"REPORT_DB_USER": flags.ReportDB.User,
"REPORT_DB_PASS": flags.ReportDB.Password,
"EXTERNALDB_ADMIN_USER": flags.DB.Admin.User,
"EXTERNALDB_ADMIN_PASS": flags.DB.Admin.Password,
"EXTERNALDB_PROVIDER": flags.DB.Provider,
"ISS_PARENT": flags.IssParent,
"ACTIVATE_SLP": "N", // Deprecated, will be removed soon
"SCC_USER": flags.SCC.User,
"SCC_PASS": flags.SCC.Password,
}
if mirror != "" {
env["MIRROR_PATH"] = "/mirror"
}

// Add the extra environment variables
for key, value := range extraEnv {
env[key] = value
}

scriptDir, cleaner, err := utils.TempDir()
if err != nil {
return "", nil, err
}

dataTemplate := templates.MgrSetupScriptTemplateData{
Env: env,
DebugJava: flags.Debug.Java,
OrgName: flags.Organization,
AdminLogin: flags.Admin.Login,
AdminPassword: strings.ReplaceAll(flags.Admin.Password, `"`, `\"`),
AdminFirstName: flags.Admin.FirstName,
AdminLastName: flags.Admin.LastName,
AdminEmail: flags.Admin.Email,
NoSSL: false,
}

scriptPath := filepath.Join(scriptDir, setupName)
if err = utils.WriteTemplateToFile(dataTemplate, scriptPath, 0555, true); err != nil {
return "", cleaner, utils.Errorf(err, L("Failed to generate setup script"))
}

return scriptDir, cleaner, nil
}

func boolToString(value bool) string {
if value {
return "Y"
}
return "N"
}
2 changes: 1 addition & 1 deletion mgradm/cmd/migrate/kubernetes/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func migrateToKubernetes(
}

// Create a secret using SCC credentials if any are provided
pullSecret, err := shared_kubernetes.GetSCCSecret(
pullSecret, err := shared_kubernetes.GetRegistrySecret(
flags.Kubernetes.Uyuni.Namespace, &flags.Installation.SCC, shared_kubernetes.ServerApp,
)
if err != nil {
Expand Down
17 changes: 14 additions & 3 deletions mgradm/shared/kubernetes/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
package kubernetes

import (
"strings"

"github.com/rs/zerolog"
"github.com/uyuni-project/uyuni-tools/shared/kubernetes"
. "github.com/uyuni-project/uyuni-tools/shared/l10n"
core "k8s.io/api/core/v1"
Expand All @@ -19,12 +22,20 @@ const (
DBSecret = "db-credentials"
// ReportdbSecret is the name of the report database credentials secret.
ReportdbSecret = "reportdb-credentials"
SCCSecret = "scc-credentials"
secretUsername = "username"
secretPassword = "password"
)

// CreateDBSecret creates a secret containing the DB credentials.
func CreateDBSecret(namespace string, name string, user string, password string) error {
// CreateBasicAuthSecret creates a secret of type basic-auth.
func CreateBasicAuthSecret(namespace string, name string, user string, password string) error {
// Check if the secret is already existing
out, err := runCmdOutput(zerolog.DebugLevel, "kubectl", "get", "-n", namespace, "secret", name, "-o", "name")
if err == nil && strings.TrimSpace(string(out)) != "" {
return nil
}

// Create the secret
secret := core.Secret{
TypeMeta: meta.TypeMeta{APIVersion: "v1", Kind: "Secret"},
ObjectMeta: meta.ObjectMeta{
Expand All @@ -40,5 +51,5 @@ func CreateDBSecret(namespace string, name string, user string, password string)
Type: core.SecretTypeBasicAuth,
}

return kubernetes.Apply([]runtime.Object{&secret}, L("failed to create the database secret"))
return kubernetes.Apply([]runtime.Object{&secret}, L("failed to create the secret"))
}
Loading

0 comments on commit 8d95587

Please sign in to comment.