Skip to content

Commit 3d967ea

Browse files
committed
merge main
2 parents a2efe24 + c6a57a4 commit 3d967ea

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+1776
-469
lines changed

Makefile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ K0S_GO_VERSION = v1.28.11+k0s.0
1212
PREVIOUS_K0S_VERSION ?= v1.28.10+k0s.0
1313
K0S_BINARY_SOURCE_OVERRIDE =
1414
PREVIOUS_K0S_BINARY_SOURCE_OVERRIDE =
15-
TROUBLESHOOT_VERSION = v0.100.0
15+
TROUBLESHOOT_VERSION = v0.102.0
1616
KOTS_VERSION = v$(shell awk '/^version/{print $$2}' pkg/addons/adminconsole/static/metadata.yaml | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+).*/\1/')
1717
# When updating KOTS_BINARY_URL_OVERRIDE, also update the KOTS_VERSION above or
1818
# scripts/ci-upload-binaries.sh may find the version in the cache and not upload the overridden binary.
@@ -269,6 +269,7 @@ list-distros:
269269

270270
.PHONY: create-node%
271271
create-node%: DISTRO = debian-bookworm
272+
create-node%: NODE_PORT = 30000
272273
create-node%:
273274
@if ! docker images | grep -q ec-$(DISTRO); then \
274275
$(MAKE) -C dev/distros build-$(DISTRO); \
@@ -282,7 +283,7 @@ create-node%:
282283
-v /var/lib/k0s \
283284
-v $(shell pwd):/replicatedhq/embedded-cluster \
284285
-v $(shell dirname $(shell pwd))/kots:/replicatedhq/kots \
285-
$(if $(filter node0,node$*),-p 30000:30000) \
286+
$(if $(filter node0,node$*),-p $(NODE_PORT):$(NODE_PORT)) \
286287
ec-$(DISTRO)
287288

288289
@$(MAKE) ssh-node$*

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ Additionally, it includes a Registry when deployed in air gap mode.
8787
```
8888
8989
1. In the Vendor Portal, create and download a license that is assigned to the channel.
90+
We recommend storing this license in the `local-dev/` directory, as it is gitignored and not otherwise used by the CI.
9091
9192
1. Install Embedded Cluster:
9293
```bash

cmd/buildtools/utils.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515

1616
"github.com/Masterminds/semver/v3"
1717
"github.com/containers/image/v5/docker"
18+
"github.com/containers/image/v5/image"
1819
"github.com/containers/image/v5/manifest"
1920
"github.com/containers/image/v5/types"
2021
"github.com/distribution/reference"
@@ -364,6 +365,18 @@ func GetImageDigest(ctx context.Context, img string, arch string) (string, error
364365
}
365366

366367
if !manifest.MIMETypeIsMultiImage(maniftype) {
368+
i, err := image.FromSource(ctx, sysctx, src)
369+
if err != nil {
370+
return "", fmt.Errorf("image from source: %w", err)
371+
}
372+
defer i.Close()
373+
info, err := i.Inspect(ctx)
374+
if err != nil {
375+
return "", fmt.Errorf("inspect image: %w", err)
376+
}
377+
if info.Architecture != arch {
378+
return "", &DockerManifestNotFoundError{image: img, arch: arch, err: err}
379+
}
367380
digest, err := manifest.Digest(manifraw)
368381
if err != nil {
369382
return "", fmt.Errorf("get manifest digest: %w", err)

cmd/embedded-cluster/flags.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"strconv"
6+
7+
"github.com/replicatedhq/embedded-cluster/pkg/defaults"
8+
"github.com/urfave/cli/v2"
9+
k8snet "k8s.io/utils/net"
10+
)
11+
12+
func getAdminColsolePortFlag() cli.Flag {
13+
return &cli.StringFlag{
14+
Name: "admin-console-port",
15+
Usage: "Port on which the Admin Console will be served",
16+
Value: strconv.Itoa(defaults.AdminConsolePort),
17+
Hidden: false,
18+
}
19+
}
20+
21+
func getAdminConsolePortFromFlag(c *cli.Context) (int, error) {
22+
portStr := c.String("admin-console-port")
23+
if portStr == "" {
24+
return defaults.AdminConsolePort, nil
25+
}
26+
// TODO: add first class support for service node port range and validate the port
27+
port, err := k8snet.ParsePort(portStr, false)
28+
if err != nil {
29+
return 0, fmt.Errorf("invalid admin console port: %w", err)
30+
}
31+
return port, nil
32+
}
33+
34+
func getLocalArtifactMirrorPortFlag() cli.Flag {
35+
return &cli.StringFlag{
36+
Name: "local-artifact-mirror-port",
37+
Usage: "Port on which the Local Artifact Mirror will be served",
38+
Value: strconv.Itoa(defaults.LocalArtifactMirrorPort),
39+
Hidden: false,
40+
}
41+
}
42+
43+
func getLocalArtifactMirrorPortFromFlag(c *cli.Context) (int, error) {
44+
portStr := c.String("local-artifact-mirror-port")
45+
if portStr == "" {
46+
return defaults.LocalArtifactMirrorPort, nil
47+
}
48+
// TODO: add first class support for service node port range and validate the port does not
49+
// conflict with this range
50+
port, err := k8snet.ParsePort(portStr, false)
51+
if err != nil {
52+
return 0, fmt.Errorf("invalid local artifact mirror port: %w", err)
53+
}
54+
if portStr == c.String("admin-console-port") {
55+
return 0, fmt.Errorf("local artifact mirror port cannot be the same as admin console port")
56+
}
57+
return port, nil
58+
}

cmd/embedded-cluster/install.go

Lines changed: 96 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/replicatedhq/embedded-cluster/pkg/goods"
2121
"github.com/replicatedhq/embedded-cluster/pkg/helpers"
2222
"github.com/replicatedhq/embedded-cluster/pkg/metrics"
23+
"github.com/replicatedhq/embedded-cluster/pkg/netutils"
2324
"github.com/replicatedhq/embedded-cluster/pkg/preflights"
2425
"github.com/replicatedhq/embedded-cluster/pkg/prompts"
2526
"github.com/replicatedhq/embedded-cluster/pkg/release"
@@ -36,18 +37,55 @@ var ErrNothingElseToAdd = fmt.Errorf("")
3637
// installAndEnableLocalArtifactMirror installs and enables the local artifact mirror. This
3738
// service is responsible for serving on localhost, through http, all files that are used
3839
// during a cluster upgrade.
39-
func installAndEnableLocalArtifactMirror() error {
40+
func installAndEnableLocalArtifactMirror(port int) error {
4041
if err := goods.MaterializeLocalArtifactMirrorUnitFile(); err != nil {
4142
return fmt.Errorf("failed to materialize artifact mirror unit: %w", err)
4243
}
44+
if err := writeLocalArtifactMirrorEnvironmentFile(port); err != nil {
45+
return fmt.Errorf("failed to write local artifact mirror environment file: %w", err)
46+
}
4347
if _, err := helpers.RunCommand("systemctl", "daemon-reload"); err != nil {
4448
return fmt.Errorf("unable to get reload systemctl daemon: %w", err)
4549
}
4650
if _, err := helpers.RunCommand("systemctl", "start", "local-artifact-mirror"); err != nil {
4751
return fmt.Errorf("unable to start the local artifact mirror: %w", err)
4852
}
4953
if _, err := helpers.RunCommand("systemctl", "enable", "local-artifact-mirror"); err != nil {
50-
return fmt.Errorf("unable to start the local artifact mirror: %w", err)
54+
return fmt.Errorf("unable to start the local artifact mirror service: %w", err)
55+
}
56+
return nil
57+
}
58+
59+
// updateLocalArtifactMirrorService updates the port on which the local artifact mirror is served.
60+
func updateLocalArtifactMirrorService(port int) error {
61+
if err := writeLocalArtifactMirrorEnvironmentFile(port); err != nil {
62+
return fmt.Errorf("failed to write local artifact mirror environment file: %w", err)
63+
}
64+
if _, err := helpers.RunCommand("systemctl", "daemon-reload"); err != nil {
65+
return fmt.Errorf("unable to get reload systemctl daemon: %w", err)
66+
}
67+
if _, err := helpers.RunCommand("systemctl", "restart", "local-artifact-mirror"); err != nil {
68+
return fmt.Errorf("unable to restart the local artifact mirror service: %w", err)
69+
}
70+
return nil
71+
}
72+
73+
const (
74+
localArtifactMirrorSystemdConfFile = "/etc/systemd/system/local-artifact-mirror.service.d/embedded-cluster.conf"
75+
localArtifactMirrorEnvironmentFileContents = `[Service]
76+
Environment="LOCAL_ARTIFACT_MIRROR_PORT=%d"`
77+
)
78+
79+
func writeLocalArtifactMirrorEnvironmentFile(port int) error {
80+
dir := filepath.Dir(localArtifactMirrorSystemdConfFile)
81+
err := os.MkdirAll(dir, 0755)
82+
if err != nil {
83+
return fmt.Errorf("create directory: %w", err)
84+
}
85+
contents := fmt.Sprintf(localArtifactMirrorEnvironmentFileContents, port)
86+
err = os.WriteFile(localArtifactMirrorSystemdConfFile, []byte(contents), 0644)
87+
if err != nil {
88+
return fmt.Errorf("write file: %w", err)
5189
}
5290
return nil
5391
}
@@ -130,8 +168,12 @@ func runHostPreflights(c *cli.Context, hpf *v1beta2.HostPreflightSpec, proxy *ec
130168

131169
err = output.SaveToDisk()
132170
if err != nil {
133-
pb.CloseWithError()
134-
return fmt.Errorf("failed to save preflights output: %w", err)
171+
logrus.Warnf("unable to save preflights output: %v", err)
172+
}
173+
174+
err = preflights.CopyBundleToECSupportDir()
175+
if err != nil {
176+
logrus.Warnf("unable to copy preflight bundle to embedded-cluster support dir: %v", err)
135177
}
136178

137179
// Failures found
@@ -327,12 +369,17 @@ func ensureK0sConfig(c *cli.Context, applier *addons.Applier) (*k0sconfig.Cluste
327369
return nil, fmt.Errorf("unable to create directory: %w", err)
328370
}
329371
cfg := config.RenderK0sConfig()
372+
address, err := netutils.FirstValidAddress(c.String("network-interface"))
373+
if err != nil {
374+
return nil, fmt.Errorf("unable to find first valid address: %w", err)
375+
}
376+
cfg.Spec.API.Address = address
377+
cfg.Spec.Storage.Etcd.PeerAddress = address
330378
cfg.Spec.Network.PodCIDR = c.String("pod-cidr")
331379
cfg.Spec.Network.ServiceCIDR = c.String("service-cidr")
332380
if err := config.UpdateHelmConfigs(applier, cfg); err != nil {
333381
return nil, fmt.Errorf("unable to update helm configs: %w", err)
334382
}
335-
var err error
336383
cfg, err = applyUnsupportedOverrides(c, cfg)
337384
if err != nil {
338385
return nil, fmt.Errorf("unable to apply unsupported overrides: %w", err)
@@ -399,13 +446,17 @@ func applyUnsupportedOverrides(c *cli.Context, cfg *k0sconfig.ClusterConfig) (*k
399446

400447
// installK0s runs the k0s install command and waits for it to finish. If no configuration
401448
// is found one is generated.
402-
func installK0s() error {
449+
func installK0s(c *cli.Context) error {
403450
ourbin := defaults.PathToEmbeddedClusterBinary("k0s")
404451
hstbin := defaults.K0sBinaryPath()
405452
if err := helpers.MoveFile(ourbin, hstbin); err != nil {
406453
return fmt.Errorf("unable to move k0s binary: %w", err)
407454
}
408-
if _, err := helpers.RunCommand(hstbin, config.InstallFlags()...); err != nil {
455+
nodeIP, err := netutils.FirstValidAddress(c.String("network-interface"))
456+
if err != nil {
457+
return fmt.Errorf("unable to find first valid address: %w", err)
458+
}
459+
if _, err := helpers.RunCommand(hstbin, config.InstallFlags(nodeIP)...); err != nil {
409460
return fmt.Errorf("unable to install: %w", err)
410461
}
411462
if _, err := helpers.RunCommand(hstbin, "start"); err != nil {
@@ -437,7 +488,7 @@ func waitForK0s() error {
437488
}
438489

439490
// installAndWaitForK0s installs the k0s binary and waits for it to be ready
440-
func installAndWaitForK0s(c *cli.Context, applier *addons.Applier) (*k0sconfig.ClusterConfig, error) {
491+
func installAndWaitForK0s(c *cli.Context, applier *addons.Applier, proxy *ecv1beta1.ProxySpec) (*k0sconfig.ClusterConfig, error) {
441492
loading := spinner.Start()
442493
defer loading.Close()
443494
loading.Infof("Installing %s node", defaults.BinaryName())
@@ -448,16 +499,15 @@ func installAndWaitForK0s(c *cli.Context, applier *addons.Applier) (*k0sconfig.C
448499
metrics.ReportApplyFinished(c, err)
449500
return nil, err
450501
}
451-
proxy := getProxySpecFromFlags(c)
452502
logrus.Debugf("creating systemd unit files")
453-
if err := createSystemdUnitFiles(false, proxy); err != nil {
503+
if err := createSystemdUnitFiles(false, proxy, applier.GetLocalArtifactMirrorPort()); err != nil {
454504
err := fmt.Errorf("unable to create systemd unit files: %w", err)
455505
metrics.ReportApplyFinished(c, err)
456506
return nil, err
457507
}
458508

459509
logrus.Debugf("installing k0s")
460-
if err := installK0s(); err != nil {
510+
if err := installK0s(c); err != nil {
461511
err := fmt.Errorf("unable update cluster: %w", err)
462512
metrics.ReportApplyFinished(c, err)
463513
return nil, err
@@ -487,7 +537,7 @@ func runOutro(c *cli.Context, applier *addons.Applier, cfg *k0sconfig.ClusterCon
487537
return fmt.Errorf("unable to process overrides file: %w", err)
488538
}
489539

490-
return applier.Outro(c.Context, cfg, eucfg, metadata)
540+
return applier.Outro(c.Context, cfg, eucfg, metadata, c.String("network-interface"))
491541
}
492542

493543
func maybeAskAdminConsolePassword(c *cli.Context) (string, error) {
@@ -554,6 +604,11 @@ var installCommand = &cli.Command{
554604
Usage: "Path to the license file",
555605
Hidden: false,
556606
},
607+
&cli.StringFlag{
608+
Name: "network-interface",
609+
Usage: "The network interface to use for the cluster",
610+
Value: "",
611+
},
557612
&cli.BoolFlag{
558613
Name: "no-prompt",
559614
Usage: "Disable interactive prompts. The Admin Console password will be set to password.",
@@ -573,10 +628,18 @@ var installCommand = &cli.Command{
573628
Name: "private-ca",
574629
Usage: "Path to a trusted private CA certificate file",
575630
},
631+
getAdminColsolePortFlag(),
632+
getLocalArtifactMirrorPortFlag(),
576633
},
577634
)),
578635
Action: func(c *cli.Context) error {
636+
var err error
579637
proxy := getProxySpecFromFlags(c)
638+
proxy, err = includeLocalIPInNoProxy(c, proxy)
639+
if err != nil {
640+
metrics.ReportApplyFinished(c, err)
641+
return err
642+
}
580643
setProxyEnv(proxy)
581644

582645
logrus.Debugf("checking if %s is already installed", binName)
@@ -608,17 +671,22 @@ var installCommand = &cli.Command{
608671
return err // we want the user to see the error message without a prefix
609672
}
610673
}
674+
if err := preflights.ValidateApp(); err != nil {
675+
metrics.ReportApplyFinished(c, err)
676+
return err
677+
}
611678
adminConsolePwd, err := maybeAskAdminConsolePassword(c)
612679
if err != nil {
613680
metrics.ReportApplyFinished(c, err)
614681
return err
615682
}
683+
616684
logrus.Debugf("materializing binaries")
617685
if err := materializeFiles(c); err != nil {
618686
metrics.ReportApplyFinished(c, err)
619687
return err
620688
}
621-
applier, err := getAddonsApplier(c, adminConsolePwd)
689+
applier, err := getAddonsApplier(c, adminConsolePwd, proxy)
622690
if err != nil {
623691
metrics.ReportApplyFinished(c, err)
624692
return err
@@ -633,7 +701,7 @@ var installCommand = &cli.Command{
633701
metrics.ReportApplyFinished(c, err)
634702
return err
635703
}
636-
cfg, err := installAndWaitForK0s(c, applier)
704+
cfg, err := installAndWaitForK0s(c, applier, proxy)
637705
if err != nil {
638706
return err
639707
}
@@ -647,7 +715,7 @@ var installCommand = &cli.Command{
647715
},
648716
}
649717

650-
func getAddonsApplier(c *cli.Context, adminConsolePwd string) (*addons.Applier, error) {
718+
func getAddonsApplier(c *cli.Context, adminConsolePwd string, proxy *ecv1beta1.ProxySpec) (*addons.Applier, error) {
651719
opts := []addons.Option{}
652720
if c.Bool("no-prompt") {
653721
opts = append(opts, addons.WithoutPrompt())
@@ -658,7 +726,6 @@ func getAddonsApplier(c *cli.Context, adminConsolePwd string) (*addons.Applier,
658726
if ab := c.String("airgap-bundle"); ab != "" {
659727
opts = append(opts, addons.WithAirgapBundle(ab))
660728
}
661-
proxy := getProxySpecFromFlags(c)
662729
if proxy != nil {
663730
opts = append(opts, addons.WithProxy(proxy.HTTPProxy, proxy.HTTPSProxy, proxy.NoProxy))
664731
}
@@ -681,6 +748,19 @@ func getAddonsApplier(c *cli.Context, adminConsolePwd string) (*addons.Applier,
681748
}
682749
opts = append(opts, addons.WithPrivateCAs(privateCAs))
683750
}
751+
752+
adminConsolePort, err := getAdminConsolePortFromFlag(c)
753+
if err != nil {
754+
return nil, err
755+
}
756+
opts = append(opts, addons.WithAdminConsolePort(adminConsolePort))
757+
758+
localArtifactMirrorPort, err := getLocalArtifactMirrorPortFromFlag(c)
759+
if err != nil {
760+
return nil, err
761+
}
762+
opts = append(opts, addons.WithLocalArtifactMirrorPort(localArtifactMirrorPort))
763+
684764
if adminConsolePwd != "" {
685765
opts = append(opts, addons.WithAdminConsolePassword(adminConsolePwd))
686766
}

0 commit comments

Comments
 (0)