mirror of
https://github.com/Azure/k8s-deploy.git
synced 2026-04-03 10:52:16 +08:00
* changed ubuntu runner * changed minikube action * Version formatting * nonedriveR * update kube version * installing conntrack' * updated other actions * update bg ingress api version * prettify * updated ingress backend for new api version * Added path type * prettify * added logging * added try catch logic to prevent future failures if annotations fail since failing annotations shouldn't affect users * added nullcheck * Added fallback filename if workflow fails to get github filepath due to runner issues * cleanup * added oliver's feedback + unit test demonstrating regex glitch and fix * no longer using blank string for failed regex * add tests and dont split so much * testing * file fix * without fix * Revert "without fix" This reverts commit 8da79a81904db93da579a82a2c93818ef4cb37ab. * fixing labels test * pretty * refactored getting tmp filename to use entire path, and refactored private to use filepath relative to tmp dir * wip * merging master * this should fail * added UTs * restructured plus UTs plus debug logs * resolved dir not existing and UTs * cleanup * no silent failure * Reverting private logic * this might work * root level files for temp... bizarre issue * need to actually write contents * no more cwdir * moving everything out of temp * deleting unused function * supporting windows filepaths for private cluster shallow path generation --------- Co-authored-by: David Gamero <david340804@gmail.com>
236 lines
7.0 KiB
TypeScript
236 lines
7.0 KiB
TypeScript
import * as fs from 'fs'
|
|
import * as https from 'https'
|
|
import * as path from 'path'
|
|
import * as core from '@actions/core'
|
|
import * as os from 'os'
|
|
import * as yaml from 'js-yaml'
|
|
import {Errorable, succeeded, failed, Failed} from '../types/errorable'
|
|
import {getCurrentTime} from './timeUtils'
|
|
import {isHttpUrl} from './githubUtils'
|
|
import {K8sObject} from '../types/k8sObject'
|
|
|
|
export const urlFileKind = 'urlfile'
|
|
|
|
export function getTempDirectory(): string {
|
|
return process.env['runner.tempDirectory'] || os.tmpdir()
|
|
}
|
|
|
|
export function writeObjectsToFile(inputObjects: any[]): string[] {
|
|
const newFilePaths = []
|
|
|
|
inputObjects.forEach((inputObject: any) => {
|
|
try {
|
|
const inputObjectString = JSON.stringify(inputObject)
|
|
|
|
if (inputObject?.metadata?.name) {
|
|
const fileName = getNewTempManifestFileName(
|
|
inputObject.kind,
|
|
inputObject.metadata.name
|
|
)
|
|
fs.writeFileSync(path.join(fileName), inputObjectString)
|
|
newFilePaths.push(fileName)
|
|
} else {
|
|
core.debug(
|
|
'Input object is not proper K8s resource object. Object: ' +
|
|
inputObjectString
|
|
)
|
|
}
|
|
} catch (ex) {
|
|
core.debug(
|
|
`Exception occurred while writing object to file ${inputObject}: ${ex}`
|
|
)
|
|
}
|
|
})
|
|
|
|
return newFilePaths
|
|
}
|
|
|
|
export function writeManifestToFile(
|
|
inputObjectString: string,
|
|
kind: string,
|
|
name: string
|
|
): string {
|
|
if (inputObjectString) {
|
|
try {
|
|
const fileName = getNewTempManifestFileName(kind, name)
|
|
fs.writeFileSync(path.join(fileName), inputObjectString)
|
|
return fileName
|
|
} catch (ex) {
|
|
throw Error(
|
|
`Exception occurred while writing object to file: ${inputObjectString}. Exception: ${ex}`
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
export function moveFileToTmpDir(originalFilepath: string) {
|
|
const tempDirectory = getTempDirectory()
|
|
const newPath = path.join(tempDirectory, originalFilepath)
|
|
|
|
core.debug(`reading original contents from path: ${originalFilepath}`)
|
|
const contents = fs.readFileSync(originalFilepath).toString()
|
|
|
|
const dirName = path.dirname(newPath)
|
|
if (!fs.existsSync(dirName)) {
|
|
core.debug(`path ${dirName} doesn't exist yet, making new dir...`)
|
|
fs.mkdirSync(dirName, {recursive: true})
|
|
}
|
|
core.debug(`writing contents to new path ${newPath}`)
|
|
fs.writeFileSync(path.join(newPath), contents)
|
|
|
|
core.debug(`moved contents from ${originalFilepath} to ${newPath}`)
|
|
|
|
return newPath
|
|
}
|
|
|
|
function getNewTempManifestFileName(kind: string, name: string) {
|
|
const filePath = `${kind}_${name}_${getCurrentTime().toString()}`
|
|
const tempDirectory = getTempDirectory()
|
|
return path.join(tempDirectory, path.basename(filePath))
|
|
}
|
|
|
|
export async function getFilesFromDirectoriesAndURLs(
|
|
filePaths: string[]
|
|
): Promise<string[]> {
|
|
const fullPathSet: Set<string> = new Set<string>()
|
|
|
|
let fileCounter = 0
|
|
for (const fileName of filePaths) {
|
|
try {
|
|
if (isHttpUrl(fileName)) {
|
|
try {
|
|
const tempFilePath: string = await writeYamlFromURLToFile(
|
|
fileName,
|
|
fileCounter++
|
|
)
|
|
fullPathSet.add(tempFilePath)
|
|
} catch (e) {
|
|
throw Error(
|
|
`encountered error trying to pull YAML from URL ${fileName}: ${e}`
|
|
)
|
|
}
|
|
} else 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}`
|
|
)
|
|
}
|
|
}
|
|
|
|
const arr = Array.from(fullPathSet)
|
|
return arr
|
|
}
|
|
|
|
export async function writeYamlFromURLToFile(
|
|
url: string,
|
|
fileNumber: number
|
|
): Promise<string> {
|
|
return new Promise((resolve, reject) => {
|
|
https
|
|
.get(url, async (response) => {
|
|
const code = response.statusCode ?? 0
|
|
if (code >= 400) {
|
|
reject(
|
|
Error(
|
|
`received response status ${response.statusMessage} from url ${url}`
|
|
)
|
|
)
|
|
}
|
|
|
|
const targetPath = getNewTempManifestFileName(
|
|
urlFileKind,
|
|
fileNumber.toString()
|
|
)
|
|
// save the file to disk
|
|
const fileWriter = fs
|
|
.createWriteStream(targetPath)
|
|
.on('finish', () => {
|
|
const verification = verifyYaml(targetPath, url)
|
|
if (succeeded(verification)) {
|
|
core.debug(
|
|
`outputting YAML contents from ${url} to ${targetPath}: ${JSON.stringify(
|
|
verification.result
|
|
)}`
|
|
)
|
|
resolve(targetPath)
|
|
} else {
|
|
reject(verification.error)
|
|
}
|
|
})
|
|
|
|
response.pipe(fileWriter)
|
|
})
|
|
.on('error', (error) => {
|
|
reject(error)
|
|
})
|
|
})
|
|
}
|
|
|
|
function verifyYaml(filepath: string, url: string): Errorable<K8sObject[]> {
|
|
const fileContents = fs.readFileSync(filepath).toString()
|
|
let inputObjects
|
|
try {
|
|
inputObjects = yaml.safeLoadAll(fileContents)
|
|
} catch (e) {
|
|
return {
|
|
succeeded: false,
|
|
error: `failed to parse manifest from url ${url}: ${e}`
|
|
}
|
|
}
|
|
|
|
if (!inputObjects || inputObjects.length == 0) {
|
|
return {
|
|
succeeded: false,
|
|
error: `failed to parse manifest from url ${url}: no objects detected in manifest`
|
|
}
|
|
}
|
|
|
|
for (const obj of inputObjects) {
|
|
if (!obj.kind || !obj.apiVersion || !obj.metadata) {
|
|
return {
|
|
succeeded: false,
|
|
error: `failed to parse manifest from ${url}: missing fields`
|
|
}
|
|
}
|
|
}
|
|
|
|
return {succeeded: true, result: inputObjects}
|
|
}
|
|
|
|
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)
|
|
}
|