Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding timeout to the rollout status #353

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ inputs:
skip-tls-verify:
description: True if the insecure-skip-tls-verify option should be used. Input should be 'true' or 'false'.
default: false
timeout:
description: 'Timeout for the rollout status'
required: false
default: 10m

branding:
color: 'green'
Expand Down
5 changes: 3 additions & 2 deletions src/actions/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import {parseTrafficSplitMethod} from '../types/trafficSplitMethod'
export async function deploy(
kubectl: Kubectl,
manifestFilePaths: string[],
deploymentStrategy: DeploymentStrategy
deploymentStrategy: DeploymentStrategy,
timeout?: string
) {
// update manifests
const inputManifestFiles: string[] = updateManifestFiles(manifestFilePaths)
Expand Down Expand Up @@ -45,7 +46,7 @@ export async function deploy(
KubernetesConstants.DiscoveryAndLoadBalancerResource.SERVICE
])
)
await checkManifestStability(kubectl, resourceTypes)
await checkManifestStability(kubectl, resourceTypes, timeout)
core.endGroup()

// print ingresses
Expand Down
34 changes: 25 additions & 9 deletions src/actions/promote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,21 +42,26 @@ import {parseRouteStrategy, RouteStrategy} from '../types/routeStrategy'
export async function promote(
kubectl: Kubectl,
manifests: string[],
deploymentStrategy: DeploymentStrategy
deploymentStrategy: DeploymentStrategy,
timeout?: string
) {
switch (deploymentStrategy) {
case DeploymentStrategy.CANARY:
await promoteCanary(kubectl, manifests)
await promoteCanary(kubectl, manifests, timeout)
break
case DeploymentStrategy.BLUE_GREEN:
await promoteBlueGreen(kubectl, manifests)
await promoteBlueGreen(kubectl, manifests, timeout)
break
default:
throw Error('Invalid promote deployment strategy')
}
}

async function promoteCanary(kubectl: Kubectl, manifests: string[]) {
async function promoteCanary(
kubectl: Kubectl,
manifests: string[],
timeout?: string
) {
let includeServices = false

const manifestFilesForDeployment: string[] = updateManifestFiles(manifests)
Expand Down Expand Up @@ -85,7 +90,8 @@ async function promoteCanary(kubectl: Kubectl, manifests: string[]) {
promoteResult = await SMICanaryDeploymentHelper.deploySMICanary(
manifestFilesForDeployment,
kubectl,
true
true,
timeout
)

core.endGroup()
Expand All @@ -94,7 +100,8 @@ async function promoteCanary(kubectl: Kubectl, manifests: string[]) {
const stableRedirectManifests =
await SMICanaryDeploymentHelper.redirectTrafficToStableDeployment(
kubectl,
manifests
manifests,
timeout
)

filesToAnnotate = promoteResult.manifestFiles.concat(
Expand All @@ -107,7 +114,8 @@ async function promoteCanary(kubectl: Kubectl, manifests: string[]) {
promoteResult = await PodCanaryHelper.deployPodCanary(
manifestFilesForDeployment,
kubectl,
true
true,
timeout
)
filesToAnnotate = promoteResult.manifestFiles
core.endGroup()
Expand Down Expand Up @@ -139,7 +147,11 @@ async function promoteCanary(kubectl: Kubectl, manifests: string[]) {
core.endGroup()
}

async function promoteBlueGreen(kubectl: Kubectl, manifests: string[]) {
async function promoteBlueGreen(
kubectl: Kubectl,
manifests: string[],
timeout?: string
) {
// update container images and pull secrets
const inputManifestFiles: string[] = updateManifestFiles(manifests)
const manifestObjects: BlueGreenManifests =
Expand Down Expand Up @@ -173,7 +185,11 @@ async function promoteBlueGreen(kubectl: Kubectl, manifests: string[]) {
models.DiscoveryAndLoadBalancerResource.SERVICE
])
)
await KubernetesManifestUtility.checkManifestStability(kubectl, resources)
await KubernetesManifestUtility.checkManifestStability(
kubectl,
resources,
timeout
)
core.endGroup()

core.startGroup(
Expand Down
31 changes: 21 additions & 10 deletions src/actions/reject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,26 @@ import {parseRouteStrategy, RouteStrategy} from '../types/routeStrategy'
export async function reject(
kubectl: Kubectl,
manifests: string[],
deploymentStrategy: DeploymentStrategy
deploymentStrategy: DeploymentStrategy,
timeout?: string
) {
switch (deploymentStrategy) {
case DeploymentStrategy.CANARY:
await rejectCanary(kubectl, manifests)
await rejectCanary(kubectl, manifests, timeout)
break
case DeploymentStrategy.BLUE_GREEN:
await rejectBlueGreen(kubectl, manifests)
await rejectBlueGreen(kubectl, manifests, timeout)
break
default:
throw 'Invalid delete deployment strategy'
}
}

async function rejectCanary(kubectl: Kubectl, manifests: string[]) {
async function rejectCanary(
kubectl: Kubectl,
manifests: string[],
timeout?: string
) {
let includeServices = false

const trafficSplitMethod = parseTrafficSplitMethod(
Expand All @@ -44,7 +49,8 @@ async function rejectCanary(kubectl: Kubectl, manifests: string[]) {
includeServices = true
await SMICanaryDeploymentHelper.redirectTrafficToStableDeployment(
kubectl,
manifests
manifests,
timeout
)
core.endGroup()
}
Expand All @@ -53,12 +59,17 @@ async function rejectCanary(kubectl: Kubectl, manifests: string[]) {
await canaryDeploymentHelper.deleteCanaryDeployment(
kubectl,
manifests,
includeServices
includeServices,
timeout
)
core.endGroup()
}

async function rejectBlueGreen(kubectl: Kubectl, manifests: string[]) {
async function rejectBlueGreen(
kubectl: Kubectl,
manifests: string[],
timeout?: string
) {
const routeStrategy = parseRouteStrategy(
core.getInput('route-method', {required: true})
)
Expand All @@ -67,11 +78,11 @@ async function rejectBlueGreen(kubectl: Kubectl, manifests: string[]) {
const manifestObjects: BlueGreenManifests = getManifestObjects(manifests)

if (routeStrategy == RouteStrategy.INGRESS) {
await rejectBlueGreenIngress(kubectl, manifestObjects)
await rejectBlueGreenIngress(kubectl, manifestObjects, timeout)
} else if (routeStrategy == RouteStrategy.SMI) {
await rejectBlueGreenSMI(kubectl, manifestObjects)
await rejectBlueGreenSMI(kubectl, manifestObjects, timeout)
} else {
await rejectBlueGreenService(kubectl, manifestObjects)
await rejectBlueGreenService(kubectl, manifestObjects, timeout)
}
core.endGroup()
}
7 changes: 4 additions & 3 deletions src/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export async function run() {
const resourceGroup = core.getInput('resource-group') || ''
const resourceName = core.getInput('name') || ''
const skipTlsVerify = core.getBooleanInput('skip-tls-verify')
const timeout = core.getInput('timeout') || '10m'

const kubectl = isPrivateCluster
? new PrivateKubectl(
Expand All @@ -49,15 +50,15 @@ export async function run() {
// run action
switch (action) {
case Action.DEPLOY: {
await deploy(kubectl, fullManifestFilePaths, strategy)
await deploy(kubectl, fullManifestFilePaths, strategy, timeout)
break
}
case Action.PROMOTE: {
await promote(kubectl, fullManifestFilePaths, strategy)
await promote(kubectl, fullManifestFilePaths, strategy, timeout)
break
}
case Action.REJECT: {
await reject(kubectl, fullManifestFilePaths, strategy)
await reject(kubectl, fullManifestFilePaths, strategy, timeout)
break
}
default: {
Expand Down
25 changes: 24 additions & 1 deletion src/strategyHelpers/blueGreen/blueGreenHelper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ describe('bluegreenhelper functions', () => {
[].concat(
testObjects.deploymentEntityList,
testObjects.serviceEntityList
)
),
'60s'
)

expect(value).toHaveLength(2)
Expand All @@ -54,6 +55,28 @@ describe('bluegreenhelper functions', () => {
})
})

test('handles timeout when deleting objects', async () => {
const deleteList = [
{name: 'nginx-service-green', kind: 'Service'},
{name: 'nginx-deployment-green', kind: 'Deployment'}
]

// Mock deleteObjects to prevent actual execution
jest.spyOn(kubectl, 'delete').mockResolvedValue({} as ExecOutput)

await bgHelper.deleteObjects(kubectl, deleteList, '60s')

// Verify kubectl.delete is called with timeout
expect(kubectl.delete).toHaveBeenCalledWith(
['Service', 'nginx-service-green'],
'60s'
)
expect(kubectl.delete).toHaveBeenCalledWith(
['Deployment', 'nginx-deployment-green'],
'60s'
)
})

test('parses objects correctly from one file (getManifestObjects)', () => {
expect(testObjects.deploymentEntityList[0].kind).toBe('Deployment')
expect(testObjects.serviceEntityList[0].kind).toBe('Service')
Expand Down
18 changes: 12 additions & 6 deletions src/strategyHelpers/blueGreen/blueGreenHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ export const STABLE_SUFFIX = '-stable'

export async function deleteGreenObjects(
kubectl: Kubectl,
toDelete: K8sObject[]
toDelete: K8sObject[],
timeout?: string
): Promise<K8sDeleteObject[]> {
// const resourcesToDelete: K8sDeleteObject[] = []
const resourcesToDelete: K8sDeleteObject[] = toDelete.map((obj) => {
Expand All @@ -45,18 +46,22 @@ export async function deleteGreenObjects(

core.debug(`deleting green objects: ${JSON.stringify(resourcesToDelete)}`)

await deleteObjects(kubectl, resourcesToDelete)
await deleteObjects(kubectl, resourcesToDelete, timeout)
return resourcesToDelete
}

export async function deleteObjects(
kubectl: Kubectl,
deleteList: K8sDeleteObject[]
deleteList: K8sDeleteObject[],
timeout?: string
) {
// delete services and deployments
for (const delObject of deleteList) {
try {
const result = await kubectl.delete([delObject.kind, delObject.name])
const result = await kubectl.delete(
[delObject.kind, delObject.name],
timeout
)
checkForErrors([result])
} catch (ex) {
core.debug(`failed to delete object ${delObject.name}: ${ex}`)
Expand Down Expand Up @@ -267,10 +272,11 @@ export async function fetchResource(

export async function deployObjects(
kubectl: Kubectl,
objectsList: any[]
objectsList: any[],
timeout?: string
): Promise<DeployResult> {
const manifestFiles = fileHelper.writeObjectsToFile(objectsList)
const execResult = await kubectl.apply(manifestFiles)
const execResult = await kubectl.apply(manifestFiles, false, timeout)

return {execResult, manifestFiles}
}
Loading
Loading