Skip to content

Run preflights in manager UI / API #2234

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 42 commits into from
Jun 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
3af8ff1
wip preflgihts ui
miaawong May 29, 2025
088dcdd
update types to match api preflight structure
miaawong May 29, 2025
f4dd47a
add comment
miaawong May 29, 2025
86ac03e
Merge branch 'main' into miawong/sc-124239/preflight-ui-step-for-the-…
miaawong May 30, 2025
548468b
fix for loading web
miaawong May 30, 2025
1d964e6
Merge branch 'main' into miawong/sc-124239/preflight-ui-step-for-the-…
miaawong Jun 2, 2025
e4035b6
f
miaawong Jun 2, 2025
d90cd90
Merge branch 'main' into miawong/sc-124239/preflight-ui-step-for-the-…
miaawong Jun 2, 2025
b82dbfc
fix the web dev
miaawong Jun 2, 2025
f0dca98
Run host preflights in manager UI
sgalsaleh May 28, 2025
a15bd63
Merge branch 'miawong/sc-124239/preflight-ui-step-for-the-new-install…
sgalsaleh Jun 2, 2025
c77250a
f
sgalsaleh Jun 2, 2025
d2d10d2
f
sgalsaleh Jun 3, 2025
45643ba
preflight checks
sgalsaleh Jun 3, 2025
2d1b7eb
[skip ci] testing
sgalsaleh Jun 3, 2025
3825c4e
f
sgalsaleh Jun 3, 2025
56ce746
f
sgalsaleh Jun 3, 2025
3db1168
runtimeconfig interface
sgalsaleh Jun 4, 2025
a8c01e1
Merge branch 'main' into run-preflights-in-manager-ui
sgalsaleh Jun 4, 2025
b04f5fc
f
sgalsaleh Jun 4, 2025
e932601
f
sgalsaleh Jun 4, 2025
c617d9c
fix dagger build
sgalsaleh Jun 4, 2025
6ca3f08
fix dagger build
sgalsaleh Jun 4, 2025
5bc987c
add polling for installation/status
miaawong Jun 3, 2025
11d558b
update
miaawong Jun 3, 2025
5810a7e
f
miaawong Jun 3, 2025
cd592a4
f
miaawong Jun 3, 2025
cb8f113
f
miaawong Jun 4, 2025
c91c351
fix dbus error
sgalsaleh Jun 4, 2025
5763381
[skip ci] f
sgalsaleh Jun 4, 2025
4adddd9
Merge branch 'miawong/preflights-manager-ui-cleanup' into run-preflig…
sgalsaleh Jun 4, 2025
34fbd09
[skip ci] no-op
sgalsaleh Jun 4, 2025
9acd699
fix ui
sgalsaleh Jun 4, 2025
3b78a3e
more ui improvements
sgalsaleh Jun 5, 2025
464411d
update complete step wording
miaawong Jun 5, 2025
b23c198
f
miaawong Jun 5, 2025
d5d92e6
clean up success message
miaawong Jun 5, 2025
87ad72c
address feedback
sgalsaleh Jun 5, 2025
39b45fe
regenerate swagger
sgalsaleh Jun 5, 2025
4d77b19
fix tests
sgalsaleh Jun 5, 2025
4204e58
no-op
sgalsaleh Jun 5, 2025
ff2d783
Merge remote-tracking branch 'origin/main' into run-preflights-in-man…
sgalsaleh Jun 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ name: CI

on:
pull_request: {}

push:
branches:
- main
Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,8 @@ envtest:
.PHONY: unit-tests
unit-tests: envtest
KUBEBUILDER_ASSETS="$(shell ./operator/bin/setup-envtest use $(ENVTEST_K8S_VERSION) --bin-dir $(shell pwd)/operator/bin -p path)" \
go test -tags $(GO_BUILD_TAGS) -v ./pkg/... ./cmd/... ./api/... ./web/... ./pkg-new/...
go test -tags $(GO_BUILD_TAGS) -v ./pkg/... ./cmd/... ./web/... ./pkg-new/...
$(MAKE) -C api unit-tests
$(MAKE) -C operator test
$(MAKE) -C utils unit-tests

Expand Down
6 changes: 6 additions & 0 deletions api/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
SHELL := /bin/bash

include ../common.mk

.PHONY: swagger
swagger: swag
swag fmt -g api.go
Expand All @@ -8,3 +10,7 @@ swagger: swag
.PHONY: swag
swag:
which swag || (go install github.com/swaggo/swag/v2/cmd/swag@latest)

.PHONY: unit-tests
unit-tests:
go test -tags $(GO_BUILD_TAGS) -v ./...
11 changes: 7 additions & 4 deletions api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ The root directory contains the main API setup files and request handlers.
### Subpackages

#### `/controllers`
Contains the business logic for different API endpoints. Each controller package focuses on a specific domain of functionality (e.g., authentication, console, installation) and implements the core business logic for that domain.
Contains the business logic for different API endpoints. Each controller package focuses on a specific domain of functionality or workflow (e.g., authentication, console, install, upgrade, join, etc.) and implements the core business logic for that domain or workflow. Controllers can utilize multiple managers with each manager handling a specific subdomain of functionality.

#### `/internal/managers`
Each manager is responsible for a specific subdomain of functionality and provides a clean, thread-safe interface for controllers to interact with. For example, the Preflight Manager manages system requirement checks and validation.

#### `/types`
Defines the core data structures and types used throughout the API. This includes:
Expand All @@ -36,12 +39,12 @@ Provides a client library for interacting with the API. The client package imple

1. **New API Endpoints**:
- Add route definitions in the root API setup
- Create corresponding controller in `/controllers`
- Create or update corresponding controller in `/controllers`
- Define request/response types in `/types`

2. **New Business Logic**:
- Place in appropriate controller under `/controllers`
- Share common logic in `/pkg` if used across multiple controllers
- Place in appropriate controller under `/controllers` if the logic represents a distinct domain or workflow
- Place in appropriate manager under `/internal/managers` if the logic represents a distinct subdomain

3. **New Types/Models**:
- Add to `/types` directory
Expand Down
95 changes: 87 additions & 8 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ import (
"github.com/replicatedhq/embedded-cluster/api/controllers/console"
"github.com/replicatedhq/embedded-cluster/api/controllers/install"
"github.com/replicatedhq/embedded-cluster/api/docs"
"github.com/replicatedhq/embedded-cluster/api/pkg/logger"
"github.com/replicatedhq/embedded-cluster/api/types"
"github.com/replicatedhq/embedded-cluster/pkg-new/hostutils"
"github.com/replicatedhq/embedded-cluster/pkg/metrics"
"github.com/replicatedhq/embedded-cluster/pkg/release"
"github.com/replicatedhq/embedded-cluster/pkg/runtimeconfig"
"github.com/sirupsen/logrus"
httpSwagger "github.com/swaggo/http-swagger/v2"
)
Expand All @@ -38,8 +43,14 @@ type API struct {
authController auth.Controller
consoleController console.Controller
installController install.Controller
rc runtimeconfig.RuntimeConfig
releaseData *release.ReleaseData
licenseFile string
airgapBundle string
configChan chan<- *types.InstallationConfig
logger logrus.FieldLogger
hostUtils hostutils.HostUtilsInterface
metricsReporter metrics.ReporterInterface
}

type APIOption func(*API)
Expand All @@ -62,24 +73,79 @@ func WithInstallController(installController install.Controller) APIOption {
}
}

func WithRuntimeConfig(rc runtimeconfig.RuntimeConfig) APIOption {
return func(a *API) {
a.rc = rc
}
}

func WithLogger(logger logrus.FieldLogger) APIOption {
return func(a *API) {
a.logger = logger
}
}

func WithHostUtils(hostUtils hostutils.HostUtilsInterface) APIOption {
return func(a *API) {
a.hostUtils = hostUtils
}
}

func WithMetricsReporter(metricsReporter metrics.ReporterInterface) APIOption {
return func(a *API) {
a.metricsReporter = metricsReporter
}
}

func WithReleaseData(releaseData *release.ReleaseData) APIOption {
return func(a *API) {
a.releaseData = releaseData
}
}

func WithConfigChan(configChan chan<- *types.InstallationConfig) APIOption {
return func(a *API) {
a.configChan = configChan
}
}

func WithLicenseFile(licenseFile string) APIOption {
return func(a *API) {
a.licenseFile = licenseFile
}
}

func WithAirgapBundle(airgapBundle string) APIOption {
return func(a *API) {
a.airgapBundle = airgapBundle
}
}

func New(password string, opts ...APIOption) (*API, error) {
api := &API{}

for _, opt := range opts {
opt(api)
}

if api.rc == nil {
api.rc = runtimeconfig.New(nil)
}

if api.logger == nil {
l, err := logger.NewLogger()
if err != nil {
return nil, fmt.Errorf("create logger: %w", err)
}
api.logger = l
}

if api.hostUtils == nil {
api.hostUtils = hostutils.New(
hostutils.WithLogger(api.logger),
)
}

if api.authController == nil {
authController, err := auth.NewAuthController(password)
if err != nil {
Expand All @@ -97,17 +163,21 @@ func New(password string, opts ...APIOption) (*API, error) {
}

if api.installController == nil {
installController, err := install.NewInstallController()
installController, err := install.NewInstallController(
install.WithRuntimeConfig(api.rc),
install.WithLogger(api.logger),
install.WithHostUtils(api.hostUtils),
install.WithMetricsReporter(api.metricsReporter),
install.WithReleaseData(api.releaseData),
install.WithLicenseFile(api.licenseFile),
install.WithAirgapBundle(api.airgapBundle),
)
Comment on lines +166 to +174
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should likely review some of these struct properties to understand if they need to be pointers to structs and we're making that choice deliberately or not. Right now I'm worried that we receive pointers to structs that we then pass to the controllers (and maybe these can even end up being used by things such as managers). If some end up unintentionally mutating state we can be in trouble trying to debug a particularly airy bug.

if err != nil {
return nil, fmt.Errorf("new install controller: %w", err)
}
api.installController = installController
}

if api.logger == nil {
api.logger = NewDiscardLogger()
}

return api, nil
}

Expand All @@ -129,10 +199,19 @@ func (a *API) RegisterRoutes(router *mux.Router) {
authenticatedRouter.Use(a.authMiddleware)

installRouter := authenticatedRouter.PathPrefix("/install").Subrouter()
installRouter.HandleFunc("", a.getInstall).Methods("GET")
installRouter.HandleFunc("/config", a.setInstallConfig).Methods("POST")
installRouter.HandleFunc("/status", a.setInstallStatus).Methods("POST")
installRouter.HandleFunc("/installation/config", a.getInstallInstallationConfig).Methods("GET")
installRouter.HandleFunc("/installation/status", a.getInstallInstallationStatus).Methods("GET")
installRouter.HandleFunc("/installation/configure", a.postInstallConfigureInstallation).Methods("POST")

installRouter.HandleFunc("/host-preflights/status", a.getInstallHostPreflightsStatus).Methods("GET")
installRouter.HandleFunc("/host-preflights/run", a.postInstallRunHostPreflights).Methods("POST")

installRouter.HandleFunc("/node/setup", a.postInstallSetupNode).Methods("POST")

// TODO (@salah): remove this once the cli isn't responsible for setting the install status
// and the ui isn't polling for it to know if the entire install is complete
installRouter.HandleFunc("/status", a.getInstallStatus).Methods("GET")
installRouter.HandleFunc("/status", a.setInstallStatus).Methods("POST")

consoleRouter := authenticatedRouter.PathPrefix("/console").Subrouter()
consoleRouter.HandleFunc("/available-network-interfaces", a.getListAvailableNetworkInterfaces).Methods("GET")
Expand Down
3 changes: 2 additions & 1 deletion api/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"net/http/httptest"
"testing"

"github.com/replicatedhq/embedded-cluster/api/pkg/logger"
"github.com/replicatedhq/embedded-cluster/api/types"
"github.com/stretchr/testify/assert"
)
Expand Down Expand Up @@ -84,7 +85,7 @@ func TestAPI_jsonError(t *testing.T) {

// Call the JSON method
api := &API{
logger: NewDiscardLogger(),
logger: logger.NewDiscardLogger(),
}
api.jsonError(rec, httptest.NewRequest("GET", "/api/test", nil), tt.apiErr)

Expand Down
7 changes: 4 additions & 3 deletions api/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import (

type Client interface {
Authenticate(password string) error
GetInstall() (*types.Install, error)
SetInstallConfig(config types.InstallationConfig) (*types.Install, error)
SetInstallStatus(status types.InstallationStatus) (*types.Install, error)
GetInstallationConfig() (*types.InstallationConfig, error)
GetInstallationStatus() (*types.Status, error)
ConfigureInstallation(config *types.InstallationConfig) (*types.Status, error)
SetInstallStatus(status *types.Status) (*types.Status, error)
}

type client struct {
Expand Down
Loading
Loading