Skip to content

Commit

Permalink
lint for candidate route being too long
Browse files Browse the repository at this point in the history
  • Loading branch information
Michiel Stigter committed Feb 5, 2024
1 parent aba01da commit 457858b
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 17 deletions.
22 changes: 20 additions & 2 deletions linters/cf_manifest.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package linters

import (
"fmt"
"github.com/springernature/halfpipe/cf"
"github.com/springernature/halfpipe/config"
"github.com/springernature/halfpipe/renderers/shared/secrets"
"golang.org/x/exp/slices"
"strings"

Expand All @@ -18,8 +20,8 @@ func LintCfManifest(task manifest.DeployCF, readCfManifest cf.ManifestReader) (e
return errs
}

manifest, err := readCfManifest(task.Manifest, nil, nil)
apps := manifest.Applications
cfManifest, err := readCfManifest(task.Manifest, nil, nil)
apps := cfManifest.Applications

if err != nil {
errs = append(errs, ErrFileInvalid.WithValue(err.Error()).WithFile(task.Manifest))
Expand All @@ -37,12 +39,28 @@ func LintCfManifest(task manifest.DeployCF, readCfManifest cf.ManifestReader) (e
}

errs = append(errs, lintRoutes(task, app)...)
errs = append(errs, lintCandidateAppRoute(task, cfManifest)...)
errs = append(errs, lintDockerPush(task, app)...)
errs = append(errs, lintBuildpack(app, task.Manifest)...)

return errs
}

func lintCandidateAppRoute(task manifest.DeployCF, m manifestparser.Manifest) (errs []error) {
if secrets.IsSecret(task.Space) {
return errs
}

testRouteHost := fmt.Sprintf("%s-%s-CANDIDATE", m.GetFirstApp().Name, task.Space)

if len(testRouteHost) > 64 {
errs = append(errs, ErrCFCandidateRouteTooLong.WithValue(fmt.Sprintf("%s length is %v", testRouteHost, len(testRouteHost))))
return
}

return errs
}

func lintDockerPush(task manifest.DeployCF, app manifestparser.Application) (errs []error) {
if app.Docker != nil {
if task.DeployArtifact != "" {
Expand Down
34 changes: 34 additions & 0 deletions linters/cf_manifest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,4 +212,38 @@ applications:
assert.Empty(t, errs)
})

t.Run("candidate app route is too long", func(t *testing.T) {
cfManifest := `
applications:
- name: test-a-veeeeeeeeeeeeeeeeeeeery-loooooooooooooooong-app
routes:
- route: test.com
buildpacks:
- java
`
errs := LintCfManifest(manifest.DeployCF{
Space: "with-a-very-loooong-space",
TestDomain: "",
}, cfManifestReader(cfManifest, nil))

assertContainsError(t, errs, ErrCFCandidateRouteTooLong)
})

t.Run("candidate app route linting is ignored when space is secret", func(t *testing.T) {
cfManifest := `
applications:
- name: test-a-veeeeeeeeeeeeeeeeeeeery-loooooooooooooooong-app
routes:
- route: test.com
buildpacks:
- java
`
errs := LintCfManifest(manifest.DeployCF{
Space: "((halfpipe.test))",
TestDomain: "",
}, cfManifestReader(cfManifest, nil))

assertNotContainsError(t, errs, ErrCFCandidateRouteTooLong)
})

}
27 changes: 14 additions & 13 deletions linters/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,20 @@ var (
ErrFileNotExecutable = newError("file is not executable")
ErrFileInvalid = newError("file is invalid")

ErrCFMissingRoutes = newError("cf application must have at least one route")
ErrCFMissingName = newError("cf application missing 'name'")
ErrCFRoutesAndNoRoute = newError("cf application cannot have both 'routes' and 'no-route'")
ErrCFNoRouteHealthcheck = newError("cf application with 'no-route: true' requires 'health-check-type: process'")
ErrCFRouteScheme = newError("cf application route must not start with http(s)://")
ErrCFRouteMissing = newError("cf application routes must contain sso_route")
ErrCFMultipleApps = newError("cf manifest must have exactly 1 application")
ErrCFBuildpackUnversioned = newError("buildpack specified without version so the latest will be used on each deploy")
ErrCFBuildpackMissing = newError("buildpack missing. Cloud Foundry will try to detect which system buildpack to use. Please see <https://docs.cloudfoundry.org/devguide/deploy-apps/manifest-attributes.html#buildpack>")
ErrCFBuildpackDeprecated = newError("'buildpack' is deprecated in favour of 'buildpacks'. Please see <http://docs.cloudfoundry.org/devguide/deploy-apps/manifest.html#deprecated>")
ErrCFArtifactAndDocker = newError("cannot combine 'deploy_artifact' in the halfpipe task and 'docker' in the cf manifest")
ErrCFFromArtifact = newError("this file must be saved as an artifact in a previous task")
ErrCFPrePromoteArtifact = newError("cannot have pre promote tasks with CF manifest restored from artifact")
ErrCFMissingRoutes = newError("cf application must have at least one route")
ErrCFMissingName = newError("cf application missing 'name'")
ErrCFRoutesAndNoRoute = newError("cf application cannot have both 'routes' and 'no-route'")
ErrCFNoRouteHealthcheck = newError("cf application with 'no-route: true' requires 'health-check-type: process'")
ErrCFRouteScheme = newError("cf application route must not start with http(s)://")
ErrCFRouteMissing = newError("cf application routes must contain sso_route")
ErrCFMultipleApps = newError("cf manifest must have exactly 1 application")
ErrCFBuildpackUnversioned = newError("buildpack specified without version so the latest will be used on each deploy")
ErrCFBuildpackMissing = newError("buildpack missing. Cloud Foundry will try to detect which system buildpack to use. Please see <https://docs.cloudfoundry.org/devguide/deploy-apps/manifest-attributes.html#buildpack>")
ErrCFBuildpackDeprecated = newError("'buildpack' is deprecated in favour of 'buildpacks'. Please see <http://docs.cloudfoundry.org/devguide/deploy-apps/manifest.html#deprecated>")
ErrCFArtifactAndDocker = newError("cannot combine 'deploy_artifact' in the halfpipe task and 'docker' in the cf manifest")
ErrCFFromArtifact = newError("this file must be saved as an artifact in a previous task")
ErrCFPrePromoteArtifact = newError("cannot have pre promote tasks with CF manifest restored from artifact")
ErrCFCandidateRouteTooLong = newError("cf does not allow routes of more than 64 characters")

ErrUnsupportedRegistry = newError("image must be from halfpipe registry. Please see <https://ee.public.springernature.app/rel-eng/docker-registry/>")
ErrDockerPushTag = newError("the field 'tag' is no longer used and is safe to delete")
Expand Down
4 changes: 2 additions & 2 deletions renderers/shared/secrets/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type Secret struct {
// New returns a Secret from a string in the "halfpipe" format
// "((map.key))" or "((/path/to/map key))"
func New(s string, team string) *Secret {
if !isSecret(s) {
if !IsSecret(s) {
return nil
}

Expand Down Expand Up @@ -45,7 +45,7 @@ func New(s string, team string) *Secret {
return nil
}

func isSecret(s string) bool {
func IsSecret(s string) bool {
return strings.HasPrefix(s, "((") && strings.HasSuffix(s, "))")
}

Expand Down

0 comments on commit 457858b

Please sign in to comment.