зеркало из https://github.com/Azure/k8s-bake.git
Vidya reddy/prettier code (#62)
This commit is contained in:
Родитель
efb25e19ed
Коммит
83c5bf7343
|
@ -4,7 +4,4 @@ about: Create a report to help us improve
|
|||
title: ''
|
||||
labels: need-to-triage
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
name: setting-default-labels
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0/3 * * *"
|
||||
schedule:
|
||||
- cron: '0 0/3 * * *'
|
||||
|
||||
jobs:
|
||||
label-issues:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v3
|
||||
name: Setting issue as idle
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-issue-message: 'This issue is idle because it has been open for 14 days with no activity.'
|
||||
stale-issue-label: 'idle'
|
||||
days-before-stale: 14
|
||||
days-before-close: -1
|
||||
operations-per-run: 100
|
||||
exempt-issue-labels: 'backlog'
|
||||
|
||||
- uses: actions/stale@v3
|
||||
name: Setting PR as idle
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-pr-message: 'This PR is idle because it has been open for 14 days with no activity.'
|
||||
stale-pr-label: 'idle'
|
||||
days-before-stale: 14
|
||||
days-before-close: -1
|
||||
operations-per-run: 100
|
||||
label-issues:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v3
|
||||
name: Setting issue as idle
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-issue-message: 'This issue is idle because it has been open for 14 days with no activity.'
|
||||
stale-issue-label: 'idle'
|
||||
days-before-stale: 14
|
||||
days-before-close: -1
|
||||
operations-per-run: 100
|
||||
exempt-issue-labels: 'backlog'
|
||||
|
||||
- uses: actions/stale@v3
|
||||
name: Setting PR as idle
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-pr-message: 'This PR is idle because it has been open for 14 days with no activity.'
|
||||
stale-pr-label: 'idle'
|
||||
days-before-stale: 14
|
||||
days-before-close: -1
|
||||
operations-per-run: 100
|
||||
|
|
|
@ -1,68 +1,68 @@
|
|||
name: Integration test for k8s-bake-v1
|
||||
on:
|
||||
pull_request:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
run-integration-test:
|
||||
name: Validate release and main branch
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-latest, ubuntu-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2.3.4
|
||||
name: Checkout branch
|
||||
run-integration-test:
|
||||
name: Validate release and main branch
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-latest, ubuntu-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2.3.4
|
||||
name: Checkout branch
|
||||
|
||||
- name: Install npm packages
|
||||
run: |
|
||||
npm install --no-bin-links
|
||||
- name: Install npm packages
|
||||
run: |
|
||||
npm install --no-bin-links
|
||||
|
||||
- name: Install ncc
|
||||
run: npm i -g @vercel/ncc
|
||||
|
||||
- name: Build
|
||||
run: ncc build src/run.ts -o lib
|
||||
- name: Install ncc
|
||||
run: npm i -g @vercel/ncc
|
||||
|
||||
- name: Bake using Helm on ${{ matrix.os }}
|
||||
uses: ./
|
||||
with:
|
||||
renderEngine: "helm"
|
||||
helmChart: "./testResources/Helm/HelmCharts"
|
||||
helm-version: "latest"
|
||||
silent: "false"
|
||||
namespace: "namespaceExample"
|
||||
overrideFiles: "./testResources/Helm/values.yaml"
|
||||
overrides: |
|
||||
serviceName:aks-helloworld-test
|
||||
id: helm-bake
|
||||
- name: Build
|
||||
run: ncc build src/run.ts -o lib
|
||||
|
||||
- name: Validate created manifest ${{ matrix.os }}
|
||||
uses: Azure/k8s-lint@v1
|
||||
with:
|
||||
manifests: ${{ steps.helm-bake.outputs.manifestsBundle }}
|
||||
- name: Bake using Helm on ${{ matrix.os }}
|
||||
uses: ./
|
||||
with:
|
||||
renderEngine: 'helm'
|
||||
helmChart: './testResources/Helm/HelmCharts'
|
||||
helm-version: 'latest'
|
||||
silent: 'false'
|
||||
namespace: 'namespaceExample'
|
||||
overrideFiles: './testResources/Helm/values.yaml'
|
||||
overrides: |
|
||||
serviceName:aks-helloworld-test
|
||||
id: helm-bake
|
||||
|
||||
- name: Executing latest changes on ${{ matrix.os }}
|
||||
uses: ./
|
||||
with:
|
||||
renderEngine: "kompose"
|
||||
dockerComposeFile: "./testResources/Kompose/docker-compose.yml"
|
||||
kompose-version: "latest"
|
||||
id: kompose-bake
|
||||
- name: Validate created manifest ${{ matrix.os }}
|
||||
uses: Azure/k8s-lint@v1
|
||||
with:
|
||||
manifests: ${{ steps.helm-bake.outputs.manifestsBundle }}
|
||||
|
||||
- name: validate created manifest ${{ matrix.os }}
|
||||
uses: Azure/k8s-lint@v1
|
||||
with:
|
||||
manifests: ${{ steps.kompose-bake.outputs.manifestsBundle }}
|
||||
- name: Executing latest changes on ${{ matrix.os }}
|
||||
uses: ./
|
||||
with:
|
||||
renderEngine: 'kompose'
|
||||
dockerComposeFile: './testResources/Kompose/docker-compose.yml'
|
||||
kompose-version: 'latest'
|
||||
id: kompose-bake
|
||||
|
||||
- name: Bake using Kustomize on ${{ matrix.os }}
|
||||
uses: ./
|
||||
with:
|
||||
renderEngine: "kustomize"
|
||||
kustomizationPath: "./testResources/Kustomize"
|
||||
kubectl-version: "latest"
|
||||
id: kustomize-bake
|
||||
- name: validate created manifest ${{ matrix.os }}
|
||||
uses: Azure/k8s-lint@v1
|
||||
with:
|
||||
manifests: ${{ steps.kompose-bake.outputs.manifestsBundle }}
|
||||
|
||||
- name: Validate created manifest ${{ matrix.os }}
|
||||
uses: Azure/k8s-lint@v1
|
||||
with:
|
||||
manifests: ${{ steps.kustomize-bake.outputs.manifestsBundle }}
|
||||
- name: Bake using Kustomize on ${{ matrix.os }}
|
||||
uses: ./
|
||||
with:
|
||||
renderEngine: 'kustomize'
|
||||
kustomizationPath: './testResources/Kustomize'
|
||||
kubectl-version: 'latest'
|
||||
id: kustomize-bake
|
||||
|
||||
- name: Validate created manifest ${{ matrix.os }}
|
||||
uses: Azure/k8s-lint@v1
|
||||
with:
|
||||
manifests: ${{ steps.kustomize-bake.outputs.manifestsBundle }}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
name: 'Run prettify'
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
prettier:
|
||||
name: Prettier Check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Enforce Prettier
|
||||
uses: actionsx/prettier@v2
|
||||
with:
|
||||
args: --check .
|
|
@ -1,14 +1,14 @@
|
|||
name: Create release PR
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release:
|
||||
description: "Define release version (ex: v1, v2, v3)"
|
||||
required: true
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release:
|
||||
description: 'Define release version (ex: v1, v2, v3)'
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
release-pr:
|
||||
uses: OliverMKing/javascript-release-workflow/.github/workflows/release-pr.yml@main
|
||||
with:
|
||||
release: ${{ github.event.inputs.release }}
|
||||
release-pr:
|
||||
uses: OliverMKing/javascript-release-workflow/.github/workflows/release-pr.yml@main
|
||||
with:
|
||||
release: ${{ github.event.inputs.release }}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
name: Tag and create release draft
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- releases/*
|
||||
push:
|
||||
branches:
|
||||
- releases/*
|
||||
|
||||
jobs:
|
||||
tag-and-release:
|
||||
uses: OliverMKing/javascript-release-workflow/.github/workflows/tag-and-release.yml@main
|
||||
tag-and-release:
|
||||
uses: OliverMKing/javascript-release-workflow/.github/workflows/tag-and-release.yml@main
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
name: "Run unit tests."
|
||||
name: 'Run unit tests.'
|
||||
on: # rebuild any PRs and main branch changes
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- "releases/*"
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- "releases/*"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- 'releases/*'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- 'releases/*'
|
||||
|
||||
jobs:
|
||||
build: # make sure build/ci works properly
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Running L0 tests.
|
||||
run: |
|
||||
sudo npm install n
|
||||
sudo n latest
|
||||
npm install
|
||||
npm test
|
||||
build: # make sure build/ci works properly
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Running L0 tests.
|
||||
run: |
|
||||
sudo npm install n
|
||||
sudo n latest
|
||||
npm install
|
||||
npm test
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
# dependencies
|
||||
/node_modules
|
||||
coverage
|
||||
/lib
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": false,
|
||||
"semi": false,
|
||||
"tabWidth": 3,
|
||||
"singleQuote": true,
|
||||
"printWidth": 80
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
# Microsoft Open Source Code of Conduct
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
|
||||
Resources:
|
||||
|
||||
- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
|
||||
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
|
||||
- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
|
||||
# Microsoft Open Source Code of Conduct
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
|
||||
Resources:
|
||||
|
||||
- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
|
||||
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
|
||||
- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# 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.
|
||||
|
||||
|
|
94
README.md
94
README.md
|
@ -13,7 +13,7 @@ Sets output variable 'manifestsBundle' which contains the location of the manife
|
|||
with:
|
||||
renderEngine: 'helm'
|
||||
helmChart: './aks-helloworld/'
|
||||
arguments: |
|
||||
arguments: |
|
||||
--ca-file
|
||||
./ca-file/
|
||||
overrideFiles: './aks-helloworld/values-override.yaml'
|
||||
|
@ -28,9 +28,9 @@ Sets output variable 'manifestsBundle' which contains the location of the manife
|
|||
```yaml
|
||||
- uses: azure/k8s-bake@v2.2
|
||||
with:
|
||||
renderEngine: "kompose"
|
||||
dockerComposeFile: "./docker-compose.yml"
|
||||
kompose-version: "latest"
|
||||
renderEngine: 'kompose'
|
||||
dockerComposeFile: './docker-compose.yml'
|
||||
kompose-version: 'latest'
|
||||
```
|
||||
|
||||
#### Bake using Kubernetes Kustomize
|
||||
|
@ -38,12 +38,12 @@ Sets output variable 'manifestsBundle' which contains the location of the manife
|
|||
```yaml
|
||||
- uses: azure/k8s-bake@v2.2
|
||||
with:
|
||||
renderEngine: "kustomize"
|
||||
kustomizationPath: "./kustomizeexample/"
|
||||
arguments: |
|
||||
--ca-file
|
||||
./ca-file/
|
||||
kubectl-version: "latest"
|
||||
renderEngine: 'kustomize'
|
||||
kustomizationPath: './kustomizeexample/'
|
||||
arguments: |
|
||||
--ca-file
|
||||
./ca-file/
|
||||
kubectl-version: 'latest'
|
||||
```
|
||||
|
||||
Refer to the [action metadata file](https://github.com/Azure/k8s-bake/blob/master/action.yml) for details about all the inputs.
|
||||
|
@ -54,49 +54,49 @@ Refer to the [action metadata file](https://github.com/Azure/k8s-bake/blob/maste
|
|||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
|
||||
- uses: Azure/docker-login@v1
|
||||
with:
|
||||
login-server: contoso.azurecr.io
|
||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
- uses: Azure/docker-login@v1
|
||||
with:
|
||||
login-server: contoso.azurecr.io
|
||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
|
||||
- run: |
|
||||
docker build . -t contoso.azurecr.io/k8sdemo:${{ github.sha }}
|
||||
docker push contoso.azurecr.io/k8sdemo:${{ github.sha }}
|
||||
- run: |
|
||||
docker build . -t contoso.azurecr.io/k8sdemo:${{ github.sha }}
|
||||
docker push contoso.azurecr.io/k8sdemo:${{ github.sha }}
|
||||
|
||||
- uses: Azure/k8s-set-context@v1
|
||||
with:
|
||||
kubeconfig: ${{ secrets.KUBE_CONFIG }}
|
||||
- uses: Azure/k8s-set-context@v1
|
||||
with:
|
||||
kubeconfig: ${{ secrets.KUBE_CONFIG }}
|
||||
|
||||
- uses: Azure/k8s-create-secret@v1
|
||||
with:
|
||||
container-registry-url: contoso.azurecr.io
|
||||
container-registry-username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
container-registry-password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
secret-name: demo-k8s-secret
|
||||
- uses: Azure/k8s-create-secret@v1
|
||||
with:
|
||||
container-registry-url: contoso.azurecr.io
|
||||
container-registry-username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
container-registry-password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
secret-name: demo-k8s-secret
|
||||
|
||||
- uses: azure/k8s-bake@v2.2
|
||||
with:
|
||||
renderEngine: "helm"
|
||||
helmChart: "./aks-helloworld/"
|
||||
overrideFiles: "./aks-helloworld/values-override.yaml"
|
||||
overrides: |
|
||||
replicas:2
|
||||
helm-version: "latest"
|
||||
id: bake
|
||||
- uses: azure/k8s-bake@v2.2
|
||||
with:
|
||||
renderEngine: 'helm'
|
||||
helmChart: './aks-helloworld/'
|
||||
overrideFiles: './aks-helloworld/values-override.yaml'
|
||||
overrides: |
|
||||
replicas:2
|
||||
helm-version: 'latest'
|
||||
id: bake
|
||||
|
||||
- uses: Azure/k8s-deploy@v1
|
||||
with:
|
||||
manifests: ${{ steps.bake.outputs.manifestsBundle }}
|
||||
images: |
|
||||
demo.azurecr.io/k8sdemo:${{ github.sha }}
|
||||
imagepullsecrets: |
|
||||
demo-k8s-secret
|
||||
- uses: Azure/k8s-deploy@v1
|
||||
with:
|
||||
manifests: ${{ steps.bake.outputs.manifestsBundle }}
|
||||
images: |
|
||||
demo.azurecr.io/k8sdemo:${{ github.sha }}
|
||||
imagepullsecrets: |
|
||||
demo-k8s-secret
|
||||
```
|
||||
|
||||
# Contributing
|
||||
|
|
82
SECURITY.md
82
SECURITY.md
|
@ -1,41 +1,41 @@
|
|||
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.3 BLOCK -->
|
||||
|
||||
## Security
|
||||
|
||||
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
|
||||
|
||||
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below.
|
||||
|
||||
## Reporting Security Issues
|
||||
|
||||
**Please do not report security vulnerabilities through public GitHub issues.**
|
||||
|
||||
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
|
||||
|
||||
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
|
||||
|
||||
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
|
||||
|
||||
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
|
||||
|
||||
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
||||
* Full paths of source file(s) related to the manifestation of the issue
|
||||
* The location of the affected source code (tag/branch/commit or direct URL)
|
||||
* Any special configuration required to reproduce the issue
|
||||
* Step-by-step instructions to reproduce the issue
|
||||
* Proof-of-concept or exploit code (if possible)
|
||||
* Impact of the issue, including how an attacker might exploit the issue
|
||||
|
||||
This information will help us triage your report more quickly.
|
||||
|
||||
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs.
|
||||
|
||||
## Preferred Languages
|
||||
|
||||
We prefer all communications to be in English.
|
||||
|
||||
## Policy
|
||||
|
||||
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
|
||||
|
||||
<!-- END MICROSOFT SECURITY.MD BLOCK -->
|
||||
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.3 BLOCK -->
|
||||
|
||||
## Security
|
||||
|
||||
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
|
||||
|
||||
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](<https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)>) of a security vulnerability, please report it to us as described below.
|
||||
|
||||
## Reporting Security Issues
|
||||
|
||||
**Please do not report security vulnerabilities through public GitHub issues.**
|
||||
|
||||
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
|
||||
|
||||
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
|
||||
|
||||
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
|
||||
|
||||
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
|
||||
|
||||
- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
||||
- Full paths of source file(s) related to the manifestation of the issue
|
||||
- The location of the affected source code (tag/branch/commit or direct URL)
|
||||
- Any special configuration required to reproduce the issue
|
||||
- Step-by-step instructions to reproduce the issue
|
||||
- Proof-of-concept or exploit code (if possible)
|
||||
- Impact of the issue, including how an attacker might exploit the issue
|
||||
|
||||
This information will help us triage your report more quickly.
|
||||
|
||||
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs.
|
||||
|
||||
## Preferred Languages
|
||||
|
||||
We prefer all communications to be in English.
|
||||
|
||||
## Policy
|
||||
|
||||
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
|
||||
|
||||
<!-- END MICROSOFT SECURITY.MD BLOCK -->
|
||||
|
|
91
action.yml
91
action.yml
|
@ -1,49 +1,50 @@
|
|||
name: "Kubernetes bake"
|
||||
description: "Use this action to bake manifest file to be used for deployments using helm, kustomize or kompose"
|
||||
name: 'Kubernetes bake'
|
||||
description: 'Use this action to bake manifest file to be used for deployments using helm, kustomize or kompose'
|
||||
inputs:
|
||||
renderEngine:
|
||||
description: "Acceptable values: helm or kompose or kustomize"
|
||||
required: true
|
||||
helmChart:
|
||||
description: "Required if renderEngine == helm. Helm chart to bake."
|
||||
required: false
|
||||
namespace:
|
||||
description: "Relevant if renderEngine == helm. Namespace to be used for Helm option."
|
||||
arguments:
|
||||
description: "Acceptable values: helm or kustomize. Arguments to be passed to the Helm or kustomize template command"
|
||||
required: false
|
||||
overrideFiles:
|
||||
description: "Relevant if renderEngine == helm. Array of path to override files. Each path should be mentioned on a newline"
|
||||
required: false
|
||||
overrides:
|
||||
description: "Relevant if renderEngine == helm. Override values to set."
|
||||
required: false
|
||||
releaseName:
|
||||
description: "Relevant if renderEngine == helm. Release name to be used for Helm option."
|
||||
required: false
|
||||
kustomizationPath:
|
||||
description: "Required if renderEngine == kustomization. Path to directory or the Git repository containing kustomization.yaml file."
|
||||
required: false
|
||||
dockerComposeFile:
|
||||
description: "Required if renderEngine == kompose. Path(s) to Docker compose files"
|
||||
required: false
|
||||
helm-version:
|
||||
description: "Version of kubectl. Installs a specific version of helm binary"
|
||||
required: false
|
||||
kubectl-version:
|
||||
description: "Version of kubectl. Installs a specific version of kubectl binary"
|
||||
required: false
|
||||
kompose-version:
|
||||
description: "Version of kubectl. Installs a specific version of kompose binary"
|
||||
required: false
|
||||
silent:
|
||||
description: "When set to true, the output of the bake command would not be shown."
|
||||
required: false
|
||||
renderEngine:
|
||||
description: 'Acceptable values: helm or kompose or kustomize'
|
||||
required: true
|
||||
helmChart:
|
||||
description: 'Required if renderEngine == helm. Helm chart to bake.'
|
||||
required: false
|
||||
namespace:
|
||||
description: 'Relevant if renderEngine == helm. Namespace to be used for Helm option.'
|
||||
arguments:
|
||||
description: 'Acceptable values: helm or kustomize. Arguments to be passed to the Helm or kustomize template command'
|
||||
required: false
|
||||
overrideFiles:
|
||||
description: 'Relevant if renderEngine == helm. Array of path to override files. Each path should be mentioned on a newline'
|
||||
required: false
|
||||
overrides:
|
||||
description: 'Relevant if renderEngine == helm. Override values to set.'
|
||||
required: false
|
||||
releaseName:
|
||||
description: 'Relevant if renderEngine == helm. Release name to be used for Helm option.'
|
||||
required: false
|
||||
kustomizationPath:
|
||||
description: 'Required if renderEngine == kustomization. Path to directory or the Git repository containing kustomization.yaml file.'
|
||||
required: false
|
||||
dockerComposeFile:
|
||||
description: 'Required if renderEngine == kompose. Path(s) to Docker compose files'
|
||||
required: false
|
||||
helm-version:
|
||||
description: 'Version of kubectl. Installs a specific version of helm binary'
|
||||
required: false
|
||||
kubectl-version:
|
||||
description: 'Version of kubectl. Installs a specific version of kubectl binary'
|
||||
required: false
|
||||
kompose-version:
|
||||
description: 'Version of kubectl. Installs a specific version of kompose binary'
|
||||
required: false
|
||||
silent:
|
||||
description: 'When set to true, the output of the bake command would not be shown.'
|
||||
required: false
|
||||
|
||||
outputs:
|
||||
manifestsBundle:
|
||||
description: "The location of the manifest bundles created by bake action"
|
||||
manifestsBundle:
|
||||
description: 'The location of the manifest bundles created by bake action'
|
||||
branding:
|
||||
color: "green" # optional, decorates the entry in the GitHub Marketplace
|
||||
color: 'green' # optional, decorates the entry in the GitHub Marketplace
|
||||
runs:
|
||||
using: "node16"
|
||||
main: "lib/index.js"
|
||||
using: 'node16'
|
||||
main: 'lib/index.js'
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
module.exports = {
|
||||
clearMocks: true,
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/*.test.ts'],
|
||||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest'
|
||||
},
|
||||
verbose: true,
|
||||
coverageThreshold: {
|
||||
"global": {
|
||||
"branches": 0,
|
||||
"functions": 14,
|
||||
"lines": 27,
|
||||
"statements": 27
|
||||
}
|
||||
}
|
||||
}
|
||||
clearMocks: true,
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/*.test.ts'],
|
||||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest'
|
||||
},
|
||||
verbose: true,
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
branches: 0,
|
||||
functions: 14,
|
||||
lines: 27,
|
||||
statements: 27
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
51
package.json
51
package.json
|
@ -1,26 +1,29 @@
|
|||
{
|
||||
"name": "k8sbake",
|
||||
"version": "1.0.0",
|
||||
"description": "Kubernetes Bake",
|
||||
"author": "Anumita Shenoy",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.6.0",
|
||||
"@actions/exec": "^1.1.0",
|
||||
"@actions/io": "^1.1.1",
|
||||
"@actions/tool-cache": "^1.7.1"
|
||||
},
|
||||
"main": "lib/run.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "jest",
|
||||
"test-coverage": "jest --coverage"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^27.0.2",
|
||||
"@types/node": "^16.11.7",
|
||||
"jest": "^27.3.1",
|
||||
"ts-jest": "^27.0.7",
|
||||
"typescript": "^4.4.4"
|
||||
}
|
||||
"name": "k8sbake",
|
||||
"version": "1.0.0",
|
||||
"description": "Kubernetes Bake",
|
||||
"author": "Anumita Shenoy",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.6.0",
|
||||
"@actions/exec": "^1.1.0",
|
||||
"@actions/io": "^1.1.1",
|
||||
"@actions/tool-cache": "^1.7.1"
|
||||
},
|
||||
"main": "lib/run.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "jest",
|
||||
"test-coverage": "jest --coverage",
|
||||
"format": "prettier --write .",
|
||||
"format-check": "prettier --check ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^27.0.2",
|
||||
"@types/node": "^16.11.7",
|
||||
"jest": "^27.3.1",
|
||||
"prettier": "2.7.1",
|
||||
"ts-jest": "^27.0.7",
|
||||
"typescript": "^4.4.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,222 +1,316 @@
|
|||
import * as helmUtil from './helm-util';
|
||||
import * as os from 'os';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as toolCache from '@actions/tool-cache';
|
||||
import * as core from '@actions/core';
|
||||
import * as io from '@actions/io';
|
||||
import * as utils from './utilities';
|
||||
|
||||
import * as helmUtil from './helm-util'
|
||||
import * as os from 'os'
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import * as toolCache from '@actions/tool-cache'
|
||||
import * as core from '@actions/core'
|
||||
import * as io from '@actions/io'
|
||||
import * as utils from './utilities'
|
||||
|
||||
describe('Testing all funcitons in helm-util file.', () => {
|
||||
|
||||
test('walkSync() - return path to the all files matching fileToFind in dir', () => {
|
||||
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
|
||||
if (file == 'mainFolder') return ['file1' as unknown as fs.Dirent, 'file2' as unknown as fs.Dirent, 'folder1' as unknown as fs.Dirent, 'folder2' as unknown as fs.Dirent];
|
||||
if (file == path.join('mainFolder', 'folder1')) return ['file11' as unknown as fs.Dirent, 'file12' as unknown as fs.Dirent];
|
||||
if (file == path.join('mainFolder', 'folder2')) return ['file21' as unknown as fs.Dirent, 'file22' as unknown as fs.Dirent];
|
||||
});
|
||||
jest.spyOn(core, 'debug').mockImplementation();
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory = (file as string).toLowerCase().indexOf('file') == -1 ? true: false
|
||||
return { isDirectory: () => isDirectory } as fs.Stats;
|
||||
});
|
||||
test('walkSync() - return path to the all files matching fileToFind in dir', () => {
|
||||
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
|
||||
if (file == 'mainFolder')
|
||||
return [
|
||||
'file1' as unknown as fs.Dirent,
|
||||
'file2' as unknown as fs.Dirent,
|
||||
'folder1' as unknown as fs.Dirent,
|
||||
'folder2' as unknown as fs.Dirent
|
||||
]
|
||||
if (file == path.join('mainFolder', 'folder1'))
|
||||
return [
|
||||
'file11' as unknown as fs.Dirent,
|
||||
'file12' as unknown as fs.Dirent
|
||||
]
|
||||
if (file == path.join('mainFolder', 'folder2'))
|
||||
return [
|
||||
'file21' as unknown as fs.Dirent,
|
||||
'file22' as unknown as fs.Dirent
|
||||
]
|
||||
})
|
||||
jest.spyOn(core, 'debug').mockImplementation()
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory =
|
||||
(file as string).toLowerCase().indexOf('file') == -1 ? true : false
|
||||
return {isDirectory: () => isDirectory} as fs.Stats
|
||||
})
|
||||
|
||||
expect(helmUtil.walkSync('mainFolder', undefined, 'file21')).toEqual([path.join('mainFolder', 'folder2', 'file21')]);
|
||||
expect(fs.readdirSync).toBeCalledTimes(3);
|
||||
expect(fs.statSync).toBeCalledTimes(8);
|
||||
});
|
||||
expect(helmUtil.walkSync('mainFolder', undefined, 'file21')).toEqual([
|
||||
path.join('mainFolder', 'folder2', 'file21')
|
||||
])
|
||||
expect(fs.readdirSync).toBeCalledTimes(3)
|
||||
expect(fs.statSync).toBeCalledTimes(8)
|
||||
})
|
||||
|
||||
test('walkSync() - return empty array if no file with name fileToFind exists', () => {
|
||||
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
|
||||
if (file == 'mainFolder') return ['file1' as unknown as fs.Dirent, 'file2' as unknown as fs.Dirent, 'folder1' as unknown as fs.Dirent, 'folder2' as unknown as fs.Dirent];
|
||||
if (file == path.join('mainFolder', 'folder1')) return ['file11' as unknown as fs.Dirent, 'file12' as unknown as fs.Dirent];
|
||||
if (file == path.join('mainFolder', 'folder2')) return ['file21' as unknown as fs.Dirent, 'file22' as unknown as fs.Dirent];
|
||||
});
|
||||
jest.spyOn(core, 'debug').mockImplementation();
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory = (file as string).toLowerCase().indexOf('file') == -1 ? true: false
|
||||
return { isDirectory: () => isDirectory } as fs.Stats;
|
||||
});
|
||||
test('walkSync() - return empty array if no file with name fileToFind exists', () => {
|
||||
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
|
||||
if (file == 'mainFolder')
|
||||
return [
|
||||
'file1' as unknown as fs.Dirent,
|
||||
'file2' as unknown as fs.Dirent,
|
||||
'folder1' as unknown as fs.Dirent,
|
||||
'folder2' as unknown as fs.Dirent
|
||||
]
|
||||
if (file == path.join('mainFolder', 'folder1'))
|
||||
return [
|
||||
'file11' as unknown as fs.Dirent,
|
||||
'file12' as unknown as fs.Dirent
|
||||
]
|
||||
if (file == path.join('mainFolder', 'folder2'))
|
||||
return [
|
||||
'file21' as unknown as fs.Dirent,
|
||||
'file22' as unknown as fs.Dirent
|
||||
]
|
||||
})
|
||||
jest.spyOn(core, 'debug').mockImplementation()
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory =
|
||||
(file as string).toLowerCase().indexOf('file') == -1 ? true : false
|
||||
return {isDirectory: () => isDirectory} as fs.Stats
|
||||
})
|
||||
|
||||
expect(helmUtil.walkSync('mainFolder', undefined, 'helm.exe')).toEqual([]);
|
||||
expect(fs.readdirSync).toBeCalledTimes(3);
|
||||
expect(fs.statSync).toBeCalledTimes(8);
|
||||
});
|
||||
expect(helmUtil.walkSync('mainFolder', undefined, 'helm.exe')).toEqual([])
|
||||
expect(fs.readdirSync).toBeCalledTimes(3)
|
||||
expect(fs.statSync).toBeCalledTimes(8)
|
||||
})
|
||||
|
||||
test('downloadHelm() - throw error when unable to download', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('');
|
||||
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => { throw 'Unable to download.'});
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
jest.spyOn(core, 'debug').mockImplementation();
|
||||
test('downloadHelm() - throw error when unable to download', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('')
|
||||
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => {
|
||||
throw 'Unable to download.'
|
||||
})
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
jest.spyOn(core, 'debug').mockImplementation()
|
||||
|
||||
await expect(helmUtil.downloadHelm('v2.14.1')).rejects.toThrow('Failed to download the helm from https://get.helm.sh/helm-v2.14.1-windows-amd64.zip. Error: Unable to download.');
|
||||
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1');
|
||||
expect(toolCache.downloadTool).toBeCalledWith('https://get.helm.sh/helm-v2.14.1-windows-amd64.zip');
|
||||
});
|
||||
await expect(helmUtil.downloadHelm('v2.14.1')).rejects.toThrow(
|
||||
'Failed to download the helm from https://get.helm.sh/helm-v2.14.1-windows-amd64.zip. Error: Unable to download.'
|
||||
)
|
||||
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1')
|
||||
expect(toolCache.downloadTool).toBeCalledWith(
|
||||
'https://get.helm.sh/helm-v2.14.1-windows-amd64.zip'
|
||||
)
|
||||
})
|
||||
|
||||
test('downloadHelm() - find helm executable in toolCache and return path', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir');
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent]);
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory = (file as string).indexOf('folder') == -1 ? false: true
|
||||
return { isDirectory: () => isDirectory } as fs.Stats;
|
||||
});
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {});
|
||||
jest.spyOn(core, 'debug').mockImplementation();
|
||||
test('downloadHelm() - find helm executable in toolCache and return path', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir')
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
jest
|
||||
.spyOn(fs, 'readdirSync')
|
||||
.mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent])
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory =
|
||||
(file as string).indexOf('folder') == -1 ? false : true
|
||||
return {isDirectory: () => isDirectory} as fs.Stats
|
||||
})
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
|
||||
jest.spyOn(core, 'debug').mockImplementation()
|
||||
|
||||
expect(await helmUtil.downloadHelm('v2.14.1')).toBe(path.join('pathToCachedDir', 'helm.exe'));
|
||||
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1');
|
||||
expect(fs.chmodSync).toBeCalledWith(path.join('pathToCachedDir', 'helm.exe'), '777');
|
||||
});
|
||||
expect(await helmUtil.downloadHelm('v2.14.1')).toBe(
|
||||
path.join('pathToCachedDir', 'helm.exe')
|
||||
)
|
||||
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1')
|
||||
expect(fs.chmodSync).toBeCalledWith(
|
||||
path.join('pathToCachedDir', 'helm.exe'),
|
||||
'777'
|
||||
)
|
||||
})
|
||||
|
||||
test('downloadHelm() - throw error if helm executable not found in cache', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('');
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {});
|
||||
jest.spyOn(toolCache, 'extractZip').mockResolvedValue('pathToUnzippedHelm');
|
||||
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir');
|
||||
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => []);
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory = (file as string).indexOf('folder') == -1 ? false: true
|
||||
return { isDirectory: () => isDirectory } as fs.Stats;
|
||||
});
|
||||
test('downloadHelm() - throw error if helm executable not found in cache', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('')
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
|
||||
jest
|
||||
.spyOn(toolCache, 'extractZip')
|
||||
.mockResolvedValue('pathToUnzippedHelm')
|
||||
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir')
|
||||
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => [])
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory =
|
||||
(file as string).indexOf('folder') == -1 ? false : true
|
||||
return {isDirectory: () => isDirectory} as fs.Stats
|
||||
})
|
||||
|
||||
await expect(helmUtil.downloadHelm('v2.14.1')).rejects.toThrow('Helm executable not found in path pathToCachedDir');
|
||||
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1');
|
||||
expect(toolCache.downloadTool).toBeCalledWith('https://get.helm.sh/helm-v2.14.1-windows-amd64.zip');
|
||||
expect(fs.chmodSync).toBeCalledWith('pathToTool', '777');
|
||||
expect(toolCache.extractZip).toBeCalledWith('pathToTool');
|
||||
});
|
||||
await expect(helmUtil.downloadHelm('v2.14.1')).rejects.toThrow(
|
||||
'Helm executable not found in path pathToCachedDir'
|
||||
)
|
||||
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1')
|
||||
expect(toolCache.downloadTool).toBeCalledWith(
|
||||
'https://get.helm.sh/helm-v2.14.1-windows-amd64.zip'
|
||||
)
|
||||
expect(fs.chmodSync).toBeCalledWith('pathToTool', '777')
|
||||
expect(toolCache.extractZip).toBeCalledWith('pathToTool')
|
||||
})
|
||||
|
||||
test('downloadHelm() - get stable version of helm, download and return path', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('');
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
|
||||
const response = JSON.stringify({
|
||||
'tag_name': 'v4.0.0'
|
||||
});
|
||||
jest.spyOn(fs, 'readFileSync').mockReturnValue(response);
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {});
|
||||
jest.spyOn(toolCache, 'extractZip').mockResolvedValue('pathToUnzippedHelm');
|
||||
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir');
|
||||
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent]);
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory = (file as string).indexOf('folder') == -1 ? false: true
|
||||
return { isDirectory: () => isDirectory } as fs.Stats;
|
||||
});
|
||||
test('downloadHelm() - get stable version of helm, download and return path', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('')
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
|
||||
const response = JSON.stringify({
|
||||
tag_name: 'v4.0.0'
|
||||
})
|
||||
jest.spyOn(fs, 'readFileSync').mockReturnValue(response)
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
|
||||
jest
|
||||
.spyOn(toolCache, 'extractZip')
|
||||
.mockResolvedValue('pathToUnzippedHelm')
|
||||
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir')
|
||||
jest
|
||||
.spyOn(fs, 'readdirSync')
|
||||
.mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent])
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory =
|
||||
(file as string).indexOf('folder') == -1 ? false : true
|
||||
return {isDirectory: () => isDirectory} as fs.Stats
|
||||
})
|
||||
|
||||
expect(await helmUtil.downloadHelm(null)).toBe(path.join('pathToCachedDir', 'helm.exe'));
|
||||
expect(toolCache.find).toBeCalledWith('helm', 'v4.0.0');
|
||||
expect(toolCache.downloadTool).toBeCalledWith('https://get.helm.sh/helm-v4.0.0-windows-amd64.zip');
|
||||
expect(fs.chmodSync).toBeCalledWith('pathToTool', '777');
|
||||
expect(toolCache.extractZip).toBeCalledWith('pathToTool');
|
||||
expect(fs.chmodSync).toBeCalledWith(path.join('pathToCachedDir', 'helm.exe'), '777');
|
||||
});
|
||||
expect(await helmUtil.downloadHelm(null)).toBe(
|
||||
path.join('pathToCachedDir', 'helm.exe')
|
||||
)
|
||||
expect(toolCache.find).toBeCalledWith('helm', 'v4.0.0')
|
||||
expect(toolCache.downloadTool).toBeCalledWith(
|
||||
'https://get.helm.sh/helm-v4.0.0-windows-amd64.zip'
|
||||
)
|
||||
expect(fs.chmodSync).toBeCalledWith('pathToTool', '777')
|
||||
expect(toolCache.extractZip).toBeCalledWith('pathToTool')
|
||||
expect(fs.chmodSync).toBeCalledWith(
|
||||
path.join('pathToCachedDir', 'helm.exe'),
|
||||
'777'
|
||||
)
|
||||
})
|
||||
|
||||
test('installHelm() - download specified version helm and return its path', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir');
|
||||
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => { throw 'Unable to download'});
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent]);
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory = (file as string).indexOf('folder') == -1 ? false: true
|
||||
return { isDirectory: () => isDirectory } as fs.Stats;
|
||||
});
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {});
|
||||
jest.spyOn(core, 'debug').mockImplementation();
|
||||
test('installHelm() - download specified version helm and return its path', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir')
|
||||
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => {
|
||||
throw 'Unable to download'
|
||||
})
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
jest
|
||||
.spyOn(fs, 'readdirSync')
|
||||
.mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent])
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory =
|
||||
(file as string).indexOf('folder') == -1 ? false : true
|
||||
return {isDirectory: () => isDirectory} as fs.Stats
|
||||
})
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
|
||||
jest.spyOn(core, 'debug').mockImplementation()
|
||||
|
||||
expect(await helmUtil.installHelm('v2.14.1')).toBe(path.join('pathToCachedDir', 'helm.exe'));
|
||||
});
|
||||
expect(await helmUtil.installHelm('v2.14.1')).toBe(
|
||||
path.join('pathToCachedDir', 'helm.exe')
|
||||
)
|
||||
})
|
||||
|
||||
test('installHelm() - get latest version of helm and return its path', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('');
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
|
||||
const response = JSON.stringify({
|
||||
'tag_name': 'v4.0.0'
|
||||
});
|
||||
jest.spyOn(fs, 'readFileSync').mockReturnValue(response);
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {});
|
||||
jest.spyOn(toolCache, 'extractZip').mockResolvedValue('pathToUnzippedHelm');
|
||||
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir');
|
||||
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent]);
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory = (file as string).indexOf('folder') == -1 ? false: true
|
||||
return { isDirectory: () => isDirectory } as fs.Stats;
|
||||
});
|
||||
jest.spyOn(core, 'debug').mockImplementation();
|
||||
test('installHelm() - get latest version of helm and return its path', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('')
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
|
||||
const response = JSON.stringify({
|
||||
tag_name: 'v4.0.0'
|
||||
})
|
||||
jest.spyOn(fs, 'readFileSync').mockReturnValue(response)
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
|
||||
jest
|
||||
.spyOn(toolCache, 'extractZip')
|
||||
.mockResolvedValue('pathToUnzippedHelm')
|
||||
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir')
|
||||
jest
|
||||
.spyOn(fs, 'readdirSync')
|
||||
.mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent])
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory =
|
||||
(file as string).indexOf('folder') == -1 ? false : true
|
||||
return {isDirectory: () => isDirectory} as fs.Stats
|
||||
})
|
||||
jest.spyOn(core, 'debug').mockImplementation()
|
||||
|
||||
expect(await helmUtil.installHelm('latest')).toBe(path.join('pathToCachedDir', 'helm.exe'));
|
||||
});
|
||||
expect(await helmUtil.installHelm('latest')).toBe(
|
||||
path.join('pathToCachedDir', 'helm.exe')
|
||||
)
|
||||
})
|
||||
|
||||
test('getHelmPath() - download helm and return its path', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('v2.14.1');
|
||||
jest.spyOn(toolCache, 'find').mockReturnValueOnce('').mockReturnValueOnce('pathToCachedDir');
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent]);
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory = (file as string).indexOf('folder') == -1 ? false: true
|
||||
return { isDirectory: () => isDirectory } as fs.Stats;
|
||||
});
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation();
|
||||
test('getHelmPath() - download helm and return its path', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('v2.14.1')
|
||||
jest
|
||||
.spyOn(toolCache, 'find')
|
||||
.mockReturnValueOnce('')
|
||||
.mockReturnValueOnce('pathToCachedDir')
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
jest
|
||||
.spyOn(fs, 'readdirSync')
|
||||
.mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent])
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory =
|
||||
(file as string).indexOf('folder') == -1 ? false : true
|
||||
return {isDirectory: () => isDirectory} as fs.Stats
|
||||
})
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation()
|
||||
|
||||
expect(await helmUtil.getHelmPath()).toBe(path.join('pathToCachedDir', 'helm.exe'));
|
||||
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1');
|
||||
});
|
||||
expect(await helmUtil.getHelmPath()).toBe(
|
||||
path.join('pathToCachedDir', 'helm.exe')
|
||||
)
|
||||
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1')
|
||||
})
|
||||
|
||||
test('getHelmPath() - return helm From toolCache', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('v2.14.1');
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToTool');
|
||||
test('getHelmPath() - return helm From toolCache', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('v2.14.1')
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToTool')
|
||||
|
||||
expect(await helmUtil.getHelmPath()).toBe('pathToTool');
|
||||
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1');
|
||||
});
|
||||
expect(await helmUtil.getHelmPath()).toBe('pathToTool')
|
||||
expect(toolCache.find).toBeCalledWith('helm', 'v2.14.1')
|
||||
})
|
||||
|
||||
test('getHelmPath() - return path any version helm executable if version input not specified', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('');
|
||||
jest.spyOn(io, 'which').mockResolvedValue('pathToHelm');
|
||||
test('getHelmPath() - return path any version helm executable if version input not specified', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('')
|
||||
jest.spyOn(io, 'which').mockResolvedValue('pathToHelm')
|
||||
|
||||
expect(await helmUtil.getHelmPath()).toBe('pathToHelm');
|
||||
expect(core.getInput).toBeCalledWith('helm-version', {"required": false});
|
||||
expect(io.which).toBeCalledWith('helm', false);
|
||||
});
|
||||
expect(await helmUtil.getHelmPath()).toBe('pathToHelm')
|
||||
expect(core.getInput).toBeCalledWith('helm-version', {required: false})
|
||||
expect(io.which).toBeCalledWith('helm', false)
|
||||
})
|
||||
|
||||
test('getHelmPath() - return path to any version helm from tool cache', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('');
|
||||
jest.spyOn(io, 'which').mockResolvedValue('');
|
||||
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue(['pathToHelm']);
|
||||
test('getHelmPath() - return path to any version helm from tool cache', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('')
|
||||
jest.spyOn(io, 'which').mockResolvedValue('')
|
||||
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue(['pathToHelm'])
|
||||
|
||||
expect(await helmUtil.getHelmPath()).toBe(path.join('pathToTool', 'helm.exe'));
|
||||
expect(toolCache.findAllVersions).toBeCalledWith('helm');
|
||||
expect(core.getInput).toBeCalledWith('helm-version', {"required": false});
|
||||
expect(io.which).toBeCalledWith('helm', false);
|
||||
});
|
||||
expect(await helmUtil.getHelmPath()).toBe(
|
||||
path.join('pathToTool', 'helm.exe')
|
||||
)
|
||||
expect(toolCache.findAllVersions).toBeCalledWith('helm')
|
||||
expect(core.getInput).toBeCalledWith('helm-version', {required: false})
|
||||
expect(io.which).toBeCalledWith('helm', false)
|
||||
})
|
||||
|
||||
test('installHelm() - throw error when version input not specified and no executable found', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('');
|
||||
jest.spyOn(io, 'which').mockResolvedValue('');
|
||||
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue([]);
|
||||
test('installHelm() - throw error when version input not specified and no executable found', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('')
|
||||
jest.spyOn(io, 'which').mockResolvedValue('')
|
||||
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue([])
|
||||
|
||||
await expect(helmUtil.getHelmPath()).rejects.toThrow('helm is not installed, either add setup-helm action or provide "helm-version" input to download helm');
|
||||
expect(toolCache.findAllVersions).toBeCalledWith('helm');
|
||||
expect(core.getInput).toBeCalledWith('helm-version', {"required": false});
|
||||
expect(io.which).toBeCalledWith('helm', false);
|
||||
});
|
||||
await expect(helmUtil.getHelmPath()).rejects.toThrow(
|
||||
'helm is not installed, either add setup-helm action or provide "helm-version" input to download helm'
|
||||
)
|
||||
expect(toolCache.findAllVersions).toBeCalledWith('helm')
|
||||
expect(core.getInput).toBeCalledWith('helm-version', {required: false})
|
||||
expect(io.which).toBeCalledWith('helm', false)
|
||||
})
|
||||
|
||||
test('findHelm() - change access permissions and find the helm in given directory', () => {
|
||||
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent]);
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {});
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory = (file as string).indexOf('folder') == -1 ? false: true
|
||||
return { isDirectory: () => isDirectory } as fs.Stats;
|
||||
});
|
||||
|
||||
expect(helmUtil.findHelm('mainFolder')).toBe(path.join('mainFolder', 'helm.exe'));
|
||||
expect(fs.chmodSync).toBeCalledWith('mainFolder', '777');
|
||||
expect(fs.readdirSync).toBeCalledWith('mainFolder');
|
||||
expect(fs.statSync).toBeCalledWith(path.join('mainFolder', 'helm.exe'));
|
||||
});
|
||||
});
|
||||
test('findHelm() - change access permissions and find the helm in given directory', () => {
|
||||
jest
|
||||
.spyOn(fs, 'readdirSync')
|
||||
.mockImplementation((file, _) => ['helm.exe' as unknown as fs.Dirent])
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory =
|
||||
(file as string).indexOf('folder') == -1 ? false : true
|
||||
return {isDirectory: () => isDirectory} as fs.Stats
|
||||
})
|
||||
|
||||
expect(helmUtil.findHelm('mainFolder')).toBe(
|
||||
path.join('mainFolder', 'helm.exe')
|
||||
)
|
||||
expect(fs.chmodSync).toBeCalledWith('mainFolder', '777')
|
||||
expect(fs.readdirSync).toBeCalledWith('mainFolder')
|
||||
expect(fs.statSync).toBeCalledWith(path.join('mainFolder', 'helm.exe'))
|
||||
})
|
||||
})
|
||||
|
|
165
src/helm-util.ts
165
src/helm-util.ts
|
@ -1,97 +1,108 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as path from 'path'
|
||||
import * as fs from 'fs'
|
||||
import * as util from 'util'
|
||||
import * as toolCache from '@actions/tool-cache'
|
||||
import * as core from '@actions/core'
|
||||
import * as io from '@actions/io'
|
||||
import {
|
||||
getExecutableExtension,
|
||||
isEqual,
|
||||
LATEST,
|
||||
setCachedToolPath,
|
||||
getStableVerison
|
||||
} from './utilities'
|
||||
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as util from 'util';
|
||||
import * as toolCache from '@actions/tool-cache';
|
||||
import * as core from '@actions/core';
|
||||
import * as io from '@actions/io';
|
||||
import { getExecutableExtension, isEqual, LATEST, setCachedToolPath, getStableVerison } from "./utilities"
|
||||
|
||||
const helmToolName = 'helm';
|
||||
const helmToolName = 'helm'
|
||||
export interface NameValuePair {
|
||||
name: string;
|
||||
value: string;
|
||||
name: string
|
||||
value: string
|
||||
}
|
||||
|
||||
export function walkSync (dir, filelist = [], fileToFind) {
|
||||
const files = fs.readdirSync(dir);
|
||||
files.forEach(function(file) {
|
||||
export function walkSync(dir, filelist = [], fileToFind) {
|
||||
const files = fs.readdirSync(dir)
|
||||
files.forEach(function (file) {
|
||||
if (fs.statSync(path.join(dir, file)).isDirectory()) {
|
||||
filelist = walkSync(path.join(dir, file), filelist, fileToFind);
|
||||
filelist = walkSync(path.join(dir, file), filelist, fileToFind)
|
||||
} else {
|
||||
core.debug(file)
|
||||
if (file == fileToFind) {
|
||||
filelist.push(path.join(dir, file))
|
||||
}
|
||||
}
|
||||
else {
|
||||
core.debug(file);
|
||||
if(file == fileToFind)
|
||||
{
|
||||
filelist.push(path.join(dir, file));
|
||||
}
|
||||
}
|
||||
});
|
||||
return filelist;
|
||||
};
|
||||
|
||||
})
|
||||
return filelist
|
||||
}
|
||||
|
||||
export async function downloadHelm(version: string): Promise<string> {
|
||||
if(!version){
|
||||
version = await getStableVerison(helmToolName);
|
||||
}
|
||||
let cachedToolpath = toolCache.find(helmToolName, version);
|
||||
if (!cachedToolpath) {
|
||||
cachedToolpath = await setCachedToolPath(helmToolName, version);
|
||||
}
|
||||
const helmpath = findHelm(cachedToolpath);
|
||||
if (!helmpath) {
|
||||
throw new Error(util.format("Helm executable not found in path ", cachedToolpath));
|
||||
}
|
||||
|
||||
fs.chmodSync(helmpath, '777');
|
||||
return helmpath;
|
||||
if (!version) {
|
||||
version = await getStableVerison(helmToolName)
|
||||
}
|
||||
let cachedToolpath = toolCache.find(helmToolName, version)
|
||||
if (!cachedToolpath) {
|
||||
cachedToolpath = await setCachedToolPath(helmToolName, version)
|
||||
}
|
||||
const helmpath = findHelm(cachedToolpath)
|
||||
if (!helmpath) {
|
||||
throw new Error(
|
||||
util.format('Helm executable not found in path ', cachedToolpath)
|
||||
)
|
||||
}
|
||||
|
||||
fs.chmodSync(helmpath, '777')
|
||||
return helmpath
|
||||
}
|
||||
|
||||
export function findHelm(rootFolder: string): string {
|
||||
fs.chmodSync(rootFolder, '777');
|
||||
const filelist: string[] = [];
|
||||
walkSync(rootFolder, filelist, helmToolName + getExecutableExtension());
|
||||
if (!filelist) {
|
||||
throw new Error(util.format("Helm executable not found in path ", rootFolder));
|
||||
}
|
||||
else {
|
||||
return filelist[0];
|
||||
}
|
||||
fs.chmodSync(rootFolder, '777')
|
||||
const filelist: string[] = []
|
||||
walkSync(rootFolder, filelist, helmToolName + getExecutableExtension())
|
||||
if (!filelist) {
|
||||
throw new Error(
|
||||
util.format('Helm executable not found in path ', rootFolder)
|
||||
)
|
||||
} else {
|
||||
return filelist[0]
|
||||
}
|
||||
}
|
||||
|
||||
export async function getHelmPath() {
|
||||
let helmPath = "";
|
||||
const version = core.getInput('helm-version', { required: false });
|
||||
if (version) {
|
||||
if ( !!version && version != LATEST ){
|
||||
helmPath = toolCache.find(helmToolName, version);
|
||||
}
|
||||
if (!helmPath) {
|
||||
helmPath = await installHelm(version);
|
||||
}
|
||||
} else {
|
||||
helmPath = await io.which(helmToolName, false);
|
||||
if (!helmPath) {
|
||||
const allVersions = toolCache.findAllVersions(helmToolName);
|
||||
helmPath = allVersions.length > 0 ? toolCache.find(helmToolName, allVersions[0]) : '';
|
||||
if (!helmPath) {
|
||||
throw new Error('helm is not installed, either add setup-helm action or provide "helm-version" input to download helm');
|
||||
}
|
||||
helmPath = path.join(helmPath, `helm${getExecutableExtension()}`);
|
||||
}
|
||||
}
|
||||
let helmPath = ''
|
||||
const version = core.getInput('helm-version', {required: false})
|
||||
if (version) {
|
||||
if (!!version && version != LATEST) {
|
||||
helmPath = toolCache.find(helmToolName, version)
|
||||
}
|
||||
if (!helmPath) {
|
||||
helmPath = await installHelm(version)
|
||||
}
|
||||
} else {
|
||||
helmPath = await io.which(helmToolName, false)
|
||||
if (!helmPath) {
|
||||
const allVersions = toolCache.findAllVersions(helmToolName)
|
||||
helmPath =
|
||||
allVersions.length > 0
|
||||
? toolCache.find(helmToolName, allVersions[0])
|
||||
: ''
|
||||
if (!helmPath) {
|
||||
throw new Error(
|
||||
'helm is not installed, either add setup-helm action or provide "helm-version" input to download helm'
|
||||
)
|
||||
}
|
||||
helmPath = path.join(helmPath, `helm${getExecutableExtension()}`)
|
||||
}
|
||||
}
|
||||
|
||||
core.debug(util.format("Helm executable path %s", helmPath));
|
||||
return helmPath;
|
||||
core.debug(util.format('Helm executable path %s', helmPath))
|
||||
return helmPath
|
||||
}
|
||||
|
||||
export async function installHelm(version: string) {
|
||||
if (isEqual(version, LATEST)) {
|
||||
version = await getStableVerison(helmToolName);
|
||||
}
|
||||
core.debug(util.format("Downloading helm version %s", version));
|
||||
return await downloadHelm(version);
|
||||
}
|
||||
if (isEqual(version, LATEST)) {
|
||||
version = await getStableVerison(helmToolName)
|
||||
}
|
||||
core.debug(util.format('Downloading helm version %s', version))
|
||||
return await downloadHelm(version)
|
||||
}
|
||||
|
|
|
@ -1,115 +1,142 @@
|
|||
import * as komposeUtil from './kompose-util';
|
||||
import * as os from 'os';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as toolCache from '@actions/tool-cache';
|
||||
import * as core from '@actions/core';
|
||||
import * as io from '@actions/io';
|
||||
import * as komposeUtil from './kompose-util'
|
||||
import * as os from 'os'
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import * as toolCache from '@actions/tool-cache'
|
||||
import * as core from '@actions/core'
|
||||
import * as io from '@actions/io'
|
||||
|
||||
describe('Testing all funcitons in kompose-util file.', () => {
|
||||
test('downloadKompose() - return path to kompose from toolCache', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool')
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation()
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
|
||||
test('downloadKompose() - return path to kompose from toolCache', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool');
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation();
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
expect(await komposeUtil.downloadKompose('v1.18.0')).toBe(
|
||||
path.join('pathToCachedTool', 'kompose.exe')
|
||||
)
|
||||
expect(fs.chmodSync).toBeCalledWith(
|
||||
path.join('pathToCachedTool', 'kompose.exe'),
|
||||
0o100
|
||||
)
|
||||
expect(toolCache.find).toBeCalledWith('kompose', 'v1.18.0')
|
||||
})
|
||||
|
||||
expect(await komposeUtil.downloadKompose('v1.18.0')).toBe(path.join('pathToCachedTool', 'kompose.exe'));
|
||||
expect(fs.chmodSync).toBeCalledWith(path.join('pathToCachedTool', 'kompose.exe'), 0o100);
|
||||
expect(toolCache.find).toBeCalledWith('kompose', 'v1.18.0');
|
||||
});
|
||||
test('downloadKompose() - download kompose, cache it and return path', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('')
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
|
||||
jest.spyOn(toolCache, 'cacheFile').mockResolvedValue('pathToCachedTool')
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation()
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
|
||||
test('downloadKompose() - download kompose, cache it and return path', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('');
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
|
||||
jest.spyOn(toolCache, 'cacheFile').mockResolvedValue('pathToCachedTool');
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation();
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
expect(await komposeUtil.downloadKompose('v1.18.0')).toBe(
|
||||
path.join('pathToCachedTool', 'kompose.exe')
|
||||
)
|
||||
expect(toolCache.downloadTool).toBeCalledWith(
|
||||
'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-windows-amd64.exe'
|
||||
)
|
||||
expect(fs.chmodSync).toBeCalledWith(
|
||||
path.join('pathToCachedTool', 'kompose.exe'),
|
||||
0o100
|
||||
)
|
||||
expect(toolCache.find).toBeCalledWith('kompose', 'v1.18.0')
|
||||
})
|
||||
|
||||
expect(await komposeUtil.downloadKompose('v1.18.0')).toBe(path.join('pathToCachedTool', 'kompose.exe'));
|
||||
expect(toolCache.downloadTool).toBeCalledWith('https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-windows-amd64.exe');
|
||||
expect(fs.chmodSync).toBeCalledWith(path.join('pathToCachedTool', 'kompose.exe'), 0o100);
|
||||
expect(toolCache.find).toBeCalledWith('kompose', 'v1.18.0');
|
||||
});
|
||||
test('downloadKompose() - throw error when unable to download', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('')
|
||||
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => {
|
||||
throw 'Unable to download.'
|
||||
})
|
||||
|
||||
test("downloadKompose() - throw error when unable to download", async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('');
|
||||
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => { throw 'Unable to download.'});
|
||||
await expect(komposeUtil.downloadKompose('v1.18.0')).rejects.toThrow(
|
||||
'Failed to download the kompose from https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-windows-amd64.exe. Error: Unable to download.'
|
||||
)
|
||||
expect(toolCache.find).toBeCalledWith('kompose', 'v1.18.0')
|
||||
})
|
||||
|
||||
await expect(komposeUtil.downloadKompose('v1.18.0')).rejects.toThrow("Failed to download the kompose from https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-windows-amd64.exe. Error: Unable to download.");
|
||||
expect(toolCache.find).toBeCalledWith('kompose', 'v1.18.0');
|
||||
});
|
||||
test('installKompose() - return path kompose from cache', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool')
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation()
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
jest.spyOn(core, 'debug').mockImplementation()
|
||||
|
||||
test("installKompose() - return path kompose from cache", async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool');
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation();
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
jest.spyOn(core, 'debug').mockImplementation();
|
||||
expect(await komposeUtil.installKompose('v1.20.0')).toBe(
|
||||
path.join('pathToCachedTool', 'kompose.exe')
|
||||
)
|
||||
})
|
||||
|
||||
expect(await komposeUtil.installKompose('v1.20.0')).toBe(path.join('pathToCachedTool', 'kompose.exe'));
|
||||
});
|
||||
test('installKompose() - return path to kompose v1.18.0 when input is latest', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool')
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation()
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
jest.spyOn(core, 'debug').mockImplementation()
|
||||
|
||||
test("installKompose() - return path to kompose v1.18.0 when input is latest", async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool');
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation();
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
jest.spyOn(core, 'debug').mockImplementation();
|
||||
expect(await komposeUtil.installKompose('latest')).toBe(
|
||||
path.join('pathToCachedTool', 'kompose.exe')
|
||||
)
|
||||
})
|
||||
|
||||
expect(await komposeUtil.installKompose('latest')).toBe(path.join('pathToCachedTool', 'kompose.exe'));
|
||||
});
|
||||
test('getKomposePath() - return path to latest version kompose from toolCache', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('latest')
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool')
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation()
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
|
||||
test("getKomposePath() - return path to latest version kompose from toolCache", async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('latest');
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool');
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation();
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
expect(await komposeUtil.getKomposePath()).toBe(
|
||||
path.join('pathToCachedTool', 'kompose.exe')
|
||||
)
|
||||
expect(core.getInput).toBeCalledWith('kompose-version', {required: false})
|
||||
expect(toolCache.find).toBeCalledWith('kompose', 'v1.18.0')
|
||||
})
|
||||
|
||||
expect(await komposeUtil.getKomposePath()).toBe(path.join('pathToCachedTool', 'kompose.exe'));
|
||||
expect(core.getInput).toBeCalledWith('kompose-version', { required: false });
|
||||
expect(toolCache.find).toBeCalledWith('kompose', 'v1.18.0');
|
||||
});
|
||||
test('getKomposePath() - return path to specified version kompose from toolCache', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('v2.0.0')
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool')
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation()
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
|
||||
test("getKomposePath() - return path to specified version kompose from toolCache", async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('v2.0.0');
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool');
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation();
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
expect(await komposeUtil.getKomposePath()).toBe('pathToCachedTool')
|
||||
expect(core.getInput).toBeCalledWith('kompose-version', {required: false})
|
||||
expect(toolCache.find).toBeCalledWith('kompose', 'v2.0.0')
|
||||
})
|
||||
|
||||
expect(await komposeUtil.getKomposePath()).toBe('pathToCachedTool');
|
||||
expect(core.getInput).toBeCalledWith('kompose-version', { required: false });
|
||||
expect(toolCache.find).toBeCalledWith('kompose', 'v2.0.0');
|
||||
});
|
||||
test('getKomposePath() - return path to any version executable when input is not given', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('')
|
||||
jest.spyOn(io, 'which').mockResolvedValue('pathToTool')
|
||||
|
||||
test("getKomposePath() - return path to any version executable when input is not given", async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('');
|
||||
jest.spyOn(io, 'which').mockResolvedValue('pathToTool');
|
||||
expect(await komposeUtil.getKomposePath()).toBe('pathToTool')
|
||||
expect(core.getInput).toBeCalledWith('kompose-version', {required: false})
|
||||
expect(io.which).toBeCalledWith('kompose', false)
|
||||
})
|
||||
|
||||
expect(await komposeUtil.getKomposePath()).toBe('pathToTool');
|
||||
expect(core.getInput).toBeCalledWith('kompose-version', { required: false });
|
||||
expect(io.which).toBeCalledWith('kompose', false);
|
||||
});
|
||||
test('getKomposePath() - return path to any version kompose from toolCache when input is not given', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('')
|
||||
jest.spyOn(io, 'which').mockResolvedValue('')
|
||||
jest
|
||||
.spyOn(toolCache, 'findAllVersions')
|
||||
.mockReturnValue(['v2.0.0', 'v2.0.1'])
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToTool')
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
|
||||
test("getKomposePath() - return path to any version kompose from toolCache when input is not given", async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('');
|
||||
jest.spyOn(io, 'which').mockResolvedValue('');
|
||||
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue(['v2.0.0', 'v2.0.1']);
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToTool');
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
expect(await komposeUtil.getKomposePath()).toBe(
|
||||
path.join('pathToTool', 'kompose.exe')
|
||||
)
|
||||
expect(core.getInput).toBeCalledWith('kompose-version', {required: false})
|
||||
expect(io.which).toBeCalledWith('kompose', false)
|
||||
expect(toolCache.findAllVersions).toBeCalledWith('kompose')
|
||||
expect(toolCache.find).toBeCalledWith('kompose', 'v2.0.0')
|
||||
})
|
||||
|
||||
expect(await komposeUtil.getKomposePath()).toBe(path.join('pathToTool', 'kompose.exe'));
|
||||
expect(core.getInput).toBeCalledWith('kompose-version', { required: false });
|
||||
expect(io.which).toBeCalledWith('kompose', false);
|
||||
expect(toolCache.findAllVersions).toBeCalledWith('kompose');
|
||||
expect(toolCache.find).toBeCalledWith('kompose', 'v2.0.0');
|
||||
});
|
||||
test('getKomposePath() - throw error when version input is not given and not kompose already exists', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('')
|
||||
jest.spyOn(io, 'which').mockResolvedValue('')
|
||||
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue([])
|
||||
|
||||
test("getKomposePath() - throw error when version input is not given and not kompose already exists", async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('');
|
||||
jest.spyOn(io, 'which').mockResolvedValue('');
|
||||
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue([]);
|
||||
|
||||
await expect(komposeUtil.getKomposePath()).rejects.toThrow('kompose is not installed, provide "kompose-version" input to download kompose');
|
||||
expect(core.getInput).toBeCalledWith('kompose-version', { required: false });
|
||||
expect(io.which).toBeCalledWith('kompose', false);
|
||||
expect(toolCache.findAllVersions).toBeCalledWith('kompose');
|
||||
});
|
||||
});
|
||||
await expect(komposeUtil.getKomposePath()).rejects.toThrow(
|
||||
'kompose is not installed, provide "kompose-version" input to download kompose'
|
||||
)
|
||||
expect(core.getInput).toBeCalledWith('kompose-version', {required: false})
|
||||
expect(io.which).toBeCalledWith('kompose', false)
|
||||
expect(toolCache.findAllVersions).toBeCalledWith('kompose')
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,58 +1,76 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as util from 'util';
|
||||
import * as toolCache from '@actions/tool-cache';
|
||||
import * as core from '@actions/core';
|
||||
import * as io from '@actions/io';
|
||||
import { getExecutableExtension, isEqual, setCachedToolPath, LATEST } from "./utilities"
|
||||
import * as path from 'path'
|
||||
import * as fs from 'fs'
|
||||
import * as util from 'util'
|
||||
import * as toolCache from '@actions/tool-cache'
|
||||
import * as core from '@actions/core'
|
||||
import * as io from '@actions/io'
|
||||
import {
|
||||
getExecutableExtension,
|
||||
isEqual,
|
||||
setCachedToolPath,
|
||||
LATEST
|
||||
} from './utilities'
|
||||
|
||||
const komposeToolName = 'kompose';
|
||||
const stableKomposeVersion = "v1.18.0";
|
||||
const komposeToolName = 'kompose'
|
||||
const stableKomposeVersion = 'v1.18.0'
|
||||
|
||||
export async function getKomposePath() {
|
||||
let komposePath = "";
|
||||
const version = core.getInput('kompose-version', { required: false });
|
||||
if (version) {
|
||||
if ( !!version && version != LATEST ){
|
||||
komposePath = toolCache.find(komposeToolName, version);
|
||||
}
|
||||
|
||||
if (!komposePath) {
|
||||
komposePath = await installKompose(version);
|
||||
}
|
||||
} else {
|
||||
komposePath = await io.which(komposeToolName, false);
|
||||
if (!komposePath) {
|
||||
const allVersions = toolCache.findAllVersions(komposeToolName);
|
||||
komposePath = allVersions.length > 0 ? toolCache.find(komposeToolName, allVersions[0]) : '';
|
||||
if (!komposePath) {
|
||||
throw new Error('kompose is not installed, provide "kompose-version" input to download kompose');
|
||||
}
|
||||
komposePath = path.join(komposePath, `kompose${getExecutableExtension()}`);
|
||||
}
|
||||
}
|
||||
let komposePath = ''
|
||||
const version = core.getInput('kompose-version', {required: false})
|
||||
if (version) {
|
||||
if (!!version && version != LATEST) {
|
||||
komposePath = toolCache.find(komposeToolName, version)
|
||||
}
|
||||
|
||||
return komposePath;
|
||||
if (!komposePath) {
|
||||
komposePath = await installKompose(version)
|
||||
}
|
||||
} else {
|
||||
komposePath = await io.which(komposeToolName, false)
|
||||
if (!komposePath) {
|
||||
const allVersions = toolCache.findAllVersions(komposeToolName)
|
||||
komposePath =
|
||||
allVersions.length > 0
|
||||
? toolCache.find(komposeToolName, allVersions[0])
|
||||
: ''
|
||||
if (!komposePath) {
|
||||
throw new Error(
|
||||
'kompose is not installed, provide "kompose-version" input to download kompose'
|
||||
)
|
||||
}
|
||||
komposePath = path.join(
|
||||
komposePath,
|
||||
`kompose${getExecutableExtension()}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return komposePath
|
||||
}
|
||||
|
||||
export async function downloadKompose(version: string=stableKomposeVersion): Promise<string> {
|
||||
let cachedToolpath = toolCache.find(komposeToolName, version);
|
||||
if (!cachedToolpath) {
|
||||
cachedToolpath = await setCachedToolPath(komposeToolName, version);
|
||||
}
|
||||
export async function downloadKompose(
|
||||
version: string = stableKomposeVersion
|
||||
): Promise<string> {
|
||||
let cachedToolpath = toolCache.find(komposeToolName, version)
|
||||
if (!cachedToolpath) {
|
||||
cachedToolpath = await setCachedToolPath(komposeToolName, version)
|
||||
}
|
||||
|
||||
const komposePath = path.join(cachedToolpath, komposeToolName + getExecutableExtension());
|
||||
fs.chmodSync(komposePath, 0o100); // execute/search by owner permissions to the tool
|
||||
return komposePath;
|
||||
const komposePath = path.join(
|
||||
cachedToolpath,
|
||||
komposeToolName + getExecutableExtension()
|
||||
)
|
||||
fs.chmodSync(komposePath, 0o100) // execute/search by owner permissions to the tool
|
||||
return komposePath
|
||||
}
|
||||
|
||||
export async function installKompose(version: string) {
|
||||
if (isEqual(version, LATEST)) {
|
||||
version = stableKomposeVersion;
|
||||
}
|
||||
core.debug(util.format("Downloading kompose version %s", version));
|
||||
return await downloadKompose(version);
|
||||
}
|
||||
if (isEqual(version, LATEST)) {
|
||||
version = stableKomposeVersion
|
||||
}
|
||||
core.debug(util.format('Downloading kompose version %s', version))
|
||||
return await downloadKompose(version)
|
||||
}
|
||||
|
|
|
@ -1,123 +1,158 @@
|
|||
import * as kubectlUtil from './kubectl-util';
|
||||
import * as os from 'os';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as toolCache from '@actions/tool-cache';
|
||||
import * as core from '@actions/core';
|
||||
import * as io from '@actions/io';
|
||||
import * as utils from './utilities';
|
||||
import * as kubectlUtil from './kubectl-util'
|
||||
import * as os from 'os'
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import * as toolCache from '@actions/tool-cache'
|
||||
import * as core from '@actions/core'
|
||||
import * as io from '@actions/io'
|
||||
import * as utils from './utilities'
|
||||
|
||||
describe('Testing all funcitons in kubectl-util file.', () => {
|
||||
|
||||
test('downloadKubectl() - download kubectl, add it to toolCache and return path to it', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('');
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
|
||||
jest.spyOn(toolCache, 'cacheFile').mockResolvedValue('pathToCachedTool');
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation();
|
||||
test('downloadKubectl() - download kubectl, add it to toolCache and return path to it', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('')
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
|
||||
jest.spyOn(toolCache, 'cacheFile').mockResolvedValue('pathToCachedTool')
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation()
|
||||
|
||||
expect(await kubectlUtil.downloadKubectl('v1.15.0')).toBe(path.join('pathToCachedTool', 'kubectl.exe'));
|
||||
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0');
|
||||
expect(toolCache.downloadTool).toBeCalled();
|
||||
expect(toolCache.cacheFile).toBeCalled();
|
||||
expect(os.type).toBeCalled();
|
||||
expect(fs.chmodSync).toBeCalledWith(path.join('pathToCachedTool', 'kubectl.exe'), '777');
|
||||
});
|
||||
expect(await kubectlUtil.downloadKubectl('v1.15.0')).toBe(
|
||||
path.join('pathToCachedTool', 'kubectl.exe')
|
||||
)
|
||||
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0')
|
||||
expect(toolCache.downloadTool).toBeCalled()
|
||||
expect(toolCache.cacheFile).toBeCalled()
|
||||
expect(os.type).toBeCalled()
|
||||
expect(fs.chmodSync).toBeCalledWith(
|
||||
path.join('pathToCachedTool', 'kubectl.exe'),
|
||||
'777'
|
||||
)
|
||||
})
|
||||
|
||||
test('downloadKubectl() - throw DownloadKubectlFailed error when unable to download kubectl', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('');
|
||||
jest.spyOn(toolCache, 'downloadTool').mockRejectedValue('Unable to download kubectl.');
|
||||
test('downloadKubectl() - throw DownloadKubectlFailed error when unable to download kubectl', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('')
|
||||
jest
|
||||
.spyOn(toolCache, 'downloadTool')
|
||||
.mockRejectedValue('Unable to download kubectl.')
|
||||
|
||||
await expect(kubectlUtil.downloadKubectl('v1.15.0')).rejects.toThrow('Failed to download the kubectl from https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/windows/amd64/kubectl.exe. Error: Unable to download kubectl.');
|
||||
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0');
|
||||
expect(toolCache.downloadTool).toBeCalled();
|
||||
});
|
||||
await expect(kubectlUtil.downloadKubectl('v1.15.0')).rejects.toThrow(
|
||||
'Failed to download the kubectl from https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/windows/amd64/kubectl.exe. Error: Unable to download kubectl.'
|
||||
)
|
||||
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0')
|
||||
expect(toolCache.downloadTool).toBeCalled()
|
||||
})
|
||||
|
||||
test('downloadKubectl() - return path to existing cache of kubectl', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool');
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {});
|
||||
test('downloadKubectl() - return path to existing cache of kubectl', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedTool')
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
|
||||
|
||||
expect(await kubectlUtil.downloadKubectl('v1.15.0')).toBe(path.join('pathToCachedTool', 'kubectl.exe'));
|
||||
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0');
|
||||
expect(os.type).toBeCalled();
|
||||
expect(fs.chmodSync).toBeCalledWith(path.join('pathToCachedTool', 'kubectl.exe'), '777');
|
||||
});
|
||||
expect(await kubectlUtil.downloadKubectl('v1.15.0')).toBe(
|
||||
path.join('pathToCachedTool', 'kubectl.exe')
|
||||
)
|
||||
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0')
|
||||
expect(os.type).toBeCalled()
|
||||
expect(fs.chmodSync).toBeCalledWith(
|
||||
path.join('pathToCachedTool', 'kubectl.exe'),
|
||||
'777'
|
||||
)
|
||||
})
|
||||
|
||||
test('installKubectl() - return its path to installed kubectl', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir');
|
||||
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => { throw 'Error!!'});
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => ['kubectl.exe' as unknown as fs.Dirent]);
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory = (file as string).indexOf('folder') == -1 ? false: true
|
||||
return { isDirectory: () => isDirectory } as fs.Stats;
|
||||
});
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation();
|
||||
jest.spyOn(core, 'debug').mockImplementation();
|
||||
test('installKubectl() - return its path to installed kubectl', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir')
|
||||
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => {
|
||||
throw 'Error!!'
|
||||
})
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
jest
|
||||
.spyOn(fs, 'readdirSync')
|
||||
.mockImplementation((file, _) => [
|
||||
'kubectl.exe' as unknown as fs.Dirent
|
||||
])
|
||||
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
|
||||
const isDirectory =
|
||||
(file as string).indexOf('folder') == -1 ? false : true
|
||||
return {isDirectory: () => isDirectory} as fs.Stats
|
||||
})
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation()
|
||||
jest.spyOn(core, 'debug').mockImplementation()
|
||||
|
||||
expect(await kubectlUtil.installKubectl('v1.15.0')).toBe(path.join('pathToCachedDir', 'kubectl.exe'));
|
||||
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0');
|
||||
});
|
||||
expect(await kubectlUtil.installKubectl('v1.15.0')).toBe(
|
||||
path.join('pathToCachedDir', 'kubectl.exe')
|
||||
)
|
||||
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0')
|
||||
})
|
||||
|
||||
test('installKubectl() - download and return path to latest kubectl', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('');
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
|
||||
jest.spyOn(toolCache, 'cacheFile').mockResolvedValue('pathToCachedTool');
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation();
|
||||
jest.spyOn(fs, 'readFileSync').mockReturnValue('v1.15.0');
|
||||
jest.spyOn(core, 'debug').mockImplementation();
|
||||
test('installKubectl() - download and return path to latest kubectl', async () => {
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('')
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
|
||||
jest.spyOn(toolCache, 'cacheFile').mockResolvedValue('pathToCachedTool')
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
jest.spyOn(fs, 'chmodSync').mockImplementation()
|
||||
jest.spyOn(fs, 'readFileSync').mockReturnValue('v1.15.0')
|
||||
jest.spyOn(core, 'debug').mockImplementation()
|
||||
|
||||
expect(await kubectlUtil.installKubectl('latest')).toBe(path.join('pathToCachedTool', 'kubectl.exe'));
|
||||
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0');
|
||||
expect(toolCache.downloadTool).toBeCalled();
|
||||
expect(toolCache.cacheFile).toBeCalled();
|
||||
expect(os.type).toBeCalled();
|
||||
expect(fs.chmodSync).toBeCalledWith(path.join('pathToCachedTool', 'kubectl.exe'), '777');
|
||||
});
|
||||
expect(await kubectlUtil.installKubectl('latest')).toBe(
|
||||
path.join('pathToCachedTool', 'kubectl.exe')
|
||||
)
|
||||
expect(toolCache.find).toBeCalledWith('kubectl', 'v1.15.0')
|
||||
expect(toolCache.downloadTool).toBeCalled()
|
||||
expect(toolCache.cacheFile).toBeCalled()
|
||||
expect(os.type).toBeCalled()
|
||||
expect(fs.chmodSync).toBeCalledWith(
|
||||
path.join('pathToCachedTool', 'kubectl.exe'),
|
||||
'777'
|
||||
)
|
||||
})
|
||||
|
||||
test('getKubectlPath() - throw if version is not provided and no kubectl is already present', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('');
|
||||
jest.spyOn(io, 'which').mockResolvedValue('');
|
||||
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue([]);
|
||||
test('getKubectlPath() - throw if version is not provided and no kubectl is already present', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('')
|
||||
jest.spyOn(io, 'which').mockResolvedValue('')
|
||||
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue([])
|
||||
|
||||
await expect(kubectlUtil.getKubectlPath()).rejects.toThrow('Kubectl is not installed, either add install-kubectl action or provide "kubectl-version" input to download kubectl');
|
||||
expect(core.getInput).toBeCalledWith('kubectl-version', {required: false});
|
||||
expect(io.which).toBeCalledWith('kubectl', false);
|
||||
expect(toolCache.findAllVersions).toBeCalledWith('kubectl');
|
||||
});
|
||||
await expect(kubectlUtil.getKubectlPath()).rejects.toThrow(
|
||||
'Kubectl is not installed, either add install-kubectl action or provide "kubectl-version" input to download kubectl'
|
||||
)
|
||||
expect(core.getInput).toBeCalledWith('kubectl-version', {required: false})
|
||||
expect(io.which).toBeCalledWith('kubectl', false)
|
||||
expect(toolCache.findAllVersions).toBeCalledWith('kubectl')
|
||||
})
|
||||
|
||||
test('getKubectlPath() - return installed version of kubectl if input not provided', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('');
|
||||
jest.spyOn(io, 'which').mockResolvedValue('pathToKubectl');
|
||||
test('getKubectlPath() - return installed version of kubectl if input not provided', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('')
|
||||
jest.spyOn(io, 'which').mockResolvedValue('pathToKubectl')
|
||||
|
||||
expect(await kubectlUtil.getKubectlPath()).toBe('pathToKubectl');
|
||||
expect(core.getInput).toBeCalledWith('kubectl-version', {required: false});
|
||||
expect(io.which).toBeCalledWith('kubectl', false);
|
||||
});
|
||||
expect(await kubectlUtil.getKubectlPath()).toBe('pathToKubectl')
|
||||
expect(core.getInput).toBeCalledWith('kubectl-version', {required: false})
|
||||
expect(io.which).toBeCalledWith('kubectl', false)
|
||||
})
|
||||
|
||||
test('getKubectlPath() - return any version of kubectl from toolCache if input not provided', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('');
|
||||
jest.spyOn(io, 'which').mockResolvedValue('');
|
||||
jest.spyOn(toolCache, 'findAllVersions').mockReturnValue(['v2.0.0', 'v1.0.0']);
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedKubectl');
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
test('getKubectlPath() - return any version of kubectl from toolCache if input not provided', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('')
|
||||
jest.spyOn(io, 'which').mockResolvedValue('')
|
||||
jest
|
||||
.spyOn(toolCache, 'findAllVersions')
|
||||
.mockReturnValue(['v2.0.0', 'v1.0.0'])
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedKubectl')
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
|
||||
expect(await kubectlUtil.getKubectlPath()).toBe(path.join('pathToCachedKubectl', 'kubectl.exe'));
|
||||
expect(core.getInput).toBeCalledWith('kubectl-version', {required: false});
|
||||
expect(io.which).toBeCalledWith('kubectl', false);
|
||||
expect(toolCache.findAllVersions).toBeCalledWith('kubectl');
|
||||
expect(toolCache.find).toBeCalledWith('kubectl', 'v2.0.0');
|
||||
});
|
||||
expect(await kubectlUtil.getKubectlPath()).toBe(
|
||||
path.join('pathToCachedKubectl', 'kubectl.exe')
|
||||
)
|
||||
expect(core.getInput).toBeCalledWith('kubectl-version', {required: false})
|
||||
expect(io.which).toBeCalledWith('kubectl', false)
|
||||
expect(toolCache.findAllVersions).toBeCalledWith('kubectl')
|
||||
expect(toolCache.find).toBeCalledWith('kubectl', 'v2.0.0')
|
||||
})
|
||||
|
||||
test('getKubectlPath() - return path to specified version kubectl from toolCache', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('v2.0.0');
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToKubectl');
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
test('getKubectlPath() - return path to specified version kubectl from toolCache', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('v2.0.0')
|
||||
jest.spyOn(toolCache, 'find').mockReturnValue('pathToKubectl')
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
|
||||
expect(await kubectlUtil.getKubectlPath()).toBe(path.join('pathToKubectl', 'kubectl.exe'));
|
||||
expect(core.getInput).toBeCalledWith('kubectl-version', {required: false});
|
||||
expect(toolCache.find).toBeCalledWith('kubectl', 'v2.0.0');
|
||||
});
|
||||
});
|
||||
expect(await kubectlUtil.getKubectlPath()).toBe(
|
||||
path.join('pathToKubectl', 'kubectl.exe')
|
||||
)
|
||||
expect(core.getInput).toBeCalledWith('kubectl-version', {required: false})
|
||||
expect(toolCache.find).toBeCalledWith('kubectl', 'v2.0.0')
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,62 +1,82 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as util from 'util';
|
||||
import * as toolCache from '@actions/tool-cache';
|
||||
import * as core from '@actions/core';
|
||||
import * as io from '@actions/io';
|
||||
import { getExecutableExtension, isEqual, LATEST, setCachedToolPath, getStableVerison} from "./utilities"
|
||||
import * as path from 'path'
|
||||
import * as fs from 'fs'
|
||||
import * as util from 'util'
|
||||
import * as toolCache from '@actions/tool-cache'
|
||||
import * as core from '@actions/core'
|
||||
import * as io from '@actions/io'
|
||||
import {
|
||||
getExecutableExtension,
|
||||
isEqual,
|
||||
LATEST,
|
||||
setCachedToolPath,
|
||||
getStableVerison
|
||||
} from './utilities'
|
||||
|
||||
const kubectlToolName = 'kubectl';
|
||||
const kubectlToolName = 'kubectl'
|
||||
|
||||
export async function downloadKubectl(version: string): Promise<string> {
|
||||
if(!version){
|
||||
version = await getStableVerison(kubectlToolName);
|
||||
}
|
||||
let cachedToolpath = toolCache.find(kubectlToolName, version);
|
||||
if (!version) {
|
||||
version = await getStableVerison(kubectlToolName)
|
||||
}
|
||||
let cachedToolpath = toolCache.find(kubectlToolName, version)
|
||||
|
||||
if (!cachedToolpath) {
|
||||
cachedToolpath = await setCachedToolPath(kubectlToolName, version);
|
||||
}
|
||||
if (!cachedToolpath) {
|
||||
cachedToolpath = await setCachedToolPath(kubectlToolName, version)
|
||||
}
|
||||
|
||||
const kubectlPath = path.join(cachedToolpath, kubectlToolName + getExecutableExtension());
|
||||
fs.chmodSync(kubectlPath, '777');
|
||||
return kubectlPath;
|
||||
const kubectlPath = path.join(
|
||||
cachedToolpath,
|
||||
kubectlToolName + getExecutableExtension()
|
||||
)
|
||||
fs.chmodSync(kubectlPath, '777')
|
||||
return kubectlPath
|
||||
}
|
||||
|
||||
export async function getKubectlPath() {
|
||||
let kubectlPath = "";
|
||||
const version = core.getInput('kubectl-version', { required: false });
|
||||
if (version) {
|
||||
if ( !!version && version != LATEST ){
|
||||
const cachedToolPath = toolCache.find(kubectlToolName, version);
|
||||
kubectlPath = path.join(cachedToolPath, kubectlToolName + getExecutableExtension())
|
||||
}
|
||||
|
||||
if (!kubectlPath) {
|
||||
kubectlPath = await installKubectl(version);
|
||||
}
|
||||
} else {
|
||||
kubectlPath = await io.which(kubectlToolName, false);
|
||||
if (!kubectlPath) {
|
||||
const allVersions = toolCache.findAllVersions(kubectlToolName);
|
||||
kubectlPath = allVersions.length > 0 ? toolCache.find(kubectlToolName, allVersions[0]) : '';
|
||||
if (!kubectlPath) {
|
||||
throw new Error('Kubectl is not installed, either add install-kubectl action or provide "kubectl-version" input to download kubectl');
|
||||
}
|
||||
kubectlPath = path.join(kubectlPath, `kubectl${getExecutableExtension()}`);
|
||||
}
|
||||
}
|
||||
let kubectlPath = ''
|
||||
const version = core.getInput('kubectl-version', {required: false})
|
||||
if (version) {
|
||||
if (!!version && version != LATEST) {
|
||||
const cachedToolPath = toolCache.find(kubectlToolName, version)
|
||||
kubectlPath = path.join(
|
||||
cachedToolPath,
|
||||
kubectlToolName + getExecutableExtension()
|
||||
)
|
||||
}
|
||||
|
||||
return kubectlPath
|
||||
if (!kubectlPath) {
|
||||
kubectlPath = await installKubectl(version)
|
||||
}
|
||||
} else {
|
||||
kubectlPath = await io.which(kubectlToolName, false)
|
||||
if (!kubectlPath) {
|
||||
const allVersions = toolCache.findAllVersions(kubectlToolName)
|
||||
kubectlPath =
|
||||
allVersions.length > 0
|
||||
? toolCache.find(kubectlToolName, allVersions[0])
|
||||
: ''
|
||||
if (!kubectlPath) {
|
||||
throw new Error(
|
||||
'Kubectl is not installed, either add install-kubectl action or provide "kubectl-version" input to download kubectl'
|
||||
)
|
||||
}
|
||||
kubectlPath = path.join(
|
||||
kubectlPath,
|
||||
`kubectl${getExecutableExtension()}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return kubectlPath
|
||||
}
|
||||
|
||||
export async function installKubectl(version: string) {
|
||||
if (isEqual(version, LATEST)) {
|
||||
version = await getStableVerison(kubectlToolName);
|
||||
}
|
||||
core.debug(util.format("Downloading kubectl version %s", version));
|
||||
return await downloadKubectl(version);
|
||||
if (isEqual(version, LATEST)) {
|
||||
version = await getStableVerison(kubectlToolName)
|
||||
}
|
||||
core.debug(util.format('Downloading kubectl version %s', version))
|
||||
return await downloadKubectl(version)
|
||||
}
|
||||
|
|
715
src/run.test.ts
715
src/run.test.ts
|
@ -1,294 +1,483 @@
|
|||
import * as helmUtil from './helm-util';
|
||||
import * as kubectlUtil from './kubectl-util';
|
||||
import * as komposeUtil from './kompose-util';
|
||||
import * as utils from './utilities';
|
||||
import { KustomizeRenderEngine, KomposeRenderEngine, HelmRenderEngine, run } from './run';
|
||||
import * as ioUtil from '@actions/io/lib/io-util';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as core from '@actions/core';
|
||||
import { ExecOptions } from "@actions/exec/lib/interfaces";
|
||||
import * as helmUtil from './helm-util'
|
||||
import * as kubectlUtil from './kubectl-util'
|
||||
import * as komposeUtil from './kompose-util'
|
||||
import * as utils from './utilities'
|
||||
import {
|
||||
KustomizeRenderEngine,
|
||||
KomposeRenderEngine,
|
||||
HelmRenderEngine,
|
||||
run
|
||||
} from './run'
|
||||
import * as ioUtil from '@actions/io/lib/io-util'
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import * as core from '@actions/core'
|
||||
import {ExecOptions} from '@actions/exec/lib/interfaces'
|
||||
|
||||
var mockStatusCode, stdOutMessage, stdErrMessage;
|
||||
var mockStatusCode, stdOutMessage, stdErrMessage
|
||||
const mockExecFn = jest.fn().mockImplementation((toolPath, args, options) => {
|
||||
options.listeners.stdout(!stdOutMessage ? '' : stdOutMessage);
|
||||
options.listeners.stderr(!stdErrMessage ? '' : stdErrMessage);
|
||||
return mockStatusCode;
|
||||
options.listeners.stdout(!stdOutMessage ? '' : stdOutMessage)
|
||||
options.listeners.stderr(!stdErrMessage ? '' : stdErrMessage)
|
||||
return mockStatusCode
|
||||
})
|
||||
jest.mock('@actions/exec/lib/toolrunner', () => {
|
||||
return {
|
||||
ToolRunner: jest.fn().mockImplementation((toolPath, args, options) => {
|
||||
return {
|
||||
exec: () => mockExecFn(toolPath, args, options)
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
return {
|
||||
ToolRunner: jest.fn().mockImplementation((toolPath, args, options) => {
|
||||
return {
|
||||
exec: () => mockExecFn(toolPath, args, options)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
describe('Test all functions in run file', () => {
|
||||
test('KustomizeRenderEngine() - throw error if kubectl doesn\'t meet required version', async () => {
|
||||
jest.spyOn(kubectlUtil, 'getKubectlPath').mockResolvedValue('pathToKubectl');
|
||||
const kubectlVersionResponse = {
|
||||
'stdout': JSON.stringify({
|
||||
"clientVersion": {
|
||||
"major": "0",
|
||||
"minor": "18",
|
||||
}
|
||||
})
|
||||
};
|
||||
jest.spyOn(utils, 'execCommand').mockResolvedValue(kubectlVersionResponse as utils.ExecResult);
|
||||
|
||||
await expect((new KustomizeRenderEngine()).bake(false)).rejects.toThrow('kubectl client version equal to v1.14 or higher is required to use kustomize features');
|
||||
expect(kubectlUtil.getKubectlPath).toBeCalled();
|
||||
expect(utils.execCommand).toBeCalledWith('pathToKubectl', ['version', '--client=true', '-o', 'json']);
|
||||
});
|
||||
|
||||
test('KustomizeRenderEngine() - validate kubetl and bake using kustomize', async () => {
|
||||
jest.spyOn(kubectlUtil, 'getKubectlPath').mockResolvedValue('pathToKubectl');
|
||||
const responseStdout = JSON.stringify({
|
||||
"clientVersion": {
|
||||
"major": "1",
|
||||
"minor": "18",
|
||||
test("KustomizeRenderEngine() - throw error if kubectl doesn't meet required version", async () => {
|
||||
jest
|
||||
.spyOn(kubectlUtil, 'getKubectlPath')
|
||||
.mockResolvedValue('pathToKubectl')
|
||||
const kubectlVersionResponse = {
|
||||
stdout: JSON.stringify({
|
||||
clientVersion: {
|
||||
major: '0',
|
||||
minor: '18'
|
||||
}
|
||||
});
|
||||
const kubectlVersionResponse = {
|
||||
'stdout': responseStdout
|
||||
};
|
||||
const kustomizeResponse = {
|
||||
'stdout': 'kustomizeOutput'
|
||||
};
|
||||
jest.spyOn(utils, 'execCommand').mockResolvedValueOnce(kubectlVersionResponse as utils.ExecResult).mockResolvedValueOnce(kustomizeResponse as utils.ExecResult);
|
||||
jest.spyOn(core, 'getInput').mockImplementation((inputName) => {
|
||||
if (inputName == "kustomizationPath") return 'pathToKustomization';
|
||||
if (inputName == "arguments") return 'additionalArguments';
|
||||
})
|
||||
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true);
|
||||
jest.spyOn(fs, 'writeFileSync').mockImplementation();
|
||||
process.env['RUNNER_TEMP'] = 'tempDir';
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
|
||||
jest.spyOn(core, 'debug').mockImplementation();
|
||||
jest.spyOn(core, 'setOutput').mockImplementation();
|
||||
jest.spyOn(console, 'log').mockImplementation();
|
||||
|
||||
expect(await (new KustomizeRenderEngine()).bake(true)).toBeUndefined();
|
||||
expect(kubectlUtil.getKubectlPath).toBeCalled();
|
||||
|
||||
expect(utils.execCommand).toBeCalledWith('pathToKubectl', ['version', '--client=true', '-o', 'json']);
|
||||
expect(utils.execCommand).toBeCalledWith('pathToKubectl', ['kustomize', 'pathToKustomization', 'additionalArguments'], { silent: true } as ExecOptions);
|
||||
|
||||
expect(core.getInput).toBeCalledWith('kustomizationPath', { required: true });
|
||||
expect(fs.writeFileSync).toBeCalledWith(path.join('tempDir', 'baked-template-12345678.yaml'), 'kustomizeOutput');
|
||||
expect(core.setOutput).toBeCalledWith('manifestsBundle', path.join('tempDir', 'baked-template-12345678.yaml'));
|
||||
});
|
||||
})
|
||||
}
|
||||
jest
|
||||
.spyOn(utils, 'execCommand')
|
||||
.mockResolvedValue(kubectlVersionResponse as utils.ExecResult)
|
||||
|
||||
test('KustomizeRenderEngine() - multiple additional arguments with leading/trailing spaces', async () => {
|
||||
jest.spyOn(kubectlUtil, 'getKubectlPath').mockResolvedValue('pathToKubectl');
|
||||
const kubectlVersionResponse = {
|
||||
'stdout': JSON.stringify({
|
||||
"clientVersion": {
|
||||
"major": "1",
|
||||
"minor": "18",
|
||||
}
|
||||
})
|
||||
};
|
||||
const kustomizeResponse = {
|
||||
'stdout': 'kustomizeOutput'
|
||||
};
|
||||
jest.spyOn(utils, 'execCommand').mockResolvedValue(kubectlVersionResponse as utils.ExecResult);
|
||||
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
|
||||
if (inputName == "kustomizationPath") return 'pathToKustomization';
|
||||
if (inputName == "arguments") return ' additional \n Arguments ';
|
||||
})
|
||||
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true);
|
||||
jest.spyOn(fs, 'writeFileSync').mockImplementation();
|
||||
process.env['RUNNER_TEMP'] = 'tempDir';
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
|
||||
jest.spyOn(core, 'debug').mockImplementation();
|
||||
jest.spyOn(core, 'setOutput').mockImplementation();
|
||||
jest.spyOn(console, 'log').mockImplementation();
|
||||
await expect(new KustomizeRenderEngine().bake(false)).rejects.toThrow(
|
||||
'kubectl client version equal to v1.14 or higher is required to use kustomize features'
|
||||
)
|
||||
expect(kubectlUtil.getKubectlPath).toBeCalled()
|
||||
expect(utils.execCommand).toBeCalledWith('pathToKubectl', [
|
||||
'version',
|
||||
'--client=true',
|
||||
'-o',
|
||||
'json'
|
||||
])
|
||||
})
|
||||
|
||||
expect(await (new KustomizeRenderEngine()).bake(true)).toBeUndefined();
|
||||
expect(kubectlUtil.getKubectlPath).toBeCalled();
|
||||
expect(utils.execCommand).toBeCalledWith('pathToKubectl', ['version', '--client=true', '-o', 'json']);
|
||||
expect(utils.execCommand).toBeCalledWith('pathToKubectl', ['kustomize', 'pathToKustomization', 'additional', 'Arguments'], { silent: true } as ExecOptions);
|
||||
});
|
||||
test('KustomizeRenderEngine() - validate kubetl and bake using kustomize', async () => {
|
||||
jest
|
||||
.spyOn(kubectlUtil, 'getKubectlPath')
|
||||
.mockResolvedValue('pathToKubectl')
|
||||
const responseStdout = JSON.stringify({
|
||||
clientVersion: {
|
||||
major: '1',
|
||||
minor: '18'
|
||||
}
|
||||
})
|
||||
const kubectlVersionResponse = {
|
||||
stdout: responseStdout
|
||||
}
|
||||
const kustomizeResponse = {
|
||||
stdout: 'kustomizeOutput'
|
||||
}
|
||||
jest
|
||||
.spyOn(utils, 'execCommand')
|
||||
.mockResolvedValueOnce(kubectlVersionResponse as utils.ExecResult)
|
||||
.mockResolvedValueOnce(kustomizeResponse as utils.ExecResult)
|
||||
jest.spyOn(core, 'getInput').mockImplementation((inputName) => {
|
||||
if (inputName == 'kustomizationPath') return 'pathToKustomization'
|
||||
if (inputName == 'arguments') return 'additionalArguments'
|
||||
})
|
||||
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true)
|
||||
jest.spyOn(fs, 'writeFileSync').mockImplementation()
|
||||
process.env['RUNNER_TEMP'] = 'tempDir'
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
|
||||
jest.spyOn(core, 'debug').mockImplementation()
|
||||
jest.spyOn(core, 'setOutput').mockImplementation()
|
||||
jest.spyOn(console, 'log').mockImplementation()
|
||||
|
||||
test('KustomizeRenderEngine() - multiple additional argument', async () => {
|
||||
jest.spyOn(kubectlUtil, 'getKubectlPath').mockResolvedValue('pathToKubectl');
|
||||
const kubectlVersionResponse = {
|
||||
'stdout': JSON.stringify({
|
||||
"clientVersion": {
|
||||
"major": "1",
|
||||
"minor": "18",
|
||||
}
|
||||
})
|
||||
};
|
||||
const kustomizeResponse = {
|
||||
'stdout': 'kustomizeOutput'
|
||||
};
|
||||
jest.spyOn(utils, 'execCommand').mockResolvedValueOnce(kubectlVersionResponse as utils.ExecResult).mockResolvedValueOnce(kustomizeResponse as utils.ExecResult);
|
||||
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
|
||||
if (inputName == "kustomizationPath") return 'pathToKustomization';
|
||||
if (inputName == "arguments") return 'add1 tional,\nArguments\nnore\nargu ments';
|
||||
})
|
||||
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true);
|
||||
jest.spyOn(fs, 'writeFileSync').mockImplementation();
|
||||
process.env['RUNNER_TEMP'] = 'tempDir';
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
|
||||
jest.spyOn(core, 'debug').mockImplementation();
|
||||
jest.spyOn(core, 'setOutput').mockImplementation();
|
||||
jest.spyOn(console, 'log').mockImplementation();
|
||||
expect(await new KustomizeRenderEngine().bake(true)).toBeUndefined()
|
||||
expect(kubectlUtil.getKubectlPath).toBeCalled()
|
||||
|
||||
expect(await (new KustomizeRenderEngine()).bake(true)).toBeUndefined();
|
||||
expect(kubectlUtil.getKubectlPath).toBeCalled();
|
||||
expect(utils.execCommand).toBeCalledWith('pathToKubectl', ['version', '--client=true', '-o', 'json']);
|
||||
expect(utils.execCommand).toBeCalledWith('pathToKubectl', ['kustomize', 'pathToKustomization', 'add1 tional', 'Arguments', 'nore', 'argu ments'], { silent: true } as ExecOptions);
|
||||
})
|
||||
expect(utils.execCommand).toBeCalledWith('pathToKubectl', [
|
||||
'version',
|
||||
'--client=true',
|
||||
'-o',
|
||||
'json'
|
||||
])
|
||||
expect(utils.execCommand).toBeCalledWith(
|
||||
'pathToKubectl',
|
||||
['kustomize', 'pathToKustomization', 'additionalArguments'],
|
||||
{silent: true} as ExecOptions
|
||||
)
|
||||
|
||||
test('KomposeRenderEngine() - throw error if unable to find temp directory', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('pathToKompose');
|
||||
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true);
|
||||
jest.spyOn(komposeUtil, 'getKomposePath').mockResolvedValue('pathToKompose');
|
||||
process.env['RUNNER_TEMP'] = '';
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
|
||||
jest.spyOn(core, 'debug').mockImplementation();
|
||||
jest.spyOn(console, 'log').mockImplementation();
|
||||
expect(core.getInput).toBeCalledWith('kustomizationPath', {
|
||||
required: true
|
||||
})
|
||||
expect(fs.writeFileSync).toBeCalledWith(
|
||||
path.join('tempDir', 'baked-template-12345678.yaml'),
|
||||
'kustomizeOutput'
|
||||
)
|
||||
expect(core.setOutput).toBeCalledWith(
|
||||
'manifestsBundle',
|
||||
path.join('tempDir', 'baked-template-12345678.yaml')
|
||||
)
|
||||
})
|
||||
|
||||
await expect((new KomposeRenderEngine()).bake(false)).rejects.toThrow('Unable to create temp directory.');
|
||||
expect(komposeUtil.getKomposePath).toBeCalled();
|
||||
});
|
||||
test('KustomizeRenderEngine() - multiple additional arguments with leading/trailing spaces', async () => {
|
||||
jest
|
||||
.spyOn(kubectlUtil, 'getKubectlPath')
|
||||
.mockResolvedValue('pathToKubectl')
|
||||
const kubectlVersionResponse = {
|
||||
stdout: JSON.stringify({
|
||||
clientVersion: {
|
||||
major: '1',
|
||||
minor: '18'
|
||||
}
|
||||
})
|
||||
}
|
||||
const kustomizeResponse = {
|
||||
stdout: 'kustomizeOutput'
|
||||
}
|
||||
jest
|
||||
.spyOn(utils, 'execCommand')
|
||||
.mockResolvedValue(kubectlVersionResponse as utils.ExecResult)
|
||||
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
|
||||
if (inputName == 'kustomizationPath') return 'pathToKustomization'
|
||||
if (inputName == 'arguments') return ' additional \n Arguments '
|
||||
})
|
||||
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true)
|
||||
jest.spyOn(fs, 'writeFileSync').mockImplementation()
|
||||
process.env['RUNNER_TEMP'] = 'tempDir'
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
|
||||
jest.spyOn(core, 'debug').mockImplementation()
|
||||
jest.spyOn(core, 'setOutput').mockImplementation()
|
||||
jest.spyOn(console, 'log').mockImplementation()
|
||||
|
||||
test('KomposeRenderEngine() - bake using kompose', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('pathToDockerCompose');
|
||||
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true);
|
||||
jest.spyOn(komposeUtil, 'getKomposePath').mockResolvedValue('pathToKompose');
|
||||
process.env['RUNNER_TEMP'] = 'tempDir';
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
|
||||
jest.spyOn(core, 'setOutput').mockImplementation();
|
||||
expect(await new KustomizeRenderEngine().bake(true)).toBeUndefined()
|
||||
expect(kubectlUtil.getKubectlPath).toBeCalled()
|
||||
expect(utils.execCommand).toBeCalledWith('pathToKubectl', [
|
||||
'version',
|
||||
'--client=true',
|
||||
'-o',
|
||||
'json'
|
||||
])
|
||||
expect(utils.execCommand).toBeCalledWith(
|
||||
'pathToKubectl',
|
||||
['kustomize', 'pathToKustomization', 'additional', 'Arguments'],
|
||||
{silent: true} as ExecOptions
|
||||
)
|
||||
})
|
||||
|
||||
expect(await (new KomposeRenderEngine()).bake(true)).toBeUndefined();
|
||||
expect(komposeUtil.getKomposePath).toBeCalled();
|
||||
expect(utils.execCommand).toBeCalledWith('pathToKompose', ['convert', '-f', 'pathToDockerCompose', '-o', path.join('tempDir', 'baked-template-12345678.yaml')], {"silent": true});
|
||||
expect(core.setOutput).toBeCalledWith('manifestsBundle', path.join('tempDir', 'baked-template-12345678.yaml'));
|
||||
});
|
||||
test('KustomizeRenderEngine() - multiple additional argument', async () => {
|
||||
jest
|
||||
.spyOn(kubectlUtil, 'getKubectlPath')
|
||||
.mockResolvedValue('pathToKubectl')
|
||||
const kubectlVersionResponse = {
|
||||
stdout: JSON.stringify({
|
||||
clientVersion: {
|
||||
major: '1',
|
||||
minor: '18'
|
||||
}
|
||||
})
|
||||
}
|
||||
const kustomizeResponse = {
|
||||
stdout: 'kustomizeOutput'
|
||||
}
|
||||
jest
|
||||
.spyOn(utils, 'execCommand')
|
||||
.mockResolvedValueOnce(kubectlVersionResponse as utils.ExecResult)
|
||||
.mockResolvedValueOnce(kustomizeResponse as utils.ExecResult)
|
||||
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
|
||||
if (inputName == 'kustomizationPath') return 'pathToKustomization'
|
||||
if (inputName == 'arguments')
|
||||
return 'add1 tional,\nArguments\nnore\nargu ments'
|
||||
})
|
||||
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true)
|
||||
jest.spyOn(fs, 'writeFileSync').mockImplementation()
|
||||
process.env['RUNNER_TEMP'] = 'tempDir'
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
|
||||
jest.spyOn(core, 'debug').mockImplementation()
|
||||
jest.spyOn(core, 'setOutput').mockImplementation()
|
||||
jest.spyOn(console, 'log').mockImplementation()
|
||||
|
||||
test('run() - throw error on wrong input from render-engine', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('someRenderEngine');
|
||||
expect(await new KustomizeRenderEngine().bake(true)).toBeUndefined()
|
||||
expect(kubectlUtil.getKubectlPath).toBeCalled()
|
||||
expect(utils.execCommand).toBeCalledWith('pathToKubectl', [
|
||||
'version',
|
||||
'--client=true',
|
||||
'-o',
|
||||
'json'
|
||||
])
|
||||
expect(utils.execCommand).toBeCalledWith(
|
||||
'pathToKubectl',
|
||||
[
|
||||
'kustomize',
|
||||
'pathToKustomization',
|
||||
'add1 tional',
|
||||
'Arguments',
|
||||
'nore',
|
||||
'argu ments'
|
||||
],
|
||||
{silent: true} as ExecOptions
|
||||
)
|
||||
})
|
||||
|
||||
await expect(run()).rejects.toThrow('Unknown render engine');
|
||||
});
|
||||
test('KomposeRenderEngine() - throw error if unable to find temp directory', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('pathToKompose')
|
||||
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true)
|
||||
jest
|
||||
.spyOn(komposeUtil, 'getKomposePath')
|
||||
.mockResolvedValue('pathToKompose')
|
||||
process.env['RUNNER_TEMP'] = ''
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
|
||||
jest.spyOn(core, 'debug').mockImplementation()
|
||||
jest.spyOn(console, 'log').mockImplementation()
|
||||
|
||||
test('run() - throw error if bake fails', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValueOnce('kompose').mockReturnValueOnce('pathToKompose');
|
||||
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true);
|
||||
jest.spyOn(komposeUtil, 'getKomposePath').mockResolvedValue('pathToKompose');
|
||||
process.env['RUNNER_TEMP'] = '';
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
|
||||
await expect(new KomposeRenderEngine().bake(false)).rejects.toThrow(
|
||||
'Unable to create temp directory.'
|
||||
)
|
||||
expect(komposeUtil.getKomposePath).toBeCalled()
|
||||
})
|
||||
|
||||
await expect(run()).rejects.toThrow('Failed to run bake action. Error: Error: Unable to create temp directory.');
|
||||
});
|
||||
test('KomposeRenderEngine() - bake using kompose', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('pathToDockerCompose')
|
||||
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true)
|
||||
jest
|
||||
.spyOn(komposeUtil, 'getKomposePath')
|
||||
.mockResolvedValue('pathToKompose')
|
||||
process.env['RUNNER_TEMP'] = 'tempDir'
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
|
||||
jest.spyOn(core, 'setOutput').mockImplementation()
|
||||
|
||||
test('HelmRenderEngine() - bake manifest using helm', async () => {
|
||||
jest.spyOn(helmUtil, 'getHelmPath').mockResolvedValue('pathToHelm');
|
||||
jest.spyOn(core, 'getInput').mockReturnValueOnce('pathToHelmChart').mockReturnValueOnce('releaseName');
|
||||
jest.spyOn(console, 'log').mockImplementation();
|
||||
mockStatusCode = 0;
|
||||
stdOutMessage = 'v2.9.1';
|
||||
process.env['RUNNER_TEMP'] = 'tempDirPath';
|
||||
jest.spyOn(fs, 'writeFileSync').mockImplementation();
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
|
||||
jest.spyOn(core, 'setOutput').mockImplementation();
|
||||
expect(await new KomposeRenderEngine().bake(true)).toBeUndefined()
|
||||
expect(komposeUtil.getKomposePath).toBeCalled()
|
||||
expect(utils.execCommand).toBeCalledWith(
|
||||
'pathToKompose',
|
||||
[
|
||||
'convert',
|
||||
'-f',
|
||||
'pathToDockerCompose',
|
||||
'-o',
|
||||
path.join('tempDir', 'baked-template-12345678.yaml')
|
||||
],
|
||||
{silent: true}
|
||||
)
|
||||
expect(core.setOutput).toBeCalledWith(
|
||||
'manifestsBundle',
|
||||
path.join('tempDir', 'baked-template-12345678.yaml')
|
||||
)
|
||||
})
|
||||
|
||||
const execResult = {
|
||||
'stdout': 'test output'
|
||||
};
|
||||
jest.spyOn(utils, 'execCommand').mockResolvedValue(execResult as utils.ExecResult);
|
||||
test('run() - throw error on wrong input from render-engine', async () => {
|
||||
jest.spyOn(core, 'getInput').mockReturnValue('someRenderEngine')
|
||||
|
||||
expect(await (new HelmRenderEngine().bake(true))).toBeUndefined();
|
||||
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['dependency', 'update', 'pathToHelmChart'], {"silent": true});
|
||||
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['version', '--template', '{{.Version}}'], {"silent": true});
|
||||
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['init', '--client-only', '--stable-repo-url', 'https://charts.helm.sh/stable'], {"silent": true});
|
||||
expect(core.setOutput).toBeCalledWith('manifestsBundle', path.join('tempDirPath', 'baked-template-12345678.yaml'));
|
||||
});
|
||||
await expect(run()).rejects.toThrow('Unknown render engine')
|
||||
})
|
||||
|
||||
test('HelmRenderEngine() - single additional argument', async () => {
|
||||
process.env['INPUT_RENDERENGINE'] = 'helm';
|
||||
jest.spyOn(helmUtil, 'getHelmPath').mockResolvedValue('pathToHelm');
|
||||
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
|
||||
if (inputName == "helmChart") return 'pathToHelmChart';
|
||||
if (inputName == "arguments") return 'additionalArguments';
|
||||
if (inputName == "releaseName") return 'releaseName';
|
||||
})
|
||||
jest.spyOn(console, 'log').mockImplementation();
|
||||
mockStatusCode = 0;
|
||||
stdOutMessage = 'v2.9.1';
|
||||
process.env['RUNNER_TEMP'] = 'tempDirPath';
|
||||
jest.spyOn(fs, 'writeFileSync').mockImplementation();
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
|
||||
jest.spyOn(core, 'setOutput').mockImplementation();
|
||||
test('run() - throw error if bake fails', async () => {
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockReturnValueOnce('kompose')
|
||||
.mockReturnValueOnce('pathToKompose')
|
||||
jest.spyOn(ioUtil, 'exists').mockResolvedValue(true)
|
||||
jest
|
||||
.spyOn(komposeUtil, 'getKomposePath')
|
||||
.mockResolvedValue('pathToKompose')
|
||||
process.env['RUNNER_TEMP'] = ''
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
|
||||
|
||||
const execResult = {
|
||||
'stdout': 'test output'
|
||||
};
|
||||
jest.spyOn(utils, 'execCommand').mockResolvedValue(execResult as utils.ExecResult);
|
||||
await expect(run()).rejects.toThrow(
|
||||
'Failed to run bake action. Error: Error: Unable to create temp directory.'
|
||||
)
|
||||
})
|
||||
|
||||
expect(await (new HelmRenderEngine().bake(true))).toBeUndefined();
|
||||
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['dependency', 'update', 'pathToHelmChart'], {"silent": true});
|
||||
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['version', '--template', '{{.Version}}'], {"silent": true});
|
||||
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['template', 'additionalArguments', '--name', 'releaseName', 'pathToHelmChart'], { "silent": true });
|
||||
});
|
||||
test('HelmRenderEngine() - bake manifest using helm', async () => {
|
||||
jest.spyOn(helmUtil, 'getHelmPath').mockResolvedValue('pathToHelm')
|
||||
jest
|
||||
.spyOn(core, 'getInput')
|
||||
.mockReturnValueOnce('pathToHelmChart')
|
||||
.mockReturnValueOnce('releaseName')
|
||||
jest.spyOn(console, 'log').mockImplementation()
|
||||
mockStatusCode = 0
|
||||
stdOutMessage = 'v2.9.1'
|
||||
process.env['RUNNER_TEMP'] = 'tempDirPath'
|
||||
jest.spyOn(fs, 'writeFileSync').mockImplementation()
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
|
||||
jest.spyOn(core, 'setOutput').mockImplementation()
|
||||
|
||||
test('HelmRenderEngine() - multiple additional arguments', async () => {
|
||||
process.env['INPUT_RENDERENGINE'] = 'helm';
|
||||
jest.spyOn(helmUtil, 'getHelmPath').mockResolvedValue('pathToHelm');
|
||||
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
|
||||
if (inputName == "helmChart") return 'pathToHelmChart';
|
||||
if (inputName == "arguments") return 'additional\nArguments';
|
||||
if (inputName == "releaseName") return 'releaseName';
|
||||
})
|
||||
jest.spyOn(console, 'log').mockImplementation();
|
||||
mockStatusCode = 0;
|
||||
stdOutMessage = 'v2.9.1';
|
||||
process.env['RUNNER_TEMP'] = 'tempDirPath';
|
||||
jest.spyOn(fs, 'writeFileSync').mockImplementation();
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
|
||||
jest.spyOn(core, 'setOutput').mockImplementation();
|
||||
const execResult = {
|
||||
stdout: 'test output'
|
||||
}
|
||||
jest
|
||||
.spyOn(utils, 'execCommand')
|
||||
.mockResolvedValue(execResult as utils.ExecResult)
|
||||
|
||||
const execResult = {
|
||||
'stdout': 'test output'
|
||||
};
|
||||
jest.spyOn(utils, 'execCommand').mockResolvedValue(execResult as utils.ExecResult);
|
||||
expect(await new HelmRenderEngine().bake(true)).toBeUndefined()
|
||||
expect(utils.execCommand).toBeCalledWith(
|
||||
'pathToHelm',
|
||||
['dependency', 'update', 'pathToHelmChart'],
|
||||
{silent: true}
|
||||
)
|
||||
expect(utils.execCommand).toBeCalledWith(
|
||||
'pathToHelm',
|
||||
['version', '--template', '{{.Version}}'],
|
||||
{silent: true}
|
||||
)
|
||||
expect(utils.execCommand).toBeCalledWith(
|
||||
'pathToHelm',
|
||||
[
|
||||
'init',
|
||||
'--client-only',
|
||||
'--stable-repo-url',
|
||||
'https://charts.helm.sh/stable'
|
||||
],
|
||||
{silent: true}
|
||||
)
|
||||
expect(core.setOutput).toBeCalledWith(
|
||||
'manifestsBundle',
|
||||
path.join('tempDirPath', 'baked-template-12345678.yaml')
|
||||
)
|
||||
})
|
||||
|
||||
expect(await (new HelmRenderEngine().bake(true))).toBeUndefined();
|
||||
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['version', '--template', '{{.Version}}'], {"silent": true});
|
||||
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['init', '--client-only', '--stable-repo-url', 'https://charts.helm.sh/stable'], {"silent": true});
|
||||
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['template', 'additional', 'Arguments', '--name', 'releaseName', 'pathToHelmChart'], { "silent": true });
|
||||
});
|
||||
test('HelmRenderEngine() - single additional argument', async () => {
|
||||
process.env['INPUT_RENDERENGINE'] = 'helm'
|
||||
jest.spyOn(helmUtil, 'getHelmPath').mockResolvedValue('pathToHelm')
|
||||
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
|
||||
if (inputName == 'helmChart') return 'pathToHelmChart'
|
||||
if (inputName == 'arguments') return 'additionalArguments'
|
||||
if (inputName == 'releaseName') return 'releaseName'
|
||||
})
|
||||
jest.spyOn(console, 'log').mockImplementation()
|
||||
mockStatusCode = 0
|
||||
stdOutMessage = 'v2.9.1'
|
||||
process.env['RUNNER_TEMP'] = 'tempDirPath'
|
||||
jest.spyOn(fs, 'writeFileSync').mockImplementation()
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
|
||||
jest.spyOn(core, 'setOutput').mockImplementation()
|
||||
|
||||
test('HelmRenderEngine() - no additional arguments', async () => {
|
||||
process.env['INPUT_RENDERENGINE'] = 'helm';
|
||||
jest.spyOn(helmUtil, 'getHelmPath').mockResolvedValue('pathToHelm');
|
||||
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
|
||||
if (inputName == "helmChart") return 'pathToHelmChart';
|
||||
if (inputName == "arguments") return '';
|
||||
if (inputName == "releaseName") return 'releaseName';
|
||||
})
|
||||
jest.spyOn(console, 'log').mockImplementation();
|
||||
mockStatusCode = 0;
|
||||
stdOutMessage = 'v2.9.1';
|
||||
process.env['RUNNER_TEMP'] = 'tempDirPath';
|
||||
jest.spyOn(fs, 'writeFileSync').mockImplementation();
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678);
|
||||
jest.spyOn(core, 'setOutput').mockImplementation();
|
||||
const execResult = {
|
||||
stdout: 'test output'
|
||||
}
|
||||
jest
|
||||
.spyOn(utils, 'execCommand')
|
||||
.mockResolvedValue(execResult as utils.ExecResult)
|
||||
|
||||
const execResult = {
|
||||
'stdout': 'test output'
|
||||
};
|
||||
jest.spyOn(utils, 'execCommand').mockResolvedValue(execResult as utils.ExecResult);
|
||||
expect(await new HelmRenderEngine().bake(true)).toBeUndefined()
|
||||
expect(utils.execCommand).toBeCalledWith(
|
||||
'pathToHelm',
|
||||
['dependency', 'update', 'pathToHelmChart'],
|
||||
{silent: true}
|
||||
)
|
||||
expect(utils.execCommand).toBeCalledWith(
|
||||
'pathToHelm',
|
||||
['version', '--template', '{{.Version}}'],
|
||||
{silent: true}
|
||||
)
|
||||
expect(utils.execCommand).toBeCalledWith(
|
||||
'pathToHelm',
|
||||
[
|
||||
'template',
|
||||
'additionalArguments',
|
||||
'--name',
|
||||
'releaseName',
|
||||
'pathToHelmChart'
|
||||
],
|
||||
{silent: true}
|
||||
)
|
||||
})
|
||||
|
||||
expect(await (new HelmRenderEngine().bake(true))).toBeUndefined();
|
||||
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['version', '--template', '{{.Version}}'], {"silent": true});
|
||||
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['init', '--client-only', '--stable-repo-url', 'https://charts.helm.sh/stable'], {"silent": true});
|
||||
expect(utils.execCommand).toBeCalledWith('pathToHelm', ['template', '--name', 'releaseName', 'pathToHelmChart'], { "silent": true });
|
||||
});
|
||||
});
|
||||
test('HelmRenderEngine() - multiple additional arguments', async () => {
|
||||
process.env['INPUT_RENDERENGINE'] = 'helm'
|
||||
jest.spyOn(helmUtil, 'getHelmPath').mockResolvedValue('pathToHelm')
|
||||
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
|
||||
if (inputName == 'helmChart') return 'pathToHelmChart'
|
||||
if (inputName == 'arguments') return 'additional\nArguments'
|
||||
if (inputName == 'releaseName') return 'releaseName'
|
||||
})
|
||||
jest.spyOn(console, 'log').mockImplementation()
|
||||
mockStatusCode = 0
|
||||
stdOutMessage = 'v2.9.1'
|
||||
process.env['RUNNER_TEMP'] = 'tempDirPath'
|
||||
jest.spyOn(fs, 'writeFileSync').mockImplementation()
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
|
||||
jest.spyOn(core, 'setOutput').mockImplementation()
|
||||
|
||||
const execResult = {
|
||||
stdout: 'test output'
|
||||
}
|
||||
jest
|
||||
.spyOn(utils, 'execCommand')
|
||||
.mockResolvedValue(execResult as utils.ExecResult)
|
||||
|
||||
expect(await new HelmRenderEngine().bake(true)).toBeUndefined()
|
||||
expect(utils.execCommand).toBeCalledWith(
|
||||
'pathToHelm',
|
||||
['version', '--template', '{{.Version}}'],
|
||||
{silent: true}
|
||||
)
|
||||
expect(utils.execCommand).toBeCalledWith(
|
||||
'pathToHelm',
|
||||
[
|
||||
'init',
|
||||
'--client-only',
|
||||
'--stable-repo-url',
|
||||
'https://charts.helm.sh/stable'
|
||||
],
|
||||
{silent: true}
|
||||
)
|
||||
expect(utils.execCommand).toBeCalledWith(
|
||||
'pathToHelm',
|
||||
[
|
||||
'template',
|
||||
'additional',
|
||||
'Arguments',
|
||||
'--name',
|
||||
'releaseName',
|
||||
'pathToHelmChart'
|
||||
],
|
||||
{silent: true}
|
||||
)
|
||||
})
|
||||
|
||||
test('HelmRenderEngine() - no additional arguments', async () => {
|
||||
process.env['INPUT_RENDERENGINE'] = 'helm'
|
||||
jest.spyOn(helmUtil, 'getHelmPath').mockResolvedValue('pathToHelm')
|
||||
jest.spyOn(core, 'getInput').mockImplementation((inputName, options) => {
|
||||
if (inputName == 'helmChart') return 'pathToHelmChart'
|
||||
if (inputName == 'arguments') return ''
|
||||
if (inputName == 'releaseName') return 'releaseName'
|
||||
})
|
||||
jest.spyOn(console, 'log').mockImplementation()
|
||||
mockStatusCode = 0
|
||||
stdOutMessage = 'v2.9.1'
|
||||
process.env['RUNNER_TEMP'] = 'tempDirPath'
|
||||
jest.spyOn(fs, 'writeFileSync').mockImplementation()
|
||||
jest.spyOn(utils, 'getCurrentTime').mockReturnValue(12345678)
|
||||
jest.spyOn(core, 'setOutput').mockImplementation()
|
||||
|
||||
const execResult = {
|
||||
stdout: 'test output'
|
||||
}
|
||||
jest
|
||||
.spyOn(utils, 'execCommand')
|
||||
.mockResolvedValue(execResult as utils.ExecResult)
|
||||
|
||||
expect(await new HelmRenderEngine().bake(true)).toBeUndefined()
|
||||
expect(utils.execCommand).toBeCalledWith(
|
||||
'pathToHelm',
|
||||
['version', '--template', '{{.Version}}'],
|
||||
{silent: true}
|
||||
)
|
||||
expect(utils.execCommand).toBeCalledWith(
|
||||
'pathToHelm',
|
||||
[
|
||||
'init',
|
||||
'--client-only',
|
||||
'--stable-repo-url',
|
||||
'https://charts.helm.sh/stable'
|
||||
],
|
||||
{silent: true}
|
||||
)
|
||||
expect(utils.execCommand).toBeCalledWith(
|
||||
'pathToHelm',
|
||||
['template', '--name', 'releaseName', 'pathToHelmChart'],
|
||||
{silent: true}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
469
src/run.ts
469
src/run.ts
|
@ -1,250 +1,307 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as core from '@actions/core';
|
||||
import * as ioUtil from '@actions/io/lib/io-util';
|
||||
import { ExecOptions } from "@actions/exec/lib/interfaces";
|
||||
import * as utilities from "./utilities"
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as util from 'util';
|
||||
import { getHelmPath, NameValuePair } from "./helm-util"
|
||||
import { getKubectlPath } from "./kubectl-util"
|
||||
import { getKomposePath } from "./kompose-util"
|
||||
|
||||
import * as core from '@actions/core'
|
||||
import * as ioUtil from '@actions/io/lib/io-util'
|
||||
import {ExecOptions} from '@actions/exec/lib/interfaces'
|
||||
import * as utilities from './utilities'
|
||||
import * as path from 'path'
|
||||
import * as fs from 'fs'
|
||||
import * as util from 'util'
|
||||
import {getHelmPath, NameValuePair} from './helm-util'
|
||||
import {getKubectlPath} from './kubectl-util'
|
||||
import {getKomposePath} from './kompose-util'
|
||||
|
||||
abstract class RenderEngine {
|
||||
public bake!: (isSilent: boolean) => Promise<any>;
|
||||
protected getTemplatePath = () => {
|
||||
const tempDirectory = process.env['RUNNER_TEMP'];
|
||||
if (!!tempDirectory) {
|
||||
return path.join(tempDirectory, 'baked-template-' + utilities.getCurrentTime().toString() + '.yaml');
|
||||
}
|
||||
else {
|
||||
throw Error("Unable to create temp directory.");
|
||||
}
|
||||
}
|
||||
public bake!: (isSilent: boolean) => Promise<any>
|
||||
protected getTemplatePath = () => {
|
||||
const tempDirectory = process.env['RUNNER_TEMP']
|
||||
if (!!tempDirectory) {
|
||||
return path.join(
|
||||
tempDirectory,
|
||||
'baked-template-' + utilities.getCurrentTime().toString() + '.yaml'
|
||||
)
|
||||
} else {
|
||||
throw Error('Unable to create temp directory.')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class HelmRenderEngine extends RenderEngine {
|
||||
public bake = async (isSilent: boolean): Promise<any> => {
|
||||
const helmPath = await getHelmPath();
|
||||
const chartPath = core.getInput('helmChart', { required: true });
|
||||
public bake = async (isSilent: boolean): Promise<any> => {
|
||||
const helmPath = await getHelmPath()
|
||||
const chartPath = core.getInput('helmChart', {required: true})
|
||||
|
||||
const options = {
|
||||
silent: isSilent
|
||||
} as ExecOptions;
|
||||
const options = {
|
||||
silent: isSilent
|
||||
} as ExecOptions
|
||||
|
||||
const dependencyArgs = this.getDependencyArgs(chartPath);
|
||||
const dependencyArgs = this.getDependencyArgs(chartPath)
|
||||
|
||||
console.log("Running helm dependency update command..");
|
||||
await utilities.execCommand(helmPath, dependencyArgs, options);
|
||||
console.log('Running helm dependency update command..')
|
||||
await utilities.execCommand(helmPath, dependencyArgs, options)
|
||||
|
||||
console.log("Getting helm version..");
|
||||
let isV3 = true;
|
||||
await this.isHelmV3(helmPath).then((result) => { isV3 = result }).catch(() => { isV3 = false });
|
||||
|
||||
try {
|
||||
if (!isV3) {
|
||||
await utilities.execCommand(helmPath, ['init', '--client-only', '--stable-repo-url', 'https://charts.helm.sh/stable'], options);
|
||||
}
|
||||
} catch (ex) {
|
||||
core.warning(util.format('Could not run helm init command: ', ex));
|
||||
}
|
||||
console.log('Getting helm version..')
|
||||
let isV3 = true
|
||||
await this.isHelmV3(helmPath)
|
||||
.then((result) => {
|
||||
isV3 = result
|
||||
})
|
||||
.catch(() => {
|
||||
isV3 = false
|
||||
})
|
||||
|
||||
console.log("Creating the template argument string..");
|
||||
const args = await this.getHelmTemplateArgs(chartPath, isV3);
|
||||
try {
|
||||
if (!isV3) {
|
||||
await utilities.execCommand(
|
||||
helmPath,
|
||||
[
|
||||
'init',
|
||||
'--client-only',
|
||||
'--stable-repo-url',
|
||||
'https://charts.helm.sh/stable'
|
||||
],
|
||||
options
|
||||
)
|
||||
}
|
||||
} catch (ex) {
|
||||
core.warning(util.format('Could not run helm init command: ', ex))
|
||||
}
|
||||
|
||||
console.log("Running helm template command..");
|
||||
const result = await utilities.execCommand(helmPath, args, options)
|
||||
console.log('Creating the template argument string..')
|
||||
const args = await this.getHelmTemplateArgs(chartPath, isV3)
|
||||
|
||||
const pathToBakedManifest = this.getTemplatePath();
|
||||
fs.writeFileSync(pathToBakedManifest, result.stdout);
|
||||
core.setOutput('manifestsBundle', pathToBakedManifest);
|
||||
}
|
||||
console.log('Running helm template command..')
|
||||
const result = await utilities.execCommand(helmPath, args, options)
|
||||
|
||||
private getOverrideValues(overrides: string[]) {
|
||||
const overrideValues: NameValuePair[] = [];
|
||||
overrides.forEach(arg => {
|
||||
const overrideInput = arg.split(':');
|
||||
const overrideName = overrideInput[0];
|
||||
const overrideValue = overrideInput.slice(1).join(':');
|
||||
overrideValues.push({
|
||||
name: overrideName,
|
||||
value: overrideValue
|
||||
} as NameValuePair);
|
||||
});
|
||||
const pathToBakedManifest = this.getTemplatePath()
|
||||
fs.writeFileSync(pathToBakedManifest, result.stdout)
|
||||
core.setOutput('manifestsBundle', pathToBakedManifest)
|
||||
}
|
||||
|
||||
return overrideValues;
|
||||
}
|
||||
private getOverrideValues(overrides: string[]) {
|
||||
const overrideValues: NameValuePair[] = []
|
||||
overrides.forEach((arg) => {
|
||||
const overrideInput = arg.split(':')
|
||||
const overrideName = overrideInput[0]
|
||||
const overrideValue = overrideInput.slice(1).join(':')
|
||||
overrideValues.push({
|
||||
name: overrideName,
|
||||
value: overrideValue
|
||||
} as NameValuePair)
|
||||
})
|
||||
|
||||
private getDependencyArgs(chartPath: string): string[] {
|
||||
let args: string[] = [];
|
||||
args.push('dependency');
|
||||
args.push('update');
|
||||
args.push(chartPath);
|
||||
return overrideValues
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
private getDependencyArgs(chartPath: string): string[] {
|
||||
let args: string[] = []
|
||||
args.push('dependency')
|
||||
args.push('update')
|
||||
args.push(chartPath)
|
||||
|
||||
private async getHelmTemplateArgs(chartPath: string, isV3: boolean): Promise<string[]> {
|
||||
const releaseName = core.getInput('releaseName', { required: false });
|
||||
let args: string[] = [];
|
||||
args.push('template');
|
||||
const templateArgs = await getTemplateArguments(chartPath);
|
||||
args = args.concat(templateArgs);
|
||||
return args
|
||||
}
|
||||
|
||||
const namespace = core.getInput('namespace', { required: false });
|
||||
if (namespace) {
|
||||
args.push('--namespace');
|
||||
args.push(namespace);
|
||||
}
|
||||
private async getHelmTemplateArgs(
|
||||
chartPath: string,
|
||||
isV3: boolean
|
||||
): Promise<string[]> {
|
||||
const releaseName = core.getInput('releaseName', {required: false})
|
||||
let args: string[] = []
|
||||
args.push('template')
|
||||
const templateArgs = await getTemplateArguments()
|
||||
args = args.concat(templateArgs)
|
||||
|
||||
if (isV3) {
|
||||
if (releaseName) {
|
||||
args.push(releaseName);
|
||||
}
|
||||
} else {
|
||||
if (releaseName) {
|
||||
args.push('--name');
|
||||
args.push(releaseName);
|
||||
}
|
||||
}
|
||||
args.push(chartPath);
|
||||
|
||||
const overrideFilesInput = core.getInput('overrideFiles', { required: false });
|
||||
if (!!overrideFilesInput) {
|
||||
core.debug("Adding overrides file inputs");
|
||||
const overrideFiles = overrideFilesInput.split('\n');
|
||||
if (overrideFiles.length > 0) {
|
||||
overrideFiles.forEach(file => {
|
||||
args.push('-f');
|
||||
args.push(file);
|
||||
});
|
||||
}
|
||||
}
|
||||
const namespace = core.getInput('namespace', {required: false})
|
||||
if (namespace) {
|
||||
args.push('--namespace')
|
||||
args.push(namespace)
|
||||
}
|
||||
|
||||
const overridesInput = core.getInput('overrides', { required: false });
|
||||
if (!!overridesInput) {
|
||||
core.debug("Adding overrides inputs");
|
||||
const overrides = overridesInput.split('\n');
|
||||
if (overrides.length > 0) {
|
||||
const overrideValues = this.getOverrideValues(overrides);
|
||||
overrideValues.forEach(overrideValue => {
|
||||
args.push('--set');
|
||||
args.push(`${overrideValue.name}=${overrideValue.value}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
return args;
|
||||
}
|
||||
if (isV3) {
|
||||
if (releaseName) {
|
||||
args.push(releaseName)
|
||||
}
|
||||
} else {
|
||||
if (releaseName) {
|
||||
args.push('--name')
|
||||
args.push(releaseName)
|
||||
}
|
||||
}
|
||||
args.push(chartPath)
|
||||
|
||||
private async isHelmV3(path: string) {
|
||||
let result = await utilities.execCommand(path, ["version", "--template", "{{.Version}}"], { silent: true });
|
||||
return result.stdout.split('.')[0] === 'v3';
|
||||
}
|
||||
const overrideFilesInput = core.getInput('overrideFiles', {
|
||||
required: false
|
||||
})
|
||||
if (!!overrideFilesInput) {
|
||||
core.debug('Adding overrides file inputs')
|
||||
const overrideFiles = overrideFilesInput.split('\n')
|
||||
if (overrideFiles.length > 0) {
|
||||
overrideFiles.forEach((file) => {
|
||||
args.push('-f')
|
||||
args.push(file)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const overridesInput = core.getInput('overrides', {required: false})
|
||||
if (!!overridesInput) {
|
||||
core.debug('Adding overrides inputs')
|
||||
const overrides = overridesInput.split('\n')
|
||||
if (overrides.length > 0) {
|
||||
const overrideValues = this.getOverrideValues(overrides)
|
||||
overrideValues.forEach((overrideValue) => {
|
||||
args.push('--set')
|
||||
args.push(`${overrideValue.name}=${overrideValue.value}`)
|
||||
})
|
||||
}
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
private async isHelmV3(path: string) {
|
||||
let result = await utilities.execCommand(
|
||||
path,
|
||||
['version', '--template', '{{.Version}}'],
|
||||
{silent: true}
|
||||
)
|
||||
return result.stdout.split('.')[0] === 'v3'
|
||||
}
|
||||
}
|
||||
|
||||
export class KomposeRenderEngine extends RenderEngine {
|
||||
public bake = async (isSilent: boolean): Promise<any> => {
|
||||
const dockerComposeFilePath = core.getInput('dockerComposeFile', { required: true });
|
||||
if (!ioUtil.exists(dockerComposeFilePath)) {
|
||||
throw Error(util.format("Docker compose file path %s does not exist. Please check the path specified", dockerComposeFilePath));
|
||||
}
|
||||
public bake = async (isSilent: boolean): Promise<any> => {
|
||||
const dockerComposeFilePath = core.getInput('dockerComposeFile', {
|
||||
required: true
|
||||
})
|
||||
if (!ioUtil.exists(dockerComposeFilePath)) {
|
||||
throw Error(
|
||||
util.format(
|
||||
'Docker compose file path %s does not exist. Please check the path specified',
|
||||
dockerComposeFilePath
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
const options = {
|
||||
silent: isSilent
|
||||
} as ExecOptions;
|
||||
const options = {
|
||||
silent: isSilent
|
||||
} as ExecOptions
|
||||
|
||||
const komposePath = await getKomposePath();
|
||||
const pathToBakedManifest = this.getTemplatePath();
|
||||
core.debug("Running kompose command..");
|
||||
await utilities.execCommand(komposePath, ['convert', '-f', dockerComposeFilePath, '-o', pathToBakedManifest], options)
|
||||
core.setOutput('manifestsBundle', pathToBakedManifest);
|
||||
}
|
||||
const komposePath = await getKomposePath()
|
||||
const pathToBakedManifest = this.getTemplatePath()
|
||||
core.debug('Running kompose command..')
|
||||
await utilities.execCommand(
|
||||
komposePath,
|
||||
['convert', '-f', dockerComposeFilePath, '-o', pathToBakedManifest],
|
||||
options
|
||||
)
|
||||
core.setOutput('manifestsBundle', pathToBakedManifest)
|
||||
}
|
||||
}
|
||||
|
||||
export class KustomizeRenderEngine extends RenderEngine {
|
||||
public bake = async (isSilent: boolean) => {
|
||||
const kubectlPath = await getKubectlPath();
|
||||
await this.validateKustomize(kubectlPath);
|
||||
const kustomizationPath = core.getInput('kustomizationPath', { required: true });
|
||||
if (!ioUtil.exists(kustomizationPath)) {
|
||||
throw Error(util.format("kustomizationPath %s does not exist. Please check whether file exists or not.", kustomizationPath));
|
||||
}
|
||||
public bake = async (isSilent: boolean) => {
|
||||
const kubectlPath = await getKubectlPath()
|
||||
await this.validateKustomize(kubectlPath)
|
||||
const kustomizationPath = core.getInput('kustomizationPath', {
|
||||
required: true
|
||||
})
|
||||
if (!ioUtil.exists(kustomizationPath)) {
|
||||
throw Error(
|
||||
util.format(
|
||||
'kustomizationPath %s does not exist. Please check whether file exists or not.',
|
||||
kustomizationPath
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
const options = {
|
||||
silent: isSilent
|
||||
} as ExecOptions;
|
||||
const options = {
|
||||
silent: isSilent
|
||||
} as ExecOptions
|
||||
|
||||
core.info("Creating the template argument string..");
|
||||
let args: string[] = ['kustomize', kustomizationPath]
|
||||
const userargs = await getTemplateArguments(kustomizationPath)
|
||||
args = args.concat(userargs)
|
||||
core.info('Creating the template argument string..')
|
||||
let tempArgs: string[] = ['kustomize', kustomizationPath]
|
||||
const userargs = await getTemplateArguments()
|
||||
tempArgs = tempArgs.concat(userargs)
|
||||
|
||||
core.debug("Running kubectl kustomize command..");
|
||||
console.log(`[command] ${kubectlPath} kustomize ${core.getInput('kustomizationPath')}`);
|
||||
const result = await utilities.execCommand(kubectlPath, args, options);
|
||||
const pathToBakedManifest = this.getTemplatePath();
|
||||
fs.writeFileSync(pathToBakedManifest, result.stdout);
|
||||
core.setOutput('manifestsBundle', pathToBakedManifest);
|
||||
};
|
||||
core.debug('Running kubectl kustomize command..')
|
||||
console.log(
|
||||
`[command] ${kubectlPath} kustomize ${core.getInput(
|
||||
'kustomizationPath'
|
||||
)}`
|
||||
)
|
||||
const result = await utilities.execCommand(kubectlPath, tempArgs, options)
|
||||
const pathToBakedManifest = this.getTemplatePath()
|
||||
fs.writeFileSync(pathToBakedManifest, result.stdout)
|
||||
core.setOutput('manifestsBundle', pathToBakedManifest)
|
||||
}
|
||||
|
||||
private async validateKustomize(kubectlPath: string) {
|
||||
const result = await utilities.execCommand(kubectlPath, ['version', '--client=true', '-o', 'json']);
|
||||
if (!!result.stdout) {
|
||||
const clientVersion = JSON.parse(result.stdout).clientVersion;
|
||||
const versionNumber = `${clientVersion.major}.${clientVersion.minor}`;
|
||||
if (!clientVersion || parseFloat(versionNumber) < parseFloat(utilities.MIN_KUBECTL_CLIENT_VERSION)) {
|
||||
throw new Error("kubectl client version equal to v1.14 or higher is required to use kustomize features");
|
||||
}
|
||||
}
|
||||
}
|
||||
private async validateKustomize(kubectlPath: string) {
|
||||
const result = await utilities.execCommand(kubectlPath, [
|
||||
'version',
|
||||
'--client=true',
|
||||
'-o',
|
||||
'json'
|
||||
])
|
||||
if (!!result.stdout) {
|
||||
const clientVersion = JSON.parse(result.stdout).clientVersion
|
||||
const versionNumber = `${clientVersion.major}.${clientVersion.minor}`
|
||||
if (
|
||||
!clientVersion ||
|
||||
parseFloat(versionNumber) <
|
||||
parseFloat(utilities.MIN_KUBECTL_CLIENT_VERSION)
|
||||
) {
|
||||
throw new Error(
|
||||
'kubectl client version equal to v1.14 or higher is required to use kustomize features'
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function getTemplateArguments(path: string) {
|
||||
const args: string[] = [];
|
||||
const additionalArgs = core.getInput('arguments', { required: false })
|
||||
if (!!additionalArgs) {
|
||||
const argumentArray = additionalArgs
|
||||
.split(/[\n,;]+/) // split into each line
|
||||
.map((manifest) => manifest.trim()) // remove surrounding whitespace
|
||||
.filter((manifest) => manifest.length > 0); // remove any blanks
|
||||
if (argumentArray.length > 0) {
|
||||
argumentArray.forEach(arg => {
|
||||
args.push(arg);
|
||||
});
|
||||
}
|
||||
}
|
||||
return args;
|
||||
export async function getTemplateArguments() {
|
||||
const args: string[] = []
|
||||
const additionalArgs = core.getInput('arguments', {required: false})
|
||||
if (!!additionalArgs) {
|
||||
const argumentArray = additionalArgs
|
||||
.split(/[\n,;]+/) // split into each line
|
||||
.map((manifest) => manifest.trim()) // remove surrounding whitespace
|
||||
.filter((manifest) => manifest.length > 0) // remove any blanks
|
||||
if (argumentArray.length > 0) {
|
||||
argumentArray.forEach((arg) => {
|
||||
args.push(arg)
|
||||
})
|
||||
}
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
export async function run() {
|
||||
const renderType = core.getInput('renderEngine', { required: true });
|
||||
let renderEngine: RenderEngine;
|
||||
switch (renderType) {
|
||||
case 'helm':
|
||||
case 'helm2':
|
||||
renderEngine = new HelmRenderEngine();
|
||||
break;
|
||||
case 'kompose':
|
||||
renderEngine = new KomposeRenderEngine();
|
||||
break;
|
||||
case 'kustomize':
|
||||
renderEngine = new KustomizeRenderEngine();
|
||||
break;
|
||||
default:
|
||||
throw Error("Unknown render engine");
|
||||
}
|
||||
const renderType = core.getInput('renderEngine', {required: true})
|
||||
let renderEngine: RenderEngine
|
||||
switch (renderType) {
|
||||
case 'helm':
|
||||
case 'helm2':
|
||||
renderEngine = new HelmRenderEngine()
|
||||
break
|
||||
case 'kompose':
|
||||
renderEngine = new KomposeRenderEngine()
|
||||
break
|
||||
case 'kustomize':
|
||||
renderEngine = new KustomizeRenderEngine()
|
||||
break
|
||||
default:
|
||||
throw Error('Unknown render engine')
|
||||
}
|
||||
|
||||
let isSilent = core.getInput('silent', { required: false }) === 'true';
|
||||
|
||||
try {
|
||||
await renderEngine.bake(isSilent);
|
||||
}
|
||||
catch (err) {
|
||||
throw Error(util.format("Failed to run bake action. Error: %s", err));
|
||||
}
|
||||
let isSilent = core.getInput('silent', {required: false}) === 'true'
|
||||
|
||||
try {
|
||||
await renderEngine.bake(isSilent)
|
||||
} catch (err) {
|
||||
throw Error(util.format('Failed to run bake action. Error: %s', err))
|
||||
}
|
||||
}
|
||||
|
||||
run().catch(core.setFailed);
|
||||
run().catch(core.setFailed)
|
||||
|
|
|
@ -1,248 +1,266 @@
|
|||
import * as os from 'os';
|
||||
import * as fs from 'fs';
|
||||
import * as toolCache from '@actions/tool-cache';
|
||||
import { ExecOptions } from "@actions/exec/lib/interfaces";
|
||||
import * as core from '@actions/core';
|
||||
import * as utils from './utilities';
|
||||
import * as os from 'os'
|
||||
import * as fs from 'fs'
|
||||
import * as toolCache from '@actions/tool-cache'
|
||||
import {ExecOptions} from '@actions/exec/lib/interfaces'
|
||||
import * as core from '@actions/core'
|
||||
import * as utils from './utilities'
|
||||
|
||||
var mockStatusCode, stdOutMessage, stdErrMessage;
|
||||
var mockStatusCode, stdOutMessage, stdErrMessage
|
||||
const mockExecFn = jest.fn().mockImplementation((toolPath, args, options) => {
|
||||
options.listeners.stdout(!stdOutMessage ? '' : stdOutMessage);
|
||||
options.listeners.stderr(!stdErrMessage ? '' : stdErrMessage);
|
||||
return mockStatusCode;
|
||||
options.listeners.stdout(!stdOutMessage ? '' : stdOutMessage)
|
||||
options.listeners.stderr(!stdErrMessage ? '' : stdErrMessage)
|
||||
return mockStatusCode
|
||||
})
|
||||
jest.mock('@actions/exec/lib/toolrunner', () => {
|
||||
return {
|
||||
ToolRunner: jest.fn().mockImplementation((toolPath, args, options) => {
|
||||
return {
|
||||
exec: () => mockExecFn(toolPath, args, options)
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
return {
|
||||
ToolRunner: jest.fn().mockImplementation((toolPath, args, options) => {
|
||||
return {
|
||||
exec: () => mockExecFn(toolPath, args, options)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
describe('Test all functions in utilities file', () => {
|
||||
test('isEqual() - ', () => {
|
||||
expect(utils.isEqual('', null)).toBeTruthy();
|
||||
expect(utils.isEqual('a', 'A')).toBeTruthy();
|
||||
expect(utils.isEqual(null, 'a')).toBeFalsy();
|
||||
});
|
||||
test('isEqual() - ', () => {
|
||||
expect(utils.isEqual('', null)).toBeTruthy()
|
||||
expect(utils.isEqual('a', 'A')).toBeTruthy()
|
||||
expect(utils.isEqual(null, 'a')).toBeFalsy()
|
||||
})
|
||||
|
||||
test('getExecutableExtension() - return .exe when os is Windows', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
test('getExecutableExtension() - return .exe when os is Windows', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
|
||||
expect(utils.getExecutableExtension()).toBe('.exe');
|
||||
expect(os.type).toBeCalled();
|
||||
});
|
||||
expect(utils.getExecutableExtension()).toBe('.exe')
|
||||
expect(os.type).toBeCalled()
|
||||
})
|
||||
|
||||
test('getExecutableExtension() - return empty string for non-windows OS', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Darwin');
|
||||
test('getExecutableExtension() - return empty string for non-windows OS', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Darwin')
|
||||
|
||||
expect(utils.getExecutableExtension()).toBe('');
|
||||
expect(os.type).toBeCalled();
|
||||
});
|
||||
expect(utils.getExecutableExtension()).toBe('')
|
||||
expect(os.type).toBeCalled()
|
||||
})
|
||||
|
||||
test('execCommand() - generate and throw error if non-zero code is returned with empty stderr', async () => {
|
||||
mockStatusCode = 1;
|
||||
stdOutMessage = '';
|
||||
stdErrMessage = '';
|
||||
test('execCommand() - generate and throw error if non-zero code is returned with empty stderr', async () => {
|
||||
mockStatusCode = 1
|
||||
stdOutMessage = ''
|
||||
stdErrMessage = ''
|
||||
|
||||
await expect(utils.execCommand('cd', ['nonEsistingDirectory'])).rejects.toThrow('cd exited with result code 1');
|
||||
});
|
||||
await expect(
|
||||
utils.execCommand('cd', ['nonEsistingDirectory'])
|
||||
).rejects.toThrow('cd exited with result code 1')
|
||||
})
|
||||
|
||||
test('execCommand() - throw stderr if non zero code is returned', async () => {
|
||||
mockStatusCode = 1;
|
||||
stdOutMessage = '';
|
||||
stdErrMessage = 'Directory doesn\'t exist';
|
||||
await expect(utils.execCommand('cd', ['nonEsistingDirectory'], {} as ExecOptions)).rejects.toThrow('Directory doesn\'t exist');
|
||||
});
|
||||
test('execCommand() - throw stderr if non zero code is returned', async () => {
|
||||
mockStatusCode = 1
|
||||
stdOutMessage = ''
|
||||
stdErrMessage = "Directory doesn't exist"
|
||||
await expect(
|
||||
utils.execCommand('cd', ['nonEsistingDirectory'], {} as ExecOptions)
|
||||
).rejects.toThrow("Directory doesn't exist")
|
||||
})
|
||||
|
||||
test('execCommand() - return ExecOptions type object with stdout if exit code is 0', async () => {
|
||||
mockStatusCode = 0;
|
||||
stdOutMessage = 'list of files';
|
||||
stdErrMessage = '';
|
||||
expect(await utils.execCommand('ls', [], {} as ExecOptions)).toMatchObject({'stderr': '', 'stdout': 'list of files'});
|
||||
});
|
||||
test('execCommand() - return ExecOptions type object with stdout if exit code is 0', async () => {
|
||||
mockStatusCode = 0
|
||||
stdOutMessage = 'list of files'
|
||||
stdErrMessage = ''
|
||||
expect(
|
||||
await utils.execCommand('ls', [], {} as ExecOptions)
|
||||
).toMatchObject({stderr: '', stdout: 'list of files'})
|
||||
})
|
||||
|
||||
test('getDownloadUrl() - return the URL to download helm for Linux_x64', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Linux');
|
||||
jest.spyOn(os, 'arch').mockReturnValue('x64');
|
||||
const helmLinuxUrl = 'https://get.helm.sh/helm-v3.2.1-linux-amd64.zip'
|
||||
test('getDownloadUrl() - return the URL to download helm for Linux_x64', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Linux')
|
||||
jest.spyOn(os, 'arch').mockReturnValue('x64')
|
||||
const helmLinuxUrl = 'https://get.helm.sh/helm-v3.2.1-linux-amd64.zip'
|
||||
|
||||
expect(utils.getDownloadUrl('helm', 'v3.2.1')).toBe(helmLinuxUrl);
|
||||
expect(os.type).toBeCalled();
|
||||
expect(os.arch).toBeCalled();
|
||||
});
|
||||
expect(utils.getDownloadUrl('helm', 'v3.2.1')).toBe(helmLinuxUrl)
|
||||
expect(os.type).toBeCalled()
|
||||
expect(os.arch).toBeCalled()
|
||||
})
|
||||
|
||||
test('getDownloadUrl() - return the URL to download helm for Linux_arm64', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Linux');
|
||||
jest.spyOn(os, 'arch').mockReturnValue('arm64');
|
||||
const helmLinuxUrl = 'https://get.helm.sh/helm-v3.2.1-linux-arm64.zip'
|
||||
test('getDownloadUrl() - return the URL to download helm for Linux_arm64', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Linux')
|
||||
jest.spyOn(os, 'arch').mockReturnValue('arm64')
|
||||
const helmLinuxUrl = 'https://get.helm.sh/helm-v3.2.1-linux-arm64.zip'
|
||||
|
||||
expect(utils.getDownloadUrl('helm', 'v3.2.1')).toBe(helmLinuxUrl);
|
||||
expect(os.type).toBeCalled();
|
||||
expect(os.arch).toBeCalled();
|
||||
});
|
||||
expect(utils.getDownloadUrl('helm', 'v3.2.1')).toBe(helmLinuxUrl)
|
||||
expect(os.type).toBeCalled()
|
||||
expect(os.arch).toBeCalled()
|
||||
})
|
||||
|
||||
test('getDownloadUrl() - return the URL to download helm for Darwin', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Darwin');
|
||||
const helmDarwinUrl = 'https://get.helm.sh/helm-v3.2.1-darwin-amd64.zip'
|
||||
test('getDownloadUrl() - return the URL to download helm for Darwin', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Darwin')
|
||||
const helmDarwinUrl = 'https://get.helm.sh/helm-v3.2.1-darwin-amd64.zip'
|
||||
|
||||
expect(utils.getDownloadUrl('helm','v3.2.1')).toBe(helmDarwinUrl);
|
||||
expect(os.type).toBeCalled();
|
||||
});
|
||||
expect(utils.getDownloadUrl('helm', 'v3.2.1')).toBe(helmDarwinUrl)
|
||||
expect(os.type).toBeCalled()
|
||||
})
|
||||
|
||||
test('getDownloadUrl() - return the URL to download helm for Windows', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
test('getDownloadUrl() - return the URL to download helm for Windows', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
|
||||
const helmWindowsUrl = 'https://get.helm.sh/helm-v3.2.1-windows-amd64.zip'
|
||||
expect(utils.getDownloadUrl('helm','v3.2.1')).toBe(helmWindowsUrl);
|
||||
expect(os.type).toBeCalled();
|
||||
});
|
||||
const helmWindowsUrl = 'https://get.helm.sh/helm-v3.2.1-windows-amd64.zip'
|
||||
expect(utils.getDownloadUrl('helm', 'v3.2.1')).toBe(helmWindowsUrl)
|
||||
expect(os.type).toBeCalled()
|
||||
})
|
||||
|
||||
test('getDownloadUrl() - return the URL to download kompose for Linux_x64', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Linux');
|
||||
jest.spyOn(os, 'arch').mockReturnValue('x64');
|
||||
const komposelLinuxUrl = 'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-linux-amd64'
|
||||
test('getDownloadUrl() - return the URL to download kompose for Linux_x64', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Linux')
|
||||
jest.spyOn(os, 'arch').mockReturnValue('x64')
|
||||
const komposelLinuxUrl =
|
||||
'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-linux-amd64'
|
||||
|
||||
expect(utils.getDownloadUrl('kompose','v1.18.0')).toBe(komposelLinuxUrl);
|
||||
expect(os.type).toBeCalled();
|
||||
expect(os.arch).toBeCalled();
|
||||
});
|
||||
expect(utils.getDownloadUrl('kompose', 'v1.18.0')).toBe(komposelLinuxUrl)
|
||||
expect(os.type).toBeCalled()
|
||||
expect(os.arch).toBeCalled()
|
||||
})
|
||||
|
||||
test('getDownloadUrl() - return the URL to download kompose for Linux_arm64', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Linux');
|
||||
jest.spyOn(os, 'arch').mockReturnValue('arm64');
|
||||
const komposelLinuxUrl = 'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-linux-arm64'
|
||||
test('getDownloadUrl() - return the URL to download kompose for Linux_arm64', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Linux')
|
||||
jest.spyOn(os, 'arch').mockReturnValue('arm64')
|
||||
const komposelLinuxUrl =
|
||||
'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-linux-arm64'
|
||||
|
||||
expect(utils.getDownloadUrl('kompose','v1.18.0')).toBe(komposelLinuxUrl);
|
||||
expect(os.type).toBeCalled();
|
||||
expect(os.arch).toBeCalled();
|
||||
});
|
||||
expect(utils.getDownloadUrl('kompose', 'v1.18.0')).toBe(komposelLinuxUrl)
|
||||
expect(os.type).toBeCalled()
|
||||
expect(os.arch).toBeCalled()
|
||||
})
|
||||
|
||||
test('getDownloadUrl() - return the URL to download kompose for Darwin', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Darwin');
|
||||
const komposelDarwinUrl = 'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-darwin-amd64'
|
||||
|
||||
expect(utils.getDownloadUrl('kompose','v1.18.0')).toBe(komposelDarwinUrl);
|
||||
expect(os.type).toBeCalled();
|
||||
});
|
||||
test('getDownloadUrl() - return the URL to download kompose for Darwin', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Darwin')
|
||||
const komposelDarwinUrl =
|
||||
'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-darwin-amd64'
|
||||
|
||||
test('getDownloadUrl() - return the URL to download kompose for Windows', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
|
||||
const komposeWindowsUrl = 'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-windows-amd64.exe'
|
||||
expect(utils.getDownloadUrl('kompose','v1.18.0')).toBe(komposeWindowsUrl);
|
||||
expect(os.type).toBeCalled();
|
||||
});
|
||||
expect(utils.getDownloadUrl('kompose', 'v1.18.0')).toBe(komposelDarwinUrl)
|
||||
expect(os.type).toBeCalled()
|
||||
})
|
||||
|
||||
test('getDownloadUrl() - return the URL to download kubectl for Linux_x64', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Linux');
|
||||
jest.spyOn(os, 'arch').mockReturnValue('x64');
|
||||
const kubectlLinuxUrl = 'https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/linux/amd64/kubectl'
|
||||
test('getDownloadUrl() - return the URL to download kompose for Windows', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
|
||||
expect(utils.getDownloadUrl('kubectl','v1.15.0')).toBe(kubectlLinuxUrl);
|
||||
expect(os.type).toBeCalled();
|
||||
expect(os.arch).toBeCalled();
|
||||
});
|
||||
const komposeWindowsUrl =
|
||||
'https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-windows-amd64.exe'
|
||||
expect(utils.getDownloadUrl('kompose', 'v1.18.0')).toBe(komposeWindowsUrl)
|
||||
expect(os.type).toBeCalled()
|
||||
})
|
||||
|
||||
test('getDownloadUrl() - return the URL to download kubectl for Linux_arm64', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Linux');
|
||||
jest.spyOn(os, 'arch').mockReturnValue('arm64');
|
||||
const kubectlLinuxUrl = 'https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/linux/arm64/kubectl'
|
||||
test('getDownloadUrl() - return the URL to download kubectl for Linux_x64', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Linux')
|
||||
jest.spyOn(os, 'arch').mockReturnValue('x64')
|
||||
const kubectlLinuxUrl =
|
||||
'https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/linux/amd64/kubectl'
|
||||
|
||||
expect(utils.getDownloadUrl('kubectl','v1.15.0')).toBe(kubectlLinuxUrl);
|
||||
expect(os.type).toBeCalled();
|
||||
expect(os.arch).toBeCalled();
|
||||
});
|
||||
expect(utils.getDownloadUrl('kubectl', 'v1.15.0')).toBe(kubectlLinuxUrl)
|
||||
expect(os.type).toBeCalled()
|
||||
expect(os.arch).toBeCalled()
|
||||
})
|
||||
|
||||
test('getDownloadUrl() - return the URL to download kubectl for Darwin', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Darwin');
|
||||
const kubectlDarwinUrl = 'https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/darwin/amd64/kubectl'
|
||||
|
||||
expect(utils.getDownloadUrl('kubectl','v1.15.0')).toBe(kubectlDarwinUrl);
|
||||
expect(os.type).toBeCalled();
|
||||
});
|
||||
test('getDownloadUrl() - return the URL to download kubectl for Linux_arm64', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Linux')
|
||||
jest.spyOn(os, 'arch').mockReturnValue('arm64')
|
||||
const kubectlLinuxUrl =
|
||||
'https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/linux/arm64/kubectl'
|
||||
|
||||
test('getDownloadUrl() - return the URL to download kubectl for Windows', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT');
|
||||
|
||||
const kubectlWindowsUrl = 'https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/windows/amd64/kubectl.exe'
|
||||
expect(utils.getDownloadUrl('kubectl','v1.15.0')).toBe(kubectlWindowsUrl);
|
||||
expect(os.type).toBeCalled();
|
||||
});
|
||||
expect(utils.getDownloadUrl('kubectl', 'v1.15.0')).toBe(kubectlLinuxUrl)
|
||||
expect(os.type).toBeCalled()
|
||||
expect(os.arch).toBeCalled()
|
||||
})
|
||||
|
||||
test('getDownloadUrl() - should throw an error if called with incorrect OS type', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('wrong_os')
|
||||
expect(() => {
|
||||
utils.getDownloadUrl('kubectl','v1.15.0')
|
||||
}).toThrow('Unknown OS or render engine type');
|
||||
expect(os.type).toBeCalled();
|
||||
});
|
||||
test('getDownloadUrl() - return the URL to download kubectl for Darwin', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Darwin')
|
||||
const kubectlDarwinUrl =
|
||||
'https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/darwin/amd64/kubectl'
|
||||
|
||||
test('getDownloadUrl() - should throw an error if called with incorrect render engine', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('test_os')
|
||||
|
||||
expect(() => {
|
||||
utils.getDownloadUrl('test_render_engine','v1.15.0')
|
||||
}).toThrow('Unknown OS or render engine type');
|
||||
expect(os.type).toBeCalled();
|
||||
});
|
||||
expect(utils.getDownloadUrl('kubectl', 'v1.15.0')).toBe(kubectlDarwinUrl)
|
||||
expect(os.type).toBeCalled()
|
||||
})
|
||||
|
||||
test('getStableVerison() - download stable version file for helm, read version and return it', async () => {
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
|
||||
const response = JSON.stringify({
|
||||
'tag_name': 'v4.0.0'
|
||||
});
|
||||
jest.spyOn(fs, 'readFileSync').mockReturnValue(response);
|
||||
test('getDownloadUrl() - return the URL to download kubectl for Windows', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
|
||||
|
||||
expect(await utils.getStableVerison('helm')).toBe('v4.0.0');
|
||||
expect(toolCache.downloadTool).toBeCalled();
|
||||
expect(fs.readFileSync).toBeCalledWith('pathToTool', 'utf8');
|
||||
});
|
||||
const kubectlWindowsUrl =
|
||||
'https://storage.googleapis.com/kubernetes-release/release/v1.15.0/bin/windows/amd64/kubectl.exe'
|
||||
expect(utils.getDownloadUrl('kubectl', 'v1.15.0')).toBe(kubectlWindowsUrl)
|
||||
expect(os.type).toBeCalled()
|
||||
})
|
||||
|
||||
test('getStableVerison() - return default helm version if stable version file is empty', async () => {
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
|
||||
const response = JSON.stringify({});
|
||||
jest.spyOn(fs, 'readFileSync').mockReturnValue(response);
|
||||
test('getDownloadUrl() - should throw an error if called with incorrect OS type', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('wrong_os')
|
||||
expect(() => {
|
||||
utils.getDownloadUrl('kubectl', 'v1.15.0')
|
||||
}).toThrow('Unknown OS or render engine type')
|
||||
expect(os.type).toBeCalled()
|
||||
})
|
||||
|
||||
expect(await utils.getStableVerison('helm')).toBe('v2.14.1');
|
||||
expect(toolCache.downloadTool).toBeCalled();
|
||||
expect(fs.readFileSync).toBeCalledWith('pathToTool', 'utf8');
|
||||
});
|
||||
test('getDownloadUrl() - should throw an error if called with incorrect render engine', () => {
|
||||
jest.spyOn(os, 'type').mockReturnValue('test_os')
|
||||
|
||||
test('getStableVerison() - return default helm version if stable version file download fails', async () => {
|
||||
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => { throw 'Error!!'});
|
||||
expect(() => {
|
||||
utils.getDownloadUrl('test_render_engine', 'v1.15.0')
|
||||
}).toThrow('Unknown OS or render engine type')
|
||||
expect(os.type).toBeCalled()
|
||||
})
|
||||
|
||||
expect(await utils.getStableVerison('helm')).toBe('v2.14.1');
|
||||
expect(toolCache.downloadTool).toBeCalled();
|
||||
});
|
||||
test('getStableVerison() - download stable version file for helm, read version and return it', async () => {
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
|
||||
const response = JSON.stringify({
|
||||
tag_name: 'v4.0.0'
|
||||
})
|
||||
jest.spyOn(fs, 'readFileSync').mockReturnValue(response)
|
||||
|
||||
test('getStableVerison() - return default kubectl v1.15.0 if unable to download file', async () => {
|
||||
jest.spyOn(toolCache, 'downloadTool').mockRejectedValue('Unable to download.');
|
||||
jest.spyOn(core, 'debug').mockImplementation();
|
||||
jest.spyOn(core, 'warning').mockImplementation();
|
||||
|
||||
expect(await utils.getStableVerison('kubectl')).toBe('v1.15.0');
|
||||
expect(toolCache.downloadTool).toBeCalled();
|
||||
});
|
||||
|
||||
test('getStableVerison() - return default kubectl v1.15.0 if version read is empty', async () => {
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
|
||||
jest.spyOn(fs, 'readFileSync').mockReturnValue('');
|
||||
jest.spyOn(core, 'warning').mockImplementation();
|
||||
|
||||
expect(await utils.getStableVerison('kubectl')).toBe('v1.15.0');
|
||||
expect(toolCache.downloadTool).toBeCalled();
|
||||
expect(fs.readFileSync).toBeCalledWith('pathToTool', 'utf8');
|
||||
});
|
||||
expect(await utils.getStableVerison('helm')).toBe('v4.0.0')
|
||||
expect(toolCache.downloadTool).toBeCalled()
|
||||
expect(fs.readFileSync).toBeCalledWith('pathToTool', 'utf8')
|
||||
})
|
||||
|
||||
test('getStableVerison() - download stable kubectl version file, read version and return it', async () => {
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool');
|
||||
jest.spyOn(fs, 'readFileSync').mockReturnValue('v2.14.1');
|
||||
|
||||
expect(await utils.getStableVerison('kubectl')).toBe('v2.14.1');
|
||||
expect(toolCache.downloadTool).toBeCalled();
|
||||
expect(fs.readFileSync).toBeCalledWith('pathToTool', 'utf8');
|
||||
});
|
||||
});
|
||||
test('getStableVerison() - return default helm version if stable version file is empty', async () => {
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
|
||||
const response = JSON.stringify({})
|
||||
jest.spyOn(fs, 'readFileSync').mockReturnValue(response)
|
||||
|
||||
expect(await utils.getStableVerison('helm')).toBe('v2.14.1')
|
||||
expect(toolCache.downloadTool).toBeCalled()
|
||||
expect(fs.readFileSync).toBeCalledWith('pathToTool', 'utf8')
|
||||
})
|
||||
|
||||
test('getStableVerison() - return default helm version if stable version file download fails', async () => {
|
||||
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => {
|
||||
throw 'Error!!'
|
||||
})
|
||||
|
||||
expect(await utils.getStableVerison('helm')).toBe('v2.14.1')
|
||||
expect(toolCache.downloadTool).toBeCalled()
|
||||
})
|
||||
|
||||
test('getStableVerison() - return default kubectl v1.15.0 if unable to download file', async () => {
|
||||
jest
|
||||
.spyOn(toolCache, 'downloadTool')
|
||||
.mockRejectedValue('Unable to download.')
|
||||
jest.spyOn(core, 'debug').mockImplementation()
|
||||
jest.spyOn(core, 'warning').mockImplementation()
|
||||
|
||||
expect(await utils.getStableVerison('kubectl')).toBe('v1.15.0')
|
||||
expect(toolCache.downloadTool).toBeCalled()
|
||||
})
|
||||
|
||||
test('getStableVerison() - return default kubectl v1.15.0 if version read is empty', async () => {
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
|
||||
jest.spyOn(fs, 'readFileSync').mockReturnValue('')
|
||||
jest.spyOn(core, 'warning').mockImplementation()
|
||||
|
||||
expect(await utils.getStableVerison('kubectl')).toBe('v1.15.0')
|
||||
expect(toolCache.downloadTool).toBeCalled()
|
||||
expect(fs.readFileSync).toBeCalledWith('pathToTool', 'utf8')
|
||||
})
|
||||
|
||||
test('getStableVerison() - download stable kubectl version file, read version and return it', async () => {
|
||||
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
|
||||
jest.spyOn(fs, 'readFileSync').mockReturnValue('v2.14.1')
|
||||
|
||||
expect(await utils.getStableVerison('kubectl')).toBe('v2.14.1')
|
||||
expect(toolCache.downloadTool).toBeCalled()
|
||||
expect(fs.readFileSync).toBeCalledWith('pathToTool', 'utf8')
|
||||
})
|
||||
})
|
||||
|
|
263
src/utilities.ts
263
src/utilities.ts
|
@ -1,151 +1,192 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import * as os from 'os';
|
||||
import * as fs from 'fs';
|
||||
import * as util from 'util';
|
||||
import { ToolRunner } from '@actions/exec/lib/toolrunner';
|
||||
import { ExecOptions } from "@actions/exec/lib/interfaces";
|
||||
import * as toolCache from '@actions/tool-cache';
|
||||
import * as core from '@actions/core';
|
||||
import * as os from 'os'
|
||||
import * as fs from 'fs'
|
||||
import * as util from 'util'
|
||||
import {ToolRunner} from '@actions/exec/lib/toolrunner'
|
||||
import {ExecOptions} from '@actions/exec/lib/interfaces'
|
||||
import * as toolCache from '@actions/tool-cache'
|
||||
import * as core from '@actions/core'
|
||||
|
||||
export interface ExecResult {
|
||||
stdout: string;
|
||||
stderr: string
|
||||
stdout: string
|
||||
stderr: string
|
||||
}
|
||||
|
||||
export function getCurrentTime(): number {
|
||||
return new Date().getTime();
|
||||
return new Date().getTime()
|
||||
}
|
||||
|
||||
export function isEqual(str1: string, str2: string) {
|
||||
if (!str1) str1 = "";
|
||||
if (!str2) str2 = "";
|
||||
return str1.toLowerCase() === str2.toLowerCase();
|
||||
if (!str1) str1 = ''
|
||||
if (!str2) str2 = ''
|
||||
return str1.toLowerCase() === str2.toLowerCase()
|
||||
}
|
||||
|
||||
export function getExecutableExtension(): string {
|
||||
if (os.type().match(/^Win/)) {
|
||||
return '.exe';
|
||||
}
|
||||
return '';
|
||||
if (os.type().match(/^Win/)) {
|
||||
return '.exe'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
export async function execCommand(toolPath: string, args: string[], options: ExecOptions = {} as ExecOptions) : Promise<ExecResult> {
|
||||
const execResult = {
|
||||
stdout : "",
|
||||
stderr : ""
|
||||
} as ExecResult;
|
||||
export async function execCommand(
|
||||
toolPath: string,
|
||||
args: string[],
|
||||
options: ExecOptions = {} as ExecOptions
|
||||
): Promise<ExecResult> {
|
||||
const execResult = {
|
||||
stdout: '',
|
||||
stderr: ''
|
||||
} as ExecResult
|
||||
|
||||
options.listeners = {
|
||||
stdout: (data: Buffer) => {
|
||||
execResult.stdout += data.toString();
|
||||
},
|
||||
stderr: (data: Buffer) => {
|
||||
execResult.stderr += data.toString();
|
||||
}
|
||||
}
|
||||
options.listeners = {
|
||||
stdout: (data: Buffer) => {
|
||||
execResult.stdout += data.toString()
|
||||
},
|
||||
stderr: (data: Buffer) => {
|
||||
execResult.stderr += data.toString()
|
||||
}
|
||||
}
|
||||
|
||||
let toolRunner = new ToolRunner(toolPath, args, options);
|
||||
const result = await toolRunner.exec();
|
||||
if (result != 0) {
|
||||
if (!!execResult.stderr) {
|
||||
throw Error(execResult.stderr);
|
||||
}
|
||||
else {
|
||||
throw Error(util.format("%s exited with result code %s", toolPath, result));
|
||||
}
|
||||
}
|
||||
let toolRunner = new ToolRunner(toolPath, args, options)
|
||||
const result = await toolRunner.exec()
|
||||
if (result != 0) {
|
||||
if (!!execResult.stderr) {
|
||||
throw Error(execResult.stderr)
|
||||
} else {
|
||||
throw Error(
|
||||
util.format('%s exited with result code %s', toolPath, result)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return execResult;
|
||||
return execResult
|
||||
}
|
||||
|
||||
export async function setCachedToolPath(toolName: string, version: string) {
|
||||
let cachedToolpath = ''
|
||||
let downloadPath = ''
|
||||
const downloadUrl = getDownloadUrl(toolName, version)
|
||||
|
||||
try {
|
||||
downloadPath = await toolCache.downloadTool(downloadUrl)
|
||||
} catch (exeption) {
|
||||
throw new Error(
|
||||
`Failed to download the ${toolName} from ${downloadUrl}. Error: ${exeption}`
|
||||
)
|
||||
}
|
||||
|
||||
export async function setCachedToolPath(toolName:string, version : string) {
|
||||
let cachedToolpath = ''
|
||||
let downloadPath = ''
|
||||
const downloadUrl = getDownloadUrl(toolName, version);
|
||||
if (toolName == 'helm') {
|
||||
fs.chmodSync(downloadPath, '777')
|
||||
const unzipedHelmPath = await toolCache.extractZip(downloadPath)
|
||||
cachedToolpath = await toolCache.cacheDir(
|
||||
unzipedHelmPath,
|
||||
toolName,
|
||||
version
|
||||
)
|
||||
} else {
|
||||
cachedToolpath = await toolCache.cacheFile(
|
||||
downloadPath,
|
||||
toolName + getExecutableExtension(),
|
||||
toolName,
|
||||
version
|
||||
)
|
||||
}
|
||||
|
||||
try {
|
||||
downloadPath = await toolCache.downloadTool(downloadUrl);
|
||||
} catch(exeption) {
|
||||
throw new Error(`Failed to download the ${toolName} from ${downloadUrl}. Error: ${exeption}`)
|
||||
}
|
||||
|
||||
if(toolName == 'helm') {
|
||||
fs.chmodSync(downloadPath, '777');
|
||||
const unzipedHelmPath = await toolCache.extractZip(downloadPath);
|
||||
cachedToolpath = await toolCache.cacheDir(unzipedHelmPath, toolName, version);
|
||||
} else {
|
||||
cachedToolpath = await toolCache.cacheFile(downloadPath, toolName + getExecutableExtension(), toolName, version);
|
||||
}
|
||||
|
||||
return cachedToolpath
|
||||
return cachedToolpath
|
||||
}
|
||||
|
||||
export function getDownloadUrl(toolName : string, version: string): string {
|
||||
const system = os.type()
|
||||
const systemAndArch = system == "Linux" ? `${system}_${os.arch()}` : system;
|
||||
export function getDownloadUrl(toolName: string, version: string): string {
|
||||
const system = os.type()
|
||||
const systemAndArch = system == 'Linux' ? `${system}_${os.arch()}` : system
|
||||
|
||||
if (!downloadLinks[systemAndArch] || !downloadLinks[systemAndArch][toolName]) {
|
||||
throw Error("Unknown OS or render engine type");
|
||||
}
|
||||
if (
|
||||
!downloadLinks[systemAndArch] ||
|
||||
!downloadLinks[systemAndArch][toolName]
|
||||
) {
|
||||
throw Error('Unknown OS or render engine type')
|
||||
}
|
||||
|
||||
return util.format(downloadLinks[systemAndArch][toolName], version)
|
||||
return util.format(downloadLinks[systemAndArch][toolName], version)
|
||||
}
|
||||
|
||||
export async function getStableVerison(toolName : string){
|
||||
if(!stableVersionUrls[toolName]){
|
||||
throw Error("Unable to download. Unknown tool name");
|
||||
}
|
||||
export async function getStableVerison(toolName: string) {
|
||||
if (!stableVersionUrls[toolName]) {
|
||||
throw Error('Unable to download. Unknown tool name')
|
||||
}
|
||||
|
||||
return toolCache.downloadTool(stableVersionUrls[toolName]).then(downloadPath => {
|
||||
let response = fs.readFileSync(downloadPath, 'utf8').toString().trim();
|
||||
if(toolName == 'helm'){
|
||||
const versionTag = JSON.parse(response);
|
||||
return versionTag.tag_name ? versionTag.tag_name : defaultStableHelmVersion;
|
||||
} else {
|
||||
return response ? response : defaultStableKubectlVersion;
|
||||
}
|
||||
}, err => {
|
||||
core.debug(err);
|
||||
core.warning(util.format("Failed to read latest %s version from URL %s. Using default stable version %s", toolName, stableVersionUrls[toolName] ,toolName == 'helm' ? defaultStableHelmVersion: defaultStableKubectlVersion));
|
||||
return toolName == 'helm' ? defaultStableHelmVersion: defaultStableKubectlVersion;
|
||||
})
|
||||
return toolCache.downloadTool(stableVersionUrls[toolName]).then(
|
||||
(downloadPath) => {
|
||||
let response = fs.readFileSync(downloadPath, 'utf8').toString().trim()
|
||||
if (toolName == 'helm') {
|
||||
const versionTag = JSON.parse(response)
|
||||
return versionTag.tag_name
|
||||
? versionTag.tag_name
|
||||
: defaultStableHelmVersion
|
||||
} else {
|
||||
return response ? response : defaultStableKubectlVersion
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
core.debug(err)
|
||||
core.warning(
|
||||
util.format(
|
||||
'Failed to read latest %s version from URL %s. Using default stable version %s',
|
||||
toolName,
|
||||
stableVersionUrls[toolName],
|
||||
toolName == 'helm'
|
||||
? defaultStableHelmVersion
|
||||
: defaultStableKubectlVersion
|
||||
)
|
||||
)
|
||||
return toolName == 'helm'
|
||||
? defaultStableHelmVersion
|
||||
: defaultStableKubectlVersion
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const defaultStableHelmVersion = 'v2.14.1';
|
||||
const defaultStableKubectlVersion = 'v1.15.0';
|
||||
const defaultStableHelmVersion = 'v2.14.1'
|
||||
const defaultStableKubectlVersion = 'v1.15.0'
|
||||
|
||||
const stableVersionUrls = {
|
||||
'kubectl' : 'https://storage.googleapis.com/kubernetes-release/release/stable.txt',
|
||||
'helm': 'https://api.github.com/repos/helm/helm/releases/latest',
|
||||
kubectl:
|
||||
'https://storage.googleapis.com/kubernetes-release/release/stable.txt',
|
||||
helm: 'https://api.github.com/repos/helm/helm/releases/latest'
|
||||
}
|
||||
|
||||
const downloadLinks = {
|
||||
'Linux_x64': {
|
||||
'helm' : 'https://get.helm.sh/helm-%s-linux-amd64.zip',
|
||||
'kompose' : 'https://github.com/kubernetes/kompose/releases/download/%s/kompose-linux-amd64',
|
||||
'kubectl' : 'https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/amd64/kubectl'
|
||||
},
|
||||
'Linux_arm64': {
|
||||
'helm' : 'https://get.helm.sh/helm-%s-linux-arm64.zip',
|
||||
'kompose' : 'https://github.com/kubernetes/kompose/releases/download/%s/kompose-linux-arm64',
|
||||
'kubectl' : 'https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/arm64/kubectl'
|
||||
},
|
||||
'Darwin' : {
|
||||
'helm' : 'https://get.helm.sh/helm-%s-darwin-amd64.zip',
|
||||
'kompose' : 'https://github.com/kubernetes/kompose/releases/download/%s/kompose-darwin-amd64',
|
||||
'kubectl' : 'https://storage.googleapis.com/kubernetes-release/release/%s/bin/darwin/amd64/kubectl'
|
||||
},
|
||||
'Windows_NT' : {
|
||||
'helm' : 'https://get.helm.sh/helm-%s-windows-amd64.zip',
|
||||
'kompose' : 'https://github.com/kubernetes/kompose/releases/download/%s/kompose-windows-amd64.exe',
|
||||
'kubectl' : 'https://storage.googleapis.com/kubernetes-release/release/%s/bin/windows/amd64/kubectl.exe'
|
||||
}
|
||||
Linux_x64: {
|
||||
helm: 'https://get.helm.sh/helm-%s-linux-amd64.zip',
|
||||
kompose:
|
||||
'https://github.com/kubernetes/kompose/releases/download/%s/kompose-linux-amd64',
|
||||
kubectl:
|
||||
'https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/amd64/kubectl'
|
||||
},
|
||||
Linux_arm64: {
|
||||
helm: 'https://get.helm.sh/helm-%s-linux-arm64.zip',
|
||||
kompose:
|
||||
'https://github.com/kubernetes/kompose/releases/download/%s/kompose-linux-arm64',
|
||||
kubectl:
|
||||
'https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/arm64/kubectl'
|
||||
},
|
||||
Darwin: {
|
||||
helm: 'https://get.helm.sh/helm-%s-darwin-amd64.zip',
|
||||
kompose:
|
||||
'https://github.com/kubernetes/kompose/releases/download/%s/kompose-darwin-amd64',
|
||||
kubectl:
|
||||
'https://storage.googleapis.com/kubernetes-release/release/%s/bin/darwin/amd64/kubectl'
|
||||
},
|
||||
Windows_NT: {
|
||||
helm: 'https://get.helm.sh/helm-%s-windows-amd64.zip',
|
||||
kompose:
|
||||
'https://github.com/kubernetes/kompose/releases/download/%s/kompose-windows-amd64.exe',
|
||||
kubectl:
|
||||
'https://storage.googleapis.com/kubernetes-release/release/%s/bin/windows/amd64/kubectl.exe'
|
||||
}
|
||||
}
|
||||
|
||||
export const LATEST = 'latest';
|
||||
export const MIN_KUBECTL_CLIENT_VERSION = "1.14"
|
||||
|
||||
export const LATEST = 'latest'
|
||||
export const MIN_KUBECTL_CLIENT_VERSION = '1.14'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: v1
|
||||
description: A Helm chart for Kubernetes
|
||||
name: aks-helloworld
|
||||
version: 0.1.1
|
||||
version: 0.1.1
|
||||
|
|
|
@ -1,35 +1,35 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: acs-helloworld-{{.Release.Name}}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
name: acs-helloworld-{{.Release.Name}}
|
||||
namespace: {{.Release.Namespace}}
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: acs-helloworld-{{.Release.Name}}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: acs-helloworld-{{.Release.Name}}
|
||||
spec:
|
||||
containers:
|
||||
- name: acs-helloworld-{{.Release.Name}}
|
||||
image: neilpeterson/aks-helloworld:v1
|
||||
ports:
|
||||
- containerPort: 80
|
||||
env:
|
||||
- name: TITLE
|
||||
value: {{ .Values.title }}
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: acs-helloworld-{{.Release.Name}}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: acs-helloworld-{{.Release.Name}}
|
||||
spec:
|
||||
containers:
|
||||
- name: acs-helloworld-{{.Release.Name}}
|
||||
image: neilpeterson/aks-helloworld:v1
|
||||
ports:
|
||||
- containerPort: 80
|
||||
env:
|
||||
- name: TITLE
|
||||
value: {{.Values.title}}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ .Values.serviceName }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
name: {{.Values.serviceName}}
|
||||
namespace: {{.Release.Namespace}}
|
||||
spec:
|
||||
type: {{ .Values.serviceType }}
|
||||
ports:
|
||||
- port: 80
|
||||
selector:
|
||||
app: acs-helloworld-{{.Release.Name}}
|
||||
type: {{.Values.serviceType}}
|
||||
ports:
|
||||
- port: 80
|
||||
selector:
|
||||
app: acs-helloworld-{{.Release.Name}}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# UI controll
|
||||
title: "Welcome to Azure Kubernetes Service (AKS)"
|
||||
title: 'Welcome to Azure Kubernetes Service (AKS)'
|
||||
|
||||
# Service controlls
|
||||
serviceName: aks-helloworld
|
||||
serviceType: ClusterIP
|
||||
serviceType: ClusterIP
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
version: "2"
|
||||
version: '2'
|
||||
|
||||
services:
|
||||
redis-master:
|
||||
image: k8s.gcr.io/redis:e2e
|
||||
ports:
|
||||
- '6379'
|
||||
|
||||
redis-master:
|
||||
image: k8s.gcr.io/redis:e2e
|
||||
ports:
|
||||
- "6379"
|
||||
redis-slave:
|
||||
image: gcr.io/google_samples/gb-redisslave:v1
|
||||
ports:
|
||||
- '6379'
|
||||
environment:
|
||||
- GET_HOSTS_FROM=dns
|
||||
|
||||
redis-slave:
|
||||
image: gcr.io/google_samples/gb-redisslave:v1
|
||||
ports:
|
||||
- "6379"
|
||||
environment:
|
||||
- GET_HOSTS_FROM=dns
|
||||
|
||||
frontend:
|
||||
image: gcr.io/google-samples/gb-frontend:v4
|
||||
ports:
|
||||
- "80:80"
|
||||
environment:
|
||||
- GET_HOSTS_FROM=dns
|
||||
labels:
|
||||
kompose.service.type: LoadBalancer
|
||||
frontend:
|
||||
image: gcr.io/google-samples/gb-frontend:v4
|
||||
ports:
|
||||
- '80:80'
|
||||
environment:
|
||||
- GET_HOSTS_FROM=dns
|
||||
labels:
|
||||
kompose.service.type: LoadBalancer
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy
|
||||
name: deploy
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
foo: bar
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
args:
|
||||
- arg1
|
||||
- arg2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
foo: bar
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
args:
|
||||
- arg1
|
||||
- arg2
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
resources:
|
||||
- deployments.yaml
|
||||
- deployments.yaml
|
||||
|
|
112
tsconfig.json
112
tsconfig.json
|
@ -1,63 +1,63 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
/* Basic Options */
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
"outDir": "./lib", /* Redirect output structure to the directory. */
|
||||
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "composite": true, /* Enable project compilation */
|
||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
"compilerOptions": {
|
||||
/* Basic Options */
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
"target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
|
||||
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
|
||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
"outDir": "./lib" /* Redirect output structure to the directory. */,
|
||||
"rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "composite": true, /* Enable project compilation */
|
||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
// "strict": true, /* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
/* Strict Type-Checking Options */
|
||||
// "strict": true, /* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
|
||||
/* Additional Checks */
|
||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
/* Additional Checks */
|
||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
|
||||
/* Module Resolution Options */
|
||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
// "types": [], /* Type declaration files to be included in compilation. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
// "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
/* Module Resolution Options */
|
||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
// "types": [], /* Type declaration files to be included in compilation. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
// "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
|
||||
/* Source Map Options */
|
||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||
/* Source Map Options */
|
||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||
|
||||
/* Experimental Options */
|
||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
},
|
||||
"exclude": ["node_modules", "**/*.test.ts"]
|
||||
/* Experimental Options */
|
||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
},
|
||||
"exclude": ["node_modules", "**/*.test.ts"]
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче