diff --git a/docs/reference/config.md b/docs/reference/config.md index 49255101d1..034c02c6c5 100644 --- a/docs/reference/config.md +++ b/docs/reference/config.md @@ -506,8 +506,8 @@ module: # Optional. dependencies: # Valid RFC1035/RFC1123 (DNS) label (may contain lowercase letters, numbers and dashes, - # must start with a letter, and cannot end with a dash) and additionally cannot contain - # consecutive dashes, or be longer than 63 characters. + # must start with a letter, and cannot end with a dash) and must not be longer than 63 + # characters. # # Optional. - @@ -854,12 +854,16 @@ module: # Optional. dependencies: # Valid RFC1035/RFC1123 (DNS) label (may contain lowercase letters, numbers and dashes, must - # start with a letter, and cannot end with a dash) and additionally cannot contain consecutive - # dashes, or be longer than 63 characters. + # start with a letter, and cannot end with a dash) and must not be longer than 63 characters. # # Optional. - + # Optionally override the release name used when installing (defaults to the module name). + # + # Optional. + releaseName: + # The repository URL to fetch the chart from. # # Optional. diff --git a/garden-service/src/config/common.ts b/garden-service/src/config/common.ts index 39a377e4e2..d2b0dcf5f5 100644 --- a/garden-service/src/config/common.ts +++ b/garden-service/src/config/common.ts @@ -30,16 +30,16 @@ export const joiPrimitive = () => Joi.alternatives().try(Joi.number(), Joi.strin .description("Number, string or boolean") export const absolutePathRegex = /^\/.*/ // Note: Only checks for the leading slash -export const identifierRegex = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/ -export const userIdentifierRegex = /^(?!garden)[a-z][a-z0-9]*(-[a-z0-9]+)*$/ +// from https://stackoverflow.com/a/12311250/3290965 +export const identifierRegex = /^(?![0-9]+$)(?!.*-$)(?!-)[a-z0-9-]{1,63}$/ +export const userIdentifierRegex = /^(?!garden)(?=.{1,63}$)[a-z][a-z0-9]*(-[a-z0-9]+)*$/ export const envVarRegex = /^(?!garden)[a-z_][a-z0-9_]*$/i export const joiIdentifier = () => Joi.string() .regex(identifierRegex) - .max(63) .description( "Valid RFC1035/RFC1123 (DNS) label (may contain lowercase letters, numbers and dashes, must start with a letter, " + - "and cannot end with a dash) and additionally cannot contain consecutive dashes, or be longer than 63 characters.", + "and cannot end with a dash) and must not be longer than 63 characters.", ) export const joiStringMap = (valueSchema: JoiObject) => Joi @@ -47,7 +47,6 @@ export const joiStringMap = (valueSchema: JoiObject) => Joi export const joiUserIdentifier = () => Joi.string() .regex(userIdentifierRegex) - .max(63) .description( "Valid RFC1035/RFC1123 (DNS) label (may contain lowercase letters, numbers and dashes, must start with a letter, " + "and cannot end with a dash), cannot contain consecutive dashes or start with `garden`, " + diff --git a/garden-service/test/src/types/common.ts b/garden-service/test/src/config/common.ts similarity index 59% rename from garden-service/test/src/types/common.ts rename to garden-service/test/src/config/common.ts index a9651f6b01..fedaf71166 100644 --- a/garden-service/test/src/types/common.ts +++ b/garden-service/test/src/config/common.ts @@ -1,7 +1,7 @@ import { expect } from "chai" import * as Joi from "joi" const stripAnsi = require("strip-ansi") -import { identifierRegex, validate, envVarRegex } from "../../../src/config/common" +import { identifierRegex, validate, envVarRegex, userIdentifierRegex } from "../../../src/config/common" import { expectError } from "../../helpers" describe("envVarRegex", () => { @@ -38,33 +38,73 @@ describe("envVarRegex", () => { }) }) +const validIdentifiers = { + "myname": "a valid identifier", + "my-name": "a valid identifier with a dash", + "my9-9name": "numbers in the middle of a string", + "o12345670123456701234567012345670123456701234567012345670123456": "a 63 char identifier", + "a": "a single char identifier", +} + +const invalidIdentifiers = { + "01010": "string with only numbers", + "-abc": "starting with a dash", + "abc-": "ending with a dash", + "": "an empty string", + "o123456701234567012345670123456701234567012345670123456701234567": "a 64 char identifier", + "UPPER": "an uppercase string", + "upPer": "a partially uppercase string", +} + describe("identifierRegex", () => { - it("should accept a valid identifier", () => { - expect(identifierRegex.test("my-name")).to.be.true - }) + for (const [value, description] of Object.entries(validIdentifiers)) { + it("should allow " + description, () => { + expect(identifierRegex.test(value)).to.be.true + }) + } + + for (const [value, description] of Object.entries(invalidIdentifiers)) { + it("should disallow " + description, () => { + expect(identifierRegex.test(value)).to.be.false + }) + } - it("should allow numbers in middle of the string", () => { - expect(identifierRegex.test("my9-9name")).to.be.true + it("should allow consecutive dashes", () => { + expect(identifierRegex.test("my--name")).to.be.true }) - it("should disallow ending with a dash", () => { - expect(identifierRegex.test("my-name-")).to.be.false + it("should allow starting with a number", () => { + expect(identifierRegex.test("9name")).to.be.true }) - it("should disallow uppercase characters", () => { - expect(identifierRegex.test("myName")).to.be.false + it("should allow strings starting with 'garden'", () => { + expect(identifierRegex.test("garden-party")).to.be.true }) +}) + +describe("userIdentifierRegex", () => { + for (const [value, description] of Object.entries(validIdentifiers)) { + it("should allow " + description, () => { + expect(userIdentifierRegex.test(value)).to.be.true + }) + } + + for (const [value, description] of Object.entries(invalidIdentifiers)) { + it("should disallow " + description, () => { + expect(userIdentifierRegex.test(value)).to.be.false + }) + } - it("should disallow starting with a dash", () => { - expect(identifierRegex.test("-my-name")).to.be.false + it("should allow consecutive dashes", () => { + expect(userIdentifierRegex.test("my--name")).to.be.false }) it("should disallow starting with a number", () => { - expect(identifierRegex.test("9name")).to.be.false + expect(userIdentifierRegex.test("9name")).to.be.false }) - it("should disallow consecutive dashes", () => { - expect(identifierRegex.test("my--name")).to.be.false + it("should allow strings starting with 'garden'", () => { + expect(userIdentifierRegex.test("garden-party")).to.be.false }) })