Skip to content

Commit

Permalink
feature expose skip state refresh on plan phase to our CLI (#104)
Browse files Browse the repository at this point in the history
  • Loading branch information
sabasabo authored Mar 9, 2022
1 parent 766ce6c commit 8d094fe
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 15 deletions.
6 changes: 6 additions & 0 deletions node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ For sensitive environment variables, use:
- Usage: `--requiresApproval <true/false>`
- Alias: `-a`

### Skip State Refresh
> Disable automatic state refresh on 'plan -destroy' phase.
- Usage: `--skipStateRefresh <true/false>`
- Alias: `-z`

### Targets (Partial Apply)
> A list of resources to explicitly include in the deployment, delimited by a comma. Format is "resource1,resource2,resource3"
- Usage: `--targets`
Expand Down Expand Up @@ -143,6 +148,7 @@ https://docs.env0.com/reference
You can compile and run the CLI from source by cloning the repo from Github and then running the following:
```bash
# clone the repo from github
# make sure env0 lib is not installed globally
yarn install
yarn link # link your local copy of the CLI to your terminal path
```
Expand Down
2 changes: 1 addition & 1 deletion node/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@env0/cli",
"version": "1.0.16",
"version": "1.0.17",
"description": "env0 CLI",
"repository": {
"type": "git",
Expand Down
4 changes: 2 additions & 2 deletions node/src/commands/deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ const deploy = async (options, variables) => {
deployment = environment.latestDeploymentLog;
} else {
assertNoWorkspaceNameChanges(options, environment);
const optionsWithoutWorkspace = { ...options }
delete optionsWithoutWorkspace[WORKSPACE_NAME]
const optionsWithoutWorkspace = { ...options };
delete optionsWithoutWorkspace[WORKSPACE_NAME];
deployment = await deployUtils.deployEnvironment(environment, optionsWithoutWorkspace, configurationChanges);
}

Expand Down
9 changes: 6 additions & 3 deletions node/src/commands/destroy.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const DeployUtils = require('../lib/deploy-utils');
const { options } = require('../config/constants');
const _ = require('lodash');
const { convertStringToBoolean } = require('../lib/general-utils');
const { convertStringToBoolean, removeEmptyValuesFromObj } = require('../lib/general-utils');

const { PROJECT_ID, ENVIRONMENT_NAME, REQUIRES_APPROVAL } = options;
const { PROJECT_ID, ENVIRONMENT_NAME, REQUIRES_APPROVAL, SKIP_STATE_REFRESH } = options;

const assertEnvironmentExists = environment => {
if (!environment) {
Expand All @@ -25,7 +25,10 @@ const destroy = async options => {
await deployUtils.updateEnvironment(environment, { requiresApproval: requiresApproval });
}

const deployment = await deployUtils.destroyEnvironment(environment);
const params = removeEmptyValuesFromObj({
[SKIP_STATE_REFRESH]: options[SKIP_STATE_REFRESH]
});
const deployment = await deployUtils.destroyEnvironment(environment, params);

status = await deployUtils.pollDeploymentStatus(deployment);

Expand Down
8 changes: 8 additions & 0 deletions node/src/config/arguments.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const {
TERRAFORM_VARIABLES,
SENSITIVE_ENVIRONMENT_VARIABLES,
REVISION,
SKIP_STATE_REFRESH,
REQUIRES_APPROVAL,
TARGETS
} = options;
Expand Down Expand Up @@ -119,6 +120,13 @@ const argumentsMap = {
group: ['deploy'],
description: 'Your git revision, can be a branch tag or a commit hash. Default value "master" '
},
[SKIP_STATE_REFRESH]: {
name: SKIP_STATE_REFRESH,
alias: 'z',
type: String,
group: ['destroy'],
description: 'Disable automatic state refresh on plan destroy phase'
},
[TARGETS]: {
name: TARGETS,
alias: 't',
Expand Down
4 changes: 2 additions & 2 deletions node/src/config/commands.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { argumentsMap, allArguments, baseArguments } = require('./arguments');
const { options } = require('./constants');

const { API_KEY, API_SECRET, ORGANIZATION_ID, PROJECT_ID, ENVIRONMENT_NAME, BLUEPRINT_ID, REQUIRES_APPROVAL } = options;
const { API_KEY, API_SECRET, ORGANIZATION_ID, PROJECT_ID, ENVIRONMENT_NAME, BLUEPRINT_ID, SKIP_STATE_REFRESH, REQUIRES_APPROVAL } = options;

const commands = {
deploy: {
Expand All @@ -14,7 +14,7 @@ const commands = {
]
},
destroy: {
options: [...baseArguments, argumentsMap[REQUIRES_APPROVAL]],
options: [...baseArguments, argumentsMap[REQUIRES_APPROVAL], argumentsMap[SKIP_STATE_REFRESH]],
help: [
{
desc: 'Destroys an environment',
Expand Down
1 change: 1 addition & 0 deletions node/src/config/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const options = {
TERRAFORM_VARIABLES: 'terraformVariables',
SENSITIVE_ENVIRONMENT_VARIABLES: 'sensitiveEnvironmentVariables',
REVISION: 'revision',
SKIP_STATE_REFRESH: 'skipStateRefresh',
REQUIRES_APPROVAL: 'requiresApproval',
TARGETS: 'targets'
};
Expand Down
6 changes: 4 additions & 2 deletions node/src/lib/deploy-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,12 @@ class DeployUtils {
});
}

async destroyEnvironment(environment) {
async destroyEnvironment(environment, params) {
logger.info('Starting to destroy environment...');

return await apiClient.callApi('post', `environments/${environment.id}/destroy`);
return await apiClient.callApi('post', `environments/${environment.id}/destroy`, {
params
});
}

async writeDeploymentStepLog(deploymentLogId, stepName) {
Expand Down
23 changes: 19 additions & 4 deletions node/tests/commands/destroy.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jest.mock('../../src/lib/deploy-utils');

const mockDeployment = { id: 'id0' };

const { ENVIRONMENT_NAME, REQUIRES_APPROVAL } = options;
const { ENVIRONMENT_NAME, REQUIRES_APPROVAL, SKIP_STATE_REFRESH } = options;

describe('destroy', () => {
beforeEach(() => {
Expand All @@ -35,11 +35,11 @@ describe('destroy', () => {

await destroy({});

expect(mockDestroyEnvironment).toBeCalledWith(mockEnvironment);
expect(mockDestroyEnvironment).toHaveBeenCalledWith(mockEnvironment, expect.anything());
expect(mockPollDeploymentStatus).toBeCalledWith(mockDeployment);
});

it('should fail when environment doesnt exist', async () => {
it("should fail when environment doesn't exist", async () => {
const mockEnvironmentName = 'environment0';
mockGetEnvironment.mockResolvedValue(undefined);

Expand All @@ -49,6 +49,21 @@ describe('destroy', () => {
);
});

describe('skipStateRefresh argument', () => {
it.each`
options
${{ [SKIP_STATE_REFRESH]: 'true' }}
${{ [SKIP_STATE_REFRESH]: 'false' }}
${{}}
`('should call destroyEnvironment with skipStateRefresh Option, options=$options', async ({ options }) => {
const mockEnvironment = { id: 'something', name: 'someone' };
mockGetEnvironment.mockResolvedValue(mockEnvironment);

await destroy(options);
expect(mockDestroyEnvironment).toBeCalledWith(expect.anything(), options);
});
});

describe('requires approval argument', () => {
it.each`
option | existing
Expand All @@ -74,7 +89,7 @@ describe('destroy', () => {

await destroy({ [REQUIRES_APPROVAL]: option });

expect(mockUpdateEnvironment).toBeCalledWith(expect.anything(), { requiresApproval: expected });
expect(mockUpdateEnvironment).toBeCalledWith(expect.anything(), { [REQUIRES_APPROVAL]: expected });
});
});
});
25 changes: 24 additions & 1 deletion node/tests/lib/deploy-utils.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,15 @@ jest.mock('../../src/lib/api-client', () =>
}))
);

const { BLUEPRINT_ID, REVISION, REQUIRES_APPROVAL, TARGETS, ENVIRONMENT_NAME, PROJECT_ID } = options;
const {
BLUEPRINT_ID,
REVISION,
SKIP_STATE_REFRESH,
REQUIRES_APPROVAL,
TARGETS,
ENVIRONMENT_NAME,
PROJECT_ID
} = options;

const mockDeploymentId = 'deployment0';
const mockDeployment = { id: mockDeploymentId };
Expand Down Expand Up @@ -45,6 +53,21 @@ describe('deploy utils', () => {
});
});

describe('skip automatic state refresh', () => {
it.each`
params
${{ [SKIP_STATE_REFRESH]: 'true' }}
${{}}
`(`should call the api with the right query params param=$params`, async ({ params }) => {
mockCallApi.mockResolvedValue([]);

await deployUtils.destroyEnvironment({ id: mockDeploymentId }, params);
expect(mockCallApi).toBeCalledWith('post', `environments/${mockDeploymentId}/destroy`, {
params
});
});
});

describe('write deployment steps', () => {
it('should call api', async () => {
mockCallApi.mockResolvedValue([]);
Expand Down

0 comments on commit 8d094fe

Please sign in to comment.