Skip to content

Commit 46bd74d

Browse files
authored
use the entire installation spec object in node join response (#1211)
* use unified join command response also check/enforce EC version mismatch * add kots image override * unit tests and preflights * update kotsadm image * f * Spec -> InstallationSpec * updated adminconsole version * remove override image --------- Co-authored-by: laverya <[email protected]>
1 parent 9570e97 commit 46bd74d

File tree

4 files changed

+78
-64
lines changed

4 files changed

+78
-64
lines changed

cmd/embedded-cluster/join.go

Lines changed: 48 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,17 @@ import (
3131
"github.com/replicatedhq/embedded-cluster/pkg/netutils"
3232
"github.com/replicatedhq/embedded-cluster/pkg/prompts"
3333
"github.com/replicatedhq/embedded-cluster/pkg/spinner"
34+
"github.com/replicatedhq/embedded-cluster/pkg/versions"
3435
)
3536

3637
// JoinCommandResponse is the response from the kots api we use to fetch the k0s join token.
3738
type JoinCommandResponse struct {
38-
K0sJoinCommand string `json:"k0sJoinCommand"`
39-
K0sToken string `json:"k0sToken"`
40-
ClusterID uuid.UUID `json:"clusterID"`
41-
K0sUnsupportedOverrides string `json:"k0sUnsupportedOverrides"`
42-
EndUserK0sConfigOverrides string `json:"endUserK0sConfigOverrides"`
43-
// MetricsBaseURL is the https://replicated.app endpoint url
44-
MetricsBaseURL string `json:"metricsBaseURL"`
45-
AirgapRegistryAddress string `json:"airgapRegistryAddress"`
46-
Proxy *ecv1beta1.ProxySpec `json:"proxy"`
47-
Network *ecv1beta1.NetworkSpec `json:"network"`
48-
LocalArtifactMirrorPort int `json:"localArtifactMirrorPort,omitempty"`
39+
K0sJoinCommand string `json:"k0sJoinCommand"`
40+
K0sToken string `json:"k0sToken"`
41+
ClusterID uuid.UUID `json:"clusterID"`
42+
EmbeddedClusterVersion string `json:"embeddedClusterVersion"`
43+
AirgapRegistryAddress string `json:"airgapRegistryAddress"`
44+
InstallationSpec ecv1beta1.InstallationSpec `json:"installationSpec,omitempty"`
4945
}
5046

5147
// extractK0sConfigOverridePatch parses the provided override and returns a dig.Mapping that
@@ -69,13 +65,13 @@ func (j JoinCommandResponse) extractK0sConfigOverridePatch(data []byte) (dig.Map
6965
// EndUserOverrides returns a dig.Mapping that can be applied on top of a k0s configuration.
7066
// This patch is assembled based on the EndUserK0sConfigOverrides field.
7167
func (j JoinCommandResponse) EndUserOverrides() (dig.Mapping, error) {
72-
return j.extractK0sConfigOverridePatch([]byte(j.EndUserK0sConfigOverrides))
68+
return j.extractK0sConfigOverridePatch([]byte(j.InstallationSpec.EndUserK0sConfigOverrides))
7369
}
7470

7571
// EmbeddedOverrides returns a dig.Mapping that can be applied on top of a k0s configuration.
7672
// This patch is assembled based on the K0sUnsupportedOverrides field.
7773
func (j JoinCommandResponse) EmbeddedOverrides() (dig.Mapping, error) {
78-
return j.extractK0sConfigOverridePatch([]byte(j.K0sUnsupportedOverrides))
74+
return j.extractK0sConfigOverridePatch([]byte(j.InstallationSpec.Config.UnsupportedOverrides.K0s))
7975
}
8076

8177
// getJoinToken issues a request to the kots api to get the actual join command
@@ -114,15 +110,15 @@ func startAndWaitForK0s(c *cli.Context, jcmd *JoinCommandResponse) error {
114110
logrus.Debugf("starting %s service", binName)
115111
if err := startK0sService(); err != nil {
116112
err := fmt.Errorf("unable to start service: %w", err)
117-
metrics.ReportJoinFailed(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID, err)
113+
metrics.ReportJoinFailed(c.Context, jcmd.InstallationSpec.MetricsBaseURL, jcmd.ClusterID, err)
118114
return err
119115
}
120116

121117
loading.Infof("Waiting for %s node to be ready", binName)
122118
logrus.Debugf("waiting for k0s to be ready")
123119
if err := waitForK0s(); err != nil {
124120
err := fmt.Errorf("unable to wait for node: %w", err)
125-
metrics.ReportJoinFailed(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID, err)
121+
metrics.ReportJoinFailed(c.Context, jcmd.InstallationSpec.MetricsBaseURL, jcmd.ClusterID, err)
126122
return err
127123
}
128124

@@ -198,13 +194,18 @@ var joinCommand = &cli.Command{
198194
return fmt.Errorf("unable to get join token: %w", err)
199195
}
200196

201-
setProxyEnv(jcmd.Proxy)
202-
proxyOK, localIP, err := checkProxyConfigForLocalIP(jcmd.Proxy, networkInterface)
197+
// check to make sure the version returned by the join token is the same as the one we are running
198+
if jcmd.EmbeddedClusterVersion != versions.Version {
199+
return fmt.Errorf("embedded cluster version mismatch - this binary is version %q, but the cluster is running version %q", versions.Version, jcmd.EmbeddedClusterVersion)
200+
}
201+
202+
setProxyEnv(jcmd.InstallationSpec.Proxy)
203+
proxyOK, localIP, err := checkProxyConfigForLocalIP(jcmd.InstallationSpec.Proxy, networkInterface)
203204
if err != nil {
204205
return fmt.Errorf("failed to check proxy config for local IP: %w", err)
205206
}
206207
if !proxyOK {
207-
return fmt.Errorf("no-proxy config %q does not allow access to local IP %q", jcmd.Proxy.NoProxy, localIP)
208+
return fmt.Errorf("no-proxy config %q does not allow access to local IP %q", jcmd.InstallationSpec.Proxy.NoProxy, localIP)
208209
}
209210

210211
isAirgap := c.String("airgap-bundle") != ""
@@ -216,25 +217,25 @@ var joinCommand = &cli.Command{
216217
}
217218
}
218219

219-
metrics.ReportJoinStarted(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID)
220+
metrics.ReportJoinStarted(c.Context, jcmd.InstallationSpec.MetricsBaseURL, jcmd.ClusterID)
220221
logrus.Debugf("materializing %s binaries", binName)
221222
if err := materializeFiles(c); err != nil {
222-
metrics.ReportJoinFailed(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID, err)
223+
metrics.ReportJoinFailed(c.Context, jcmd.InstallationSpec.MetricsBaseURL, jcmd.ClusterID, err)
223224
return err
224225
}
225226

226-
applier, err := getAddonsApplier(c, "", jcmd.Proxy)
227+
applier, err := getAddonsApplier(c, "", jcmd.InstallationSpec.Proxy)
227228
if err != nil {
228-
metrics.ReportJoinFailed(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID, err)
229+
metrics.ReportJoinFailed(c.Context, jcmd.InstallationSpec.MetricsBaseURL, jcmd.ClusterID, err)
229230
return err
230231
}
231232

232-
// jcmd.MetricsBaseURL is the replicated.app endpoint url
233-
replicatedAPIURL := jcmd.MetricsBaseURL
233+
// jcmd.InstallationSpec.MetricsBaseURL is the replicated.app endpoint url
234+
replicatedAPIURL := jcmd.InstallationSpec.MetricsBaseURL
234235
proxyRegistryURL := fmt.Sprintf("https://%s", defaults.ProxyRegistryAddress)
235-
if err := RunHostPreflights(c, applier, replicatedAPIURL, proxyRegistryURL, isAirgap, jcmd.Proxy); err != nil {
236+
if err := RunHostPreflights(c, applier, replicatedAPIURL, proxyRegistryURL, isAirgap, jcmd.InstallationSpec.Proxy); err != nil {
236237
err := fmt.Errorf("unable to run host preflights locally: %w", err)
237-
metrics.ReportJoinFailed(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID, err)
238+
metrics.ReportJoinFailed(c.Context, jcmd.InstallationSpec.MetricsBaseURL, jcmd.ClusterID, err)
238239
return err
239240
}
240241

@@ -246,54 +247,54 @@ var joinCommand = &cli.Command{
246247
logrus.Debugf("saving token to disk")
247248
if err := saveTokenToDisk(jcmd.K0sToken); err != nil {
248249
err := fmt.Errorf("unable to save token to disk: %w", err)
249-
metrics.ReportJoinFailed(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID, err)
250+
metrics.ReportJoinFailed(c.Context, jcmd.InstallationSpec.MetricsBaseURL, jcmd.ClusterID, err)
250251
return err
251252
}
252253

253254
logrus.Debugf("installing %s binaries", binName)
254255
if err := installK0sBinary(); err != nil {
255256
err := fmt.Errorf("unable to install k0s binary: %w", err)
256-
metrics.ReportJoinFailed(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID, err)
257+
metrics.ReportJoinFailed(c.Context, jcmd.InstallationSpec.MetricsBaseURL, jcmd.ClusterID, err)
257258
return err
258259
}
259260

260261
if jcmd.AirgapRegistryAddress != "" {
261262
if err := airgap.AddInsecureRegistry(jcmd.AirgapRegistryAddress); err != nil {
262263
err := fmt.Errorf("unable to add insecure registry: %w", err)
263-
metrics.ReportJoinFailed(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID, err)
264+
metrics.ReportJoinFailed(c.Context, jcmd.InstallationSpec.MetricsBaseURL, jcmd.ClusterID, err)
264265
return err
265266
}
266267
}
267268

268269
logrus.Debugf("creating systemd unit files")
269270
localArtifactMirrorPort := defaults.LocalArtifactMirrorPort
270-
if jcmd.LocalArtifactMirrorPort > 0 {
271-
localArtifactMirrorPort = jcmd.LocalArtifactMirrorPort
271+
if jcmd.InstallationSpec.LocalArtifactMirror != nil && jcmd.InstallationSpec.LocalArtifactMirror.Port > 0 {
272+
localArtifactMirrorPort = jcmd.InstallationSpec.LocalArtifactMirror.Port
272273
}
273274
// both controller and worker nodes will have 'worker' in the join command
274-
if err := createSystemdUnitFiles(!strings.Contains(jcmd.K0sJoinCommand, "controller"), jcmd.Proxy, localArtifactMirrorPort); err != nil {
275+
if err := createSystemdUnitFiles(!strings.Contains(jcmd.K0sJoinCommand, "controller"), jcmd.InstallationSpec.Proxy, localArtifactMirrorPort); err != nil {
275276
err := fmt.Errorf("unable to create systemd unit files: %w", err)
276-
metrics.ReportJoinFailed(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID, err)
277+
metrics.ReportJoinFailed(c.Context, jcmd.InstallationSpec.MetricsBaseURL, jcmd.ClusterID, err)
277278
return err
278279
}
279280

280281
logrus.Debugf("overriding network configuration")
281282
if err := applyNetworkConfiguration(jcmd, networkInterface); err != nil {
282283
err := fmt.Errorf("unable to apply network configuration: %w", err)
283-
metrics.ReportJoinFailed(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID, err)
284+
metrics.ReportJoinFailed(c.Context, jcmd.InstallationSpec.MetricsBaseURL, jcmd.ClusterID, err)
284285
}
285286

286287
logrus.Debugf("applying configuration overrides")
287288
if err := applyJoinConfigurationOverrides(jcmd); err != nil {
288289
err := fmt.Errorf("unable to apply configuration overrides: %w", err)
289-
metrics.ReportJoinFailed(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID, err)
290+
metrics.ReportJoinFailed(c.Context, jcmd.InstallationSpec.MetricsBaseURL, jcmd.ClusterID, err)
290291
return err
291292
}
292293

293294
logrus.Debugf("joining node to cluster")
294295
if err := runK0sInstallCommand(jcmd.K0sJoinCommand, networkInterface); err != nil {
295296
err := fmt.Errorf("unable to join node to cluster: %w", err)
296-
metrics.ReportJoinFailed(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID, err)
297+
metrics.ReportJoinFailed(c.Context, jcmd.InstallationSpec.MetricsBaseURL, jcmd.ClusterID, err)
297298
return err
298299
}
299300

@@ -302,45 +303,45 @@ var joinCommand = &cli.Command{
302303
}
303304

304305
if !strings.Contains(jcmd.K0sJoinCommand, "controller") {
305-
metrics.ReportJoinSucceeded(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID)
306+
metrics.ReportJoinSucceeded(c.Context, jcmd.InstallationSpec.MetricsBaseURL, jcmd.ClusterID)
306307
logrus.Debugf("worker node join finished")
307308
return nil
308309
}
309310

310311
kcli, err := kubeutils.KubeClient()
311312
if err != nil {
312313
err := fmt.Errorf("unable to get kube client: %w", err)
313-
metrics.ReportJoinFailed(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID, err)
314+
metrics.ReportJoinFailed(c.Context, jcmd.InstallationSpec.MetricsBaseURL, jcmd.ClusterID, err)
314315
return err
315316
}
316317
hostname, err := os.Hostname()
317318
if err != nil {
318319
err := fmt.Errorf("unable to get hostname: %w", err)
319-
metrics.ReportJoinFailed(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID, err)
320+
metrics.ReportJoinFailed(c.Context, jcmd.InstallationSpec.MetricsBaseURL, jcmd.ClusterID, err)
320321
return err
321322
}
322323
if err := waitForNode(c.Context, kcli, hostname); err != nil {
323324
err := fmt.Errorf("unable to wait for node: %w", err)
324-
metrics.ReportJoinFailed(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID, err)
325+
metrics.ReportJoinFailed(c.Context, jcmd.InstallationSpec.MetricsBaseURL, jcmd.ClusterID, err)
325326
return err
326327
}
327328

328329
if c.Bool("enable-ha") {
329330
if err := maybeEnableHA(c.Context, kcli); err != nil {
330331
err := fmt.Errorf("unable to enable high availability: %w", err)
331-
metrics.ReportJoinFailed(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID, err)
332+
metrics.ReportJoinFailed(c.Context, jcmd.InstallationSpec.MetricsBaseURL, jcmd.ClusterID, err)
332333
return err
333334
}
334335
}
335336

336-
metrics.ReportJoinSucceeded(c.Context, jcmd.MetricsBaseURL, jcmd.ClusterID)
337+
metrics.ReportJoinSucceeded(c.Context, jcmd.InstallationSpec.MetricsBaseURL, jcmd.ClusterID)
337338
logrus.Debugf("controller node join finished")
338339
return nil
339340
},
340341
}
341342

342343
func applyNetworkConfiguration(jcmd *JoinCommandResponse, networkInterface string) error {
343-
if jcmd.Network != nil {
344+
if jcmd.InstallationSpec.Network != nil {
344345
clusterSpec := config.RenderK0sConfig()
345346
address, err := netutils.FirstValidAddress(networkInterface)
346347
if err != nil {
@@ -350,13 +351,13 @@ func applyNetworkConfiguration(jcmd *JoinCommandResponse, networkInterface strin
350351
clusterSpec.Spec.Storage.Etcd.PeerAddress = address
351352
// NOTE: we should be copying everything from the in cluster config spec and overriding
352353
// the node specific config from clusterSpec.GetClusterWideConfig()
353-
clusterSpec.Spec.Network.PodCIDR = jcmd.Network.PodCIDR
354-
clusterSpec.Spec.Network.ServiceCIDR = jcmd.Network.ServiceCIDR
355-
if jcmd.Network.NodePortRange != "" {
354+
clusterSpec.Spec.Network.PodCIDR = jcmd.InstallationSpec.Network.PodCIDR
355+
clusterSpec.Spec.Network.ServiceCIDR = jcmd.InstallationSpec.Network.ServiceCIDR
356+
if jcmd.InstallationSpec.Network.NodePortRange != "" {
356357
if clusterSpec.Spec.API.ExtraArgs == nil {
357358
clusterSpec.Spec.API.ExtraArgs = map[string]string{}
358359
}
359-
clusterSpec.Spec.API.ExtraArgs["service-node-port-range"] = jcmd.Network.NodePortRange
360+
clusterSpec.Spec.API.ExtraArgs["service-node-port-range"] = jcmd.InstallationSpec.Network.NodePortRange
360361
}
361362
clusterSpecYaml, err := k8syaml.Marshal(clusterSpec)
362363

cmd/embedded-cluster/join_test.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
"github.com/k0sproject/dig"
1212
k0sconfig "github.com/k0sproject/k0s/pkg/apis/k0s/v1beta1"
13+
ecv1beta1 "github.com/replicatedhq/embedded-cluster/kinds/apis/v1beta1"
1314
embeddedclusterv1beta1 "github.com/replicatedhq/embedded-cluster/kinds/apis/v1beta1"
1415
"github.com/stretchr/testify/assert"
1516
"github.com/stretchr/testify/require"
@@ -101,8 +102,14 @@ func TestJoinCommandResponseOverrides(t *testing.T) {
101102
t.Run(tname, func(t *testing.T) {
102103
req := require.New(t)
103104
join := JoinCommandResponse{
104-
K0sUnsupportedOverrides: tt.EmbeddedOverrides,
105-
EndUserK0sConfigOverrides: tt.EndUserOverrides,
105+
InstallationSpec: ecv1beta1.InstallationSpec{
106+
Config: &ecv1beta1.ConfigSpec{
107+
UnsupportedOverrides: ecv1beta1.UnsupportedOverrides{
108+
K0s: tt.EmbeddedOverrides,
109+
},
110+
},
111+
EndUserK0sConfigOverrides: tt.EndUserOverrides,
112+
},
106113
}
107114

108115
embedded, err := join.EmbeddedOverrides()

cmd/embedded-cluster/preflights.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/replicatedhq/embedded-cluster/pkg/defaults"
99
"github.com/replicatedhq/embedded-cluster/pkg/netutils"
10+
"github.com/replicatedhq/embedded-cluster/pkg/versions"
1011
"github.com/sirupsen/logrus"
1112
"github.com/urfave/cli/v2"
1213
)
@@ -126,13 +127,18 @@ var joinRunPreflightsCommand = &cli.Command{
126127
return fmt.Errorf("unable to get join token: %w", err)
127128
}
128129

129-
setProxyEnv(jcmd.Proxy)
130-
proxyOK, localIP, err := checkProxyConfigForLocalIP(jcmd.Proxy, networkInterface)
130+
// check to make sure the version returned by the join token is the same as the one we are running
131+
if jcmd.EmbeddedClusterVersion != versions.Version {
132+
return fmt.Errorf("embedded cluster version mismatch - this binary is version %q, but the cluster is running version %q", versions.Version, jcmd.EmbeddedClusterVersion)
133+
}
134+
135+
setProxyEnv(jcmd.InstallationSpec.Proxy)
136+
proxyOK, localIP, err := checkProxyConfigForLocalIP(jcmd.InstallationSpec.Proxy, networkInterface)
131137
if err != nil {
132138
return fmt.Errorf("failed to check proxy config for local IP: %w", err)
133139
}
134140
if !proxyOK {
135-
return fmt.Errorf("no-proxy config %q does not allow access to local IP %q", jcmd.Proxy.NoProxy, localIP)
141+
return fmt.Errorf("no-proxy config %q does not allow access to local IP %q", jcmd.InstallationSpec.Proxy.NoProxy, localIP)
136142
}
137143

138144
isAirgap := c.String("airgap-bundle") != ""
@@ -142,15 +148,15 @@ var joinRunPreflightsCommand = &cli.Command{
142148
return err
143149
}
144150

145-
applier, err := getAddonsApplier(c, "", jcmd.Proxy)
151+
applier, err := getAddonsApplier(c, "", jcmd.InstallationSpec.Proxy)
146152
if err != nil {
147153
return err
148154
}
149155

150156
logrus.Debugf("running host preflights")
151-
replicatedAPIURL := jcmd.MetricsBaseURL
157+
replicatedAPIURL := jcmd.InstallationSpec.MetricsBaseURL
152158
proxyRegistryURL := fmt.Sprintf("https://%s", defaults.ProxyRegistryAddress)
153-
if err := RunHostPreflights(c, applier, replicatedAPIURL, proxyRegistryURL, isAirgap, jcmd.Proxy); err != nil {
159+
if err := RunHostPreflights(c, applier, replicatedAPIURL, proxyRegistryURL, isAirgap, jcmd.InstallationSpec.Proxy); err != nil {
154160
err := fmt.Errorf("unable to run host preflights locally: %w", err)
155161
return err
156162
}

pkg/addons/adminconsole/static/metadata.yaml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,26 @@
55
# $ make buildtools
66
# $ output/bin/buildtools update addon <addon name>
77
#
8-
version: 1.117.2
8+
version: 1.117.3
99
location: oci://proxy.replicated.com/anonymous/registry.replicated.com/library/admin-console
1010
images:
1111
kotsadm:
1212
repo: proxy.replicated.com/anonymous/kotsadm/kotsadm
1313
tag:
14-
amd64: v1.117.2-amd64@sha256:eb36a5a9af101164598f1e2f7f0745aad59bdb8d8870e09e2702d8c75c753380
15-
arm64: v1.117.2-arm64@sha256:a60cf01f935a785b1a5e693d65a18bd6f4e8d7aac7be30a3311c4c17f3b8222f
14+
amd64: v1.117.3-amd64@sha256:d47ac4df627ac357452efffb717776adb452c3ab9b466ef3ccaf808df722b7a6
15+
arm64: v1.117.3-arm64@sha256:6b1b7bfc42fb3c7f21fe077b4645194fbdd1d497f92f4b12c00ceadb40969b8e
1616
kotsadm-migrations:
1717
repo: proxy.replicated.com/anonymous/kotsadm/kotsadm-migrations
1818
tag:
19-
amd64: v1.117.2-amd64@sha256:afb070977dfc16d3b85d2ae9e3cf68fc317e17e3ab05e6ad08d353201f1682ef
20-
arm64: v1.117.2-arm64@sha256:cff8c43da1094d7969ef689eca3fd11c17aae936f45d1584fd00e25085a6112b
19+
amd64: v1.117.3-amd64@sha256:56d2765497a57c06ef6e9f7705cf5218d21a978d197575a3c22fe7d84db07f0a
20+
arm64: v1.117.3-arm64@sha256:25ff2b4697425be55d576f5f068480a3ab8fe6216341f2ec3b3c1962d3ac08ba
2121
kurl-proxy:
2222
repo: proxy.replicated.com/anonymous/kotsadm/kurl-proxy
2323
tag:
24-
amd64: v1.117.2-amd64@sha256:b2e4a7ee3ca4cedd1028fbac0678fcab091b1e0a81fd39d6b8d5d20f509b2304
25-
arm64: v1.117.2-arm64@sha256:056b640c03ff824553adb2fc95fb4930e4cdea18c89b656ed81c1937d8ab3c73
24+
amd64: v1.117.3-amd64@sha256:816bcbc273ec51255d7b459e49831ce09fd361db4a295d31f61d7af02177860f
25+
arm64: v1.117.3-arm64@sha256:c4f5632ca9ea3fae2208b4ca7923900c6e958a0906b4a9dd4f6b5ebdab4b9d89
2626
rqlite:
2727
repo: proxy.replicated.com/anonymous/kotsadm/rqlite
2828
tag:
29-
amd64: 8.30.3-r0-amd64@sha256:2f0c6a90c462b8be8f08c5a1a83f71932be96b846beb3dfbd9fa0e3d13c66d63
30-
arm64: 8.30.3-r0-arm64@sha256:4e96628236b7a1e9549bfdb16d44ff71ee7607b2450548b7e0f86f1f48b36c4e
29+
amd64: 8.30.4-r0-amd64@sha256:884ac56b236e059e420858c94d90a083fe48b666c8b3433da612b9380906ce41
30+
arm64: 8.30.4-r0-arm64@sha256:cfb55508de1fb59cfc5d14586f52d8a09b776e766ea612351df77d19ae2e6d9a

0 commit comments

Comments
 (0)