Merge pull request #162 from crazy-max/nodes-output

nodes metadata JSON ouput
This commit is contained in:
CrazyMax 2022-09-22 11:05:09 +02:00 committed by GitHub
commit d5234d6605
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 332 additions and 72 deletions

View file

@ -30,9 +30,16 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
- -
name: Set up Docker Buildx name: Set up Docker Buildx
id: buildx
uses: ./ uses: ./
with: with:
version: ${{ matrix.buildx-version }} version: ${{ matrix.buildx-version }}
-
name: Nodes output
run: |
cat << EOF
${{ steps.buildx.outputs.nodes }}
EOF
multi: multi:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View file

@ -29,6 +29,7 @@ ___
* [outputs](#outputs) * [outputs](#outputs)
* [environment variables](#environment-variables) * [environment variables](#environment-variables)
* [Notes](#notes) * [Notes](#notes)
* [`nodes` output](#nodes-output)
* [BuildKit container logs](#buildkit-container-logs) * [BuildKit container logs](#buildkit-container-logs)
* [Keep up-to-date with GitHub Dependabot](#keep-up-to-date-with-github-dependabot) * [Keep up-to-date with GitHub Dependabot](#keep-up-to-date-with-github-dependabot)
@ -99,13 +100,11 @@ Following inputs can be used as `step.with` keys
Following outputs are available Following outputs are available
| Name | Type | Description | | Name | Type | Description |
|---------------|---------|---------------------------------------| |-------------|--------|-------------------------------------------------|
| `name` | String | Builder name | | `name` | String | Builder name |
| `driver` | String | Builder driver | | `driver` | String | Builder driver |
| `endpoint` | String | Builder node endpoint | | `platforms` | String | Builder node platforms (preferred or available) |
| `status` | String | Builder node status | | `nodes` | JSON | Builder [nodes metadata](#nodes-output) |
| `flags` | String | Builder node flags (if applicable) |
| `platforms` | String | Builder node platforms available (comma separated) |
### environment variables ### environment variables
@ -117,6 +116,35 @@ The following [official docker environment variables](https://docs.docker.com/en
## Notes ## Notes
### `nodes` output
```json
[
{
"name": "builder-3820d274-502c-4498-ae24-d4c32b3023d90",
"endpoint": "unix:///var/run/docker.sock",
"driver-opts": [
"network=host",
"image=moby/buildkit:master"
],
"status": "running",
"buildkitd-flags": "--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
"buildkit": "3fab389",
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/amd64/v4,linux/386"
}
]
```
| Name | Type | Description |
|-------------------|--------|----------------------------|
| `name` | String | Node name |
| `endpoint` | String | Node endpoint |
| `driver-opts` | List | Options for the driver |
| `status` | String | Node status |
| `buildkitd-flags` | String | Flags for buildkitd daemon |
| `buildkit` | String | BuildKit version |
| `platforms` | String | Platforms available |
### BuildKit container logs ### BuildKit container logs
To display BuildKit container logs (when `docker-container` driver is used) you have to [enable step debug logging](https://docs.github.com/en/actions/managing-workflow-runs/enabling-debug-logging#enabling-step-debug-logging), To display BuildKit container logs (when `docker-container` driver is used) you have to [enable step debug logging](https://docs.github.com/en/actions/managing-workflow-runs/enabling-debug-logging#enabling-step-debug-logging),

View file

@ -1,4 +1,4 @@
import {describe, expect, jest, test, beforeEach} from '@jest/globals'; import {describe, expect, test, beforeEach} from '@jest/globals';
import * as fs from 'fs'; import * as fs from 'fs';
import * as os from 'os'; import * as os from 'os';
import * as path from 'path'; import * as path from 'path';

View file

@ -73,10 +73,128 @@ describe('inspect', () => {
expect(builder).not.toBeUndefined(); expect(builder).not.toBeUndefined();
expect(builder.name).not.toEqual(''); expect(builder.name).not.toEqual('');
expect(builder.driver).not.toEqual(''); expect(builder.driver).not.toEqual('');
expect(builder.node_platforms).not.toEqual(''); expect(builder.nodes).not.toEqual({});
}, 100000); }, 100000);
}); });
describe('parseInspect', () => {
// prettier-ignore
test.each([
[
'inspect1.txt',
{
"nodes": [
{
"name": "builder-5cb467f7-0940-47e1-b94b-d51f54054d620",
"endpoint": "unix:///var/run/docker.sock",
"status": "running",
"buildkitd-flags": "--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
"buildkit": "v0.10.4",
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/amd64/v4,linux/arm64,linux/riscv64,linux/386,linux/arm/v7,linux/arm/v6"
}
],
"name": "builder-5cb467f7-0940-47e1-b94b-d51f54054d62",
"driver": "docker-container"
}
],
[
'inspect2.txt',
{
"nodes": [
{
"name": "builder-5f449644-ff29-48af-8344-abb0292d06730",
"endpoint": "unix:///var/run/docker.sock",
"driver-opts": [
"image=moby/buildkit:latest"
],
"status": "running",
"buildkitd-flags": "--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
"buildkit": "v0.10.4",
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/amd64/v4,linux/386"
}
],
"name": "builder-5f449644-ff29-48af-8344-abb0292d0673",
"driver": "docker-container"
}
],
[
'inspect3.txt',
{
"nodes": [
{
"name": "builder-9929e463-7954-4dc3-89cd-514cca29ff800",
"endpoint": "unix:///var/run/docker.sock",
"driver-opts": [
"image=moby/buildkit:master",
"network=host"
],
"status": "running",
"buildkitd-flags": "--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
"buildkit": "3fab389",
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/amd64/v4,linux/386"
}
],
"name": "builder-9929e463-7954-4dc3-89cd-514cca29ff80",
"driver": "docker-container"
}
],
[
'inspect4.txt',
{
"nodes": [
{
"name": "default",
"endpoint": "default",
"status": "running",
"buildkit": "20.10.17",
"platforms": "linux/amd64,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6"
}
],
"name": "default",
"driver": "docker"
}
],
[
'inspect5.txt',
{
"nodes": [
{
"name": "aws_graviton2",
"endpoint": "tcp://1.23.45.67:1234",
"driver-opts": [
"cert=/home/user/.certs/aws_graviton2/cert.pem",
"key=/home/user/.certs/aws_graviton2/key.pem",
"cacert=/home/user/.certs/aws_graviton2/ca.pem"
],
"status": "running",
"platforms": "darwin/arm64,linux/arm64,linux/arm/v5,linux/arm/v6,linux/arm/v7,windows/arm64"
}
],
"name": "remote-builder",
"driver": "remote"
}
],
[
'inspect6.txt',
{
"nodes": [
{
"name": "builder-17cfff01-48d9-4c3d-9332-9992e308a5100",
"endpoint": "unix:///var/run/docker.sock",
"status": "running",
"buildkitd-flags": "--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/386"
}
],
"name": "builder-17cfff01-48d9-4c3d-9332-9992e308a510",
"driver": "docker-container"
}
],
])('given %p', async (inspectFile, expected) => {
expect(await buildx.parseInspect(fs.readFileSync(path.join(__dirname, 'fixtures', inspectFile)).toString())).toEqual(expected);
});
});
describe('build', () => { describe('build', () => {
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'setup-buildx-')); const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'setup-buildx-'));

View file

@ -0,0 +1,10 @@
Name: builder-5cb467f7-0940-47e1-b94b-d51f54054d62
Driver: docker-container
Nodes:
Name: builder-5cb467f7-0940-47e1-b94b-d51f54054d620
Endpoint: unix:///var/run/docker.sock
Status: running
Flags: --allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host
Buildkit: v0.10.4
Platforms: linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/amd64/v4, linux/arm64, linux/riscv64, linux/386, linux/arm/v7, linux/arm/v6

View file

@ -0,0 +1,11 @@
Name: builder-5f449644-ff29-48af-8344-abb0292d0673
Driver: docker-container
Nodes:
Name: builder-5f449644-ff29-48af-8344-abb0292d06730
Endpoint: unix:///var/run/docker.sock
Driver Options: image="moby/buildkit:latest"
Status: running
Flags: --allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host
Buildkit: v0.10.4
Platforms: linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/amd64/v4, linux/386

View file

@ -0,0 +1,11 @@
Name: builder-9929e463-7954-4dc3-89cd-514cca29ff80
Driver: docker-container
Nodes:
Name: builder-9929e463-7954-4dc3-89cd-514cca29ff800
Endpoint: unix:///var/run/docker.sock
Driver Options: image="moby/buildkit:master" network="host"
Status: running
Flags: --allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host
Buildkit: 3fab389
Platforms: linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/amd64/v4, linux/386

View file

@ -0,0 +1,9 @@
Name: default
Driver: docker
Nodes:
Name: default
Endpoint: default
Status: running
Buildkit: 20.10.17
Platforms: linux/amd64, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

View file

@ -0,0 +1,9 @@
Name: remote-builder
Driver: remote
Nodes:
Name: aws_graviton2
Endpoint: tcp://1.23.45.67:1234
Driver Options: cert="/home/user/.certs/aws_graviton2/cert.pem" key="/home/user/.certs/aws_graviton2/key.pem" cacert="/home/user/.certs/aws_graviton2/ca.pem"
Status: running
Platforms: darwin/arm64*, linux/arm64*, linux/arm/v5*, linux/arm/v6*, linux/arm/v7*, windows/arm64*, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/mips64le, linux/mips64

View file

@ -0,0 +1,9 @@
Name: builder-17cfff01-48d9-4c3d-9332-9992e308a510
Driver: docker-container
Nodes:
Name: builder-17cfff01-48d9-4c3d-9332-9992e308a5100
Endpoint: unix:///var/run/docker.sock
Status: running
Flags: --allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host
Platforms: linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/386

View file

@ -44,14 +44,16 @@ outputs:
description: 'Builder name' description: 'Builder name'
driver: driver:
description: 'Builder driver' description: 'Builder driver'
endpoint:
description: 'Builder node endpoint'
status:
description: 'Builder node status'
flags:
description: 'Builder node flags (if applicable)'
platforms: platforms:
description: 'Builder node platforms available (comma separated)' description: 'Builder node platforms (preferred or available)'
nodes:
description: 'Builder nodes metadata'
endpoint:
description: 'Builder node endpoint (deprecated, use nodes output instead)'
status:
description: 'Builder node status (deprecated, use nodes output instead)'
flags:
description: 'Builder node flags (deprecated, use nodes output instead)'
runs: runs:
using: 'node16' using: 'node16'

4
dist/index.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/index.js.map generated vendored

File diff suppressed because one or more lines are too long

View file

@ -12,11 +12,17 @@ import * as tc from '@actions/tool-cache';
export type Builder = { export type Builder = {
name?: string; name?: string;
driver?: string; driver?: string;
node_name?: string; nodes: Node[];
node_endpoint?: string; };
node_status?: string;
node_flags?: string; export type Node = {
node_platforms?: string; name?: string;
endpoint?: string;
'driver-opts'?: Array<string>;
status?: string;
'buildkitd-flags'?: string;
buildkit?: string;
platforms?: string;
}; };
export async function getConfigInline(s: string): Promise<string> { export async function getConfigInline(s: string): Promise<string> {
@ -98,46 +104,81 @@ export async function inspect(name: string, standalone?: boolean): Promise<Build
if (res.stderr.length > 0 && res.exitCode != 0) { if (res.stderr.length > 0 && res.exitCode != 0) {
throw new Error(res.stderr.trim()); throw new Error(res.stderr.trim());
} }
const builder: Builder = {}; return parseInspect(res.stdout);
itlines: for (const line of res.stdout.trim().split(`\n`)) { });
}
export async function parseInspect(data: string): Promise<Builder> {
const builder: Builder = {
nodes: []
};
let node: Node = {};
for (const line of data.trim().split(`\n`)) {
const [key, ...rest] = line.split(':'); const [key, ...rest] = line.split(':');
const value = rest.map(v => v.trim()).join(':'); const value = rest.map(v => v.trim()).join(':');
if (key.length == 0 || value.length == 0) { if (key.length == 0 || value.length == 0) {
continue; continue;
} }
switch (key) { switch (key.toLowerCase()) {
case 'Name': { case 'name': {
if (builder.name == undefined) { if (builder.name == undefined) {
builder.name = value; builder.name = value;
} else { } else {
builder.node_name = value; if (Object.keys(node).length > 0) {
builder.nodes.push(node);
node = {};
}
node.name = value;
} }
break; break;
} }
case 'Driver': { case 'driver': {
builder.driver = value; builder.driver = value;
break; break;
} }
case 'Endpoint': { case 'endpoint': {
builder.node_endpoint = value; node.endpoint = value;
break; break;
} }
case 'Status': { case 'driver options': {
builder.node_status = value; node['driver-opts'] = (value.match(/(\w+)="([^"]*)"/g) || []).map(v => v.replace(/^(.*)="(.*)"$/g, '$1=$2'));
break; break;
} }
case 'Flags': { case 'status': {
builder.node_flags = value; node.status = value;
break; break;
} }
case 'Platforms': { case 'flags': {
builder.node_platforms = value.replace(/\s/g, ''); node['buildkitd-flags'] = value;
break itlines; break;
}
case 'buildkit': {
node.buildkit = value;
break;
}
case 'platforms': {
let platforms: Array<string> = [];
// if a preferred platform is being set then use only these
// https://docs.docker.com/engine/reference/commandline/buildx_inspect/#get-information-about-a-builder-instance
if (value.includes('*')) {
for (const platform of value.split(', ')) {
if (platform.includes('*')) {
platforms.push(platform.replace('*', ''));
} }
} }
} else {
// otherwise set all platforms available
platforms = value.split(', ');
}
node.platforms = platforms.join(',');
break;
}
}
}
if (Object.keys(node).length > 0) {
builder.nodes.push(node);
} }
return builder; return builder;
});
} }
export async function build(inputBuildRef: string, dest: string, standalone: boolean): Promise<string> { export async function build(inputBuildRef: string, dest: string, standalone: boolean): Promise<string> {

View file

@ -115,21 +115,26 @@ async function run(): Promise<void> {
core.startGroup(`Inspect builder`); core.startGroup(`Inspect builder`);
const builder = await buildx.inspect(builderName, standalone); const builder = await buildx.inspect(builderName, standalone);
const firstNode = builder.nodes[0];
core.info(JSON.stringify(builder, undefined, 2)); core.info(JSON.stringify(builder, undefined, 2));
context.setOutput('driver', builder.driver); context.setOutput('driver', builder.driver);
context.setOutput('endpoint', builder.node_endpoint); context.setOutput('platforms', firstNode.platforms);
context.setOutput('status', builder.node_status); context.setOutput('nodes', JSON.stringify(builder.nodes, undefined, 2));
context.setOutput('flags', builder.node_flags); context.setOutput('endpoint', firstNode.endpoint); // TODO: deprecated, to be removed in a later version
context.setOutput('platforms', builder.node_platforms); context.setOutput('status', firstNode.status); // TODO: deprecated, to be removed in a later version
context.setOutput('flags', firstNode['buildkitd-flags']); // TODO: deprecated, to be removed in a later version
core.endGroup(); core.endGroup();
if (!standalone && inputs.driver == 'docker-container') { if (!standalone && builder.driver == 'docker-container') {
stateHelper.setContainerName(`buildx_buildkit_${builder.node_name}`); stateHelper.setContainerName(`buildx_buildkit_${firstNode.name}`);
core.startGroup(`BuildKit version`); core.startGroup(`BuildKit version`);
core.info(await buildx.getBuildKitVersion(`buildx_buildkit_${builder.node_name}`)); for (const node of builder.nodes) {
const bkvers = await buildx.getBuildKitVersion(`buildx_buildkit_${node.name}`);
core.info(`${node.name}: ${bkvers}`);
}
core.endGroup(); core.endGroup();
} }
if (core.isDebug() || builder.node_flags?.includes('--debug')) { if (core.isDebug() || firstNode['buildkitd-flags']?.includes('--debug')) {
stateHelper.setDebug('true'); stateHelper.setDebug('true');
} }
} catch (error) { } catch (error) {