From 74d6d00a6c2200d69c4dbb861b50b959444d0475 Mon Sep 17 00:00:00 2001 From: Oliver King Date: Tue, 8 Feb 2022 09:28:00 -0500 Subject: [PATCH] Switch to using az (adds OIDC) (#48) * refactor project to rely on azure/login and az --- README.md | 72 +++++------ action.yml | 12 +- package-lock.json | 247 ++++++++++------------------------- package.json | 6 +- src/run.test.ts | 323 +++++++--------------------------------------- src/run.ts | 108 ++++------------ 6 files changed, 177 insertions(+), 591 deletions(-) diff --git a/README.md b/README.md index ce8c2315..b7aafee1 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Azure Kubernetes Service set context -This action can be used to set cluster context before other actions like [`azure/k8s-deploy`](https://github.com/Azure/k8s-deploy/tree/master), [`azure/k8s-create-secret`](https://github.com/Azure/k8s-create-secret/tree/master) or any kubectl commands (in script) can be run subsequently in the workflow. +This action can be used to set cluster context before other actions like [`azure/k8s-deploy`](https://github.com/Azure/k8s-deploy/tree/master) and [`azure/k8s-create-secret`](https://github.com/Azure/k8s-create-secret/tree/master). Any kubectl commands (in script) can also be run subsequently in the workflow. -Refer to [starter templates](https://github.com/Azure/actions-workflow-samples/tree/master/Kubernetes) to deploy to any Kubernetes cluster on-premise or any cloud including Azure Kubernetes service. +You must run [Azure/login](https://github.com/Azure/login) before this action. ## Action inputs @@ -15,62 +15,48 @@ Refer to [starter templates](https://github.com/Azure/actions-workflow-samples/t - creds
Credentials - (Required) Credentials required to authenticate with Azure. Steps to obtain these credentials are provided below + resource-group
(Required) + Resource group containing the AKS cluster - resource-group
Resource group - (Required) Resource group containing the AKS cluster - - - cluster-name
Cluster name - (Required) Name of the AKS cluster + cluster-name
(Required) + Name of the AKS cluster ## Example +### OIDC Authentication (recommended) + ```yaml -uses: azure/aks-set-context@v1 - with: - creds: '${{ secrets.AZURE_CREDENTIALS }}' # Azure credentials - resource-group: '' - cluster-name: '' - id: login +- uses: azure/login@v1 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + +- uses: azure/aks-set-context@v2.0 + with: + resource-group: "" + cluster-name: "" ``` -To fetch the credentials required to authenticate with Azure, run the following command: - -```sh -az ad sp create-for-rbac --sdk-auth -``` +### Service Principal Authentication -For more details on this command, refer to [service principal documentation](https://docs.microsoft.com/cli/azure/ad/sp?view=azure-cli-latest#az-ad-sp-create-for-rbac) - -This generates a service principal and the output of the above command will be in the following format: - -```json -{ - "clientId": "", - "clientSecret": "", - "subscriptionId": "", - "tenantId": "", - "activeDirectoryEndpointUrl": "https://login.microsoftonline.com", - "resourceManagerEndpointUrl": "https://management.azure.com/", - "activeDirectoryGraphResourceId": "https://graph.windows.net/", - "sqlManagementEndpointUrl": "https://management.core.windows.net:8443/", - "galleryEndpointUrl": "https://gallery.azure.com/", - "managementEndpointUrl": "https://management.core.windows.net/" -} +```yaml +- uses: azure/login@v1 + with: + creds: ${{ secrets.AZURE_CREDENTIALS }} + +- uses: azure/aks-set-context@v2.0 + with: + resource-group: "" + cluster-name: "" ``` -Add the json output as [a secret](https://developer.github.com/actions/managing-workflows/storing-secrets/) (let's say with the name `AZURE_CREDENTIALS`) in the GitHub repository. The example YAML snippet given above showcases how this secret is referenced in the action for specifying the credentials as input to the action. - -aks-set-context GitHub Actions is supported for the Azure public cloud as well as Azure government clouds ('AzureUSGovernment' or 'AzureChinaCloud'). Before running this action, login to the respective Azure Cloud using [Azure Login](https://github.com/Azure/login) by setting appropriate value for the `environment` parameter. - ## Contributing -This project welcomes contributions and suggestions. Most contributions require you to agree to a +This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. diff --git a/action.yml b/action.yml index a40ba6e6..e7707a27 100644 --- a/action.yml +++ b/action.yml @@ -1,21 +1,15 @@ name: "Azure Kubernetes set context" -description: "Sets the kubeconfig on the machine to communicate with the Azure Kubernetes cluster. Github.com/Azure/Actions" +description: "Sets the kubeconfig on the machine to communicate with the Azure Kubernetes cluster." +# Azure/login must be run before this action inputs: - creds: - description: "Azure credentials i.e. output of `az ad sp create-for-rbac --sdk-auth`" - required: true resource-group: description: "Resource Group Name" required: true cluster-name: description: "AKS Cluster Name" required: true - subscription-id: - description: "Subscription ID" - required: false - default: "" branding: - color: "green" # optional, decorates the entry in the GitHub Marketplace + color: "green" runs: using: "node12" main: "lib/run.js" diff --git a/package-lock.json b/package-lock.json index cfaa0965..51f21030 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,8 @@ "license": "MIT", "dependencies": { "@actions/core": "^1.2.6", - "@azure-actions/auth": "0.0.2", - "@azure-actions/utilities": "0.0.2" + "@actions/exec": "^1.1.0", + "@actions/io": "^1.1.1" }, "devDependencies": { "@types/jest": "^25.2.2", @@ -26,25 +26,18 @@ "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz", "integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA==" }, - "node_modules/@azure-actions/auth": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@azure-actions/auth/-/auth-0.0.2.tgz", - "integrity": "sha512-VRqT/GIHJKakSs8Y7/HKu0LGB+UjAL5Qa/tIKQXmh4NGOvUnyCm8ZxRwQTgBdZKmoY8ilam6z50qyHDBY/pcQg==", + "node_modules/@actions/exec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.0.tgz", + "integrity": "sha512-LImpN9AY0J1R1mEYJjVJfSZWU4zYOlEcwSTgPve1rFQqK5AwrEs6uWW5Rv70gbDIQIAUwI86z6B+9mPK4w9Sbg==", "dependencies": { - "@azure-actions/utilities": "0.0.2", - "querystring": "0.2.1" + "@actions/io": "^1.0.1" } }, - "node_modules/@azure-actions/utilities": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@azure-actions/utilities/-/utilities-0.0.2.tgz", - "integrity": "sha512-mbHGKYGx4A29gwdMXacmjbedkn/Z0EsGd9Ggz18sqM9p1HVdJg+GGcrnuj/XmyRZM+rTx+gzI+Av4cH8rkYSWQ==", - "dependencies": { - "@actions/core": "1.2.6", - "minimatch": "3.0.4", - "shelljs": "0.8.4", - "typed-rest-client": "1.8.1" - } + "node_modules/@actions/io": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.1.tgz", + "integrity": "sha512-Qi4JoKXjmE0O67wAOH6y0n26QXhMKMFo7GD/4IXNVcrtLjUlGjGuVys6pQgwF3ArfGTQu0XpqaNr0YhED2RaRA==" }, "node_modules/@babel/code-frame": { "version": "7.12.13", @@ -1260,7 +1253,8 @@ "node_modules/balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true }, "node_modules/base": { "version": "0.11.2", @@ -1343,6 +1337,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1634,7 +1629,8 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "node_modules/convert-source-map": { "version": "1.7.0", @@ -2313,7 +2309,8 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "node_modules/fsevents": { "version": "2.3.2", @@ -2332,7 +2329,8 @@ "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "node_modules/gensync": { "version": "1.0.0-beta.2", @@ -2395,6 +2393,7 @@ "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2459,6 +2458,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -2624,6 +2624,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -2632,15 +2633,8 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "engines": { - "node": ">= 0.10" - } + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "node_modules/ip-regex": { "version": "2.1.0", @@ -2703,6 +2697,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "dev": true, "dependencies": { "has": "^1.0.3" }, @@ -3904,6 +3899,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -4165,6 +4161,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "dependencies": { "wrappy": "1" } @@ -4304,6 +4301,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -4320,7 +4318,8 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true }, "node_modules/performance-now": { "version": "2.1.0", @@ -4441,26 +4440,6 @@ "node": ">=6" } }, - "node_modules/qs": { - "version": "6.9.6", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", - "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==", - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/querystring": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", - "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", - "engines": { - "node": ">=0.4.x" - } - }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -4517,17 +4496,6 @@ "node": ">=8" } }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -4684,6 +4652,7 @@ "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, "dependencies": { "is-core-module": "^2.2.0", "path-parse": "^1.0.6" @@ -5016,22 +4985,6 @@ "node": ">=0.10.0" } }, - "node_modules/shelljs": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", - "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", - "dependencies": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - }, - "bin": { - "shjs": "bin/shjs" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/shellwords": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", @@ -5654,14 +5607,6 @@ "typescript": ">=3.4 <4.0" } }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } - }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -5710,16 +5655,6 @@ "node": ">=8" } }, - "node_modules/typed-rest-client": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.1.tgz", - "integrity": "sha512-7JbJFBZZuu3G64u6ksklN1xtVGfqBKiR5MQoTe5oLTi68OyB6pRuuIQCllfK/BdGjQtZYp62rgUOnEYDz4e9Xg==", - "dependencies": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "1.8.3" - } - }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -5742,11 +5677,6 @@ "node": ">=4.2.0" } }, - "node_modules/underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - }, "node_modules/union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -6000,7 +5930,8 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, "node_modules/write-file-atomic": { "version": "3.0.3", @@ -6095,25 +6026,18 @@ "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz", "integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA==" }, - "@azure-actions/auth": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@azure-actions/auth/-/auth-0.0.2.tgz", - "integrity": "sha512-VRqT/GIHJKakSs8Y7/HKu0LGB+UjAL5Qa/tIKQXmh4NGOvUnyCm8ZxRwQTgBdZKmoY8ilam6z50qyHDBY/pcQg==", + "@actions/exec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.0.tgz", + "integrity": "sha512-LImpN9AY0J1R1mEYJjVJfSZWU4zYOlEcwSTgPve1rFQqK5AwrEs6uWW5Rv70gbDIQIAUwI86z6B+9mPK4w9Sbg==", "requires": { - "@azure-actions/utilities": "0.0.2", - "querystring": "0.2.1" + "@actions/io": "^1.0.1" } }, - "@azure-actions/utilities": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@azure-actions/utilities/-/utilities-0.0.2.tgz", - "integrity": "sha512-mbHGKYGx4A29gwdMXacmjbedkn/Z0EsGd9Ggz18sqM9p1HVdJg+GGcrnuj/XmyRZM+rTx+gzI+Av4cH8rkYSWQ==", - "requires": { - "@actions/core": "1.2.6", - "minimatch": "3.0.4", - "shelljs": "0.8.4", - "typed-rest-client": "1.8.1" - } + "@actions/io": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.1.tgz", + "integrity": "sha512-Qi4JoKXjmE0O67wAOH6y0n26QXhMKMFo7GD/4IXNVcrtLjUlGjGuVys6pQgwF3ArfGTQu0XpqaNr0YhED2RaRA==" }, "@babel/code-frame": { "version": "7.12.13", @@ -7131,7 +7055,8 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true }, "base": { "version": "0.11.2", @@ -7201,6 +7126,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7444,7 +7370,8 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "convert-source-map": { "version": "1.7.0", @@ -7988,7 +7915,8 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "fsevents": { "version": "2.3.2", @@ -8000,7 +7928,8 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "gensync": { "version": "1.0.0-beta.2", @@ -8048,6 +7977,7 @@ "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -8096,6 +8026,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -8225,6 +8156,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -8233,12 +8165,8 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "ip-regex": { "version": "2.1.0", @@ -8291,6 +8219,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "dev": true, "requires": { "has": "^1.0.3" } @@ -9232,6 +9161,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -9453,6 +9383,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "requires": { "wrappy": "1" } @@ -9549,7 +9480,8 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true }, "path-key": { "version": "2.0.1", @@ -9560,7 +9492,8 @@ "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true }, "performance-now": { "version": "2.1.0", @@ -9654,16 +9587,6 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, - "qs": { - "version": "6.9.6", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", - "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==" - }, - "querystring": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", - "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==" - }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -9707,14 +9630,6 @@ "integrity": "sha512-v1SEYUOXXdbBZK8ZuNgO4TBjamPsiSgcFr0aP+tEKpQZK8vooEUqV6nm6Cv502mX4NF2EfsnVqtNAHG+/6Ur1Q==", "dev": true }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "requires": { - "resolve": "^1.1.6" - } - }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -9837,6 +9752,7 @@ "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, "requires": { "is-core-module": "^2.2.0", "path-parse": "^1.0.6" @@ -10105,16 +10021,6 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, - "shelljs": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", - "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", - "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - } - }, "shellwords": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", @@ -10619,11 +10525,6 @@ "yargs-parser": "18.x" } }, - "tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" - }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -10660,16 +10561,6 @@ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true }, - "typed-rest-client": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.1.tgz", - "integrity": "sha512-7JbJFBZZuu3G64u6ksklN1xtVGfqBKiR5MQoTe5oLTi68OyB6pRuuIQCllfK/BdGjQtZYp62rgUOnEYDz4e9Xg==", - "requires": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "1.8.3" - } - }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -10685,11 +10576,6 @@ "integrity": "sha512-q2ktq4n/uLuNNShyayit+DTobV2ApPEo/6so68JaD5ojvc/6GClBipedB9zNWYxRSAlZXAe405Rlijzl6qDiSw==", "dev": true }, - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -10905,7 +10791,8 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, "write-file-atomic": { "version": "3.0.3", diff --git a/package.json b/package.json index ebc99a9f..e12084e2 100644 --- a/package.json +++ b/package.json @@ -17,13 +17,13 @@ "license": "MIT", "dependencies": { "@actions/core": "^1.2.6", - "@azure-actions/auth": "0.0.2", - "@azure-actions/utilities": "0.0.2" + "@actions/exec": "^1.1.0", + "@actions/io": "^1.1.1" }, "devDependencies": { + "@types/jest": "^25.2.2", "@types/node": "^12.0.4", "jest": "^25.5.4", - "@types/jest": "^25.2.2", "ts-jest": "^25.5.1", "typescript": "3.9.2" } diff --git a/src/run.test.ts b/src/run.test.ts index 2727969e..6ce29e67 100644 --- a/src/run.test.ts +++ b/src/run.test.ts @@ -1,292 +1,65 @@ -import * as login from "./run"; +import { run } from "./run"; import * as core from "@actions/core"; +import * as io from "@actions/io"; +import * as exec from "@actions/exec"; import * as fs from "fs"; -import * as path from "path"; -import * as azureActionsUtil from "@azure-actions/utilities/lib/http"; -describe("Testing all functions in login file.", () => { - test("getAKSKubeconfig() - get kubeconfig from aks API and return it", async () => { - jest.spyOn(core, "getInput").mockImplementation((inputName, options) => { - if (inputName == "resource-group") return "sample-rg"; - if (inputName == "cluster-name") return "testing"; - }); - const response = { - statusCode: 200, - body: { - properties: { - kubeConfig: Buffer.from("###").toString("base64"), - }, - }, - } as azureActionsUtil.WebResponse; - jest.spyOn(azureActionsUtil, "sendRequest").mockResolvedValue(response); +const resourceGroup = "sample-rg"; +const clusterName = "sample-cluster"; +const azPath = "path"; +const runnerTemp = "temp"; +const date = 1644272184664; - expect( - await login.getAKSKubeconfig( - "", - "", - "https://management.azure.com/", - "sample-rg", - "testing" - ) - ).toBe("###"); - const request = { - body: "", - method: "GET", - headers: { - Authorization: "Bearer ", - "Content-Type": "application/json; charset=utf-8", - }, - uri: "https://management.azure.com//subscriptions//resourceGroups/sample-rg/providers/Microsoft.ContainerService/managedClusters/testing/accessProfiles/clusterAdmin?api-version=2017-08-31", - } as azureActionsUtil.WebRequest; - expect(azureActionsUtil.sendRequest).toBeCalledWith(request); +describe("Set context", () => { + it("throws without resource-group", async () => { + await expect(run()).rejects.toThrow(); }); - test("getAKSKubeconfig() - reject if response not in expected format", async () => { - const response = { - statusCode: 200, - body: { - error: "ErrorMessage", - }, - } as azureActionsUtil.WebResponse; - jest.spyOn(azureActionsUtil, "sendRequest").mockResolvedValue(response); - - await login - .getAKSKubeconfig( - "", - "", - "https://management.azure.com/", - "sample-rg", - "testing" - ) - .then((response) => expect(response).toBeUndefined()) - .catch((error) => expect(error).toBe(JSON.stringify(response.body))); - const request = { - body: "", - method: "GET", - headers: { - Authorization: "Bearer ", - "Content-Type": "application/json; charset=utf-8", - }, - uri: "https://management.azure.com//subscriptions//resourceGroups/sample-rg/providers/Microsoft.ContainerService/managedClusters/testing/accessProfiles/clusterAdmin?api-version=2017-08-31", - } as azureActionsUtil.WebRequest; - expect(azureActionsUtil.sendRequest).toBeCalledWith(request); - }); - - test("getAKSKubeconfig() - reject if error recieved", async () => { - jest - .spyOn(azureActionsUtil, "sendRequest") - .mockRejectedValue("ErrorMessage"); - - await login - .getAKSKubeconfig( - "", - "", - "https://management.azure.com/", - "sample-rg", - "testing" - ) - .then((response) => expect(response).toBeUndefined()) - .catch((error) => expect(error).toBe("ErrorMessage")); - const request = { - body: "", - method: "GET", - headers: { - Authorization: "Bearer ", - "Content-Type": "application/json; charset=utf-8", - }, - uri: "https://management.azure.com//subscriptions//resourceGroups/sample-rg/providers/Microsoft.ContainerService/managedClusters/testing/accessProfiles/clusterAdmin?api-version=2017-08-31", - } as azureActionsUtil.WebRequest; - expect(azureActionsUtil.sendRequest).toBeCalledWith(request); - }); - - test("getKubeconfig() - reject if incorrect credentials", async () => { - jest.spyOn(core, "getInput").mockReturnValue("Wrong cred."); - - await expect( - login.getKubeconfig({}, "subscriptionId", "sample-rg", "testing") - ).rejects.toThrow(); - }); - - test("getKubeconfig() - get access token, use it to get kubeconfig and return it ", async () => { - const creds = { - clientId: "", - clientSecret: "", - subscriptionId: "", - tenantId: "", - activeDirectoryEndpointUrl: "https://login.k8s.microsoftonline.com", - resourceManagerEndpointUrl: "https://management.k8s.azure.com/", - activeDirectoryGraphResourceId: "https://graph.windows.net/", - sqlManagementEndpointUrl: "https://management.core.windows.net:8443/", - galleryEndpointUrl: "https://gallery.azure.com/", - managementEndpointUrl: "https://management.core.windows.net/", - }; - const responseKube = { - statusCode: 200, - body: { - properties: { - kubeConfig: Buffer.from("###").toString("base64"), - }, - }, - } as azureActionsUtil.WebResponse; - const responseLogin = { - statusCode: 200, - body: { - access_token: "", - }, - } as azureActionsUtil.WebResponse; - jest - .spyOn(azureActionsUtil, "sendRequest") - .mockResolvedValueOnce(responseLogin) - .mockResolvedValueOnce(responseKube); - - await login - .getKubeconfig(creds, creds["subscriptionId"], "sample-rg", "testing") - .then((response) => expect(response).toBe("###")) - .catch((error) => expect(error).toBeUndefined()); - const requestForToken = { - method: "POST", - uri: "https://login.k8s.microsoftonline.com//oauth2/token/", - body: "resource=https%3A%2F%2Fmanagement.k8s.azure.com%2F&client_id=%3Cclient%20id%3E&grant_type=client_credentials&client_secret=%3Cclient%20secret%3E", - headers: { - "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", - }, - } as azureActionsUtil.WebRequest; - let optionsForToken = { - retriableStatusCodes: [400, 408, 409, 500, 502, 503, 504], - } as azureActionsUtil.WebRequestOptions; - expect(azureActionsUtil.sendRequest).toBeCalledWith( - requestForToken, - optionsForToken - ); - const requestForKubecongig = { - body: "", - method: "GET", - headers: { - Authorization: "Bearer ", - "Content-Type": "application/json; charset=utf-8", - }, - uri: "https://management.k8s.azure.com//subscriptions//resourceGroups/sample-rg/providers/Microsoft.ContainerService/managedClusters/testing/accessProfiles/clusterAdmin?api-version=2017-08-31", - } as azureActionsUtil.WebRequest; - expect(azureActionsUtil.sendRequest).toBeCalledWith(requestForKubecongig); + it("throws without cluster-name", async () => { + jest.spyOn(core, "getInput").mockImplementation((inputName, options) => { + if (inputName == "resource-group") return resourceGroup; + }); + await expect(run()).rejects.toThrow(); }); - test("getKubeconfig() - use default endpoints if not provided in creds", async () => { - const creds = { - clientId: "", - clientSecret: "", - subscriptionId: "", - tenantId: "", - activeDirectoryGraphResourceId: "https://graph.windows.net/", - sqlManagementEndpointUrl: "https://management.core.windows.net:8443/", - galleryEndpointUrl: "https://gallery.azure.com/", - managementEndpointUrl: "https://management.core.windows.net/", - }; - const responseKube = { - statusCode: 200, - body: { - properties: { - kubeConfig: Buffer.from("###").toString("base64"), - }, - }, - } as azureActionsUtil.WebResponse; - const responseLogin = { - statusCode: 200, - body: { - access_token: "", - }, - } as azureActionsUtil.WebResponse; - jest - .spyOn(azureActionsUtil, "sendRequest") - .mockResolvedValueOnce(responseLogin) - .mockResolvedValueOnce(responseKube); - - await login - .getKubeconfig(creds, creds["subscriptionId"], "sample-rg", "testing") - .then((response) => expect(response).toBe("###")) - .catch((error) => expect(error).toBeUndefined()); - const requestForToken = { - method: "POST", - uri: "https://login.microsoftonline.com//oauth2/token/", - body: "resource=https%3A%2F%2Fmanagement.azure.com%2F&client_id=%3Cclient%20id%3E&grant_type=client_credentials&client_secret=%3Cclient%20secret%3E", - headers: { - "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", - }, - } as azureActionsUtil.WebRequest; - let optionsForToken = { - retriableStatusCodes: [400, 408, 409, 500, 502, 503, 504], - } as azureActionsUtil.WebRequestOptions; - expect(azureActionsUtil.sendRequest).toBeCalledWith( - requestForToken, - optionsForToken - ); - const requestForKubecongig = { - body: "", - method: "GET", - headers: { - Authorization: "Bearer ", - "Content-Type": "application/json; charset=utf-8", - }, - uri: "https://management.azure.com//subscriptions//resourceGroups/sample-rg/providers/Microsoft.ContainerService/managedClusters/testing/accessProfiles/clusterAdmin?api-version=2017-08-31", - } as azureActionsUtil.WebRequest; - expect(azureActionsUtil.sendRequest).toBeCalledWith(requestForKubecongig); + it("throws without az tools", async () => { + jest.spyOn(core, "getInput").mockImplementation((inputName, options) => { + if (inputName == "resource-group") return resourceGroup; + if (inputName == "cluster-name") return clusterName; + }); + await expect(run()).rejects.toThrow(); }); - test("run() - create kubeconfig, export variable and give appropriate access", async () => { - jest.spyOn(fs, "writeFileSync").mockImplementation(); + it("gets the kubeconfig and sets the context", async () => { + jest.spyOn(core, "getInput").mockImplementation((inputName, options) => { + if (inputName == "resource-group") return resourceGroup; + if (inputName == "cluster-name") return clusterName; + }); + jest.spyOn(io, "which").mockImplementation(async () => azPath); + process.env["RUNNER_TEMP"] = runnerTemp; + jest.spyOn(Date, "now").mockImplementation(() => date); + jest.spyOn(exec, "exec").mockImplementation(async () => 0); jest.spyOn(fs, "chmodSync").mockImplementation(); jest.spyOn(core, "exportVariable").mockImplementation(); - jest.spyOn(console, "log").mockImplementation(); jest.spyOn(core, "debug").mockImplementation(); - jest.spyOn(core, "getInput").mockImplementation((inputName, options) => { - if (inputName == "resource-group") return "sample-rg"; - if (inputName == "cluster-name") return "testing"; - if (inputName == "creds") return JSON.stringify(creds); - }); - const creds = { - clientId: "", - clientSecret: "", - subscriptionId: "", - tenantId: "", - activeDirectoryEndpointUrl: "https://login.microsoftonline.com", - resourceManagerEndpointUrl: "https://management.azure.com/", - activeDirectoryGraphResourceId: "https://graph.windows.net/", - sqlManagementEndpointUrl: "https://management.core.windows.net:8443/", - galleryEndpointUrl: "https://gallery.azure.com/", - managementEndpointUrl: "https://management.core.windows.net/", - }; - const responseKube = { - statusCode: 200, - body: { - properties: { - kubeConfig: Buffer.from("###").toString("base64"), - }, - }, - } as azureActionsUtil.WebResponse; - const responseLogin = { - statusCode: 200, - body: { - access_token: "", - }, - } as azureActionsUtil.WebResponse; - jest - .spyOn(azureActionsUtil, "sendRequest") - .mockResolvedValueOnce(responseLogin) - .mockResolvedValueOnce(responseKube); - process.env["RUNNER_TEMP"] = "tempDirPath"; - jest.spyOn(Date, "now").mockImplementation(() => 1234561234567); - expect(await login.run()); - expect(fs.writeFileSync).toHaveBeenCalledWith( - path.join("tempDirPath", "kubeconfig_1234561234567"), - "###" - ); - expect(fs.chmodSync).toHaveBeenCalledWith( - path.join("tempDirPath", "kubeconfig_1234561234567"), - "600" - ); - expect(core.exportVariable).toHaveBeenCalledWith( - "KUBECONFIG", - path.join("tempDirPath", "kubeconfig_1234561234567") + await expect(run()).resolves.not.toThrowError(); + const kubeconfigPath = `${runnerTemp}/kubeconfig_${date}`; + expect(exec.exec).toBeCalledWith( + "az", + [ + "aks", + "get-credentials", + "--resource-group", + resourceGroup, + "--name", + clusterName, + "-f", + kubeconfigPath, + ], + { failOnStdErr: true } ); + expect(fs.chmodSync).toBeCalledWith(kubeconfigPath, "600"); + expect(core.exportVariable).toBeCalledWith("KUBECONFIG", kubeconfigPath); }); }); diff --git a/src/run.ts b/src/run.ts index 3f316079..0d9d6e94 100644 --- a/src/run.ts +++ b/src/run.ts @@ -1,103 +1,49 @@ import * as core from "@actions/core"; +import * as io from "@actions/io"; +import * as exec from "@actions/exec"; import * as path from "path"; import * as fs from "fs"; -import { - WebRequest, - WebResponse, - sendRequest, -} from "@azure-actions/utilities/lib/http"; -import { getAzureAccessToken } from "@azure-actions/auth"; + +const AZ_TOOL_NAME = "az"; export async function run() { // get inputs - const creds = core.getInput("creds", { required: true }); - let credsObject: { [key: string]: string }; - try { - credsObject = JSON.parse(creds); - } catch (ex) { - throw new Error("Credentials object is not a valid JSON: " + ex); - } - const subscriptionId = - core.getInput("subscription-id") || credsObject["subscriptionId"]; const resourceGroupName = core.getInput("resource-group", { required: true }); const clusterName = core.getInput("cluster-name", { required: true }); - // get kubeconfig - core.debug("Getting kubeconfig"); - const kubeconfig = await getKubeconfig( - credsObject, - subscriptionId, - resourceGroupName, - clusterName - ); + // check az tools + const azPath = await io.which(AZ_TOOL_NAME, false); + if (!azPath) + throw Error( + "Az cli tools not installed. You must install them before running this action." + ); - // create file + // get kubeconfig const runnerTempDirectory = process.env["RUNNER_TEMP"]; // use process.env until the core libs are updated const kubeconfigPath = path.join( runnerTempDirectory, `kubeconfig_${Date.now()}` ); core.debug(`Writing kubeconfig to ${kubeconfigPath}`); - fs.writeFileSync(kubeconfigPath, kubeconfig); + await exec.exec( + AZ_TOOL_NAME, + [ + "aks", + "get-credentials", + "--resource-group", + resourceGroupName, + "--name", + clusterName, + "-f", + kubeconfigPath, + ], + { failOnStdErr: true } + ); fs.chmodSync(kubeconfigPath, "600"); - // export + // export variable core.exportVariable("KUBECONFIG", kubeconfigPath); - core.debug("KUBECONFIG environment variable is set"); -} - -export async function getKubeconfig( - creds: { - [key: string]: string; - }, - subscriptionId: string, - resourceGroupName: string, - clusterName: string -): Promise { - const managementEndpointUrl = - creds["resourceManagerEndpointUrl"] || "https://management.azure.com/"; - const azureSessionToken = await getAzureAccessToken(JSON.stringify(creds)); - - return await getAKSKubeconfig( - azureSessionToken, - subscriptionId, - managementEndpointUrl, - resourceGroupName, - clusterName - ); -} - -export function getAKSKubeconfig( - azureSessionToken: string, - subscriptionId: string, - managementEndpointUrl: string, - resourceGroupName: string, - clusterName: string -): Promise { - return new Promise((resolve, reject) => { - const webRequest = new WebRequest(); - webRequest.method = "GET"; - webRequest.uri = `${managementEndpointUrl}/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.ContainerService/managedClusters/${clusterName}/accessProfiles/clusterAdmin?api-version=2017-08-31`; - webRequest.headers = { - Authorization: "Bearer " + azureSessionToken, - "Content-Type": "application/json; charset=utf-8", - }; - - sendRequest(webRequest) - .then((response: WebResponse) => { - const accessProfile = response.body; - if (accessProfile?.properties?.kubeConfig) { - const kubeconfig = Buffer.from( - accessProfile.properties.kubeConfig, - "base64" - ); - resolve(kubeconfig.toString()); - } else { - reject(JSON.stringify(response.body)); - } - }) - .catch(reject); - }); + core.debug("KUBECONFIG environment variable set"); } run().catch(core.setFailed);