Skip to content

support for private AKS clusters#181

Open
devdoxxx wants to merge 4 commits into
Azure:mainfrom
devdoxxx:aks-private-cluster-support
Open

support for private AKS clusters#181
devdoxxx wants to merge 4 commits into
Azure:mainfrom
devdoxxx:aks-private-cluster-support

Conversation

@devdoxxx

@devdoxxx devdoxxx commented Jul 29, 2025

Copy link
Copy Markdown
Contributor

This PR introduces full support for deploying Kubernetes secrets to private AKS clusters, which do not expose a public API server. It enables secure secret creation by leveraging az aks command invoke to execute kubectl commands directly within the cluster's internal context.

Key Features
Private Cluster Support: Uses az aks command invoke to apply or delete secrets within private AKS clusters.

Fallback to Kubernetes API: Maintains existing functionality for public clusters via the Kubernetes API client.

Temporary Secret File Handling: Writes secrets to a JSON temp file and applies them securely via kubectl apply -f.

Robust Cleanup: Ensures the temporary file is removed after execution, even if an error occurs.

Input-Driven Control: Introduces use-invoke-command input to toggle between public/private cluster deployment modes.

It also includes full unit test coverage for the private cluster pathway and related helper functions.

This addresses #82

@devdoxxx devdoxxx marked this pull request as ready for review July 29, 2025 18:12
@devdoxxx devdoxxx requested a review from a team as a code owner July 29, 2025 18:12
@devdoxxx devdoxxx requested a review from Copilot July 29, 2025 18:12
@devdoxxx devdoxxx self-assigned this Jul 29, 2025

This comment was marked as outdated.

@ReinierCC ReinierCC requested a review from Copilot August 12, 2025 19:24

This comment was marked as outdated.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@ReinierCC ReinierCC requested a review from Copilot August 12, 2025 21:04

This comment was marked as outdated.

ReinierCC and others added 2 commits August 12, 2025 17:10
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@ReinierCC ReinierCC requested a review from Copilot August 12, 2025 21:21

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for deploying Kubernetes secrets to private AKS clusters by introducing an alternative execution path that uses az aks command invoke instead of direct API calls.

  • Adds runKubectlViaAz function to execute kubectl commands via Azure CLI for private clusters
  • Introduces conditional logic in the main run function to use the new invoke command when enabled
  • Adds three new input parameters to control private cluster deployment mode

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
src/run.ts Implements core functionality for private cluster support with temp file handling and Azure CLI execution
action.yml Adds input parameters for controlling private cluster mode and cluster identification
test/run.test.ts Adds comprehensive unit tests for the new private cluster functionality

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment thread src/run.ts
)
}
// Write secret to temp file
const tempFile = path.join(os.tmpdir(), `secret-${secretName}.json`)

Copilot AI Aug 12, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line creates a tempFile variable that is immediately overwritten on line 74. This dead code should be removed as it serves no purpose and could cause confusion.

Suggested change
const tempFile = path.join(os.tmpdir(), `secret-${secretName}.json`)

Copilot uses AI. Check for mistakes.
Comment thread src/run.ts
)
}
// Write secret to temp file
const tempFile = path.join(os.tmpdir(), `secret-${secretName}.json`)

Copilot AI Aug 12, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line redeclares the tempFile variable that was already declared on line 71, which will cause a compilation error in TypeScript due to duplicate variable declaration in the same scope.

Suggested change
const tempFile = path.join(os.tmpdir(), `secret-${secretName}.json`)

Copilot uses AI. Check for mistakes.
Comment thread src/run.ts
'--name',
clusterName,
'--command',
`kubectl apply -f - -n ${namespace}`,

Copilot AI Aug 12, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The kubectl command uses -f - (stdin) but then specifies --file parameter with the temp file path. This is inconsistent - either use -f - with stdin or -f ${tempFile} with the file parameter, but not both.

Suggested change
`kubectl apply -f - -n ${namespace}`,
`kubectl apply -f ${secretName}.json -n ${namespace}`,

Copilot uses AI. Check for mistakes.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.

Comments suppressed due to low confidence (1)

src/run.ts:71

  • The initial value of tempFile is unused, since it is always overwritten.
   const tempFile = path.join(os.tmpdir(), `secret-${secretName}.json`)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/run.ts
Comment on lines +71 to +73
const tempFile = path.join(os.tmpdir(), `secret-${secretName}.json`)
// Write secret to temp file securely
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'secret-'));

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable tempDir is declared on line 73 but never has a corresponding declaration statement. This will cause a reference error since tempDir is used in the finally block (lines 107-109) but is only accessible within the scope after line 73. The tempDir variable needs to be declared before line 73 (e.g., let tempDir: string;) to be accessible in the finally block.

Suggested change
const tempFile = path.join(os.tmpdir(), `secret-${secretName}.json`)
// Write secret to temp file securely
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'secret-'));
let tempDir: string;
// Write secret to temp file securely
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'secret-'));

Copilot uses AI. Check for mistakes.
Comment thread src/run.ts
Comment on lines +279 to +284
const sec = await buildSecret(secretName, namespace, secretType)

if (core.getInput('use-invoke-command') === 'true') {
await runKubectlViaAz(sec, namespace, secretName)
return
}

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The checkClusterContext() function is still called unconditionally at the start of run(), which checks for the KUBECONFIG environment variable. However, when use-invoke-command is true, the KUBECONFIG is not needed since the action uses az aks command invoke instead. This will cause the action to fail for private clusters even when the invoke command path is selected. Consider making this check conditional or moving it to only execute when the Kubernetes API path is used.

Copilot uses AI. Check for mistakes.
Comment thread test/run.test.ts
Comment on lines +189 to +193
beforeEach(() => {
jest.spyOn(fs, 'writeFileSync').mockImplementation(() => {})
jest.spyOn(fs, 'unlinkSync').mockImplementation(() => {})
jest.spyOn(exec, 'exec').mockResolvedValue(0)
})

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test is missing mocks for fs.mkdtempSync, fs.existsSync, and fs.rmSync which are called in the runKubectlViaAz function (lines 73, 103, 107-108 in src/run.ts). Without these mocks, the tests may attempt to create/delete actual temporary directories on the filesystem during test execution. Add mocks for these methods in the beforeEach block.

Copilot uses AI. Check for mistakes.
Comment thread test/run.test.ts
Comment on lines +197 to +221
it('calls az aks command invoke for delete and apply', async () => {
jest
.spyOn(core, 'getInput')
.mockImplementation((name: string) =>
name === 'cluster-resource-group'
? 'rg'
: name === 'cluster-name'
? 'aks'
: ''
)
const {runKubectlViaAz} = require('../src/run')
await runKubectlViaAz(mockSecret, 'test-ns', 'test-secret')
expect(exec.exec).toHaveBeenCalledWith(
'az',
expect.arrayContaining([
'aks',
'command',
'invoke',
'--resource-group',
'rg',
'--name',
'aks'
])
)
})

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test only verifies that exec.exec was called with certain arguments but doesn't verify:

  1. That it was called exactly twice (once for delete, once for apply)
  2. The complete command arguments including the kubectl commands
  3. That the temp file operations occurred in the correct order

Consider using toHaveBeenCalledTimes(2) and more specific matchers to verify both the delete and apply commands were executed with the correct full argument lists.

Copilot uses AI. Check for mistakes.
Comment thread src/run.ts
Comment on lines +102 to +105
// Remove temp file if it exists
if (fs.existsSync(tempFile)) {
fs.unlinkSync(tempFile)
}

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cleanup logic is redundant. Lines 103-105 attempt to delete tempFile individually, but lines 107-109 already delete the entire tempDir recursively with { recursive: true, force: true }, which would remove tempFile as well. The individual file deletion (lines 103-105) is unnecessary and can be removed.

Suggested change
// Remove temp file if it exists
if (fs.existsSync(tempFile)) {
fs.unlinkSync(tempFile)
}

Copilot uses AI. Check for mistakes.
Comment thread src/run.ts
Comment on lines +70 to +71
// Write secret to temp file
const tempFile = path.join(os.tmpdir(), `secret-${secretName}.json`)

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assignment to variable tempFile, which is declared constant.

Suggested change
// Write secret to temp file
const tempFile = path.join(os.tmpdir(), `secret-${secretName}.json`)

Copilot uses AI. Check for mistakes.
Comment thread src/run.ts
Comment on lines +70 to +71
// Write secret to temp file
const tempFile = path.join(os.tmpdir(), `secret-${secretName}.json`)

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assignment to variable tempFile, which is declared constant.

Suggested change
// Write secret to temp file
const tempFile = path.join(os.tmpdir(), `secret-${secretName}.json`)

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants