Skip to content

Commit bb34dfd

Browse files
author
Craig O'Donnell
authored
ignore failing non strict preflights if skipped (#4661)
1 parent b9d8385 commit bb34dfd

File tree

19 files changed

+156
-51
lines changed

19 files changed

+156
-51
lines changed

.github/workflows/build-test.yaml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,52 @@ jobs:
912912
printf "App is installed successfully and is ready\n\n"
913913
./bin/kots get apps --namespace "$APP_SLUG"
914914
915+
# enable the failing non-strict preflight check
916+
./bin/kots set config "$APP_SLUG" enable_failing_non_strict_analyzers="1" --namespace "$APP_SLUG"
917+
918+
# download the config
919+
./bin/kots get config --namespace "$APP_SLUG" > config.yaml
920+
921+
# remove the app
922+
./bin/kots remove "$APP_SLUG" --namespace "$APP_SLUG" --undeploy
923+
924+
# install the app and skip preflights
925+
./bin/kots \
926+
install "$APP_SLUG/automated" \
927+
--license-file license.yaml \
928+
--config-values config.yaml \
929+
--no-port-forward \
930+
--namespace "$APP_SLUG" \
931+
--shared-password password \
932+
--kotsadm-registry ttl.sh \
933+
--kotsadm-namespace automated-${{ github.run_id }} \
934+
--skip-preflights \
935+
--kotsadm-tag 24h
936+
937+
if ! kubectl logs deploy/kotsadm -n "$APP_SLUG" | grep -q "preflights will not be skipped, strict preflights are set to true"; then
938+
echo "Failed to find a log line about strict preflights not being skipped in kotsadm logs"
939+
echo "kotsadm logs:"
940+
kubectl logs deploy/kotsadm -n "$APP_SLUG"
941+
exit 1
942+
fi
943+
944+
COUNTER=1
945+
while [ "$(./bin/kots get apps --namespace "$APP_SLUG" | awk 'NR>1{print $2}')" != "ready" ]; do
946+
((COUNTER += 1))
947+
if [ $COUNTER -gt 120 ]; then
948+
echo "Timed out waiting for app to be ready"
949+
./bin/kots get apps --namespace "$APP_SLUG"
950+
echo "kotsadm logs:"
951+
kubectl logs deploy/kotsadm --tail=100 -n "$APP_SLUG"
952+
exit 1
953+
fi
954+
sleep 1
955+
done
956+
957+
printf "App is installed successfully and is ready\n\n"
958+
./bin/kots get apps --namespace "$APP_SLUG"
959+
960+
915961
- name: Generate support bundle on failure
916962
if: failure()
917963
uses: ./.github/actions/generate-support-bundle

cmd/kots/cli/install.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -937,7 +937,7 @@ func ValidatePreflightStatus(deployOptions kotsadmtypes.DeployOptions, authSlug
937937
continue
938938
}
939939

940-
resultsAvailable, err := checkPreflightResults(response)
940+
resultsAvailable, err := checkPreflightResults(response, deployOptions.SkipPreflights)
941941
if err != nil {
942942
return err
943943
}
@@ -1011,7 +1011,7 @@ func (e preflightError) Error() string {
10111011

10121012
func (e preflightError) Unwrap() error { return fmt.Errorf(e.Msg) }
10131013

1014-
func checkPreflightResults(response *handlers.GetPreflightResultResponse) (bool, error) {
1014+
func checkPreflightResults(response *handlers.GetPreflightResultResponse, skipPreflights bool) (bool, error) {
10151015
if response.PreflightResult.Result == "" {
10161016
return false, nil
10171017
}
@@ -1042,6 +1042,10 @@ func checkPreflightResults(response *handlers.GetPreflightResultResponse) (bool,
10421042

10431043
var isWarn, isFail bool
10441044
for _, result := range results.Results {
1045+
if skipPreflights && !result.Strict {
1046+
// if we're skipping preflights, we should only check the strict preflight results
1047+
continue
1048+
}
10451049
if result.IsWarn {
10461050
isWarn = true
10471051
}

cmd/kots/cli/install_test.go

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ var _ = Describe("Install", func() {
5757
License: validLicense,
5858
}
5959

60-
inProgressPreflightResponse, err := createPreflightResponse(false, false, true, false)
60+
inProgressPreflightResponse, err := createPreflightResponse(false, false, false, true, false)
6161
Expect(err).ToNot(HaveOccurred())
6262

6363
server.AppendHandlers(
@@ -155,10 +155,10 @@ var _ = Describe("Install", func() {
155155
}
156156
server.AllowUnhandledRequests = false
157157

158-
pendingResults, err := createPreflightResponse(false, false, false, true)
158+
pendingResults, err := createPreflightResponse(false, false, false, false, true)
159159
Expect(err).ToNot(HaveOccurred())
160160

161-
completedPreflightResponse, err := createPreflightResponse(false, false, false, false)
161+
completedPreflightResponse, err := createPreflightResponse(false, false, false, false, false)
162162
Expect(err).ToNot(HaveOccurred())
163163

164164
server.AppendHandlers(
@@ -193,10 +193,10 @@ var _ = Describe("Install", func() {
193193
}
194194
server.AllowUnhandledRequests = false
195195

196-
inProgressPreflightResponse, err := createPreflightResponse(false, false, true, false)
196+
inProgressPreflightResponse, err := createPreflightResponse(false, false, false, true, false)
197197
Expect(err).ToNot(HaveOccurred())
198198

199-
completedPreflightResponse, err := createPreflightResponse(false, false, false, false)
199+
completedPreflightResponse, err := createPreflightResponse(false, false, false, false, false)
200200
Expect(err).ToNot(HaveOccurred())
201201

202202
server.AppendHandlers(
@@ -267,8 +267,8 @@ var _ = Describe("Install", func() {
267267
Expect(err.Error()).To(ContainSubstring("failed to unmarshal upload preflight results"))
268268
})
269269

270-
DescribeTable("warning and failure preflight states", func(isFail bool, isWarn bool, expectedErr string) {
271-
preflightResponse, err := createPreflightResponse(isFail, isWarn, false, false)
270+
DescribeTable("warning and failure preflight states when not skipping preflights", func(isFail bool, isWarn bool, expectedErr string) {
271+
preflightResponse, err := createPreflightResponse(isFail, isWarn, false, false, false)
272272
Expect(err).ToNot(HaveOccurred())
273273

274274
server.AppendHandlers(
@@ -291,8 +291,29 @@ var _ = Describe("Install", func() {
291291
Entry("failures only", true, false, "There are preflight check failures for the application"),
292292
)
293293

294+
It("does not return an error if there are no warnings and failures for strict preflights when skipping preflights", func() {
295+
validPreflightResponse, err := createPreflightResponse(true, true, true, false, false)
296+
Expect(err).ToNot(HaveOccurred())
297+
298+
server.AppendHandlers(
299+
ghttp.CombineHandlers(
300+
ghttp.VerifyRequest("GET", fmt.Sprintf("/app/%s/preflight/result", appSlug)),
301+
ghttp.VerifyHeader(http.Header{
302+
"Authorization": []string{authSlug},
303+
"Content-Type": []string{"application/json"},
304+
}),
305+
ghttp.RespondWith(http.StatusOK, validPreflightResponse),
306+
),
307+
)
308+
309+
deployOptions := validDeployOptions
310+
deployOptions.SkipPreflights = true
311+
err = ValidatePreflightStatus(deployOptions, authSlug, server.URL())
312+
Expect(err).ToNot(HaveOccurred())
313+
})
314+
294315
It("does not return an error if there are no warnings and failures", func() {
295-
validPreflightResponse, err := createPreflightResponse(false, false, false, false)
316+
validPreflightResponse, err := createPreflightResponse(false, false, false, false, false)
296317
Expect(err).ToNot(HaveOccurred())
297318

298319
server.AppendHandlers(
@@ -514,7 +535,7 @@ var _ = Describe("Install", func() {
514535
})
515536
})
516537

517-
func createPreflightResponse(isFail bool, isWarn bool, pendingCompletion bool, pendingResults bool) ([]byte, error) {
538+
func createPreflightResponse(isFail bool, isWarn bool, hasPassingStrict bool, pendingCompletion bool, pendingResults bool) ([]byte, error) {
518539
var preflightProgress = ""
519540
if pendingCompletion {
520541
collectProgress := preflight.CollectProgress{
@@ -535,8 +556,15 @@ func createPreflightResponse(isFail bool, isWarn bool, pendingCompletion bool, p
535556

536557
var uploadPreflightResults = ""
537558
if !pendingResults {
559+
results := []*preflight.UploadPreflightResult{uploadPreflightResult}
560+
if hasPassingStrict {
561+
results = append(results, &preflight.UploadPreflightResult{
562+
Strict: true,
563+
IsPass: true,
564+
})
565+
}
538566
uploadPreflightResultsBytes, err := json.Marshal(preflight.UploadPreflightResults{
539-
Results: []*preflight.UploadPreflightResult{uploadPreflightResult},
567+
Results: results,
540568
Errors: nil,
541569
})
542570
if err != nil {

pkg/airgap/airgap.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ func CreateAppFromAirgap(opts CreateAirgapAppOpts) (finalError error) {
325325
}
326326

327327
if !opts.SkipPreflights || hasStrictPreflights {
328-
if err := preflight.Run(opts.PendingApp.ID, opts.PendingApp.Slug, newSequence, true, tmpRoot); err != nil {
328+
if err := preflight.Run(opts.PendingApp.ID, opts.PendingApp.Slug, newSequence, true, opts.SkipPreflights, tmpRoot); err != nil {
329329
return errors.Wrap(err, "failed to start preflights")
330330
}
331331
}

pkg/airgap/update.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ func UpdateAppFromPath(a *apptypes.App, airgapRoot string, airgapBundlePath stri
212212
}
213213

214214
if !skipPreflights || hasStrictPreflights {
215-
if err := preflight.Run(a.ID, a.Slug, newSequence, true, archiveDir); err != nil {
215+
if err := preflight.Run(a.ID, a.Slug, newSequence, true, skipPreflights, archiveDir); err != nil {
216216
return errors.Wrap(err, "failed to start preflights")
217217
}
218218
}

pkg/handlers/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,7 @@ func updateAppConfig(updateApp *apptypes.App, sequence int64, configGroups []kot
743743
}
744744

745745
if !skipPreflights || hasStrictPreflights {
746-
if err := preflight.Run(updateApp.ID, updateApp.Slug, int64(sequence), updateApp.IsAirgap, archiveDir); err != nil {
746+
if err := preflight.Run(updateApp.ID, updateApp.Slug, int64(sequence), updateApp.IsAirgap, skipPreflights, archiveDir); err != nil {
747747
updateAppConfigResponse.Error = errors.Cause(err).Error()
748748
return updateAppConfigResponse, err
749749
}

pkg/handlers/embedded_cluster_confirm_cluster_management.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func (h *Handler) ConfirmEmbeddedClusterManagement(w http.ResponseWriter, r *htt
8686
downstreamVersionStatus = storetypes.VersionPendingConfig
8787
} else if kotsKinds.HasPreflights() {
8888
downstreamVersionStatus = storetypes.VersionPendingPreflight
89-
if err := preflight.Run(app.ID, app.Slug, pendingVersion.Sequence, false, archiveDir); err != nil {
89+
if err := preflight.Run(app.ID, app.Slug, pendingVersion.Sequence, false, false, archiveDir); err != nil {
9090
logger.Error(errors.Wrap(err, "failed to start preflights"))
9191
w.WriteHeader(http.StatusInternalServerError)
9292
return

pkg/handlers/identity.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ func (h *Handler) ConfigureAppIdentityService(w http.ResponseWriter, r *http.Req
477477
return
478478
}
479479

480-
if err := preflight.Run(a.ID, a.Slug, newSequence, a.IsAirgap, archiveDir); err != nil {
480+
if err := preflight.Run(a.ID, a.Slug, newSequence, a.IsAirgap, false, archiveDir); err != nil {
481481
err = errors.Wrap(err, "failed to run preflights")
482482
logger.Error(err)
483483
w.WriteHeader(http.StatusInternalServerError)

pkg/handlers/preflight.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ func (h *Handler) IgnorePreflightRBACErrors(w http.ResponseWriter, r *http.Reque
157157
removeArchiveDir = false
158158
go func() {
159159
defer os.RemoveAll(archiveDir)
160-
if err := preflight.Run(foundApp.ID, foundApp.Slug, int64(sequence), foundApp.IsAirgap, archiveDir); err != nil {
160+
if err := preflight.Run(foundApp.ID, foundApp.Slug, int64(sequence), foundApp.IsAirgap, false, archiveDir); err != nil {
161161
logger.Error(errors.Wrap(err, "failed to run preflights"))
162162
return
163163
}
@@ -224,7 +224,7 @@ func (h *Handler) StartPreflightChecks(w http.ResponseWriter, r *http.Request) {
224224
removeArchiveDir = false
225225
go func() {
226226
defer os.RemoveAll(archiveDir)
227-
if err := preflight.Run(foundApp.ID, foundApp.Slug, int64(sequence), foundApp.IsAirgap, archiveDir); err != nil {
227+
if err := preflight.Run(foundApp.ID, foundApp.Slug, int64(sequence), foundApp.IsAirgap, false, archiveDir); err != nil {
228228
logger.Error(errors.Wrap(err, "failed to run preflights"))
229229
return
230230
}

pkg/handlers/registry.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ func (h *Handler) UpdateAppRegistry(w http.ResponseWriter, r *http.Request) {
269269
return
270270
}
271271

272-
if err := preflight.Run(foundApp.ID, foundApp.Slug, newSequence, foundApp.IsAirgap, appDir); err != nil {
272+
if err := preflight.Run(foundApp.ID, foundApp.Slug, newSequence, foundApp.IsAirgap, false, appDir); err != nil {
273273
logger.Error(errors.Wrap(err, "failed to run preflights"))
274274
return
275275
}

pkg/handlers/upload.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ func (h *Handler) UploadExistingApp(w http.ResponseWriter, r *http.Request) {
209209
}
210210

211211
if !uploadExistingAppRequest.SkipPreflights || hasStrictPreflights {
212-
if err := preflight.Run(a.ID, a.Slug, newSequence, a.IsAirgap, archiveDir); err != nil {
212+
if err := preflight.Run(a.ID, a.Slug, newSequence, a.IsAirgap, uploadExistingAppRequest.SkipPreflights, archiveDir); err != nil {
213213
uploadResponse.Error = util.StrPointer("failed to get run preflights")
214214
logger.Error(errors.Wrap(err, *uploadResponse.Error))
215215
JSON(w, http.StatusInternalServerError, uploadResponse)

pkg/kotsadmlicense/license.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ func Sync(a *apptypes.App, licenseString string, failOnVersionCreate bool) (*kot
8989
return nil, false, errors.Wrap(err, "failed to update license")
9090
}
9191

92-
if err := preflight.Run(a.ID, a.Slug, newSequence, a.IsAirgap, archiveDir); err != nil {
92+
if err := preflight.Run(a.ID, a.Slug, newSequence, a.IsAirgap, false, archiveDir); err != nil {
9393
return nil, false, errors.Wrap(err, "failed to run preflights")
9494
}
9595
synced = true
@@ -195,7 +195,7 @@ func Change(a *apptypes.App, newLicenseString string) (*kotsv1beta1.License, err
195195
return nil, errors.Wrap(err, "failed to update license")
196196
}
197197

198-
if err := preflight.Run(a.ID, a.Slug, newSequence, a.IsAirgap, archiveDir); err != nil {
198+
if err := preflight.Run(a.ID, a.Slug, newSequence, a.IsAirgap, false, archiveDir); err != nil {
199199
return nil, errors.Wrap(err, "failed to run preflights")
200200
}
201201

pkg/kotsadmupstream/upstream.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ func DownloadUpdate(appID string, update types.Update, skipPreflights bool, skip
276276
}
277277

278278
if !skipPreflights || hasStrictPreflights {
279-
if err := preflight.Run(appID, a.Slug, *finalSequence, a.IsAirgap, archiveDir); err != nil {
279+
if err := preflight.Run(appID, a.Slug, *finalSequence, a.IsAirgap, skipPreflights, archiveDir); err != nil {
280280
finalError = errors.Wrap(err, "failed to run preflights")
281281
return
282282
}

pkg/online/online.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ func CreateAppFromOnline(opts CreateOnlineAppOpts) (_ *kotsutil.KotsKinds, final
250250
}
251251

252252
if !opts.SkipPreflights || hasStrictPreflights {
253-
if err := preflight.Run(opts.PendingApp.ID, opts.PendingApp.Slug, newSequence, false, tmpRoot); err != nil {
253+
if err := preflight.Run(opts.PendingApp.ID, opts.PendingApp.Slug, newSequence, false, opts.SkipPreflights, tmpRoot); err != nil {
254254
return nil, errors.Wrap(err, "failed to start preflights")
255255
}
256256
}

pkg/preflight/preflight.go

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const (
4545
SpecDataKey = "preflight-spec"
4646
)
4747

48-
func Run(appID string, appSlug string, sequence int64, isAirgap bool, archiveDir string) error {
48+
func Run(appID string, appSlug string, sequence int64, isAirgap bool, ignoreNonStrict bool, archiveDir string) error {
4949
kotsKinds, err := kotsutil.LoadKotsKinds(archiveDir)
5050
if err != nil {
5151
return errors.Wrap(err, "failed to load rendered kots kinds")
@@ -176,20 +176,7 @@ func Run(appID string, appSlug string, sequence int64, isAirgap bool, archiveDir
176176
logger.Error(errors.Wrap(err, "failed to run preflight checks"))
177177
return
178178
}
179-
180-
// Log the preflight results if there are any warnings or errors
181-
// The app may not get installed so we need to see this info for debugging
182-
if GetPreflightState(uploadPreflightResults) != "pass" {
183-
logger.Warnf("Preflight checks completed with warnings or errors. The application will not get deployed")
184-
for _, result := range uploadPreflightResults.Results {
185-
if result == nil {
186-
continue
187-
}
188-
logger.Infof("preflight state=%s title=%q message=%q", GetPreflightCheckState(result), result.Title, result.Message)
189-
}
190-
} else {
191-
logger.Info("preflight checks completed")
192-
}
179+
logger.Info("preflight checks completed")
193180

194181
go func() {
195182
err := reporting.GetReporter().SubmitAppInfo(appID) // send app and preflight info when preflights finish
@@ -208,7 +195,7 @@ func Run(appID string, appSlug string, sequence int64, isAirgap bool, archiveDir
208195
return
209196
}
210197

211-
isDeployed, err := maybeDeployFirstVersion(appID, sequence, uploadPreflightResults)
198+
isDeployed, err := maybeDeployFirstVersion(appID, sequence, uploadPreflightResults, ignoreNonStrict)
212199
if err != nil {
213200
logger.Error(errors.Wrap(err, "failed to deploy first version"))
214201
return
@@ -224,7 +211,7 @@ func Run(appID string, appSlug string, sequence int64, isAirgap bool, archiveDir
224211
}()
225212
} else if status != storetypes.VersionDeployed && status != storetypes.VersionFailed {
226213
if sequence == 0 {
227-
_, err := maybeDeployFirstVersion(appID, sequence, &types.PreflightResults{})
214+
_, err := maybeDeployFirstVersion(appID, sequence, &types.PreflightResults{}, ignoreNonStrict)
228215
if err != nil {
229216
return errors.Wrap(err, "failed to deploy first version")
230217
}
@@ -260,7 +247,7 @@ func GetPreflightCheckState(p *troubleshootpreflight.UploadPreflightResult) stri
260247
}
261248

262249
// maybeDeployFirstVersion will deploy the first version if preflight checks pass
263-
func maybeDeployFirstVersion(appID string, sequence int64, preflightResults *types.PreflightResults) (bool, error) {
250+
func maybeDeployFirstVersion(appID string, sequence int64, preflightResults *types.PreflightResults, ignoreNonStrictPreflights bool) (bool, error) {
264251
if sequence != 0 {
265252
return false, nil
266253
}
@@ -275,8 +262,16 @@ func maybeDeployFirstVersion(appID string, sequence int64, preflightResults *typ
275262
return false, nil
276263
}
277264

278-
preflightState := GetPreflightState(preflightResults)
265+
preflightState := GetPreflightState(preflightResults, ignoreNonStrictPreflights)
279266
if preflightState != "pass" {
267+
// log the preflight results if there are any warnings or errors as this is useful for debugging
268+
logger.Warnf("Preflight checks completed with warnings or errors. The application will not get deployed")
269+
for _, result := range preflightResults.Results {
270+
if result == nil {
271+
continue
272+
}
273+
logger.Infof("preflight state=%s title=%q message=%q", GetPreflightCheckState(result), result.Title, result.Message)
274+
}
280275
return false, nil
281276
}
282277

@@ -297,7 +292,7 @@ func maybeDeployFirstVersion(appID string, sequence int64, preflightResults *typ
297292
// preflight checks results. If there are any errors, the state is fail.
298293
// If there are no errors and any warnings, the state is warn.
299294
// Otherwise, the state is pass.
300-
func GetPreflightState(preflightResults *types.PreflightResults) string {
295+
func GetPreflightState(preflightResults *types.PreflightResults, ignoreNonStrict bool) string {
301296
if len(preflightResults.Errors) > 0 {
302297
return "fail"
303298
}
@@ -308,6 +303,9 @@ func GetPreflightState(preflightResults *types.PreflightResults) string {
308303

309304
state := "pass"
310305
for _, result := range preflightResults.Results {
306+
if ignoreNonStrict && !result.Strict {
307+
continue
308+
}
311309
if result.IsFail {
312310
return "fail"
313311
} else if result.IsWarn {

0 commit comments

Comments
 (0)