Skip to content

Commit

Permalink
Merge pull request #766 from schummar/feature/buildkit-support
Browse files Browse the repository at this point in the history
POC: BuildKit support
  • Loading branch information
apocas authored Jan 3, 2025
2 parents 21d8397 + edfb8f1 commit 92df7b1
Show file tree
Hide file tree
Showing 7 changed files with 419 additions and 124 deletions.
52 changes: 37 additions & 15 deletions lib/docker.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ var EventEmitter = require('events').EventEmitter,
Node = require('./node'),
Exec = require('./exec'),
util = require('./util'),
withSession = require('./session');
extend = util.extend;

var Docker = function(opts) {
Expand Down Expand Up @@ -287,25 +288,46 @@ Docker.prototype.buildImage = function(file, opts, callback) {
}
}

if (callback === undefined) {
return new self.modem.Promise(function(resolve, reject) {
util.prepareBuildContext(file, (ctx) => {
optsf.file = ctx;
self.modem.dial(optsf, function(err, data) {
if (err) {
return reject(err);
function dial(callback) {
util.prepareBuildContext(file, (ctx) => {
optsf.file = ctx;
self.modem.dial(optsf, callback);
});
}

function dialWithSession(callback) {
if (opts?.version === "2") {
withSession(self, optsf.authconfig,(err, sessionId, done) => {
if (err) {
return callback(err);
}

optsf.options.session = sessionId;

dial((err, data) => {
callback(err, data);

if (data) {
data.on("end", done);
}
resolve(data);
});
});
} else {
dial(null, callback);
}
}

if (callback === undefined) {
return new self.modem.Promise(function (resolve, reject) {
dialWithSession(function (err, data) {
if (err) {
return reject(err);
}
resolve(data);
});
});
} else {
util.prepareBuildContext(file, (ctx) => {
optsf.file = ctx;
self.modem.dial(optsf, function(err, data) {
callback(err, data);
});
})
dialWithSession(callback);
}
};

Expand Down Expand Up @@ -1850,4 +1872,4 @@ Docker.Task = Task;
Docker.Node = Node;
Docker.Exec = Exec;

module.exports = Docker;
module.exports = Docker;
54 changes: 54 additions & 0 deletions lib/proto/auth.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
syntax = "proto3";

package moby.filesync.v1;

option go_package = "auth";

service Auth{
rpc Credentials(CredentialsRequest) returns (CredentialsResponse);
rpc FetchToken(FetchTokenRequest) returns (FetchTokenResponse);
rpc GetTokenAuthority(GetTokenAuthorityRequest) returns (GetTokenAuthorityResponse);
rpc VerifyTokenAuthority(VerifyTokenAuthorityRequest) returns (VerifyTokenAuthorityResponse);
}

message CredentialsRequest {
string Host = 1;
}

message CredentialsResponse {
string Username = 1;
string Secret = 2;
}

message FetchTokenRequest {
string ClientID = 1;
string Host = 2;
string Realm = 3;
string Service = 4;
repeated string Scopes = 5;
}

message FetchTokenResponse {
string Token = 1;
int64 ExpiresIn = 2; // seconds
int64 IssuedAt = 3; // timestamp
}

message GetTokenAuthorityRequest {
string Host = 1;
bytes Salt = 2;
}

message GetTokenAuthorityResponse {
bytes PublicKey = 1;
}

message VerifyTokenAuthorityRequest {
string Host = 1;
bytes Payload = 2;
bytes Salt = 3;
}

message VerifyTokenAuthorityResponse {
bytes Signed = 1;
}
63 changes: 63 additions & 0 deletions lib/session.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
var grpc = require("@grpc/grpc-js"),
protoLoader = require("@grpc/proto-loader"),
path = require("path"),
uuid = require("uuid").v4;

function withSession(docker, auth, handler) {
const sessionId = uuid();

const opts = {
method: "POST",
path: "/session",
hijack: true,
headers: {
Upgrade: "h2c",
"X-Docker-Expose-Session-Uuid": sessionId,
"X-Docker-Expose-Session-Name": "testcontainers",
},
statusCodes: {
200: true,
500: "server error",
},
};

docker.modem.dial(opts, function (err, socket) {
if (err) {
return handler(err, null, () => undefined);
}

const server = new grpc.Server();
const creds = grpc.ServerCredentials.createInsecure();
const injector = server.createConnectionInjector(creds);
injector.injectConnection(socket);

const pkg = protoLoader.loadSync(
path.resolve(__dirname, "proto", "auth.proto")
);
const service = grpc.loadPackageDefinition(pkg);

server.addService(service.moby.filesync.v1.Auth.service, {
Credentials({ request }, callback) {
// We probably want to have the possibility to pass credentials per
// hots. The correct one could be returned based on `request.Host`
if (auth) {
callback(null, {
Username: auth.username,
Secret: auth.password,
});
} else {
callback(null, {});
}
},
});

function done() {
server.forceShutdown();
socket.end();
}

handler(null, sessionId, done);
});
}

module.exports = withSession;
Loading

0 comments on commit 92df7b1

Please sign in to comment.