-
Notifications
You must be signed in to change notification settings - Fork 171
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extract unrelated code fixes/features out of k8s native apply work (#196
) ### Breaking Changes: * `localhost` is no longer a valid option for cluster ingress when initializing a zarf cluster. Instead you have to use a `127.0.0.1` or some other local ip found via `ifconfig` ### Fixes: * No longer depends on 127.0.0.1 local bindings for the registry / gitops service * should fix #193 * Resolve outstanding issues with image hostname swapping and * fixes #18 * fixes #44 * fixes #194 ### Features: * Adds `before` and `after` script options when defining a `zarf.yaml` with an optional retry flag * Add symlink to ZarfFile for creating links to places files * Add template boolean to ZarfFile to allow injection of zarf variables into text files * Adds a new `zarf tool` command to print out config schema and commit the output to the repo (will need to make a git hook or something later on) * Changes `zarf destroy` command to run any script that starts with `zarf-clean` instead of only running the k3s-remove script * Add new ZarfState and `.zarf-state.yaml` for persisting host information from `zarf init` to `zarf package deploy` * Remove all hard-coded logic for k3s install, now uses only standard zarf component features like everything else * Add user prompt with host/IP address suggestions for ingress #### Misc: * Upgrades k3s from v1.21.2 to v1.21.6 * Adds optional regex filter for when performing RecursiveFileList() * Adds more description to the components in zarf.yaml * Renames type ZarfConfig to ZarfPackage in the config pkg * Handful of general code organizing changes (moving yaml related functions to the `...../utils/yaml.go`, etc.) * Expose execCommand() with stdout control * Move traefik to standalone component and drop the internal k3s install of traefik * Use the airgap tarball of K3s instead of manually listing images * Cleanup init prompt logic
- Loading branch information
1 parent
2a1a876
commit b2c7a26
Showing
40 changed files
with
1,254 additions
and
603 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
--- | ||
apiVersion: helm.cattle.io/v1 | ||
kind: HelmChart | ||
metadata: | ||
name: traefik | ||
namespace: kube-system | ||
spec: | ||
chart: https://%{KUBERNETES_API}%/static/charts/traefik-9.18.2.tgz | ||
targetNamespace: kube-system | ||
valuesContent: |- | ||
rbac: | ||
enabled: true | ||
ports: | ||
websecure: | ||
tls: | ||
enabled: true | ||
podAnnotations: | ||
prometheus.io/port: "8082" | ||
prometheus.io/scrape: "true" | ||
providers: | ||
kubernetesIngress: | ||
publishedService: | ||
enabled: true | ||
priorityClassName: "system-cluster-critical" | ||
image: | ||
name: "rancher/library-traefik" | ||
tolerations: | ||
- key: "CriticalAddonsOnly" | ||
operator: "Exists" | ||
- key: "node-role.kubernetes.io/control-plane" | ||
operator: "Exists" | ||
effect: "NoSchedule" | ||
- key: "node-role.kubernetes.io/master" | ||
operator: "Exists" | ||
effect: "NoSchedule" | ||
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,19 @@ | ||
mirrors: | ||
registry.dso.mil: | ||
endpoint: | ||
- "https://127.0.0.1" | ||
- "https://###ZARF_TARGET_ENDPOINT###" | ||
registry1.dso.mil: | ||
endpoint: | ||
- "https://127.0.0.1" | ||
- "https://###ZARF_TARGET_ENDPOINT###" | ||
docker.io: | ||
endpoint: | ||
- "https://127.0.0.1" | ||
- "https://###ZARF_TARGET_ENDPOINT###" | ||
registry-1.docker.io: | ||
endpoint: | ||
- "https://127.0.0.1" | ||
- "https://###ZARF_TARGET_ENDPOINT###" | ||
ghcr.io: | ||
endpoint: | ||
- "https://127.0.0.1" | ||
- "https://###ZARF_TARGET_ENDPOINT###" | ||
registry.opensource.zalan.do: | ||
endpoint: | ||
- "https://127.0.0.1" | ||
- "https://###ZARF_TARGET_ENDPOINT###" |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,79 +1,176 @@ | ||
package cmd | ||
|
||
import ( | ||
"net" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/defenseunicorns/zarf/cli/internal/k3s" | ||
"github.com/defenseunicorns/zarf/cli/config" | ||
"github.com/defenseunicorns/zarf/cli/internal/packager" | ||
|
||
"github.com/defenseunicorns/zarf/cli/internal/pki" | ||
"github.com/defenseunicorns/zarf/cli/internal/utils" | ||
|
||
"github.com/AlecAivazis/survey/v2" | ||
"github.com/sirupsen/logrus" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var initOptions = k3s.InstallOptions{} | ||
const invalidHostMessage = "The hostname provided (%v) was not a valid hostname. The hostname can only contain: 'a-z', 'A-Z', '0-9', '-', and '.' characters as defined by RFC-1035. If using localhost, you must use the 127.0.0.1.\n" | ||
|
||
var initOptions = packager.InstallOptions{} | ||
var state = config.ZarfState{ | ||
Kind: "ZarfState", | ||
} | ||
|
||
// initCmd represents the init command | ||
var initCmd = &cobra.Command{ | ||
Use: "init", | ||
Short: "Deploys the gitops service or appliance cluster on a clean linux box", | ||
Long: "Flags are only required if running via automation, otherwise the init command will prompt you for your configuration choices", | ||
Run: func(cmd *cobra.Command, args []string) { | ||
|
||
if !initOptions.Confirmed { | ||
var confirm bool | ||
prompt := &survey.Confirm{ | ||
Message: "⚠️ This will initialize a new Zarf deployment on this machine which will make changes to your filesystem. You should not run zarf init more than once without first running zarf destroy. Do you want to continue?", | ||
} | ||
_ = survey.AskOne(prompt, &confirm) | ||
if !confirm { | ||
// Gracefully exit because they didn't want to play after all :-/ | ||
os.Exit(0) | ||
} | ||
} | ||
|
||
handleTLSOptions() | ||
k3s.Install(initOptions) | ||
pki.HandlePKI() | ||
packager.Install(&initOptions) | ||
}, | ||
} | ||
|
||
func handleTLSOptions() { | ||
// Check to see if the certpaths or host entries are set as flags first | ||
if initOptions.PKI.CertPublicPath == "" && initOptions.PKI.Host == "" { | ||
// Check for cert paths provided via automation (both required) | ||
func hasCertPaths() bool { | ||
return state.TLS.CertPrivatePath != "" && state.TLS.CertPublicPath != "" | ||
} | ||
|
||
const Generate = 0 | ||
// Ask user if they will be importing or generating certs, return true if importing certs | ||
func promptIsImportCerts() bool { | ||
var mode int | ||
|
||
var tlsMode int | ||
if hasCertPaths() { | ||
return true | ||
} | ||
|
||
// Determine flow for generate or import | ||
modePrompt := &survey.Select{ | ||
Message: "Will Zarf be generating a TLS chain or importing an existing ingress cert?", | ||
Options: []string{ | ||
"Generate TLS chain with an ephemeral CA", | ||
"Import user-provided cert keypair", | ||
}, | ||
if initOptions.Confirmed { | ||
// Assume generate on confirmed without cert paths | ||
return false | ||
} | ||
|
||
// Determine flow for generate or import | ||
modePrompt := &survey.Select{ | ||
Message: "Will Zarf be generating a TLS chain or importing an existing ingress cert?", | ||
Options: []string{ | ||
"Generate TLS chain with an ephemeral CA", | ||
"Import user-provided cert keypair", | ||
}, | ||
} | ||
_ = survey.AskOne(modePrompt, &mode) | ||
|
||
return mode == 1 | ||
} | ||
|
||
// Ask user for the public and private key paths to import into the cluster | ||
func promptCertPaths() { | ||
prompt := &survey.Input{ | ||
Message: "Enter a file path to the ingress public key", | ||
Suggest: func(toComplete string) []string { | ||
// Give some suggestions to users | ||
files, _ := filepath.Glob(toComplete + "*") | ||
return files | ||
}, | ||
} | ||
_ = survey.AskOne(prompt, &state.TLS.CertPublicPath, survey.WithValidator(survey.Required)) | ||
|
||
prompt.Message = "Enter a file path to the ingress private key" | ||
_ = survey.AskOne(prompt, &state.TLS.CertPrivatePath, survey.WithValidator(survey.Required)) | ||
} | ||
|
||
// Ask user for the hostname or ip if not provided via automation and validate the input | ||
func promptAndValidateHost() { | ||
if state.TLS.Host == "" { | ||
if initOptions.Confirmed { | ||
// Fail if host is not provided on confirm | ||
logrus.Fatalf(invalidHostMessage, state.TLS.Host) | ||
} | ||
_ = survey.AskOne(modePrompt, &tlsMode) | ||
|
||
if tlsMode == Generate { | ||
// Generate mode requires a host entry | ||
prompt := &survey.Input{ | ||
Message: "Enter a host DNS entry or IP Address for the cluster ingress", | ||
} | ||
_ = survey.AskOne(prompt, &initOptions.PKI.Host, survey.WithValidator(survey.Required)) | ||
} else { | ||
// Import mode requires the public and private key paths | ||
prompt := &survey.Input{ | ||
Message: "Enter a file path to the ingress public key", | ||
Suggest: func(toComplete string) []string { | ||
// Give some suggestions to users | ||
files, _ := filepath.Glob(toComplete + "*") | ||
return files | ||
}, | ||
} | ||
_ = survey.AskOne(prompt, &initOptions.PKI.CertPublicPath, survey.WithValidator(survey.Required)) | ||
// If not provided, always ask for a host entry to avoid having to guess which entry in a cert if provided | ||
prompt := &survey.Input{ | ||
Message: "Enter a host DNS entry or IP Address for the cluster ingress. If using localhost, use 127.0.0.1", | ||
Suggest: func(toComplete string) []string { | ||
var suggestions []string | ||
// Create a list of IPs to add to the suggestion box | ||
interfaces, err := net.InterfaceAddrs() | ||
if err == nil { | ||
for _, iface := range interfaces { | ||
// Conver the CIRD to the IP string if valid | ||
ip, _, _ := net.ParseCIDR(iface.String()) | ||
if iface.String() != "" { | ||
suggestions = append(suggestions, ip.String()) | ||
} | ||
} | ||
} | ||
// Add the localhost hostname as well | ||
hostname, _ := os.Hostname() | ||
if hostname != "" { | ||
suggestions = append(suggestions, hostname) | ||
} | ||
|
||
return suggestions | ||
}, | ||
} | ||
err := survey.AskOne(prompt, &state.TLS.Host, survey.WithValidator(survey.Required)) | ||
if err != nil && err.Error() == os.Interrupt.String() { | ||
// Handle CTRL+C | ||
os.Exit(0) | ||
} | ||
} | ||
|
||
prompt.Message = "Enter a file path to the ingress private key" | ||
_ = survey.AskOne(prompt, &initOptions.PKI.CertPrivatePath, survey.WithValidator(survey.Required)) | ||
if !utils.ValidHostname(state.TLS.Host) { | ||
// When hitting an invalid hostname... | ||
if initOptions.Confirmed { | ||
// ...if using automation end it all | ||
logrus.Fatalf(invalidHostMessage, state.TLS.Host) | ||
} | ||
// ...otherwise, warn user, reset the field, and cycle the function | ||
logrus.Warnf(invalidHostMessage, state.TLS.Host) | ||
state.TLS.Host = "" | ||
promptAndValidateHost() | ||
} | ||
if !utils.CheckHostName(initOptions.PKI.Host) { | ||
logrus.Fatalf("The hostname provided (%v) was not a valid hostname. The hostname can only contain: 'a-z', 'A-Z', '0-9', '-', and '.' characters.\n", initOptions.PKI.Host) | ||
} | ||
|
||
func handleTLSOptions() { | ||
|
||
// Get and validate host | ||
promptAndValidateHost() | ||
|
||
// Get the cert path if this is an import | ||
if promptIsImportCerts() && !hasCertPaths() { | ||
promptCertPaths() | ||
} | ||
|
||
// Persist the config the ZarfState | ||
if err := config.WriteState(state); err != nil { | ||
logrus.Debug(err) | ||
logrus.Fatal("Unable to save the zarf state file.") | ||
} | ||
} | ||
|
||
func init() { | ||
|
||
rootCmd.AddCommand(initCmd) | ||
initCmd.Flags().BoolVar(&initOptions.Confirmed, "confirm", false, "Confirm the install without prompting") | ||
initCmd.Flags().StringVar(&initOptions.PKI.Host, "host", "", "Specify the host or IP for the gitops service ingress. E.g. host=10.10.10.5 or host=gitops.domain.com") | ||
initCmd.Flags().StringVar(&initOptions.PKI.CertPublicPath, "server-crt", "", "Path to the server public key if not generating unique PKI") | ||
initCmd.Flags().StringVar(&initOptions.PKI.CertPrivatePath, "server-key", "", "Path to the server private key if not generating unique PKI") | ||
initCmd.Flags().StringVar(&state.TLS.Host, "host", "", "Specify the host or IP for the gitops service ingress. E.g. host=10.10.10.5 or host=gitops.domain.com") | ||
initCmd.Flags().StringVar(&state.TLS.CertPublicPath, "server-crt", "", "Path to the server public key if not generating unique PKI") | ||
initCmd.Flags().StringVar(&state.TLS.CertPrivatePath, "server-key", "", "Path to the server private key if not generating unique PKI") | ||
initCmd.Flags().StringVar(&initOptions.Components, "components", "", "Comma-separated list of components to install. Adding this flag will skip the init prompts for which components to install") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.