Skip to content
Merged
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/aio-cli-plugin-api-mesh",
"version": "5.2.4-alpha.0",
"version": "5.2.4-alpha.1",
"description": "Adobe I/O CLI plugin to develop and manage API mesh sources",
"keywords": [
"oclif-plugin"
Expand Down
106 changes: 106 additions & 0 deletions src/commands/api-mesh/__tests__/delete-log-forwarding.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
Copyright 2021 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/

const DeleteLogForwardingCommand = require('../config/delete/log-forwarding');
const { initSdk, promptConfirm } = require('../../../helpers');
const { getMeshId, deleteLogForwarding } = require('../../../lib/smsClient');

jest.mock('../../../helpers', () => ({
initSdk: jest.fn().mockResolvedValue({}),
initRequestId: jest.fn().mockResolvedValue({}),
promptConfirm: jest.fn().mockResolvedValue(true),
}));
jest.mock('../../../lib/smsClient');

let logSpy, errorLogSpy, parseSpy;

describe('delete log forwarding command tests', () => {
beforeEach(() => {
initSdk.mockResolvedValue({
imsOrgCode: 'mockOrgCode',
projectId: 'mockProjectId',
workspaceId: 'mockWorkspaceId',
workspaceName: 'mockWorkspaceName',
});

getMeshId.mockResolvedValue('mockMeshId');
deleteLogForwarding.mockResolvedValue();

global.requestId = 'dummy_request_id';

logSpy = jest.spyOn(DeleteLogForwardingCommand.prototype, 'log');
errorLogSpy = jest.spyOn(DeleteLogForwardingCommand.prototype, 'error');
parseSpy = jest.spyOn(DeleteLogForwardingCommand.prototype, 'parse');
});

afterEach(() => {
jest.clearAllMocks();
});

test('should fail if mesh ID is not found', async () => {
getMeshId.mockResolvedValueOnce(null);

await expect(DeleteLogForwardingCommand.run()).rejects.toThrow(
'Unable to delete log forwarding details. No mesh found for Org(mockOrgCode) -> Project(mockProjectId) -> Workspace(mockWorkspaceId). Check the details and try again.',
);

expect(logSpy).not.toHaveBeenCalled();
expect(errorLogSpy).toHaveBeenCalledWith(
'Unable to delete log forwarding details. No mesh found for Org(mockOrgCode) -> Project(mockProjectId) -> Workspace(mockWorkspaceId). Check the details and try again.',
);
});

test('should skip confirmation if autoConfirmAction is set', async () => {
parseSpy.mockResolvedValueOnce({
flags: {
ignoreCache: false,
autoConfirmAction: true,
},
});

await DeleteLogForwardingCommand.run();

expect(promptConfirm).not.toHaveBeenCalled();
expect(deleteLogForwarding).toHaveBeenCalledWith(
'mockOrgCode',
'mockProjectId',
'mockWorkspaceId',
'mockMeshId',
);
expect(logSpy).toHaveBeenCalledWith('Successfully deleted log forwarding details');
});

test('should fail if deleteLogForwarding throws an error', async () => {
deleteLogForwarding.mockRejectedValueOnce(new Error('Deletion failed'));

await expect(DeleteLogForwardingCommand.run()).rejects.toThrow(
'Unable to delete log forwarding details. Try again. RequestId: dummy_request_id',
);

expect(logSpy).not.toHaveBeenCalledWith('Successfully deleted log forwarding details');
expect(errorLogSpy).toHaveBeenCalledWith(
'Unable to delete log forwarding details. Try again. RequestId: dummy_request_id',
);
});

test('should delete log forwarding details successfully', async () => {
await DeleteLogForwardingCommand.run();

expect(deleteLogForwarding).toHaveBeenCalledWith(
'mockOrgCode',
'mockProjectId',
'mockWorkspaceId',
'mockMeshId',
);
expect(logSpy).toHaveBeenCalledWith('Successfully deleted log forwarding details');
});
});
80 changes: 80 additions & 0 deletions src/commands/api-mesh/config/delete/log-forwarding.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
Copyright 2021 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/

const { Command } = require('@oclif/core');
const logger = require('../../../../classes/logger');
const { initSdk, promptConfirm } = require('../../../../helpers');
const { ignoreCacheFlag, autoConfirmActionFlag } = require('../../../../utils');
const { deleteLogForwarding, getMeshId } = require('../../../../lib/smsClient');

class DeleteLogForwardingCommand extends Command {
static flags = {
ignoreCache: ignoreCacheFlag,
autoConfirmAction: autoConfirmActionFlag,
};

async run() {
logger.info(`RequestId: ${global.requestId}`);

const { flags } = await this.parse(DeleteLogForwardingCommand);

const ignoreCache = await flags.ignoreCache;
const autoConfirmAction = await flags.autoConfirmAction;

const { imsOrgCode, projectId, workspaceId, workspaceName } = await initSdk({
ignoreCache,
});

let meshId = null;

try {
meshId = await getMeshId(imsOrgCode, projectId, workspaceId, workspaceName);
} catch (err) {
this.error(
`Unable to get mesh ID. Please check the details and try again. RequestId: ${global.requestId}`,
);
}

// mesh could not be found
if (!meshId) {
this.error(
`Unable to delete log forwarding details. No mesh found for Org(${imsOrgCode}) -> Project(${projectId}) -> Workspace(${workspaceId}). Check the details and try again.`,
);
}

let shouldContinue = true;

if (!autoConfirmAction) {
shouldContinue = await promptConfirm(
`Are you sure you want to delete the log forwarding details for mesh: ${meshId}?`,
);
}

if (shouldContinue) {
try {
await deleteLogForwarding(imsOrgCode, projectId, workspaceId, meshId);
this.log('Successfully deleted log forwarding details');
} catch (error) {
this.log(error.message);
this.error(
`Unable to delete log forwarding details. Try again. RequestId: ${global.requestId}`,
);
}
} else {
this.log('delete log-forwarding cancelled');
return 'delete log-forwarding cancelled';
}
}
}

DeleteLogForwardingCommand.description = 'Delete log forwarding details for a given mesh';

module.exports = DeleteLogForwardingCommand;
101 changes: 101 additions & 0 deletions src/lib/smsClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -1397,6 +1397,106 @@ const getLogForwarding = async (organizationCode, projectId, workspaceId, meshId
}
};

/**
* Deletes the log forwarding configuration for a given mesh.
*
* @param {string} organizationCode - The IMS org code
* @param {string} projectId - The project ID
* @param {string} workspaceId - The workspace ID
* @param {string} meshId - The mesh ID
*/
const deleteLogForwarding = async (organizationCode, projectId, workspaceId, meshId) => {
const { accessToken } = await getDevConsoleConfig();
const config = {
method: 'DELETE',
url: `${SMS_BASE_URL}/organizations/${organizationCode}/projects/${projectId}/workspaces/${workspaceId}/meshes/${meshId}/log/forwarding`,
headers: {
'Authorization': `Bearer ${accessToken}`,
'x-request-id': global.requestId,
'x-api-key': SMS_API_KEY,
},
};

logger.info(
'Initiating DELETE %s',
`${SMS_BASE_URL}/organizations/${organizationCode}/projects/${projectId}/workspaces/${workspaceId}/meshes/${meshId}/log/forwarding`,
);

try {
const response = await axios(config);

logger.info('Response from DELETE %s', response.status);

if (response && response?.status === 204) {
return response;
} else {
logger.error(
`Unable to delete log forwarding config: ${objToString(
response,
['data'],
'Error',
)}. Received ${response.status}, expected 204`,
);
throw new Error(
`something went wrong: ${objToString(
response,
['data'],
'Unable to delete log forwarding',
)}`,
);
}
} catch (error) {
logger.info('Response from DELETE %s', error.response.status);

if (error.response.status === 404) {
// The request was made and the server responded with a 404 status code
logger.error('log forwarding details not found');

throw new Error('log forwarding details not found');
} else if (error.response && error.response.data) {
// The request was made and the server responded with an unsupported status code
logger.error(
'Error while deleting log forwarding details. Response: %s',
objToString(error, ['response', 'data'], 'Unable to delete log forwarding details'),
);

if (error.response.data.messages) {
const message = objToString(
error,
['response', 'data', 'messages', '0', 'message'],
'Unable to delete log forwarding details',
);

throw new Error(message);
} else if (error.response.data.message) {
const message = objToString(
error,
['response', 'data', 'message'],
'Unable to delete log forwarding details',
);

throw new Error(message);
} else {
const message = objToString(
error,
['response', 'data'],
'Unable to delete log forwarding details',
);

throw new Error(message);
}
} else {
// The request was made but no response was received
logger.error(
'Error while deleting log forwarding details. No response received from the server: %s',
objToString(error, [], 'Unable to delete log forwarding details'),
);

throw new Error('Unable to delete log forwarding details: %s', error.message);
}
}
};

module.exports = {
getApiKeyCredential,
describeMesh,
Expand All @@ -1420,4 +1520,5 @@ module.exports = {
cachePurge,
setLogForwarding,
getLogForwarding,
deleteLogForwarding,
};
Loading