Skip to content

Commit ded75d1

Browse files
committed
Merge remote-tracking branch 'origin/main' into k0s-1-28-7
2 parents 65a4d26 + 35c10ff commit ded75d1

40 files changed

+1751
-82
lines changed

.github/workflows/dependencies.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,18 @@ jobs:
2727
run: |
2828
export VERSION=`curl https://api.github.com/repos/openebs/charts/releases/latest | jq -r .name | tr -d openebs-`
2929
sed -i "/^OPENEBS_CHART_VERSION/c\OPENEBS_CHART_VERSION = $VERSION" Makefile
30+
- name: SeaweedFS
31+
run: |
32+
export VERSION=`curl https://raw.githubusercontent.com/seaweedfs/seaweedfs/master/k8s/charts/seaweedfs/Chart.yaml | grep version | tr -d 'version: '`
33+
sed -i "/^SEAWEEDFS_CHART_VERSION/c\SEAWEEDFS_CHART_VERSION = $VERSION" Makefile
34+
- name: Registry Chart
35+
run: |
36+
export VERSION=`curl https://api.github.com/repos/twuni/docker-registry.helm/tags | jq -r .[].name | head -1 | tr -d v`
37+
sed -i "/^REGISTRY_CHART_VERSION/c\REGISTRY_CHART_VERSION = $VERSION" Makefile
38+
- name: Registry Image
39+
run: |
40+
export VERSION=`curl https://api.github.com/repos/distribution/distribution/tags | jq -r '.[].name' | tr -d v | grep -v alpha | grep -v beta | head -n 1`
41+
sed -i "/^REGISTRY_IMAGE_VERSION/c\REGISTRY_IMAGE_VERSION = $VERSION" Makefile
3042
- name: Kubectl
3143
run: |
3244
export VERSION=`curl -L -s https://dl.k8s.io/release/stable.txt`

Makefile

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,23 @@ ARCH := $(shell uname -m)
44
APP_NAME = embedded-cluster
55
ADMIN_CONSOLE_CHART_URL = oci://registry.replicated.com/library
66
ADMIN_CONSOLE_CHART_NAME = admin-console
7-
ADMIN_CONSOLE_CHART_VERSION = 1.108.0-build.1
7+
ADMIN_CONSOLE_CHART_VERSION = 1.108.1
88
ADMIN_CONSOLE_IMAGE_OVERRIDE =
99
ADMIN_CONSOLE_MIGRATIONS_IMAGE_OVERRIDE =
1010
EMBEDDED_OPERATOR_CHART_URL = oci://registry.replicated.com/library
1111
EMBEDDED_OPERATOR_CHART_NAME = embedded-cluster-operator
12-
EMBEDDED_OPERATOR_CHART_VERSION = 0.24.1
12+
EMBEDDED_OPERATOR_CHART_VERSION = 0.25.0
1313
OPENEBS_CHART_URL = https://openebs.github.io/charts
1414
OPENEBS_CHART_NAME = openebs/openebs
1515
OPENEBS_CHART_VERSION = 3.10.0
16+
REGISTRY_CHART_URL = https://helm.twun.io
17+
REGISTRY_CHART_NAME = twuni/docker-registry
18+
REGISTRY_CHART_VERSION = 2.2.3
19+
REGISTRY_IMAGE_VERSION = 2.8.3
1620
KUBECTL_VERSION = v1.28.7
1721
K0S_VERSION = v1.28.7+k0s.0
1822
K0S_BINARY_SOURCE_OVERRIDE =
19-
TROUBLESHOOT_VERSION = v0.83.0
23+
TROUBLESHOOT_VERSION = v0.84.1
2024
LD_FLAGS = -X github.com/replicatedhq/embedded-cluster/pkg/defaults.K0sVersion=$(K0S_VERSION) \
2125
-X github.com/replicatedhq/embedded-cluster/pkg/defaults.Version=$(VERSION) \
2226
-X github.com/replicatedhq/embedded-cluster/pkg/defaults.K0sBinaryURL=$(K0S_BINARY_SOURCE_OVERRIDE) \
@@ -32,7 +36,11 @@ LD_FLAGS = -X github.com/replicatedhq/embedded-cluster/pkg/defaults.K0sVersion=$
3236
-X github.com/replicatedhq/embedded-cluster/pkg/addons/embeddedclusteroperator.Version=$(EMBEDDED_OPERATOR_CHART_VERSION) \
3337
-X github.com/replicatedhq/embedded-cluster/pkg/addons/openebs.ChartURL=$(OPENEBS_CHART_URL) \
3438
-X github.com/replicatedhq/embedded-cluster/pkg/addons/openebs.ChartName=$(OPENEBS_CHART_NAME) \
35-
-X github.com/replicatedhq/embedded-cluster/pkg/addons/openebs.Version=$(OPENEBS_CHART_VERSION)
39+
-X github.com/replicatedhq/embedded-cluster/pkg/addons/openebs.Version=$(OPENEBS_CHART_VERSION) \
40+
-X github.com/replicatedhq/embedded-cluster/pkg/addons/registry.ChartURL=$(REGISTRY_CHART_URL) \
41+
-X github.com/replicatedhq/embedded-cluster/pkg/addons/registry.ChartName=$(REGISTRY_CHART_NAME) \
42+
-X github.com/replicatedhq/embedded-cluster/pkg/addons/registry.Version=$(REGISTRY_CHART_VERSION) \
43+
-X github.com/replicatedhq/embedded-cluster/pkg/addons/registry.ImageVersion=$(REGISTRY_IMAGE_VERSION)
3644

3745
.DEFAULT_GOAL := default
3846
default: embedded-cluster-linux-amd64

cmd/embedded-cluster/install.go

Lines changed: 129 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ import (
1414
k8syaml "sigs.k8s.io/yaml"
1515

1616
"github.com/replicatedhq/embedded-cluster/pkg/addons"
17+
"github.com/replicatedhq/embedded-cluster/pkg/airgap"
1718
"github.com/replicatedhq/embedded-cluster/pkg/config"
1819
"github.com/replicatedhq/embedded-cluster/pkg/defaults"
1920
"github.com/replicatedhq/embedded-cluster/pkg/goods"
2021
"github.com/replicatedhq/embedded-cluster/pkg/helpers"
22+
"github.com/replicatedhq/embedded-cluster/pkg/kubeutils"
2123
"github.com/replicatedhq/embedded-cluster/pkg/metrics"
2224
"github.com/replicatedhq/embedded-cluster/pkg/preflights"
2325
"github.com/replicatedhq/embedded-cluster/pkg/prompts"
@@ -52,7 +54,7 @@ func runCommand(bin string, args ...string) (string, error) {
5254
}
5355

5456
// installAndEnableLocalArtifactMirror installs and enables the local artifact mirror. This
55-
// service is reponsible for serving on localhost, through http, all files that are used
57+
// service is responsible for serving on localhost, through http, all files that are used
5658
// during a cluster upgrade.
5759
func installAndEnableLocalArtifactMirror() error {
5860
ourbin := defaults.PathToEmbeddedClusterBinary("local-artifact-mirror")
@@ -179,7 +181,73 @@ func checkLicenseMatches(c *cli.Context) error {
179181
}
180182

181183
return nil
184+
}
185+
186+
func checkAirgapMatches(c *cli.Context) error {
187+
rel, err := release.GetChannelRelease()
188+
if err != nil {
189+
return fmt.Errorf("failed to get release from binary: %w", err) // this should only be if the release is malformed
190+
}
191+
if rel == nil {
192+
return fmt.Errorf("airgap bundle provided but no release was found in binary, please rerun without the airgap-bundle flag")
193+
}
194+
195+
// read file from path
196+
rawfile, err := os.Open(c.String("airgap-bundle"))
197+
if err != nil {
198+
return fmt.Errorf("failed to open airgap file: %w", err)
199+
}
200+
defer rawfile.Close()
201+
202+
appSlug, channelID, airgapVersion, err := airgap.ChannelReleaseMetadata(rawfile)
203+
if err != nil {
204+
return fmt.Errorf("failed to get airgap bundle versions: %w", err)
205+
}
206+
207+
// Check if the airgap bundle matches the application version data
208+
if rel.AppSlug != appSlug {
209+
// if the app is different, we will not be able to provide the correct vendor supplied charts and k0s overrides
210+
return fmt.Errorf("airgap bundle app %s does not match binary app %s, please provide the correct bundle", appSlug, rel.AppSlug)
211+
}
212+
if rel.ChannelID != channelID {
213+
// if the channel is different, we will not be able to install the pinned vendor application version within kots
214+
return fmt.Errorf("airgap bundle channel %s does not match binary channel %s, please provide the correct bundle", channelID, rel.ChannelID)
215+
}
216+
if rel.VersionLabel != airgapVersion {
217+
// if the version is different, who knows what might be different
218+
return fmt.Errorf("airgap bundle version %s does not match binary version %s, please provide the correct bundle", airgapVersion, rel.VersionLabel)
219+
}
220+
221+
return nil
222+
}
223+
224+
func materializeFiles(c *cli.Context) error {
225+
mat := spinner.Start()
226+
defer mat.Close()
227+
mat.Infof("Materializing files")
228+
229+
if err := goods.Materialize(); err != nil {
230+
return fmt.Errorf("unable to materialize binaries: %w", err)
231+
}
232+
if c.String("airgap-bundle") != "" {
233+
mat.Infof("Materializing airgap installation files")
234+
235+
// read file from path
236+
rawfile, err := os.Open(c.String("airgap-bundle"))
237+
if err != nil {
238+
return fmt.Errorf("failed to open airgap file: %w", err)
239+
}
240+
defer rawfile.Close()
182241

242+
if err := airgap.MaterializeAirgap(rawfile); err != nil {
243+
err = fmt.Errorf("unable to materialize airgap files: %w", err)
244+
return err
245+
}
246+
}
247+
248+
mat.Infof("Host files materialized")
249+
250+
return nil
183251
}
184252

185253
// createK0sConfig creates a new k0s.yaml configuration file. The file is saved in the
@@ -205,13 +273,21 @@ func ensureK0sConfig(c *cli.Context) error {
205273
}
206274
opts = append(opts, addons.WithLicense(license))
207275
}
276+
if c.String("airgap-bundle") != "" {
277+
opts = append(opts, addons.Airgap())
278+
}
208279
if err := config.UpdateHelmConfigs(cfg, opts...); err != nil {
209280
return fmt.Errorf("unable to update helm configs: %w", err)
210281
}
211282
var err error
212283
if cfg, err = applyUnsupportedOverrides(c, cfg); err != nil {
213284
return fmt.Errorf("unable to apply unsupported overrides: %w", err)
214285
}
286+
if c.String("airgap-bundle") != "" {
287+
// update the k0s config to install with airgap
288+
airgap.RemapHelm(cfg)
289+
airgap.SetAirgapConfig(cfg)
290+
}
215291
data, err := k8syaml.Marshal(cfg)
216292
if err != nil {
217293
return fmt.Errorf("unable to marshal config: %w", err)
@@ -296,6 +372,32 @@ func waitForK0s() error {
296372
return nil
297373
}
298374

375+
// createAirgapConfigMaps creates the airgap configmaps in the k8s cluster from the airgap file.
376+
func createAirgapConfigMaps(c *cli.Context) error {
377+
loading := spinner.Start()
378+
defer loading.Close()
379+
loading.Infof("Creating airgap configmaps")
380+
// create k8s client
381+
os.Setenv("KUBECONFIG", defaults.PathToKubeConfig())
382+
cli, err := kubeutils.KubeClient()
383+
if err != nil {
384+
return fmt.Errorf("failed to create k8s client: %w", err)
385+
}
386+
387+
// read file from path
388+
rawfile, err := os.Open(c.String("airgap-bundle"))
389+
if err != nil {
390+
return fmt.Errorf("failed to open airgap file: %w", err)
391+
}
392+
defer rawfile.Close()
393+
394+
if err = airgap.CreateAppConfigMaps(c.Context, cli, rawfile); err != nil {
395+
return fmt.Errorf("unable to create airgap configmaps: %w", err)
396+
}
397+
loading.Infof("Airgap configmaps created")
398+
return nil
399+
}
400+
299401
// runOutro calls Outro() in all enabled addons by means of Applier.
300402
func runOutro(c *cli.Context) error {
301403
os.Setenv("KUBECONFIG", defaults.PathToKubeConfig())
@@ -314,6 +416,9 @@ func runOutro(c *cli.Context) error {
314416
}
315417
opts = append(opts, addons.WithEndUserConfig(eucfg))
316418
}
419+
if c.String("airgap-bundle") != "" {
420+
opts = append(opts, addons.Airgap())
421+
}
317422
return addons.NewApplier(opts...).Outro(c.Context)
318423
}
319424

@@ -327,6 +432,10 @@ var installCommand = &cli.Command{
327432
if os.Getuid() != 0 {
328433
return fmt.Errorf("install command must be run as root")
329434
}
435+
436+
if c.String("airgap-bundle") != "" {
437+
metrics.DisableMetrics()
438+
}
330439
return nil
331440
},
332441
Flags: []cli.Flag{
@@ -346,6 +455,11 @@ var installCommand = &cli.Command{
346455
Usage: "Path to the application license file",
347456
Hidden: false,
348457
},
458+
&cli.StringFlag{
459+
Name: "airgap-bundle",
460+
Usage: "Path to the airgap bundle. If set, the installation will be completed without internet access.",
461+
Hidden: false,
462+
},
349463
},
350464
Action: func(c *cli.Context) error {
351465
logrus.Debugf("checking if %s is already installed", binName)
@@ -365,9 +479,14 @@ var installCommand = &cli.Command{
365479
metrics.ReportApplyFinished(c, metricErr)
366480
return err // do not return the metricErr, as we want the user to see the error message without a prefix
367481
}
482+
if c.String("airgap-bundle") != "" {
483+
logrus.Debugf("checking airgap bundle matches binary")
484+
if err := checkAirgapMatches(c); err != nil {
485+
return err // we want the user to see the error message without a prefix
486+
}
487+
}
368488
logrus.Debugf("materializing binaries")
369-
if err := goods.Materialize(); err != nil {
370-
err := fmt.Errorf("unable to materialize binaries: %w", err)
489+
if err := materializeFiles(c); err != nil {
371490
metrics.ReportApplyFinished(c, err)
372491
return err
373492
}
@@ -401,6 +520,13 @@ var installCommand = &cli.Command{
401520
metrics.ReportApplyFinished(c, err)
402521
return err
403522
}
523+
if c.String("airgap-bundle") != "" {
524+
err := createAirgapConfigMaps(c)
525+
if err != nil {
526+
err = fmt.Errorf("unable to create airgap configmaps: %w", err)
527+
return err
528+
}
529+
}
404530
logrus.Debugf("running outro")
405531
if err := runOutro(c); err != nil {
406532
metrics.ReportApplyFinished(c, err)

cmd/embedded-cluster/join.go

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ import (
1919
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2020
k8syaml "sigs.k8s.io/yaml"
2121

22+
"github.com/replicatedhq/embedded-cluster/pkg/airgap"
2223
"github.com/replicatedhq/embedded-cluster/pkg/config"
2324
"github.com/replicatedhq/embedded-cluster/pkg/defaults"
24-
"github.com/replicatedhq/embedded-cluster/pkg/goods"
2525
"github.com/replicatedhq/embedded-cluster/pkg/helpers"
2626
"github.com/replicatedhq/embedded-cluster/pkg/metrics"
2727
)
@@ -34,6 +34,7 @@ type JoinCommandResponse struct {
3434
K0sUnsupportedOverrides string `json:"k0sUnsupportedOverrides"`
3535
EndUserK0sConfigOverrides string `json:"endUserK0sConfigOverrides"`
3636
MetricsBaseURL string `json:"metricsBaseURL"`
37+
AirgapRegistryAddress string `json:"airgapRegistryAddress"`
3738
}
3839

3940
// extractK0sConfigOverridePatch parses the provided override and returns a dig.Mapping that
@@ -98,10 +99,21 @@ var joinCommand = &cli.Command{
9899
Name: "join",
99100
Usage: fmt.Sprintf("Join the current node to a %s cluster", binName),
100101
ArgsUsage: "<url> <token>",
102+
Flags: []cli.Flag{
103+
&cli.StringFlag{
104+
Name: "airgap-bundle",
105+
Usage: "Path to the airgap bundle. If set, the installation will be completed without internet access.",
106+
Hidden: true,
107+
},
108+
},
101109
Before: func(c *cli.Context) error {
102110
if os.Getuid() != 0 {
103111
return fmt.Errorf("node join command must be run as root")
104112
}
113+
114+
if c.String("airgap-bundle") != "" {
115+
metrics.DisableMetrics()
116+
}
105117
return nil
106118
},
107119
Action: func(c *cli.Context) error {
@@ -126,10 +138,16 @@ var joinCommand = &cli.Command{
126138
return fmt.Errorf("unable to get join token: %w", err)
127139
}
128140

141+
if c.String("airgap-bundle") != "" {
142+
logrus.Debugf("checking airgap bundle matches binary")
143+
if err := checkAirgapMatches(c); err != nil {
144+
return err // we want the user to see the error message without a prefix
145+
}
146+
}
147+
129148
metrics.ReportJoinStarted(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID)
130149
logrus.Infof("Materializing %s binaries", binName)
131-
if err := goods.Materialize(); err != nil {
132-
err := fmt.Errorf("unable to materialize binaries: %w", err)
150+
if err := materializeFiles(c); err != nil {
133151
metrics.ReportJoinFailed(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID, err)
134152
return err
135153
}
@@ -154,6 +172,13 @@ var joinCommand = &cli.Command{
154172
return err
155173
}
156174

175+
if jcmd.AirgapRegistryAddress != "" {
176+
if err := airgap.AddInsecureRegistry(jcmd.AirgapRegistryAddress); err != nil {
177+
err := fmt.Errorf("unable to add insecure registry: %w", err)
178+
metrics.ReportJoinFailed(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID, err)
179+
}
180+
}
181+
157182
logrus.Infof("Joining node to cluster")
158183
if err := runK0sInstallCommand(jcmd.K0sJoinCommand); err != nil {
159184
err := fmt.Errorf("unable to join node to cluster: %w", err)

cmd/embedded-cluster/types/types.go

Lines changed: 0 additions & 14 deletions
This file was deleted.

cmd/embedded-cluster/version.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import (
99
"github.com/jedib0t/go-pretty/table"
1010
"github.com/k0sproject/k0s/pkg/airgap"
1111
k0sconfig "github.com/k0sproject/k0s/pkg/apis/k0s/v1beta1"
12+
"github.com/replicatedhq/embedded-cluster-kinds/types"
1213
"github.com/urfave/cli/v2"
1314

14-
"github.com/replicatedhq/embedded-cluster/cmd/embedded-cluster/types"
1515
"github.com/replicatedhq/embedded-cluster/pkg/addons"
1616
"github.com/replicatedhq/embedded-cluster/pkg/config"
1717
"github.com/replicatedhq/embedded-cluster/pkg/defaults"
@@ -98,6 +98,17 @@ var metadataCommand = &cli.Command{
9898
}
9999
meta.Protected = protectedFields
100100

101+
// Airgap
102+
airgapCht, airgapRepo, err := applier.GetAirgapCharts()
103+
if err != nil {
104+
return fmt.Errorf("unable to get airgap charts: %w", err)
105+
}
106+
meta.AirgapConfigs = k0sconfig.HelmExtensions{
107+
ConcurrencyLevel: 1,
108+
Charts: airgapCht,
109+
Repositories: airgapRepo,
110+
}
111+
101112
// Render k0s config to get the images contained within
102113
k0sConfig := config.RenderK0sConfig()
103114
if err != nil {

0 commit comments

Comments
 (0)