Skip to content

Commit 0fb8270

Browse files
keeganirbykaranA-aws
authored andcommitted
fix(cwl): LiveTail fails to start when clicking with Play next to a LogGroup aws#5986
## Problem Starting a LiveTail session by clicking Play next to a specific LogGroup in the explorer menu is failing. This is because the LogGroup name is passed into the Wizard response, and not a fully qualified Arn. StartLiveTail API request requires ARNs. ## Solution Detect if the context when initializing the TailLogGroup wizard is a LogGroup Name or Arn. If it is just a name, construct the Arn and set that in the Wizard response. Renames `LogGroupName` in `LiveTailSession` to `LogGroupArn` to make it more clear what is expected.
1 parent 34c5c34 commit 0fb8270

File tree

7 files changed

+64
-23
lines changed

7 files changed

+64
-23
lines changed

packages/core/src/awsService/cloudWatchLogs/commands/tailLogGroup.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export async function tailLogGroup(
2727
}
2828

2929
const liveTailSessionConfig: LiveTailSessionConfiguration = {
30-
logGroupName: wizardResponse.regionLogGroupSubmenuResponse.data,
30+
logGroupArn: wizardResponse.regionLogGroupSubmenuResponse.data,
3131
logStreamFilter: wizardResponse.logStreamFilter,
3232
logEventFilterPattern: wizardResponse.filterPattern,
3333
region: wizardResponse.regionLogGroupSubmenuResponse.region,

packages/core/src/awsService/cloudWatchLogs/registry/liveTailSession.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ import {
99
StartLiveTailResponseStream,
1010
} from '@aws-sdk/client-cloudwatch-logs'
1111
import { LogStreamFilterResponse } from '../wizard/liveTailLogStreamSubmenu'
12-
import { CloudWatchLogsSettings } from '../cloudWatchLogsUtils'
13-
import { convertToTimeString, globals, Settings, ToolkitError } from '../../../shared'
12+
import { CloudWatchLogsSettings, uriToKey } from '../cloudWatchLogsUtils'
13+
import { convertToTimeString, getLogger, globals, Settings, ToolkitError } from '../../../shared'
1414
import { createLiveTailURIFromArgs } from './liveTailSessionRegistry'
1515
import { getUserAgent } from '../../../shared/telemetry/util'
1616

1717
export type LiveTailSessionConfiguration = {
18-
logGroupName: string
18+
logGroupArn: string
1919
logStreamFilter?: LogStreamFilterResponse
2020
logEventFilterPattern?: string
2121
region: string
@@ -28,7 +28,7 @@ export type LiveTailSessionClient = {
2828

2929
export class LiveTailSession {
3030
private liveTailClient: LiveTailSessionClient
31-
private _logGroupName: string
31+
private _logGroupArn: string
3232
private logStreamFilter?: LogStreamFilterResponse
3333
private logEventFilterPattern?: string
3434
private _maxLines: number
@@ -45,7 +45,7 @@ export class LiveTailSession {
4545
static settings = new CloudWatchLogsSettings(Settings.instance)
4646

4747
public constructor(configuration: LiveTailSessionConfiguration) {
48-
this._logGroupName = configuration.logGroupName
48+
this._logGroupArn = configuration.logGroupArn
4949
this.logStreamFilter = configuration.logStreamFilter
5050
this.liveTailClient = {
5151
cwlClient: new CloudWatchLogsClient({
@@ -69,8 +69,8 @@ export class LiveTailSession {
6969
return this._uri
7070
}
7171

72-
public get logGroupName() {
73-
return this._logGroupName
72+
public get logGroupArn() {
73+
return this._logGroupArn
7474
}
7575

7676
public set eventRate(rate: number) {
@@ -93,6 +93,7 @@ export class LiveTailSession {
9393
this.statusBarUpdateTimer = globals.clock.setInterval(() => {
9494
this.updateStatusBarItemText()
9595
}, 500)
96+
getLogger().info(`LiveTail session started: ${uriToKey(this.uri)}`)
9697
return commandOutput.responseStream
9798
}
9899

@@ -130,7 +131,7 @@ export class LiveTailSession {
130131
}
131132

132133
return new StartLiveTailCommand({
133-
logGroupIdentifiers: [this.logGroupName],
134+
logGroupIdentifiers: [this.logGroupArn],
134135
logStreamNamePrefixes: logStreamNamePrefix ? [logStreamNamePrefix] : undefined,
135136
logStreamNames: logStreamName ? [logStreamName] : undefined,
136137
logEventFilterPattern: this.logEventFilterPattern ? this.logEventFilterPattern : undefined,

packages/core/src/awsService/cloudWatchLogs/registry/liveTailSessionRegistry.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export class LiveTailSessionRegistry extends Map<string, LiveTailSession> {
1919
}
2020

2121
export function createLiveTailURIFromArgs(sessionData: LiveTailSessionConfiguration): vscode.Uri {
22-
let uriStr = `${cloudwatchLogsLiveTailScheme}:${sessionData.region}:${sessionData.logGroupName}`
22+
let uriStr = `${cloudwatchLogsLiveTailScheme}:${sessionData.region}:${sessionData.logGroupArn}`
2323

2424
if (sessionData.logStreamFilter) {
2525
if (sessionData.logStreamFilter.type !== 'all') {

packages/core/src/awsService/cloudWatchLogs/wizard/tailLogGroupWizard.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
import * as nls from 'vscode-nls'
7-
import { ToolkitError } from '../../../shared'
7+
import { globals, ToolkitError } from '../../../shared'
88
import { DefaultCloudWatchLogsClient } from '../../../shared/clients/cloudWatchLogsClient'
99
import { cwlFilterPatternHelpUrl } from '../../../shared/constants'
1010
import { createBackButton, createExitButton, createHelpButton } from '../../../shared/ui/buttons'
@@ -29,7 +29,7 @@ export class TailLogGroupWizard extends Wizard<TailLogGroupWizardResponse> {
2929
initState: {
3030
regionLogGroupSubmenuResponse: logGroupInfo
3131
? {
32-
data: logGroupInfo.groupName,
32+
data: buildLogGroupArn(logGroupInfo.groupName, logGroupInfo.regionName),
3333
region: logGroupInfo.regionName,
3434
}
3535
: undefined,
@@ -81,6 +81,19 @@ async function getLogGroupQuickPickOptions(regionCode: string): Promise<DataQuic
8181
return logGroupsOptions
8282
}
8383

84+
export function buildLogGroupArn(logGroupName: string, region: string): string {
85+
if (logGroupName.startsWith('arn:')) {
86+
return logGroupName
87+
}
88+
const awsAccountId = globals.awsContext.getCredentialAccountId()
89+
if (awsAccountId === undefined) {
90+
throw new ToolkitError(
91+
`Failed to construct Arn for LogGroup because awsAccountId is undefined. LogGroup: ${logGroupName}`
92+
)
93+
}
94+
return `arn:aws:logs:${region}:${awsAccountId}:log-group:${logGroupName}`
95+
}
96+
8497
function formatLogGroupArn(logGroupArn: string): string {
8598
return logGroupArn.endsWith(':*') ? logGroupArn.substring(0, logGroupArn.length - 2) : logGroupArn
8699
}

packages/core/src/test/awsService/cloudWatchLogs/commands/tailLogGroup.test.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ import {
2020
import { getTestWindow } from '../../../shared/vscode/window'
2121
import { CloudWatchLogsSettings, uriToKey } from '../../../../awsService/cloudWatchLogs/cloudWatchLogsUtils'
2222
import { installFakeClock } from '../../../testUtil'
23+
import { DefaultAwsContext } from '../../../../shared'
2324

2425
describe('TailLogGroup', function () {
2526
const testLogGroup = 'test-log-group'
2627
const testRegion = 'test-region'
2728
const testMessage = 'test-message'
29+
const testAwsAccountId = '1234'
2830

2931
let sandbox: sinon.SinonSandbox
3032
let registry: LiveTailSessionRegistry
@@ -54,6 +56,7 @@ describe('TailLogGroup', function () {
5456
})
5557

5658
it('starts LiveTailSession and writes to document. Closes tab and asserts session gets closed.', async function () {
59+
sandbox.stub(DefaultAwsContext.prototype, 'getCredentialAccountId').returns(testAwsAccountId)
5760
wizardSpy = sandbox.stub(TailLogGroupWizard.prototype, 'run').callsFake(async function () {
5861
return getTestWizardResponse()
5962
})
@@ -127,7 +130,7 @@ describe('TailLogGroup', function () {
127130
})
128131

129132
const session = new LiveTailSession({
130-
logGroupName: testLogGroup,
133+
logGroupArn: testLogGroup,
131134
region: testRegion,
132135
})
133136
registry.set(uriToKey(session.uri), session)
@@ -140,7 +143,7 @@ describe('TailLogGroup', function () {
140143

141144
it('clearDocument clears all text from document', async function () {
142145
const session = new LiveTailSession({
143-
logGroupName: testLogGroup,
146+
logGroupArn: testLogGroup,
144147
region: testRegion,
145148
})
146149
const testData = 'blah blah blah'

packages/core/src/test/awsService/cloudWatchLogs/registry/liveTailRegistry.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ describe('LiveTailSession URI', async function () {
1515

1616
it('is correct with no logStream filter, no filter pattern', function () {
1717
const config: LiveTailSessionConfiguration = {
18-
logGroupName: testLogGroupName,
18+
logGroupArn: testLogGroupName,
1919
region: testRegion,
2020
}
2121
const expectedUri = vscode.Uri.parse(expectedUriBase)
@@ -25,7 +25,7 @@ describe('LiveTailSession URI', async function () {
2525

2626
it('is correct with no logStream filter, with filter pattern', function () {
2727
const config: LiveTailSessionConfiguration = {
28-
logGroupName: testLogGroupName,
28+
logGroupArn: testLogGroupName,
2929
region: testRegion,
3030
logEventFilterPattern: 'test-filter',
3131
}
@@ -36,7 +36,7 @@ describe('LiveTailSession URI', async function () {
3636

3737
it('is correct with ALL logStream filter', function () {
3838
const config: LiveTailSessionConfiguration = {
39-
logGroupName: testLogGroupName,
39+
logGroupArn: testLogGroupName,
4040
region: testRegion,
4141
logStreamFilter: {
4242
type: 'all',
@@ -49,7 +49,7 @@ describe('LiveTailSession URI', async function () {
4949

5050
it('is correct with prefix logStream filter', function () {
5151
const config: LiveTailSessionConfiguration = {
52-
logGroupName: testLogGroupName,
52+
logGroupArn: testLogGroupName,
5353
region: testRegion,
5454
logStreamFilter: {
5555
type: 'prefix',
@@ -63,7 +63,7 @@ describe('LiveTailSession URI', async function () {
6363

6464
it('is correct with specific logStream filter', function () {
6565
const config: LiveTailSessionConfiguration = {
66-
logGroupName: testLogGroupName,
66+
logGroupArn: testLogGroupName,
6767
region: testRegion,
6868
logStreamFilter: {
6969
type: 'specific',
@@ -77,7 +77,7 @@ describe('LiveTailSession URI', async function () {
7777

7878
it('is correct with specific logStream filter and filter pattern', function () {
7979
const config: LiveTailSessionConfiguration = {
80-
logGroupName: testLogGroupName,
80+
logGroupArn: testLogGroupName,
8181
region: testRegion,
8282
logStreamFilter: {
8383
type: 'specific',

packages/core/src/test/awsService/cloudWatchLogs/wizard/tailLogGroupWizard.test.ts

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,28 @@
22
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
33
* SPDX-License-Identifier: Apache-2.0
44
*/
5+
import * as sinon from 'sinon'
56

6-
import { TailLogGroupWizard } from '../../../../awsService/cloudWatchLogs/wizard/tailLogGroupWizard'
7+
import assert from 'assert'
8+
import { buildLogGroupArn, TailLogGroupWizard } from '../../../../awsService/cloudWatchLogs/wizard/tailLogGroupWizard'
79
import { createWizardTester } from '../../../shared/wizards/wizardTestUtils'
10+
import { DefaultAwsContext } from '../../../../shared'
811

912
describe('TailLogGroupWizard', async function () {
13+
let sandbox: sinon.SinonSandbox
14+
15+
const testLogGroupName = 'testLogGroup'
16+
const testRegion = 'testRegion'
17+
const testAwsAccountId = '1234'
18+
19+
beforeEach(function () {
20+
sandbox = sinon.createSandbox()
21+
})
22+
23+
afterEach(function () {
24+
sandbox.restore()
25+
})
26+
1027
it('prompts regionLogGroup submenu first if context not provided', async function () {
1128
const wizard = new TailLogGroupWizard()
1229
const tester = await createWizardTester(wizard)
@@ -16,13 +33,20 @@ describe('TailLogGroupWizard', async function () {
1633
})
1734

1835
it('skips regionLogGroup submenu if context provided', async function () {
36+
sandbox.stub(DefaultAwsContext.prototype, 'getCredentialAccountId').returns(testAwsAccountId)
1937
const wizard = new TailLogGroupWizard({
20-
groupName: 'test-groupName',
21-
regionName: 'test-regionName',
38+
groupName: testLogGroupName,
39+
regionName: testRegion,
2240
})
2341
const tester = await createWizardTester(wizard)
2442
tester.regionLogGroupSubmenuResponse.assertDoesNotShow()
2543
tester.logStreamFilter.assertShowFirst()
2644
tester.filterPattern.assertShowSecond()
2745
})
46+
47+
it('builds LogGroup Arn properly', async function () {
48+
sandbox.stub(DefaultAwsContext.prototype, 'getCredentialAccountId').returns(testAwsAccountId)
49+
const arn = buildLogGroupArn(testLogGroupName, testRegion)
50+
assert.strictEqual(arn, `arn:aws:logs:${testRegion}:${testAwsAccountId}:log-group:${testLogGroupName}`)
51+
})
2852
})

0 commit comments

Comments
 (0)