Skip to content

Commit

Permalink
show initial preflight page for helm chart preflights (#4402)
Browse files Browse the repository at this point in the history
* load preflights from helm chart templates as kotskinds

* re-fetch app details after initial config is saved

* read installation just before writing kotskinds
  • Loading branch information
Craig O'Donnell authored Feb 2, 2024
1 parent 862f5a8 commit c124cbd
Show file tree
Hide file tree
Showing 13 changed files with 174 additions and 34 deletions.
14 changes: 11 additions & 3 deletions pkg/kotsutil/kots.go
Original file line number Diff line number Diff line change
Expand Up @@ -1475,14 +1475,22 @@ func FilterV1Beta1ChartsWithV1Beta2Charts(v1Beta1Charts []kotsv1beta1.HelmChart,
}

func MustMarshalInstallation(installation *kotsv1beta1.Installation) []byte {
b, err := MarshalRuntimeObject(installation)
if err != nil {
panic(err)
}
return b
}

func MarshalRuntimeObject(obj runtime.Object) ([]byte, error) {
s := json.NewYAMLSerializer(json.DefaultMetaFactory, scheme.Scheme, scheme.Scheme)

var b bytes.Buffer
if err := s.Encode(installation, &b); err != nil {
panic(err)
if err := s.Encode(obj, &b); err != nil {
return nil, errors.Wrap(err, "failed to encode object")
}

return b.Bytes()
return b.Bytes(), nil
}

// this is here to avoid a circular dependency
Expand Down
45 changes: 34 additions & 11 deletions pkg/pull/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import (
"github.com/replicatedhq/kots/pkg/util"
kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
kotsv1beta2 "github.com/replicatedhq/kotskinds/apis/kots/v1beta2"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
troubleshootpreflight "github.com/replicatedhq/troubleshoot/pkg/preflight"
k8sjson "k8s.io/apimachinery/pkg/runtime/serializer/json"
"k8s.io/client-go/kubernetes/scheme"
)
Expand Down Expand Up @@ -578,17 +580,6 @@ func Pull(upstreamURI string, pullOptions PullOptions) (string, error) {
}
}

// installation spec gets updated during the process, ensure the map has the latest version
installationBytes, err := os.ReadFile(filepath.Join(u.GetUpstreamDir(writeUpstreamOptions), "userdata", "installation.yaml"))
if err != nil {
return "", errors.Wrap(err, "failed to read installation file")
}
renderedKotsKindsMap["userdata/installation.yaml"] = []byte(installationBytes)

if err := kotsutil.WriteKotsKinds(renderedKotsKindsMap, u.GetKotsKindsDir(writeUpstreamOptions)); err != nil {
return "", errors.Wrap(err, "failed to write the rendered kots kinds")
}

if err := rendered.WriteRenderedApp(&rendered.WriteOptions{
BaseDir: u.GetBaseDir(writeUpstreamOptions),
OverlaysDir: u.GetOverlaysDir(writeUpstreamOptions),
Expand All @@ -604,6 +595,38 @@ func Pull(upstreamURI string, pullOptions PullOptions) (string, error) {
return "", errors.Wrap(err, "failed to write rendered")
}

// preflights may also be included within helm chart templates, so load any from the rendered dir
tsKinds, err := kotsutil.LoadTSKindsFromPath(u.GetRenderedDir(writeUpstreamOptions))
if err != nil {
return "", errors.Wrap(err, fmt.Sprintf("failed to load troubleshoot kinds from path: %s", u.GetRenderedDir(writeUpstreamOptions)))
}

if tsKinds.PreflightsV1Beta2 != nil {
var renderedPreflight *troubleshootv1beta2.Preflight
for _, v := range tsKinds.PreflightsV1Beta2 {
renderedPreflight = troubleshootpreflight.ConcatPreflightSpec(renderedPreflight, &v)
}

if renderedPreflight != nil {
renderedPreflightBytes, err := kotsutil.MarshalRuntimeObject(renderedPreflight)
if err != nil {
return "", errors.Wrap(err, "failed to marshal rendered preflight")
}
renderedKotsKindsMap["helm-preflight.yaml"] = renderedPreflightBytes
}
}

// installation spec gets updated during the process, ensure the map has the latest version
installationBytes, err := os.ReadFile(filepath.Join(u.GetUpstreamDir(writeUpstreamOptions), "userdata", "installation.yaml"))
if err != nil {
return "", errors.Wrap(err, "failed to read installation file")
}
renderedKotsKindsMap["userdata/installation.yaml"] = []byte(installationBytes)

if err := kotsutil.WriteKotsKinds(renderedKotsKindsMap, u.GetKotsKindsDir(writeUpstreamOptions)); err != nil {
return "", errors.Wrap(err, "failed to write the rendered kots kinds")
}

return filepath.Join(pullOptions.RootDir, u.Name), nil
}

Expand Down
45 changes: 34 additions & 11 deletions pkg/rewrite/rewrite.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import (
"github.com/replicatedhq/kots/pkg/upstream"
upstreamtypes "github.com/replicatedhq/kots/pkg/upstream/types"
kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
troubleshootpreflight "github.com/replicatedhq/troubleshoot/pkg/preflight"
)

type RewriteOptions struct {
Expand Down Expand Up @@ -313,17 +315,6 @@ func Rewrite(rewriteOptions RewriteOptions) error {
return errors.Wrap(err, "failed to update installation spec")
}

// installation spec gets updated during the process, ensure the map has the latest version
installationBytes, err := os.ReadFile(filepath.Join(u.GetUpstreamDir(writeUpstreamOptions), "userdata", "installation.yaml"))
if err != nil {
return errors.Wrap(err, "failed to read installation file")
}
renderedKotsKindsMap["userdata/installation.yaml"] = installationBytes

if err := kotsutil.WriteKotsKinds(renderedKotsKindsMap, u.GetKotsKindsDir(writeUpstreamOptions)); err != nil {
return errors.Wrap(err, "failed to write kots base")
}

if err := rendered.WriteRenderedApp(&rendered.WriteOptions{
BaseDir: u.GetBaseDir(writeUpstreamOptions),
OverlaysDir: u.GetOverlaysDir(writeUpstreamOptions),
Expand All @@ -339,6 +330,38 @@ func Rewrite(rewriteOptions RewriteOptions) error {
return errors.Wrap(err, "failed to write rendered")
}

// preflights may also be included within helm chart templates, so load any from the rendered dir
tsKinds, err := kotsutil.LoadTSKindsFromPath(u.GetRenderedDir(writeUpstreamOptions))
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to load troubleshoot kinds from path: %s", u.GetRenderedDir(writeUpstreamOptions)))
}

if tsKinds.PreflightsV1Beta2 != nil {
var renderedPreflight *troubleshootv1beta2.Preflight
for _, v := range tsKinds.PreflightsV1Beta2 {
renderedPreflight = troubleshootpreflight.ConcatPreflightSpec(renderedPreflight, &v)
}

if renderedPreflight != nil {
renderedPreflightBytes, err := kotsutil.MarshalRuntimeObject(renderedPreflight)
if err != nil {
return errors.Wrap(err, "failed to marshal rendered preflight")
}
renderedKotsKindsMap["helm-preflight.yaml"] = renderedPreflightBytes
}
}

// installation spec gets updated during the process, ensure the map has the latest version
installationBytes, err := os.ReadFile(filepath.Join(u.GetUpstreamDir(writeUpstreamOptions), "userdata", "installation.yaml"))
if err != nil {
return errors.Wrap(err, "failed to read installation file")
}
renderedKotsKindsMap["userdata/installation.yaml"] = installationBytes

if err := kotsutil.WriteKotsKinds(renderedKotsKindsMap, u.GetKotsKindsDir(writeUpstreamOptions)); err != nil {
return errors.Wrap(err, "failed to write the rendered kots kinds")
}

log.FinishSpinner()

return nil
Expand Down
Binary file not shown.
11 changes: 11 additions & 0 deletions pkg/tests/pull/cases/kotskinds/upstream/my-preflight-chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# this chart validates that preflights inside helm chart templates are processed correctly as kotskinds
apiVersion: kots.io/v1beta2
kind: HelmChart
metadata:
name: my-preflight-chart
annotations:
kots.io/exclude: "true"
spec:
chart:
name: my-preflight-chart
chartVersion: 0.1.0
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
apiVersion: troubleshoot.sh/v1beta2
kind: Preflight
metadata:
creationTimestamp: null
name: airgap-smoke-test-preflight
spec:
analyzers:
- clusterVersion:
outcomes:
- fail:
message: The application requires at Kubernetes 1.13.0 or later, and recommends
1.15.0.
uri: https://www.kubernetes.io
when: < 1.13.0
- warn:
message: Your cluster meets the minimum version of Kubernetes, but we recommend
you update to 1.15.0 or later.
uri: https://kubernetes.io
when: < 1.15.0
- pass:
message: Your cluster meets the minimum version of Kubernetes recommended
by the application.
status: {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# this chart validates that preflights inside helm chart templates are processed correctly as kotskinds
apiVersion: kots.io/v1beta2
kind: HelmChart
metadata:
name: my-preflight-chart
annotations:
kots.io/exclude: "true"
spec:
chart:
name: my-preflight-chart
chartVersion: 0.1.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
# Source: my-preflight-chart/templates/my-chart-preflight.yaml
apiVersion: v1
kind: Secret
metadata:
labels:
troubleshoot.sh/kind: preflight
name: "my-preflight-chart-preflight-config"
stringData:
preflight.yaml: |
apiVersion: troubleshoot.sh/v1beta2
kind: Preflight
metadata:
name: airgap-smoke-test-preflight
spec:
collectors: []
analyzers:
- clusterVersion:
outcomes:
- fail:
when: "< 1.13.0"
message: The application requires at Kubernetes 1.13.0 or later, and recommends 1.15.0.
uri: https://www.kubernetes.io
- warn:
when: "< 1.15.0"
message: Your cluster meets the minimum version of Kubernetes, but we recommend you update to 1.15.0 or later.
uri: https://kubernetes.io
- pass:
message: Your cluster meets the minimum version of Kubernetes recommended by the application.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# this chart validates that preflights inside helm chart templates are processed correctly as kotskinds
apiVersion: kots.io/v1beta2
kind: HelmChart
metadata:
name: my-preflight-chart
annotations:
kots.io/exclude: "true"
spec:
chart:
name: my-preflight-chart
chartVersion: 0.1.0
18 changes: 9 additions & 9 deletions web/src/features/AppConfig/components/AppConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,10 @@ class AppConfig extends Component<Props, State> {
}
window.addEventListener("resize", this.determineSidebarHeight);

if (!this.props.app) {
this.getApp();
if (!app) {
this.fetchApp();
} else {
this.setState({ app });
}
this.getConfig();
}
Expand Down Expand Up @@ -204,11 +206,7 @@ class AppConfig extends Component<Props, State> {
}
};

getApp = async () => {
if (this.props.app) {
return;
}

fetchApp = async (): Promise<App | undefined> => {
try {
const { slug } = this.props.params;
const res = await fetch(`${process.env.API_ENDPOINT}/app/${slug}`, {
Expand All @@ -221,6 +219,7 @@ class AppConfig extends Component<Props, State> {
if (res.ok && res.status == 200) {
const app = await res.json();
this.setState({ app });
return app;
}
} catch (err) {
console.log(err);
Expand Down Expand Up @@ -416,7 +415,8 @@ class AppConfig extends Component<Props, State> {
}

if (fromLicenseFlow) {
const hasPreflight = this.props.app.hasPreflight;
const app = await this.fetchApp();
const hasPreflight = app?.hasPreflight;

if (hasPreflight) {
navigate(`/${slug}/preflight`, { replace: true });
Expand Down Expand Up @@ -661,6 +661,7 @@ class AppConfig extends Component<Props, State> {

render() {
const {
app,
changed,
showConfigError,
configErrorMessage,
Expand All @@ -675,7 +676,6 @@ class AppConfig extends Component<Props, State> {
showValidationError,
} = this.state;
const { fromLicenseFlow, params, isHelmManaged } = this.props;
const app = this.props.app;

if (configLoading || !app) {
return (
Expand Down

0 comments on commit c124cbd

Please sign in to comment.