Skip to content

Commit 716e711

Browse files
authored
feat(api): helm binary migration (#3063)
* feat(api): Lookup template function * f * f * f * f * f
1 parent cf8d45d commit 716e711

File tree

101 files changed

+2712
-695
lines changed

Some content is hidden

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

101 files changed

+2712
-695
lines changed

.github/workflows/dependencies.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ jobs:
4141
echo "troubleshoot version: $version"
4242
sed -i "/^TROUBLESHOOT_VERSION/c\TROUBLESHOOT_VERSION = $version" versions.mk
4343
44+
- name: Helm
45+
env:
46+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
47+
run: |
48+
version=$(gh release list --repo helm/helm --json tagName,isLatest | jq -r '.[] | select(.isLatest) | .tagName')
49+
echo "helm version: $version"
50+
sed -i "/^HELM_VERSION/c\HELM_VERSION = $version" versions.mk
51+
4452
- name: FIO
4553
env:
4654
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Makefile

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,23 @@ output/bins/k0s-override:
7777
chmod +x $@
7878
touch $@
7979

80+
.PHONY: cmd/installer/goods/bins/helm
81+
cmd/installer/goods/bins/helm:
82+
$(MAKE) output/bins/helm-$(HELM_VERSION)-$(ARCH)
83+
cp output/bins/helm-$(HELM_VERSION)-$(ARCH) $@
84+
touch $@
85+
86+
output/bins/helm-%:
87+
mkdir -p output/bins
88+
mkdir -p output/tmp
89+
curl --retry 5 --retry-all-errors -fL -o output/tmp/helm.tar.gz \
90+
https://get.helm.sh/helm-$(call split-hyphen,$*,1)-$(OS)-$(call split-hyphen,$*,2).tar.gz
91+
tar -xzf output/tmp/helm.tar.gz -C output/tmp
92+
mv output/tmp/$(OS)-$(call split-hyphen,$*,2)/helm $@
93+
rm -rf output/tmp
94+
chmod +x $@
95+
touch $@
96+
8097
.PHONY: cmd/installer/goods/bins/kubectl-support_bundle
8198
cmd/installer/goods/bins/kubectl-support_bundle:
8299
$(MAKE) output/bins/kubectl-support_bundle-$(TROUBLESHOOT_VERSION)-$(ARCH)
@@ -217,6 +234,7 @@ static: cmd/installer/goods/bins/k0s \
217234
cmd/installer/goods/bins/kubectl-support_bundle \
218235
cmd/installer/goods/bins/local-artifact-mirror \
219236
cmd/installer/goods/bins/fio \
237+
cmd/installer/goods/bins/helm \
220238
cmd/installer/goods/internal/bins/kubectl-kots
221239

222240
.PHONY: static-dryrun
@@ -226,6 +244,7 @@ static-dryrun:
226244
cmd/installer/goods/bins/kubectl-support_bundle \
227245
cmd/installer/goods/bins/local-artifact-mirror \
228246
cmd/installer/goods/bins/fio \
247+
cmd/installer/goods/bins/helm \
229248
cmd/installer/goods/internal/bins/kubectl-kots
230249

231250
.PHONY: embedded-cluster-linux-amd64

api/api.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
linuxupgrade "github.com/replicatedhq/embedded-cluster/api/controllers/linux/upgrade"
1212
"github.com/replicatedhq/embedded-cluster/api/pkg/logger"
1313
"github.com/replicatedhq/embedded-cluster/api/types"
14+
"github.com/replicatedhq/embedded-cluster/pkg/helm"
1415
"github.com/replicatedhq/embedded-cluster/pkg/metrics"
1516
"github.com/replicatedhq/embedded-cluster/pkg/runtimeconfig"
1617
"github.com/sirupsen/logrus"
@@ -39,6 +40,7 @@ import (
3940
type API struct {
4041
cfg types.APIConfig
4142

43+
hcli helm.Client
4244
logger logrus.FieldLogger
4345
metricsReporter metrics.ReporterInterface
4446

@@ -111,8 +113,19 @@ func WithMetricsReporter(metricsReporter metrics.ReporterInterface) Option {
111113
}
112114
}
113115

116+
// WithHelmClient configures the helm client for the API.
117+
func WithHelmClient(hcli helm.Client) Option {
118+
return func(a *API) {
119+
a.hcli = hcli
120+
}
121+
}
122+
114123
// New creates a new API instance.
115124
func New(cfg types.APIConfig, opts ...Option) (*API, error) {
125+
if cfg.InstallTarget == "" {
126+
return nil, fmt.Errorf("target is required")
127+
}
128+
116129
api := &API{
117130
cfg: cfg,
118131
}
@@ -133,6 +146,10 @@ func New(cfg types.APIConfig, opts ...Option) (*API, error) {
133146
api.logger = l
134147
}
135148

149+
if err := api.initClients(); err != nil {
150+
return nil, fmt.Errorf("init clients: %w", err)
151+
}
152+
136153
if err := api.initHandlers(); err != nil {
137154
return nil, fmt.Errorf("init handlers: %w", err)
138155
}

api/clients.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package api
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/replicatedhq/embedded-cluster/api/internal/clients"
7+
"github.com/replicatedhq/embedded-cluster/api/types"
8+
"github.com/replicatedhq/embedded-cluster/pkg/helm"
9+
"github.com/replicatedhq/embedded-cluster/pkg/versions"
10+
)
11+
12+
func (a *API) initClients() error {
13+
if a.hcli == nil {
14+
if err := a.initHelmClient(); err != nil {
15+
return fmt.Errorf("init helm client: %w", err)
16+
}
17+
}
18+
return nil
19+
}
20+
21+
// initHelmClient initializes the Helm client based on the installation target
22+
func (a *API) initHelmClient() error {
23+
switch a.cfg.InstallTarget {
24+
case types.InstallTargetLinux:
25+
return a.initLinuxHelmClient()
26+
case types.InstallTargetKubernetes:
27+
return a.initKubernetesHelmClient()
28+
default:
29+
return fmt.Errorf("unsupported install target: %s", a.cfg.InstallTarget)
30+
}
31+
}
32+
33+
// initLinuxHelmClient initializes the Helm client for Linux installations
34+
func (a *API) initLinuxHelmClient() error {
35+
airgapPath := ""
36+
if a.cfg.AirgapBundle != "" {
37+
airgapPath = a.cfg.RuntimeConfig.EmbeddedClusterChartsSubDir()
38+
}
39+
40+
hcli, err := helm.NewClient(helm.HelmOptions{
41+
HelmPath: a.cfg.RuntimeConfig.PathToEmbeddedClusterBinary("helm"),
42+
KubernetesEnvSettings: a.cfg.RuntimeConfig.GetKubernetesEnvSettings(),
43+
K8sVersion: versions.K0sVersion,
44+
AirgapPath: airgapPath,
45+
})
46+
if err != nil {
47+
return fmt.Errorf("create linux helm client: %w", err)
48+
}
49+
50+
a.hcli = hcli
51+
return nil
52+
}
53+
54+
// initKubernetesHelmClient initializes the Helm client for Kubernetes installations
55+
func (a *API) initKubernetesHelmClient() error {
56+
// get the kubernetes version
57+
kcli, err := clients.NewDiscoveryClient(clients.KubeClientOptions{
58+
RESTClientGetter: a.cfg.Installation.GetKubernetesEnvSettings().RESTClientGetter(),
59+
})
60+
if err != nil {
61+
return fmt.Errorf("create discovery client: %w", err)
62+
}
63+
k8sVersion, err := kcli.ServerVersion()
64+
if err != nil {
65+
return fmt.Errorf("get server version: %w", err)
66+
}
67+
68+
// get the helm binary path
69+
helmPath, err := a.cfg.Installation.PathToEmbeddedBinary("helm")
70+
if err != nil {
71+
return fmt.Errorf("get helm path: %w", err)
72+
}
73+
74+
// create the helm client
75+
hcli, err := helm.NewClient(helm.HelmOptions{
76+
HelmPath: helmPath,
77+
KubernetesEnvSettings: a.cfg.Installation.GetKubernetesEnvSettings(),
78+
// TODO: how can we support airgap?
79+
AirgapPath: "",
80+
K8sVersion: k8sVersion.String(),
81+
})
82+
if err != nil {
83+
return fmt.Errorf("create kubernetes helm client: %w", err)
84+
}
85+
86+
a.hcli = hcli
87+
return nil
88+
}

api/controllers/app/controller.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/replicatedhq/embedded-cluster/api/internal/store"
1515
"github.com/replicatedhq/embedded-cluster/api/pkg/logger"
1616
"github.com/replicatedhq/embedded-cluster/api/types"
17+
"github.com/replicatedhq/embedded-cluster/pkg/helm"
1718
"github.com/replicatedhq/embedded-cluster/pkg/release"
1819
kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
1920
"github.com/sirupsen/logrus"
@@ -46,6 +47,7 @@ type AppController struct {
4647
logger logrus.FieldLogger
4748
license []byte
4849
releaseData *release.ReleaseData
50+
hcli helm.Client
4951
store store.Store
5052
configValues types.AppConfigValues
5153
clusterID string
@@ -109,6 +111,12 @@ func WithReleaseData(releaseData *release.ReleaseData) AppControllerOption {
109111
}
110112
}
111113

114+
func WithHelmClient(hcli helm.Client) AppControllerOption {
115+
return func(c *AppController) {
116+
c.hcli = hcli
117+
}
118+
}
119+
112120
func WithConfigValues(configValues types.AppConfigValues) AppControllerOption {
113121
return func(c *AppController) {
114122
c.configValues = configValues
@@ -202,6 +210,7 @@ func NewAppController(opts ...AppControllerOption) (*AppController, error) {
202210
appreleasemanager.WithLicense(license),
203211
appreleasemanager.WithIsAirgap(controller.airgapBundle != ""),
204212
appreleasemanager.WithPrivateCACertConfigMapName(controller.privateCACertConfigMapName),
213+
appreleasemanager.WithHelmClient(controller.hcli),
205214
)
206215
if err != nil {
207216
return nil, fmt.Errorf("create app release manager: %w", err)

api/controllers/kubernetes/install/controller.go

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ import (
1414
"github.com/replicatedhq/embedded-cluster/api/types"
1515
ecv1beta1 "github.com/replicatedhq/embedded-cluster/kinds/apis/v1beta1"
1616
"github.com/replicatedhq/embedded-cluster/pkg-new/kubernetesinstallation"
17+
"github.com/replicatedhq/embedded-cluster/pkg/helm"
1718
"github.com/replicatedhq/embedded-cluster/pkg/metrics"
1819
"github.com/replicatedhq/embedded-cluster/pkg/release"
1920
"github.com/sirupsen/logrus"
2021
helmcli "helm.sh/helm/v3/pkg/cli"
21-
"k8s.io/cli-runtime/pkg/genericclioptions"
2222
)
2323

2424
type Controller interface {
@@ -34,21 +34,22 @@ type Controller interface {
3434
var _ Controller = (*InstallController)(nil)
3535

3636
type InstallController struct {
37-
installationManager installation.InstallationManager
38-
infraManager infra.InfraManager
39-
metricsReporter metrics.ReporterInterface
40-
restClientGetter genericclioptions.RESTClientGetter
41-
releaseData *release.ReleaseData
42-
password string
43-
tlsConfig types.TLSConfig
44-
license []byte
45-
airgapBundle string
46-
configValues types.AppConfigValues
47-
endUserConfig *ecv1beta1.Config
48-
store store.Store
49-
ki kubernetesinstallation.Installation
50-
stateMachine statemachine.Interface
51-
logger logrus.FieldLogger
37+
installationManager installation.InstallationManager
38+
infraManager infra.InfraManager
39+
metricsReporter metrics.ReporterInterface
40+
kubernetesEnvSettings *helmcli.EnvSettings
41+
hcli helm.Client
42+
releaseData *release.ReleaseData
43+
password string
44+
tlsConfig types.TLSConfig
45+
license []byte
46+
airgapBundle string
47+
configValues types.AppConfigValues
48+
endUserConfig *ecv1beta1.Config
49+
store store.Store
50+
ki kubernetesinstallation.Installation
51+
stateMachine statemachine.Interface
52+
logger logrus.FieldLogger
5253
// App controller composition
5354
*appcontroller.AppController
5455
}
@@ -73,9 +74,15 @@ func WithMetricsReporter(metricsReporter metrics.ReporterInterface) InstallContr
7374
}
7475
}
7576

76-
func WithRESTClientGetter(restClientGetter genericclioptions.RESTClientGetter) InstallControllerOption {
77+
func WithHelmClient(hcli helm.Client) InstallControllerOption {
7778
return func(c *InstallController) {
78-
c.restClientGetter = restClientGetter
79+
c.hcli = hcli
80+
}
81+
}
82+
83+
func WithKubernetesEnvSettings(envSettings *helmcli.EnvSettings) InstallControllerOption {
84+
return func(c *InstallController) {
85+
c.kubernetesEnvSettings = envSettings
7986
}
8087
}
8188

@@ -169,9 +176,9 @@ func NewInstallController(opts ...InstallControllerOption) (*InstallController,
169176
controller.stateMachine = NewStateMachine(WithStateMachineLogger(controller.logger))
170177
}
171178

172-
// If none is provided, use the default env settings from helm to create a RESTClientGetter
173-
if controller.restClientGetter == nil {
174-
controller.restClientGetter = helmcli.New().RESTClientGetter()
179+
// If none is provided, use the default env settings from helm
180+
if controller.kubernetesEnvSettings == nil {
181+
controller.kubernetesEnvSettings = helmcli.New()
175182
}
176183

177184
if controller.installationManager == nil {
@@ -192,6 +199,7 @@ func NewInstallController(opts ...InstallControllerOption) (*InstallController,
192199
appcontroller.WithConfigValues(controller.configValues),
193200
appcontroller.WithAirgapBundle(controller.airgapBundle),
194201
appcontroller.WithPrivateCACertConfigMapName(""), // Private CA ConfigMap functionality not yet implemented for Kubernetes installations
202+
appcontroller.WithHelmClient(controller.hcli),
195203
)
196204
if err != nil {
197205
return nil, fmt.Errorf("create app install controller: %w", err)
@@ -203,13 +211,14 @@ func NewInstallController(opts ...InstallControllerOption) (*InstallController,
203211
infraManager, err := infra.NewInfraManager(
204212
infra.WithLogger(controller.logger),
205213
infra.WithInfraStore(controller.store.KubernetesInfraStore()),
206-
infra.WithRESTClientGetter(controller.restClientGetter),
214+
infra.WithKubernetesEnvSettings(controller.kubernetesEnvSettings),
207215
infra.WithPassword(controller.password),
208216
infra.WithTLSConfig(controller.tlsConfig),
209217
infra.WithLicense(controller.license),
210218
infra.WithAirgapBundle(controller.airgapBundle),
211219
infra.WithReleaseData(controller.releaseData),
212220
infra.WithEndUserConfig(controller.endUserConfig),
221+
infra.WithHelmClient(controller.hcli),
213222
)
214223
if err != nil {
215224
return nil, fmt.Errorf("create infra manager: %w", err)

api/controllers/kubernetes/install/controller_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/replicatedhq/embedded-cluster/api/types"
1616
ecv1beta1 "github.com/replicatedhq/embedded-cluster/kinds/apis/v1beta1"
1717
"github.com/replicatedhq/embedded-cluster/pkg-new/kubernetesinstallation"
18+
"github.com/replicatedhq/embedded-cluster/pkg/helm"
1819
"github.com/replicatedhq/embedded-cluster/pkg/metrics"
1920
"github.com/replicatedhq/embedded-cluster/pkg/release"
2021
kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
@@ -111,6 +112,7 @@ func TestGetInstallationConfig(t *testing.T) {
111112
WithInstallation(ki),
112113
WithInstallationManager(mockManager),
113114
WithReleaseData(getTestReleaseData(&kotsv1beta1.Config{})),
115+
WithHelmClient(&helm.MockClient{}),
114116
)
115117
require.NoError(t, err)
116118

@@ -228,6 +230,7 @@ func TestConfigureInstallation(t *testing.T) {
228230
WithStore(mockStore),
229231
WithMetricsReporter(mockMetricsReporter),
230232
WithReleaseData(getTestReleaseData(&kotsv1beta1.Config{})),
233+
WithHelmClient(&helm.MockClient{}),
231234
)
232235
require.NoError(t, err)
233236

@@ -299,6 +302,7 @@ func TestGetInstallationStatus(t *testing.T) {
299302
controller, err := NewInstallController(
300303
WithInstallationManager(mockManager),
301304
WithReleaseData(getTestReleaseData(&kotsv1beta1.Config{})),
305+
WithHelmClient(&helm.MockClient{}),
302306
)
303307
require.NoError(t, err)
304308

@@ -425,6 +429,7 @@ func TestSetupInfra(t *testing.T) {
425429
appcontroller.WithStore(mockStore),
426430
appcontroller.WithReleaseData(getTestReleaseData(&appConfig)),
427431
appcontroller.WithAppConfigManager(mockAppConfigManager),
432+
appcontroller.WithHelmClient(&helm.MockClient{}),
428433
)
429434
require.NoError(t, err)
430435

@@ -437,6 +442,7 @@ func TestSetupInfra(t *testing.T) {
437442
WithMetricsReporter(mockMetricsReporter),
438443
WithReleaseData(getTestReleaseData(&appConfig)),
439444
WithStore(mockStore),
445+
WithHelmClient(&helm.MockClient{}),
440446
)
441447
require.NoError(t, err)
442448

@@ -538,6 +544,7 @@ func TestGetInfra(t *testing.T) {
538544
controller, err := NewInstallController(
539545
WithInfraManager(mockManager),
540546
WithReleaseData(getTestReleaseData(&kotsv1beta1.Config{})),
547+
WithHelmClient(&helm.MockClient{}),
541548
)
542549
require.NoError(t, err)
543550

0 commit comments

Comments
 (0)