Skip to content

Commit abc058a

Browse files
committed
Merge remote-tracking branch 'origin/main' into k0s-1-30
2 parents 89f7777 + f0b4d23 commit abc058a

File tree

115 files changed

+6731
-944
lines changed

Some content is hidden

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

115 files changed

+6731
-944
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: Cleanup Resources
2+
3+
on:
4+
schedule:
5+
# Run every 12 hours
6+
- cron: '0 */12 * * *'
7+
workflow_dispatch: # Allow manual triggering
8+
9+
jobs:
10+
archive-instances:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout code
15+
uses: actions/checkout@v4
16+
17+
- name: Run archive instances script
18+
env:
19+
REPLICATED_APP: "embedded-cluster-smoke-test-staging-app"
20+
REPLICATED_API_TOKEN: ${{ secrets.STAGING_REPLICATED_API_TOKEN }}
21+
REPLICATED_API_ORIGIN: "https://api.staging.replicated.com"
22+
DRY_RUN: "false"
23+
run: |
24+
# Make script executable and run it
25+
chmod +x ./scripts/archive-instances.sh
26+
./scripts/archive-instances.sh
27+
28+
demote-channel-releases:
29+
runs-on: ubuntu-latest
30+
31+
steps:
32+
- name: Checkout code
33+
uses: actions/checkout@v4
34+
35+
- name: Run demote channel releases script
36+
env:
37+
REPLICATED_APP: "embedded-cluster-smoke-test-staging-app"
38+
REPLICATED_API_TOKEN: ${{ secrets.STAGING_REPLICATED_API_TOKEN }}
39+
REPLICATED_API_ORIGIN: "https://api.staging.replicated.com"
40+
DRY_RUN: "false"
41+
run: |
42+
# Make script executable and run it
43+
chmod +x ./scripts/demote-channel-releases.sh
44+
./scripts/demote-channel-releases.sh

api/controllers/app/install/controller.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ type Controller interface {
2525
GetAppPreflightStatus(ctx context.Context) (types.Status, error)
2626
GetAppPreflightOutput(ctx context.Context) (*types.PreflightsOutput, error)
2727
GetAppPreflightTitles(ctx context.Context) ([]string, error)
28-
InstallApp(ctx context.Context) error
28+
InstallApp(ctx context.Context, ignoreAppPreflights bool) error
2929
GetAppInstallStatus(ctx context.Context) (types.AppInstall, error)
3030
}
3131

@@ -159,6 +159,7 @@ func NewInstallController(opts ...InstallControllerOption) (*InstallController,
159159
if controller.appPreflightManager == nil {
160160
controller.appPreflightManager = apppreflightmanager.NewAppPreflightManager(
161161
apppreflightmanager.WithLogger(controller.logger),
162+
apppreflightmanager.WithAppPreflightStore(controller.store.AppPreflightStore()),
162163
)
163164
}
164165

@@ -181,6 +182,7 @@ func NewInstallController(opts ...InstallControllerOption) (*InstallController,
181182
appinstallmanager.WithReleaseData(controller.releaseData),
182183
appinstallmanager.WithClusterID(controller.clusterID),
183184
appinstallmanager.WithAirgapBundle(controller.airgapBundle),
185+
appinstallmanager.WithAppInstallStore(controller.store.AppInstallStore()),
184186
)
185187
if err != nil {
186188
return nil, fmt.Errorf("create app install manager: %w", err)

api/controllers/app/install/controller_mock.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ func (m *MockController) GetAppPreflightTitles(ctx context.Context) ([]string, e
6969
}
7070

7171
// InstallApp mocks the InstallApp method
72-
func (m *MockController) InstallApp(ctx context.Context) error {
73-
args := m.Called(ctx)
72+
func (m *MockController) InstallApp(ctx context.Context, ignoreAppPreflights bool) error {
73+
args := m.Called(ctx, ignoreAppPreflights)
7474
return args.Error(0)
7575
}
7676

api/controllers/app/install/install.go

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,20 @@ package install
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"runtime/debug"
78

89
states "github.com/replicatedhq/embedded-cluster/api/internal/states/install"
910
"github.com/replicatedhq/embedded-cluster/api/types"
1011
)
1112

13+
var (
14+
ErrAppPreflightChecksFailed = errors.New("app preflight checks failed")
15+
)
16+
1217
// InstallApp triggers app installation with proper state transitions and panic handling
13-
func (c *InstallController) InstallApp(ctx context.Context) (finalErr error) {
18+
func (c *InstallController) InstallApp(ctx context.Context, ignoreAppPreflights bool) (finalErr error) {
1419
lock, err := c.stateMachine.AcquireLock()
1520
if err != nil {
1621
return types.NewConflictError(err)
@@ -25,6 +30,18 @@ func (c *InstallController) InstallApp(ctx context.Context) (finalErr error) {
2530
}
2631
}()
2732

33+
// Check if app preflights have failed and if we should ignore them
34+
if c.stateMachine.CurrentState() == states.StateAppPreflightsFailed {
35+
allowIgnoreAppPreflights := true // TODO: implement once we check for strict app preflights
36+
if !ignoreAppPreflights || !allowIgnoreAppPreflights {
37+
return types.NewBadRequestError(ErrAppPreflightChecksFailed)
38+
}
39+
err = c.stateMachine.Transition(lock, states.StateAppPreflightsFailedBypassed)
40+
if err != nil {
41+
return fmt.Errorf("failed to transition states: %w", err)
42+
}
43+
}
44+
2845
if err := c.stateMachine.ValidateTransition(lock, states.StateAppInstalling); err != nil {
2946
return types.NewConflictError(err)
3047
}
@@ -48,21 +65,18 @@ func (c *InstallController) InstallApp(ctx context.Context) (finalErr error) {
4865

4966
defer func() {
5067
if r := recover(); r != nil {
51-
finalErr = fmt.Errorf("panic installing app: %v: %s", r, string(debug.Stack()))
68+
finalErr = fmt.Errorf("panic: %v: %s", r, string(debug.Stack()))
5269
}
53-
// Handle errors from app installation
5470
if finalErr != nil {
5571
c.logger.Error(finalErr)
5672

5773
if err := c.stateMachine.Transition(lock, states.StateAppInstallFailed); err != nil {
5874
c.logger.Errorf("failed to transition states: %w", err)
5975
}
60-
return
61-
}
62-
63-
// Transition to succeeded state on successful app installation
64-
if err := c.stateMachine.Transition(lock, states.StateSucceeded); err != nil {
65-
c.logger.Errorf("failed to transition states: %w", err)
76+
} else {
77+
if err := c.stateMachine.Transition(lock, states.StateSucceeded); err != nil {
78+
c.logger.Errorf("failed to transition states: %w", err)
79+
}
6680
}
6781
}()
6882

@@ -78,23 +92,6 @@ func (c *InstallController) InstallApp(ctx context.Context) (finalErr error) {
7892
return nil
7993
}
8094

81-
// TODO: remove this once we have endpoints to trigger app installation and report status
82-
// and the app installation is decoupled from the infra installation
83-
func (c *InstallController) InstallAppNoState(ctx context.Context) error {
84-
// Get config values for app installation
85-
configValues, err := c.appConfigManager.GetKotsadmConfigValues()
86-
if err != nil {
87-
return fmt.Errorf("get kotsadm config values for app install: %w", err)
88-
}
89-
90-
// Install the app using the app install manager
91-
if err := c.appInstallManager.Install(ctx, configValues); err != nil {
92-
return fmt.Errorf("install app: %w", err)
93-
}
94-
95-
return nil
96-
}
97-
9895
func (c *InstallController) GetAppInstallStatus(ctx context.Context) (types.AppInstall, error) {
9996
return c.appInstallManager.GetStatus()
10097
}

api/controllers/app/install/test_suite.go

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ func (s *AppInstallControllerTestSuite) TestRunAppPreflights() {
185185
opts: RunAppPreflightOptions{
186186
PreflightBinaryPath: "/usr/bin/preflight",
187187
},
188-
currentState: states.StateSucceeded,
188+
currentState: states.StateInfrastructureInstalled,
189189
expectedState: states.StateAppPreflightsSucceeded,
190190
setupMocks: func(apm *apppreflightmanager.MockAppPreflightManager, arm *appreleasemanager.MockAppReleaseManager, acm *appconfig.MockAppConfigManager) {
191191
mock.InOrder(
@@ -263,7 +263,7 @@ func (s *AppInstallControllerTestSuite) TestRunAppPreflights() {
263263
opts: RunAppPreflightOptions{
264264
PreflightBinaryPath: "/usr/bin/preflight",
265265
},
266-
currentState: states.StateSucceeded,
266+
currentState: states.StateInfrastructureInstalled,
267267
expectedState: states.StateAppPreflightsFailed,
268268
setupMocks: func(apm *apppreflightmanager.MockAppPreflightManager, arm *appreleasemanager.MockAppReleaseManager, acm *appconfig.MockAppConfigManager) {
269269
mock.InOrder(
@@ -289,7 +289,7 @@ func (s *AppInstallControllerTestSuite) TestRunAppPreflights() {
289289
opts: RunAppPreflightOptions{
290290
PreflightBinaryPath: "/usr/bin/preflight",
291291
},
292-
currentState: states.StateSucceeded,
292+
currentState: states.StateInfrastructureInstalled,
293293
expectedState: states.StateAppPreflightsExecutionFailed,
294294
setupMocks: func(apm *apppreflightmanager.MockAppPreflightManager, arm *appreleasemanager.MockAppReleaseManager, acm *appconfig.MockAppConfigManager) {
295295
mock.InOrder(
@@ -308,7 +308,7 @@ func (s *AppInstallControllerTestSuite) TestRunAppPreflights() {
308308
opts: RunAppPreflightOptions{
309309
PreflightBinaryPath: "/usr/bin/preflight",
310310
},
311-
currentState: states.StateSucceeded,
311+
currentState: states.StateInfrastructureInstalled,
312312
expectedState: states.StateAppPreflightsSucceeded,
313313
setupMocks: func(apm *apppreflightmanager.MockAppPreflightManager, arm *appreleasemanager.MockAppReleaseManager, acm *appconfig.MockAppConfigManager) {
314314
mock.InOrder(
@@ -327,7 +327,7 @@ func (s *AppInstallControllerTestSuite) TestRunAppPreflights() {
327327
opts: RunAppPreflightOptions{
328328
PreflightBinaryPath: "/usr/bin/preflight",
329329
},
330-
currentState: states.StateSucceeded,
330+
currentState: states.StateInfrastructureInstalled,
331331
expectedState: states.StateAppPreflightsSucceeded,
332332
setupMocks: func(apm *apppreflightmanager.MockAppPreflightManager, arm *appreleasemanager.MockAppReleaseManager, acm *appconfig.MockAppConfigManager) {
333333
mock.InOrder(
@@ -353,8 +353,8 @@ func (s *AppInstallControllerTestSuite) TestRunAppPreflights() {
353353
opts: RunAppPreflightOptions{
354354
PreflightBinaryPath: "/usr/bin/preflight",
355355
},
356-
currentState: states.StateSucceeded,
357-
expectedState: states.StateSucceeded,
356+
currentState: states.StateInfrastructureInstalled,
357+
expectedState: states.StateInfrastructureInstalled,
358358
setupMocks: func(apm *apppreflightmanager.MockAppPreflightManager, arm *appreleasemanager.MockAppReleaseManager, acm *appconfig.MockAppConfigManager) {
359359
mock.InOrder(
360360
acm.On("GetConfigValues").Return(types.AppConfigValues{"test-item": types.AppConfigValue{Value: "test-value"}}, nil),
@@ -368,7 +368,7 @@ func (s *AppInstallControllerTestSuite) TestRunAppPreflights() {
368368
opts: RunAppPreflightOptions{
369369
PreflightBinaryPath: "/usr/bin/preflight",
370370
},
371-
currentState: states.StateSucceeded,
371+
currentState: states.StateInfrastructureInstalled,
372372
expectedState: states.StateAppPreflightsExecutionFailed,
373373
setupMocks: func(apm *apppreflightmanager.MockAppPreflightManager, arm *appreleasemanager.MockAppReleaseManager, acm *appconfig.MockAppConfigManager) {
374374
mock.InOrder(
@@ -501,11 +501,12 @@ func (s *AppInstallControllerTestSuite) TestGetAppInstallStatus() {
501501

502502
func (s *AppInstallControllerTestSuite) TestInstallApp() {
503503
tests := []struct {
504-
name string
505-
currentState statemachine.State
506-
expectedState statemachine.State
507-
setupMocks func(*appconfig.MockAppConfigManager, *appinstallmanager.MockAppInstallManager)
508-
expectedErr bool
504+
name string
505+
ignoreAppPreflights bool
506+
currentState statemachine.State
507+
expectedState statemachine.State
508+
setupMocks func(*appconfig.MockAppConfigManager, *appinstallmanager.MockAppInstallManager)
509+
expectedErr bool
509510
}{
510511
{
511512
name: "invalid state transition from succeeded state",
@@ -574,6 +575,37 @@ func (s *AppInstallControllerTestSuite) TestInstallApp() {
574575
},
575576
expectedErr: true,
576577
},
578+
{
579+
name: "successful app installation with failed preflights - ignored",
580+
ignoreAppPreflights: true,
581+
currentState: states.StateAppPreflightsFailed,
582+
expectedState: states.StateSucceeded,
583+
setupMocks: func(acm *appconfig.MockAppConfigManager, aim *appinstallmanager.MockAppInstallManager) {
584+
mock.InOrder(
585+
acm.On("GetKotsadmConfigValues").Return(kotsv1beta1.ConfigValues{
586+
Spec: kotsv1beta1.ConfigValuesSpec{
587+
Values: map[string]kotsv1beta1.ConfigValue{
588+
"test-key": {Value: "test-value"},
589+
},
590+
},
591+
}, nil),
592+
aim.On("Install", mock.Anything, mock.MatchedBy(func(cv kotsv1beta1.ConfigValues) bool {
593+
return cv.Spec.Values["test-key"].Value == "test-value"
594+
})).Return(nil),
595+
)
596+
},
597+
expectedErr: false,
598+
},
599+
{
600+
name: "failed app installation with failed preflights - not ignored",
601+
ignoreAppPreflights: false,
602+
currentState: states.StateAppPreflightsFailed,
603+
expectedState: states.StateAppPreflightsFailed,
604+
setupMocks: func(acm *appconfig.MockAppConfigManager, aim *appinstallmanager.MockAppInstallManager) {
605+
// No mocks needed as method should return early with error
606+
},
607+
expectedErr: true,
608+
},
577609
}
578610

579611
for _, tt := range tests {
@@ -596,7 +628,7 @@ func (s *AppInstallControllerTestSuite) TestInstallApp() {
596628
require.NoError(t, err, "failed to create install controller")
597629

598630
tt.setupMocks(appConfigManager, appInstallManager)
599-
err = controller.InstallApp(t.Context())
631+
err = controller.InstallApp(t.Context(), tt.ignoreAppPreflights)
600632

601633
if tt.expectedErr {
602634
assert.Error(t, err)

api/controllers/kubernetes/install/controller.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ func NewInstallController(opts ...InstallControllerOption) (*InstallController,
201201
if controller.infraManager == nil {
202202
infraManager, err := infra.NewInfraManager(
203203
infra.WithLogger(controller.logger),
204-
infra.WithInfraStore(controller.store.LinuxInfraStore()),
204+
infra.WithInfraStore(controller.store.KubernetesInfraStore()),
205205
infra.WithRESTClientGetter(controller.restClientGetter),
206206
infra.WithPassword(controller.password),
207207
infra.WithTLSConfig(controller.tlsConfig),
@@ -216,6 +216,8 @@ func NewInstallController(opts ...InstallControllerOption) (*InstallController,
216216
controller.infraManager = infraManager
217217
}
218218

219+
controller.registerReportingHandlers()
220+
219221
return controller, nil
220222
}
221223

api/controllers/kubernetes/install/controller_mock.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ func (m *MockController) RunAppPreflights(ctx context.Context, opts appcontrolle
109109
}
110110

111111
// InstallApp mocks the InstallApp method
112-
func (m *MockController) InstallApp(ctx context.Context) error {
113-
args := m.Called(ctx)
112+
func (m *MockController) InstallApp(ctx context.Context, ignoreAppPreflights bool) error {
113+
args := m.Called(ctx, ignoreAppPreflights)
114114
return args.Error(0)
115115
}
116116

0 commit comments

Comments
 (0)