-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow the logic about processing OS release files to be reused in the future for static analysis.
- Loading branch information
1 parent
780919a
commit 8d89eae
Showing
7 changed files
with
215 additions
and
156 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import { Docker, DockerOptions } from "../../docker"; | ||
import { DockerFileAnalysis } from "../../docker-file"; | ||
import { | ||
getAlpineRelease, | ||
getDebianVersion, | ||
getLsbRelease, | ||
getOracleRelease, | ||
getOsRelease, | ||
getRedHatRelease, | ||
} from "../../inputs/os-release/docker"; | ||
import { OSRelease } from "../types"; | ||
import { | ||
tryAlpineRelease, | ||
tryDebianVersion, | ||
tryLsbRelease, | ||
tryOracleRelease, | ||
tryOSRelease, | ||
tryRedHatRelease, | ||
} from "./release-analyzer"; | ||
|
||
export async function detect( | ||
targetImage: string, | ||
dockerfileAnalysis?: DockerFileAnalysis, | ||
options?: DockerOptions, | ||
): Promise<OSRelease> { | ||
const docker = new Docker(targetImage, options); | ||
|
||
let osRelease = await getOsRelease(docker).then((release) => | ||
tryOSRelease(release), | ||
); | ||
|
||
// First generic fallback | ||
if (!osRelease) { | ||
osRelease = await getLsbRelease(docker).then((release) => | ||
tryLsbRelease(release), | ||
); | ||
} | ||
|
||
// Fallbacks for specific older distributions | ||
if (!osRelease) { | ||
osRelease = await getDebianVersion(docker).then((release) => | ||
tryDebianVersion(release), | ||
); | ||
} | ||
|
||
if (!osRelease) { | ||
osRelease = await getAlpineRelease(docker).then((release) => | ||
tryAlpineRelease(release), | ||
); | ||
} | ||
|
||
if (!osRelease) { | ||
osRelease = await getOracleRelease(docker).then((release) => | ||
tryOracleRelease(release), | ||
); | ||
} | ||
|
||
if (!osRelease) { | ||
osRelease = await getRedHatRelease(docker).then((release) => | ||
tryRedHatRelease(release), | ||
); | ||
} | ||
|
||
if (!osRelease) { | ||
if (dockerfileAnalysis && dockerfileAnalysis.baseImage === "scratch") { | ||
// If the docker file was build from a scratch image | ||
// then we don't have a known OS | ||
|
||
osRelease = { name: "scratch", version: "0.0" }; | ||
} else { | ||
throw new Error("Failed to detect OS release"); | ||
} | ||
} | ||
|
||
// Oracle Linux identifies itself as "ol" | ||
if (osRelease.name.trim() === "ol") { | ||
osRelease.name = "oracle"; | ||
} | ||
|
||
return osRelease; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { detect } from "./docker"; | ||
|
||
export { detect }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import { OSRelease } from "../types"; | ||
|
||
export async function tryOSRelease(text: string): Promise<OSRelease | null> { | ||
if (!text) { | ||
return null; | ||
} | ||
const idRes = text.match(/^ID=(.+)$/m); | ||
if (!idRes) { | ||
throw new Error("Failed to parse /etc/os-release"); | ||
} | ||
const name = idRes[1].replace(/"/g, ""); | ||
const versionRes = text.match(/^VERSION_ID=(.+)$/m); | ||
let version = versionRes ? versionRes[1].replace(/"/g, "") : "unstable"; | ||
|
||
if (name === "ol") { | ||
version = version.split(".")[0]; | ||
} | ||
|
||
return { name, version }; | ||
} | ||
|
||
export async function tryLsbRelease(text: string): Promise<OSRelease | null> { | ||
if (!text) { | ||
return null; | ||
} | ||
const idRes = text.match(/^DISTRIB_ID=(.+)$/m); | ||
const versionRes = text.match(/^DISTRIB_RELEASE=(.+)$/m); | ||
if (!idRes || !versionRes) { | ||
throw new Error("Failed to parse /etc/lsb-release"); | ||
} | ||
const name = idRes[1].replace(/"/g, "").toLowerCase(); | ||
const version = versionRes[1].replace(/"/g, ""); | ||
return { name, version }; | ||
} | ||
|
||
export async function tryDebianVersion( | ||
text: string, | ||
): Promise<OSRelease | null> { | ||
if (!text) { | ||
return null; | ||
} | ||
text = text.trim(); | ||
if (text.length < 2) { | ||
throw new Error("Failed to parse /etc/debian_version"); | ||
} | ||
return { name: "debian", version: text.split(".")[0] }; | ||
} | ||
|
||
export async function tryAlpineRelease( | ||
text: string, | ||
): Promise<OSRelease | null> { | ||
if (!text) { | ||
return null; | ||
} | ||
text = text.trim(); | ||
if (text.length < 2) { | ||
throw new Error("Failed to parse /etc/alpine-release"); | ||
} | ||
return { name: "alpine", version: text }; | ||
} | ||
|
||
export async function tryRedHatRelease( | ||
text: string, | ||
): Promise<OSRelease | null> { | ||
if (!text) { | ||
return null; | ||
} | ||
const idRes = text.match(/^(\S+)/m); | ||
const versionRes = text.match(/(\d+)\./m); | ||
if (!idRes || !versionRes) { | ||
throw new Error("Failed to parse /etc/redhat-release"); | ||
} | ||
const name = idRes[1].replace(/"/g, "").toLowerCase(); | ||
const version = versionRes[1].replace(/"/g, ""); | ||
return { name, version }; | ||
} | ||
|
||
export async function tryOracleRelease( | ||
text: string, | ||
): Promise<OSRelease | null> { | ||
if (!text) { | ||
return null; | ||
} | ||
const idRes = text.match(/^(\S+)/m); | ||
const versionRes = text.match(/(\d+\.\d+)/m); | ||
if (!idRes || !versionRes) { | ||
throw new Error("Failed to parse /etc/oracle-release"); | ||
} | ||
const name = idRes[1].replace(/"/g, "").toLowerCase(); | ||
const version = versionRes[1].replace(/"/g, "").split(".")[0]; | ||
|
||
return { name, version }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { Docker } from "../../docker"; | ||
|
||
export function getOsRelease(docker: Docker): Promise<string> { | ||
return getFileContent(docker, "/etc/os-release"); | ||
} | ||
|
||
export function getLsbRelease(docker: Docker): Promise<string> { | ||
return getFileContent(docker, "/etc/lsb-release"); | ||
} | ||
|
||
export function getDebianVersion(docker: Docker): Promise<string> { | ||
return getFileContent(docker, "/etc/debian_version"); | ||
} | ||
|
||
export function getAlpineRelease(docker: Docker): Promise<string> { | ||
return getFileContent(docker, "/etc/alpine-release"); | ||
} | ||
|
||
export function getRedHatRelease(docker: Docker): Promise<string> { | ||
return getFileContent(docker, "/etc/redhat-release"); | ||
} | ||
|
||
export function getOracleRelease(docker: Docker): Promise<string> { | ||
return getFileContent(docker, "/etc/oracle-release"); | ||
} | ||
|
||
async function getFileContent( | ||
docker: Docker, | ||
release: string, | ||
): Promise<string> { | ||
try { | ||
return (await docker.catSafe(release)).stdout; | ||
} catch (error) { | ||
throw new Error(error.stderr); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters