Skip to content

Commit

Permalink
kube driver: improve flag validation
Browse files Browse the repository at this point in the history
  • Loading branch information
Roy Razon committed Jan 30, 2024
1 parent d4f746c commit 1f29630
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 6 deletions.
23 changes: 21 additions & 2 deletions packages/driver-kube-pod/src/driver/client/labels.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, it, expect } from '@jest/globals'
import { describe, it, expect, test } from '@jest/globals'
import { repeat } from 'lodash-es'
import { sanitizeLabel, sanitizeLabels } from './labels.js'
import { isValidRfc1123LabelName, sanitizeLabel, sanitizeLabels } from './labels.js'

describe('labels', () => {
describe('sanitizeLabel', () => {
Expand Down Expand Up @@ -44,4 +44,23 @@ describe('labels', () => {
})
})
})

describe('isValidRfc1123LabelName', () => {
test('invalid chars', () => {
expect(isValidRfc1123LabelName('A')).toBe(false)
expect(isValidRfc1123LabelName('a@')).toBe(false)
expect(isValidRfc1123LabelName('-a')).toBe(false)
})

test('invalid length', () => {
expect(isValidRfc1123LabelName('')).toBe(false)
expect(isValidRfc1123LabelName('a'.repeat(64))).toBe(false)
})

test('valid', () => {
expect(isValidRfc1123LabelName('abc-123')).toBe(true)
expect(isValidRfc1123LabelName('123-abc')).toBe(true)
expect(isValidRfc1123LabelName('a'.repeat(63))).toBe(true)
})
})
})
2 changes: 2 additions & 0 deletions packages/driver-kube-pod/src/driver/client/labels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ export const sanitizeLabel = (s: string) => truncateWithHash(
)

export const sanitizeLabels = <T extends Record<string, string>>(labels: T) => mapValues(labels, sanitizeLabel) as T

export const isValidRfc1123LabelName = (s: string) => s.length <= MAX_LABEL_LENGTH && /^[a-z0-9]([-a-z0-9]*[a-z0-9])?$/.test(s)
13 changes: 11 additions & 2 deletions packages/driver-kube-pod/src/driver/creation-driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import * as k8s from '@kubernetes/client-node'
import { Flags, Interfaces } from '@oclif/core'
import { Logger, MachineCreationDriver, MachineCreationDriverFactory, telemetryEmitter } from '@preevy/core'
import { pick } from 'lodash-es'
import { CLIError } from '@oclif/core/lib/errors/index.js'
import { inspect } from 'util'
import { DeploymentMachine, ResourceType, StatefulSetMachine, k8sObjectToMachine } from './common.js'
import { clientFromConfiguration, listMachines, machineConnection, flags as machineDriverFlags } from './driver.js'
import { clientFromConfiguration, listMachines, machineConnection, flags as machineDriverFlags, parseRfc1123Flag } from './driver.js'
import { Client, CreationClient, kubeCreationClient, loadKubeConfig } from './client/index.js'
import { DEFAULT_TEMPLATE, packageJson } from '../static.js'

Expand All @@ -23,12 +25,19 @@ export const flags = {
'storage-class': Flags.string({
description: 'Storage class to use for Pod data volume',
required: false,
parse: parseRfc1123Flag,
}),
'storage-size': Flags.custom<number>({
description: 'Size of Pod data volume in GiB',
required: false,
default: 5,
parse: async v => Number(v),
parse: async v => {
const num = Number(v)
if (Number.isNaN(num) || num <= 0) {
throw new CLIError(`Expected a positive number but received: ${inspect(v)}`)
}
return num
},
})(),
} as const

Expand Down
17 changes: 15 additions & 2 deletions packages/driver-kube-pod/src/driver/driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ import { asyncConcat, asyncMap } from 'iter-tools-es'
import { AddressInfo } from 'net'
import { Readable, Writable } from 'stream'
import { orderedOutput } from '@preevy/common'
import { CLIError } from '@oclif/core/lib/errors/index.js'
import { inspect } from 'util'
import { StatefulSetMachine, k8sObjectToMachine, DeploymentMachine } from './common.js'
import { Client, extractName, loadKubeConfig, kubeClient as createClient } from './client/index.js'
import { isValidRfc1123LabelName } from './client/labels.js'

export type DriverContext = {
log: Logger
Expand Down Expand Up @@ -137,12 +140,22 @@ const machineDriver = (
},
})

export const parseRfc1123Flag = async (v: unknown) => {
if (v !== undefined && (typeof v !== 'string' || !isValidRfc1123LabelName(v))) {
throw new CLIError(`Expected a valid lowercase RFC 1123 subdomain name but received: ${inspect(v)}`, {
ref: 'https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names',
})
}
return v
}

export const flags = {
namespace: Flags.string({
namespace: Flags.custom<string>({
description: 'Kubernetes namespace in which resources will be provisioned (needs to exist)',
required: false,
default: 'default',
}),
parse: parseRfc1123Flag,
})(),
kubeconfig: Flags.string({
description: 'Path to kubeconfig file (will load config from defaults if not specified)',
required: false,
Expand Down

0 comments on commit 1f29630

Please sign in to comment.