feat(core): add experimantal cli arg to validate manifest by olblak · Pull Request #9721 · updatecli/updatecli · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 7 additions & 9 deletions _typos.toml
2 changes: 2 additions & 0 deletions cmd/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ var (
e.Options.Pipeline.Target.CleanGitBranches = applyCleanGitBranches
e.Options.Pipeline.Target.ExistingOnly = applyExistingOnly
e.Options.Pipeline.DisableChangelog = disableChangelog
e.Options.Config.ValidateSchema = validateSchema

logrus.Warningln("Deprecated command, please instead use `updatecli pipeline apply`")

Expand Down Expand Up @@ -77,6 +78,7 @@ func init() {
applyCmd.Flags().StringArrayVar(&labels, "labels", []string{}, "Filter pipelines by their labels, accepted as a comma separated list (key:value)")

addDisableChangelogFlag(applyCmd, &disableChangelog)
addValidateSchemaFlag(applyCmd, &validateSchema)
addExportReportToYAMLFlag(applyCmd, &exportReportToYAML)
addDisableUdashReportFlag(applyCmd, &disableUdashReport)
}
3 changes: 3 additions & 0 deletions cmd/compose_apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ var (
e.Options.Pipeline.Target.CleanGitBranches = composeApplyCleanGitBranches
e.Options.Pipeline.Target.ExistingOnly = composeApplyExistingOnly
e.Options.Pipeline.DisableChangelog = disableChangelog
e.Options.Config.ValidateSchema = validateSchema
compose.ValidateSchema = validateSchema

err = run("compose/apply")
if err != nil {
Expand All @@ -79,6 +81,7 @@ func init() {
composeApplyCmd.Flags().StringArrayVar(&composeApplyIgnoredPolicyIDs, "ignored-policy-ids", []string{}, "Filter policies to ignore by their policy IDs, accepted as a comma separated list")

addDisableChangelogFlag(composeApplyCmd, &disableChangelog)
addValidateSchemaFlag(composeApplyCmd, &validateSchema)
addExportReportToYAMLFlag(composeApplyCmd, &exportReportToYAML)
addDisableUdashReportFlag(composeApplyCmd, &disableUdashReport)

Expand Down
3 changes: 3 additions & 0 deletions cmd/compose_diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ var (
e.Options.Pipeline.Target.Clean = composeCmdClean
e.Options.Pipeline.Target.DryRun = true
e.Options.Pipeline.DisableChangelog = disableChangelog
e.Options.Config.ValidateSchema = validateSchema
compose.ValidateSchema = validateSchema

err = run("compose/diff")
if err != nil {
Expand All @@ -68,6 +70,7 @@ func init() {
composeDiffCmd.Flags().StringArrayVar(&composeDiffIgnoredPolicyIDs, "ignored-policy-ids", []string{}, "Filter policies to ignore by their policy IDs, accepted as a comma separated list")

addDisableChangelogFlag(composeDiffCmd, &disableChangelog)
addValidateSchemaFlag(composeDiffCmd, &validateSchema)
addExportReportToYAMLFlag(composeDiffCmd, &exportReportToYAML)
addDisableUdashReportFlag(composeDiffCmd, &disableUdashReport)

Expand Down
2 changes: 2 additions & 0 deletions cmd/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ var (
e.Options.Pipeline.Target.Clean = diffClean
e.Options.Pipeline.Target.DryRun = true
e.Options.Pipeline.DisableChangelog = disableChangelog
e.Options.Config.ValidateSchema = validateSchema

logrus.Warningln("Deprecated command, please instead use `updatecli pipeline diff`")

Expand All @@ -60,6 +61,7 @@ func init() {
diffCmd.Flags().StringArrayVar(&labels, "labels", []string{}, "Filter pipelines to apply by their labels, accepted as a comma separated list (key:value)")

addDisableChangelogFlag(diffCmd, &disableChangelog)
addValidateSchemaFlag(diffCmd, &validateSchema)
addExportReportToYAMLFlag(diffCmd, &exportReportToYAML)
addDisableUdashReportFlag(diffCmd, &disableUdashReport)
}
2 changes: 2 additions & 0 deletions cmd/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ const DisableChangelogEnvVar = "UPDATECLI_DISABLE_CHANGELOG"

const DisableVersionCheckEnvVar = "UPDATECLI_DISABLE_VERSION_CHECK"

const ValidateSchemaEnvVar = "UPDATECLI_VALIDATE_SCHEMA"

// getEnvBoolOrDefault reads a boolean environment variable.
// It returns defaultValue when the variable is unset or invalid.
func getEnvBoolOrDefault(envVar string, defaultValue bool) bool {
Expand Down
12 changes: 12 additions & 0 deletions cmd/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ func addDisableChangelogFlag(cmd *cobra.Command, dest *bool) {
)
}

// addValidateSchemaFlag registers the shared --validate-schema flag on the provided
// command, using the value from UPDATECLI_VALIDATE_SCHEMA as the default when the flag is
// not explicitly passed.
func addValidateSchemaFlag(cmd *cobra.Command, dest *bool) {
cmd.Flags().BoolVar(
dest,
"validate-schema",
getEnvBoolOrDefault(ValidateSchemaEnvVar, false),
"Report manifest keys not matching the Updatecli schema as warnings (env: "+ValidateSchemaEnvVar+")",
)
}

// addExportReportToYAMLFlag registers the shared --export-report-to-yaml flag on
// the provided command. Exporting is opt-in as it writes files to disk.
func addExportReportToYAMLFlag(cmd *cobra.Command, dest *bool) {
Expand Down
4 changes: 4 additions & 0 deletions cmd/flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func TestAddDisableChangelogFlagRegistration(t *testing.T) {
flag := cmd.Flags().Lookup("disable-changelog")
if flag == nil {
t.Fatal("flag not registered")
return
}

// Check flag has help text
Expand Down Expand Up @@ -63,6 +64,7 @@ func TestAddExportReportToYAMLFlagRegistration(t *testing.T) {
flag := cmd.Flags().Lookup("export-report-to-yaml")
if flag == nil {
t.Fatal("flag not registered")
return
}

// Check flag has help text
Expand Down Expand Up @@ -92,6 +94,7 @@ func TestAddDisableUdashReportFlagRegistration(t *testing.T) {
flag := cmd.Flags().Lookup("disable-udash-report")
if flag == nil {
t.Fatal("flag not registered")
return
}

// Check flag has help text
Expand Down Expand Up @@ -151,6 +154,7 @@ func TestAddDisableChangelogFlagUsesEnvDefault(t *testing.T) {
flag := cmd.Flags().Lookup("disable-changelog")
if flag == nil {
t.Fatal("flag not registered")
return
}

if flag.DefValue != tt.expectedDef {
Expand Down
61 changes: 61 additions & 0 deletions cmd/manifest_validate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package cmd

import (
"os"

"github.com/sirupsen/logrus"

"github.com/spf13/cobra"

"github.com/updatecli/updatecli/pkg/core/cmdoptions"
"github.com/updatecli/updatecli/pkg/core/engine/manifest"
)

var (
manifestValidateDisableTemplating bool
manifestValidateStrict bool

manifestValidateCmd = &cobra.Command{
Use: "validate",
Short: "**Experimental** validate manifest(s) against the Updatecli schema",
Long: `**Experimental** validate reports the manifest keys that do not match the
Updatecli schema, such as a misspelled one, which Updatecli would otherwise silently
ignore.

A deprecated keyword, or a key Updatecli cannot check reliably, is reported as a warning
and does not fail the command unless '--strict' is specified.`,
Run: func(cmd *cobra.Command, args []string) {
// TODO: To be removed once not experimental anymore
if !cmdoptions.Experimental {
logrus.Warningf("The 'manifest validate' command is experimental, please use the '--experimental' flag to enable it")
os.Exit(1)
}

e.Options.Manifests = append(e.Options.Manifests, manifest.Manifest{
Manifests: manifestFiles,
Values: valuesFiles,
ValuesInline: valuesInline,
Secrets: secretsFiles,
})

e.Options.Config.DisableTemplating = manifestValidateDisableTemplating

err := run("manifest/validate")
if err != nil {
logrus.Errorf("command failed: %s", err)
os.Exit(1)
}
},
}
)

func init() {
manifestValidateCmd.Flags().StringArrayVarP(&manifestFiles, "config", "c", []string{}, "Sets config file or directory. By default, Updatecli looks for a file named 'updatecli.yaml' or a directory named 'updatecli.d'")
manifestValidateCmd.Flags().StringArrayVarP(&valuesFiles, "values", "v", []string{}, "Sets values file uses for templating")
manifestValidateCmd.Flags().StringArrayVarP(&valuesInline, "values-inline", "i", []string{}, "Sets inline values uses for templating, accepted valid json/yaml string")
manifestValidateCmd.Flags().StringArrayVar(&secretsFiles, "secrets", []string{}, "Sets secrets file uses for templating")
manifestValidateCmd.Flags().BoolVar(&manifestValidateDisableTemplating, "disable-templating", false, "Disable manifest templating")
manifestValidateCmd.Flags().BoolVar(&manifestValidateStrict, "strict", false, "Report warnings as errors")

manifestCmd.AddCommand(manifestValidateCmd)
}
2 changes: 2 additions & 0 deletions cmd/pipeline_apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ var (
e.Options.Pipeline.Target.CleanGitBranches = applyCleanGitBranches
e.Options.Pipeline.Target.ExistingOnly = applyExistingOnly
e.Options.Pipeline.DisableChangelog = disableChangelog
e.Options.Config.ValidateSchema = validateSchema

err = run("pipeline/apply")
if err != nil {
Expand All @@ -69,6 +70,7 @@ func init() {
pipelineApplyCmd.Flags().StringArrayVar(&labels, "labels", []string{}, "Filter pipelines to apply by their labels, accepted as a comma separated list (key:value)")

addDisableChangelogFlag(pipelineApplyCmd, &disableChangelog)
addValidateSchemaFlag(pipelineApplyCmd, &validateSchema)
addExportReportToYAMLFlag(pipelineApplyCmd, &exportReportToYAML)
addDisableUdashReportFlag(pipelineApplyCmd, &disableUdashReport)

Expand Down
2 changes: 2 additions & 0 deletions cmd/pipeline_diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ var (
e.Options.Pipeline.Target.Clean = diffClean
e.Options.Pipeline.Target.DryRun = true
e.Options.Pipeline.DisableChangelog = disableChangelog
e.Options.Config.ValidateSchema = validateSchema

err = run("pipeline/diff")
if err != nil {
Expand All @@ -56,6 +57,7 @@ func init() {
pipelineDiffCmd.Flags().StringArrayVar(&labels, "labels", []string{}, "Filter pipelines to apply by their labels, accepted as a comma separated list (key:value)")

addDisableChangelogFlag(pipelineDiffCmd, &disableChangelog)
addValidateSchemaFlag(pipelineDiffCmd, &validateSchema)
addExportReportToYAMLFlag(pipelineDiffCmd, &exportReportToYAML)
addDisableUdashReportFlag(pipelineDiffCmd, &disableUdashReport)

Expand Down
8 changes: 8 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ var (
experimental bool
disableTLS bool
disableChangelog bool
validateSchema bool
uniqueTmpDir bool
disableVersionCheck bool
exportReportToYAML bool
Expand Down Expand Up @@ -246,6 +247,13 @@ func run(command string) error {
return err
}

case "manifest/validate":
err := e.ValidateManifests(manifestValidateStrict)
if err != nil {
logrus.Errorf("%s %s", result.FAILURE, err)
return err
}

case "manifest/pull":
err := e.PullFromRegistry(manifestPullPolicyReference, disableTLS)
if err != nil {
Expand Down
11 changes: 11 additions & 0 deletions e2e/scripts/test_manifest_validate.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env bash

set -eux

: "${VENOM_VAR_binpath:? Please set VENOM_VAR_binpath to updatecli binary dirname}"
: "${VENOM_VAR_rootpath:=../..}"

## In order for the Updatecli manifest to work, we must be at the root of the git repository
pushd "$VENOM_VAR_rootpath"

"$VENOM_VAR_binpath/updatecli" manifest validate --experimental --config e2e/updatecli.d/deprecated.d/
22 changes: 22 additions & 0 deletions e2e/scripts/test_manifest_validate_invalid.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bash

## This script expects 'updatecli manifest validate' to fail, so the exit code is
## inverted: the test passes when the invalid manifest is rejected.

set -ux

: "${VENOM_VAR_binpath:? Please set VENOM_VAR_binpath to updatecli binary dirname}"
: "${VENOM_VAR_rootpath:=../..}"

## In order for the Updatecli manifest to work, we must be at the root of the git repository
pushd "$VENOM_VAR_rootpath" || exit 1

"$VENOM_VAR_binpath/updatecli" manifest validate --experimental --config e2e/updatecli.d/invalid.d/

if [[ $? -eq 0 ]]; then
echo "ERROR: the invalid manifest should have been rejected"
exit 1
fi

echo "The invalid manifest was rejected as expected"
exit 0
19 changes: 19 additions & 0 deletions e2e/updatecli.d/invalid.d/typos.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
## This manifest deliberately holds keys that do not match the Updatecli schema, so that
## 'updatecli manifest validate' is checked to report them.
## It is not meant to run, only to be validated.
name: A manifest holding keys Updatecli would silently ignore
sourcs:
typo-at-the-root: {}
sources:
latest:
kind: dockerimage
spec:
image: ghcr.io/updatecli/updatecli
versionfliter:
kind: semver
targets:
update:
kind: dockerimag
sourceid: latest
spec:
file: /tmp/updatecli-e2e-invalid
25 changes: 14 additions & 11 deletions e2e/updatecli.d/success.d/dockerimage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,15 @@ sources:
spec:
image: "quay.io/calico/node"

quayio-semver-strict:
name: "Get latest calico image using strict semantic versioning"
jenkins-semver-strict:
name: "Get latest jenkins image using strict semantic versioning"
kind: dockerimage
spec:
image: "quay.io/calico/node"
strict: true

image: "ghcr.io/jenkinsci/helm-charts/jenkins"
versionfilter:
kind: semver
strict: true

conditions:
## GitHub action is not configured with DockerHub credentials
#dockerhub-private:
Expand Down Expand Up @@ -136,13 +138,15 @@ conditions:
spec:
image: "quay.io/calico/node"

quayio-semver-strict:
name: "Get latest calico image"
jenkins-semver-strict:
name: "Get latest ghcr.io/jenkinsci/jenkins image"
kind: dockerimage
sourceid: quayio-semver-strict
sourceid: jenkins-semver-strict
spec:
image: "quay.io/calico/node"
strict: true
image: "ghcr.io/jenkinsci/helm-charts/jenkins"
versionfilter:
kind: semver
strict: true

quayio-regex:
name: "Get latest calico image"
Expand All @@ -157,4 +161,3 @@ conditions:
kind: dockerimage
spec:
image: "quay.io/calico/node"

2 changes: 0 additions & 2 deletions e2e/updatecli.d/success.d/golang/gomod.yaml
Loading
Loading