mirror of
https://github.com/Azure/k8s-deploy.git
synced 2026-04-17 20:32:20 +08:00
Add directory functionality (#181)
This commit is contained in:
parent
fd893fd074
commit
aabcfcba3e
8
.github/workflows/run-integration-tests.yml
vendored
8
.github/workflows/run-integration-tests.yml
vendored
@ -21,11 +21,15 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Building latest changes
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
rm -rf node_modules/
|
rm -rf node_modules/
|
||||||
npm install
|
npm install
|
||||||
npm run build
|
|
||||||
|
- name: Install ncc
|
||||||
|
run: npm i -g @vercel/ncc
|
||||||
|
- name: Build
|
||||||
|
run: ncc build src/run.ts -o lib
|
||||||
|
|
||||||
- name: Set name of ns
|
- name: Set name of ns
|
||||||
run: echo "::set-output name=name::$(echo `date +%Y%m%d%H%M%S`)"
|
run: echo "::set-output name=name::$(echo `date +%Y%m%d%H%M%S`)"
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { promote } from "./actions/promote";
|
|||||||
import { reject } from "./actions/reject";
|
import { reject } from "./actions/reject";
|
||||||
import { Action, parseAction } from "./types/action";
|
import { Action, parseAction } from "./types/action";
|
||||||
import { parseDeploymentStrategy } from "./types/deploymentStrategy";
|
import { parseDeploymentStrategy } from "./types/deploymentStrategy";
|
||||||
|
import { getFilesFromDirectories } from "./utilities/fileUtils";
|
||||||
|
|
||||||
export async function run() {
|
export async function run() {
|
||||||
// verify kubeconfig is set
|
// verify kubeconfig is set
|
||||||
@ -24,6 +25,7 @@ export async function run() {
|
|||||||
.map((manifest) => manifest.trim()) // remove surrounding whitespace
|
.map((manifest) => manifest.trim()) // remove surrounding whitespace
|
||||||
.filter((manifest) => manifest.length > 0); // remove any blanks
|
.filter((manifest) => manifest.length > 0); // remove any blanks
|
||||||
|
|
||||||
|
const fullManifestFilePaths = getFilesFromDirectories(manifestFilePaths)
|
||||||
// create kubectl
|
// create kubectl
|
||||||
const kubectlPath = await getKubectlPath();
|
const kubectlPath = await getKubectlPath();
|
||||||
const namespace = core.getInput("namespace") || "default";
|
const namespace = core.getInput("namespace") || "default";
|
||||||
@ -32,15 +34,15 @@ export async function run() {
|
|||||||
// run action
|
// run action
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case Action.DEPLOY: {
|
case Action.DEPLOY: {
|
||||||
await deploy(kubectl, manifestFilePaths, strategy);
|
await deploy(kubectl, fullManifestFilePaths, strategy);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Action.PROMOTE: {
|
case Action.PROMOTE: {
|
||||||
await promote(kubectl, manifestFilePaths, strategy);
|
await promote(kubectl, fullManifestFilePaths, strategy);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Action.REJECT: {
|
case Action.REJECT: {
|
||||||
await reject(kubectl, manifestFilePaths, strategy);
|
await reject(kubectl, fullManifestFilePaths, strategy);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
|||||||
49
src/utilities/fileUtils.test.ts
Normal file
49
src/utilities/fileUtils.test.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import {
|
||||||
|
getFilesFromDirectories
|
||||||
|
} from "./fileUtils";
|
||||||
|
|
||||||
|
import * as path from "path";
|
||||||
|
|
||||||
|
describe("File utils", () => {
|
||||||
|
it("detects files in nested directories and ignores non-manifest files and empty dirs", () => {
|
||||||
|
const testPath = path.join("test", "unit", "manifests")
|
||||||
|
const testSearch: string[] = getFilesFromDirectories([testPath])
|
||||||
|
|
||||||
|
const expectedManifests =
|
||||||
|
[
|
||||||
|
"test/unit/manifests/manifest_test_dir/another_layer/deep-ingress.yaml",
|
||||||
|
"test/unit/manifests/manifest_test_dir/another_layer/deep-service.yaml",
|
||||||
|
"test/unit/manifests/manifest_test_dir/nested-test-service.yaml",
|
||||||
|
"test/unit/manifests/test-ingress.yml",
|
||||||
|
"test/unit/manifests/test-service.yml"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
// is there a more efficient way to test equality w random order?
|
||||||
|
expect(testSearch).toHaveLength(5);
|
||||||
|
expectedManifests.forEach((fileName) => {
|
||||||
|
expect(testSearch).toContain(fileName)
|
||||||
|
})
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("crashes when an invalid file is provided", () => {
|
||||||
|
const badPath = path.join("test", "unit", "manifests", "nonexistent.yaml")
|
||||||
|
const goodPath = path.join("test", "unit", "manifests", "manifest_test_dir")
|
||||||
|
|
||||||
|
expect(() => {getFilesFromDirectories([badPath, goodPath])}).toThrowError()
|
||||||
|
});
|
||||||
|
|
||||||
|
it("doesn't duplicate files when nested dir included", () => {
|
||||||
|
const outerPath = path.join("test", "unit", "manifests")
|
||||||
|
const fileAtOuter = path.join("test", "unit", "manifests", "test-service.yml")
|
||||||
|
const innerPath = path.join("test", "unit", "manifests", "manifest_test_dir")
|
||||||
|
|
||||||
|
expect(getFilesFromDirectories([outerPath, fileAtOuter, innerPath])).toHaveLength(5)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// files that don't exist / nested files that don't exist / something else with non-manifest
|
||||||
|
// lots of combinations of pointing to a directory and non yaml/yaml file
|
||||||
|
// similarly named files in different folders
|
||||||
@ -61,3 +61,49 @@ function getManifestFileName(kind: string, name: string) {
|
|||||||
const tempDirectory = getTempDirectory();
|
const tempDirectory = getTempDirectory();
|
||||||
return path.join(tempDirectory, path.basename(filePath));
|
return path.join(tempDirectory, path.basename(filePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getFilesFromDirectories(
|
||||||
|
filePaths: string[]
|
||||||
|
): string[]{
|
||||||
|
|
||||||
|
const fullPathSet: Set<string> = new Set<string>()
|
||||||
|
|
||||||
|
filePaths.forEach((fileName => {
|
||||||
|
try {
|
||||||
|
if(fs.lstatSync(fileName).isDirectory()){
|
||||||
|
recurisveManifestGetter(fileName).forEach((file) => {fullPathSet.add(file)})
|
||||||
|
} else if(getFileExtension(fileName) === "yml" || getFileExtension(fileName) === "yaml"){
|
||||||
|
fullPathSet.add(fileName)
|
||||||
|
} else{
|
||||||
|
core.debug(`Detected non-manifest file, ${fileName}, continuing... ` )
|
||||||
|
}
|
||||||
|
} catch (ex) {
|
||||||
|
throw Error(
|
||||||
|
`Exception occurred while reading the file ${fileName}: ${ex}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
return Array.from(fullPathSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
function recurisveManifestGetter(dirName: string): string[]{
|
||||||
|
const toRet: string[] = []
|
||||||
|
|
||||||
|
fs.readdirSync(dirName).forEach((fileName) => {
|
||||||
|
const fnwd: string = path.join(dirName, fileName)
|
||||||
|
if(fs.lstatSync(fnwd).isDirectory()){
|
||||||
|
toRet.push(...recurisveManifestGetter(fnwd))
|
||||||
|
} else if(getFileExtension(fileName) === "yml" || getFileExtension(fileName) === "yaml"){
|
||||||
|
toRet.push(path.join(dirName, fileName))
|
||||||
|
} else{
|
||||||
|
core.debug(`Detected non-manifest file, ${fileName}, continuing... ` )
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return toRet
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFileExtension(fileName: string){
|
||||||
|
return fileName.slice((fileName.lastIndexOf(".") - 1 >>> 0) + 2)
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
weaker than the average human?
|
||||||
52
test/unit/manifests/test-ingress.yml
Normal file
52
test/unit/manifests/test-ingress.yml
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nginx-deployment
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: nginx
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:1.14.2
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: nginx-service
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 80
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1beta1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: nginx-ingress
|
||||||
|
annotations:
|
||||||
|
nginx.ingress.kubernetes.io/rewrite-target: /
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- http:
|
||||||
|
paths:
|
||||||
|
- path: /testpath
|
||||||
|
backend:
|
||||||
|
serviceName: nginx-service
|
||||||
|
servicePort: 80
|
||||||
|
- path: /testpath2
|
||||||
|
backend:
|
||||||
|
serviceName: unrouted-service
|
||||||
|
servicePort: 80
|
||||||
33
test/unit/manifests/test-service.yml
Normal file
33
test/unit/manifests/test-service.yml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nginx-deployment
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: nginx
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:1.14.2
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: nginx-service
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 80
|
||||||
Loading…
x
Reference in New Issue
Block a user