diff --git a/.github/workflows/build-test.yaml b/.github/workflows/build-test.yaml index 469f3ba770..b11e7af339 100644 --- a/.github/workflows/build-test.yaml +++ b/.github/workflows/build-test.yaml @@ -745,29 +745,22 @@ jobs: --kotsadm-registry ttl.sh \ --kotsadm-namespace automated-${{ github.run_id }} \ --skip-preflights \ - --kotsadm-tag 24h + --kotsadm-tag 24h | tee output.txt - EXIT_CODE=$? - if [ $EXIT_CODE -ne 0 ]; then - echo "------pods:" - kubectl -n "$APP_SLUG" get pods - echo "------kotsadm logs" - kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG" - exit $EXIT_CODE + if ! grep -q "The Kubernetes RBAC policy that the Admin Console is running with does not have access to complete the Preflight Checks. It's recommended that you run these manually before proceeding." output.txt; then + echo "Expected to see an RBAC error for preflight checks, but did not" + exit 1 fi - COUNTER=1 - while [ "$(./bin/kots get apps --namespace "$APP_SLUG" | awk 'NR>1{print $2}')" != "ready" ]; do - ((COUNTER += 1)) - if [ $COUNTER -gt 180 ]; then - echo "Timed out waiting for app to be ready" - ./bin/kots get apps --namespace "$APP_SLUG" - echo "kotsadm logs:" - kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG" - exit 1 - fi - sleep 1 - done + if ! grep -q 'The app was not deployed.' output.txt; then + printf "Expected to see message about app not being deployed, but did not\n" + exit 1 + fi + + if grep FAIL output.txt | grep -q 'This application requires at least 100 nodes'; then + printf "Did not expect to see a failure about number of nodes, but did\n" + exit 1 + fi if ! kubectl get role -n "$APP_SLUG" | grep -q kotsadm; then echo "kotsadm role not found in namespace $APP_SLUG" @@ -1172,7 +1165,22 @@ jobs: --kotsadm-registry ttl.sh \ --kotsadm-namespace automated-${{ github.run_id }} \ --kotsadm-tag 24h \ - --use-minimal-rbac + --use-minimal-rbac | tee output.txt + + if ! grep -q "The Kubernetes RBAC policy that the Admin Console is running with does not have access to complete the Preflight Checks. It's recommended that you run these manually before proceeding." output.txt; then + echo "Expected to see an RBAC error for preflight checks, but did not" + exit 1 + fi + + if ! grep -q 'The app was not deployed.' output.txt; then + printf "Expected to see message about app not being deployed, but did not\n" + exit 1 + fi + + if grep FAIL output.txt | grep -q 'This application requires at least 100 nodes'; then + printf "Did not expect to see a failure about number of nodes, but did\n" + exit 1 + fi if ! kubectl get role -n "$APP_SLUG" | grep -q kotsadm; then echo "kotsadm role not found in namespace $APP_SLUG" @@ -1214,7 +1222,22 @@ jobs: --shared-password password \ --kotsadm-registry ttl.sh \ --kotsadm-namespace automated-${{ github.run_id }} \ - --kotsadm-tag 24h + --kotsadm-tag 24h | tee output.txt + + if grep -q "The Kubernetes RBAC policy that the Admin Console is running with does not have access to complete the Preflight Checks. It's recommended that you run these manually before proceeding." output.txt; then + echo "Did not expect to see an RBAC error for preflight checks, but did" + exit 1 + fi + + if ! grep -q 'The app was not deployed.' output.txt; then + printf "Expected to see message about app not being deployed, but did not\n" + exit 1 + fi + + if ! grep FAIL output.txt | grep -q 'This application requires at least 100 nodes'; then + printf "Expected to see a failure about number of nodes, but did not\n" + exit 1 + fi if kubectl get role -n "$APP_SLUG" | grep -q kotsadm; then echo "kotsadm role found in cluster scoped install" diff --git a/cmd/kots/cli/install.go b/cmd/kots/cli/install.go index 84170c7dbc..7ca212a246 100644 --- a/cmd/kots/cli/install.go +++ b/cmd/kots/cli/install.go @@ -32,6 +32,7 @@ import ( "github.com/replicatedhq/kots/pkg/kurl" "github.com/replicatedhq/kots/pkg/logger" "github.com/replicatedhq/kots/pkg/metrics" + preflighttypes "github.com/replicatedhq/kots/pkg/preflight/types" "github.com/replicatedhq/kots/pkg/print" "github.com/replicatedhq/kots/pkg/pull" "github.com/replicatedhq/kots/pkg/replicatedapp" @@ -447,14 +448,14 @@ func InstallCmd() *cobra.Command { log.FinishSpinner() switch status { - case storetypes.VersionPendingPreflight: + case storetypes.VersionPendingPreflight, storetypes.VersionPending: log.ActionWithSpinner("Waiting for preflight checks to complete") if err := ValidatePreflightStatus(deployOptions, authSlug, apiEndpoint); err != nil { perr := preflightError{} if errors.As(err, &perr) { log.FinishSpinner() // We succeeded waiting for the results. Don't finish with an error log.Errorf(perr.Msg) - print.PreflightErrors(log, perr.Results) + print.PreflightResults(perr.Results) cmd.SilenceErrors = true // Stop Cobra from printing the error, we format the message ourselves } else { log.FinishSpinnerWithError() @@ -1020,7 +1021,7 @@ func checkPreflightsComplete(response *handlers.GetPreflightResultResponse) (boo type preflightError struct { Msg string - Results []*preflight.UploadPreflightResult + Results preflighttypes.PreflightResults } func (e preflightError) Error() string { @@ -1034,12 +1035,30 @@ func checkPreflightResults(response *handlers.GetPreflightResultResponse) (bool, return false, nil } - var results preflight.UploadPreflightResults + var results preflighttypes.PreflightResults err := json.Unmarshal([]byte(response.PreflightResult.Result), &results) if err != nil { return false, errors.Wrap(err, fmt.Sprintf("failed to unmarshal upload preflight results from response: %v", response.PreflightResult.Result)) } + if len(results.Errors) > 0 { + isRBAC := false + for _, err := range results.Errors { + if err.IsRBAC { + isRBAC = true + break + } + } + msg := "There are preflight check errors for the application. The app was not deployed." + if isRBAC { + msg = "The Kubernetes RBAC policy that the Admin Console is running with does not have access to complete the Preflight Checks. It's recommended that you run these manually before proceeding. The app was not deployed." + } + return false, preflightError{ + Msg: msg, + Results: results, + } + } + var isWarn, isFail bool for _, result := range results.Results { if result.IsWarn { @@ -1053,20 +1072,20 @@ func checkPreflightResults(response *handlers.GetPreflightResultResponse) (bool, if isWarn && isFail { return false, preflightError{ Msg: "There are preflight check failures and warnings for the application. The app was not deployed.", - Results: results.Results, + Results: results, } } if isWarn { return false, preflightError{ Msg: "There are preflight check warnings for the application. The app was not deployed.", - Results: results.Results, + Results: results, } } if isFail { return false, preflightError{ Msg: "There are preflight check failures for the application. The app was not deployed.", - Results: results.Results, + Results: results, } } diff --git a/pkg/print/config.go b/pkg/print/config.go index 3507dcc75a..adadbbe4cf 100644 --- a/pkg/print/config.go +++ b/pkg/print/config.go @@ -6,8 +6,6 @@ import ( configtypes "github.com/replicatedhq/kots/pkg/kotsadmconfig/types" "github.com/replicatedhq/kots/pkg/logger" - "github.com/replicatedhq/kots/pkg/preflight" - tsPreflight "github.com/replicatedhq/troubleshoot/pkg/preflight" ) func ConfigValidationErrors(log *logger.CLILogger, groupValidationErrors []configtypes.ConfigGroupValidationError) { @@ -28,16 +26,3 @@ func ConfigValidationErrors(log *logger.CLILogger, groupValidationErrors []confi log.FinishSpinnerWithError() log.Errorf(sb.String()) } - -func PreflightErrors(log *logger.CLILogger, results []*tsPreflight.UploadPreflightResult) { - w := NewTabWriter() - defer w.Flush() - - fmt.Fprintf(w, "\n") - fmtColumns := "%s\t%s\t%s\n" - fmt.Fprintf(w, fmtColumns, "STATE", "TITLE", "MESSAGE") - for _, result := range results { - fmt.Fprintf(w, fmtColumns, strings.ToUpper(preflight.GetPreflightCheckState(result)), result.Title, result.Message) - } - fmt.Fprintf(w, "\n") -} diff --git a/pkg/print/preflight.go b/pkg/print/preflight.go new file mode 100644 index 0000000000..5020363943 --- /dev/null +++ b/pkg/print/preflight.go @@ -0,0 +1,33 @@ +package print + +import ( + "fmt" + "strings" + + "github.com/replicatedhq/kots/pkg/preflight" + preflighttypes "github.com/replicatedhq/kots/pkg/preflight/types" +) + +func PreflightResults(results preflighttypes.PreflightResults) { + w := NewTabWriter() + defer w.Flush() + + if len(results.Errors) > 0 { + fmt.Fprintf(w, "\n") + for _, err := range results.Errors { + fmtColumns := " - %s\n" + fmt.Fprintf(w, fmtColumns, err.Error) + } + fmt.Fprintf(w, "\n") + } + + if len(results.Results) > 0 { + fmt.Fprintf(w, "\n") + fmtColumns := "%s\t%s\t%s\n" + fmt.Fprintf(w, fmtColumns, "STATE", "TITLE", "MESSAGE") + for _, result := range results.Results { + fmt.Fprintf(w, fmtColumns, strings.ToUpper(preflight.GetPreflightCheckState(result)), result.Title, result.Message) + } + fmt.Fprintf(w, "\n") + } +}