Skip to content

Commit

Permalink
Add --network and --add-host to Image
Browse files Browse the repository at this point in the history
  • Loading branch information
blampe committed Nov 29, 2023
1 parent 5a70e48 commit b2f645e
Show file tree
Hide file tree
Showing 20 changed files with 411 additions and 47 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sdk/**/* linguist-generated=true
32 changes: 32 additions & 0 deletions examples/examples_yaml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,35 @@ func TestSecretsYAML(t *testing.T) {
},
})
}

func TestBuilderVersionsYAML(t *testing.T) {
cwd, err := os.Getwd()
if !assert.NoError(t, err) {
t.FailNow()
}

t.Run("v1", func(t *testing.T) {
integration.ProgramTest(t, &integration.ProgramTestOptions{
Dir: path.Join(cwd, "test-builder-version", "v1"),
Quick: true,
SkipRefresh: true,
ExtraRuntimeValidation: func(t *testing.T, stack integration.RuntimeValidationStackInfo) {
platform, ok := stack.Outputs["platform"]
assert.True(t, ok)
assert.NotEmpty(t, platform)
},
})
})
t.Run("v2", func(t *testing.T) {
integration.ProgramTest(t, &integration.ProgramTestOptions{
Dir: path.Join(cwd, "test-builder-version", "v2"),
Quick: true,
SkipRefresh: true,
ExtraRuntimeValidation: func(t *testing.T, stack integration.RuntimeValidationStackInfo) {
platform, ok := stack.Outputs["platform"]
assert.True(t, ok)
assert.NotEmpty(t, platform)
},
})
})
}
3 changes: 3 additions & 0 deletions examples/test-builder-version/v1/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM bash AS base

RUN getent hosts metadata.google.internal # Remember to --add-host!
22 changes: 22 additions & 0 deletions examples/test-builder-version/v1/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: builder-v1
runtime: yaml
resources:
v1Image:
type: docker:Image
properties:
imageName: docker.io/pulumi/v1-builder:latest
skipPush: true
build:
builderVersion: BuilderV1
context: .
dockerfile: Dockerfile
platform: linux/amd64
target: base
cacheFrom:
images:
- docker.io/pulumi/pulumi-base:latest
addHosts:
- metadata.google.internal:169.254.169.254
network: host
outputs:
platform: ${v1Image.platform}
3 changes: 3 additions & 0 deletions examples/test-builder-version/v2/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM bash AS base

RUN getent hosts metadata.google.internal # Remember to --add-host!
22 changes: 22 additions & 0 deletions examples/test-builder-version/v2/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: builder-v2
runtime: yaml
resources:
v2Image:
type: docker:Image
properties:
imageName: docker.io/pulumi/v2-builder:latest
skipPush: true
build:
builderVersion: BuilderBuildKit
context: .
dockerfile: Dockerfile
platform: linux/amd64
target: base
cacheFrom:
images:
- docker.io/pulumi/pulumi-base:latest
addHosts:
- metadata.google.internal:169.254.169.254
network: host
outputs:
platform: ${v2Image.platform}
15 changes: 15 additions & 0 deletions provider/cmd/pulumi-resource-docker/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1882,6 +1882,13 @@
"docker:index/dockerBuild:DockerBuild": {
"description": "The Docker build context",
"properties": {
"addHosts": {
"type": "array",
"items": {
"type": "string"
},
"description": "Custom host-to-IP mappings to use while building (format: \"host:ip\")"
},
"args": {
"type": "object",
"additionalProperties": {
Expand All @@ -1905,6 +1912,10 @@
"type": "string",
"description": "The path to the Dockerfile to use."
},
"network": {
"type": "string",
"description": "Set the networking mode for RUN instructions"
},
"platform": {
"type": "string",
"description": "The architecture of the platform you want to build this image for, e.g. `linux/arm64`."
Expand Down Expand Up @@ -3149,6 +3160,10 @@
"type": "string",
"description": "The fully qualified image name"
},
"platform": {
"type": "string",
"description": "The image's architecture and OS"
},
"registryServer": {
"type": "string",
"description": "The name of the registry server hosting the image."
Expand Down
93 changes: 61 additions & 32 deletions provider/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ import (
"github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin"
)

const defaultDockerfile = "Dockerfile"
const defaultBuilder = "2"
const (
defaultDockerfile = "Dockerfile"
defaultBuilder = "2"
)

type Image struct {
Name string
Expand All @@ -67,6 +69,8 @@ type Build struct {
Args map[string]*string
Target string
Platform string
Network string
ExtraHosts []string
BuilderVersion types.BuilderVersion
}

Expand All @@ -81,10 +85,9 @@ type Config struct {

func (p *dockerNativeProvider) dockerBuild(ctx context.Context,
urn resource.URN,
props *structpb.Struct) (string, *structpb.Struct, error) {

props *structpb.Struct,
) (string, *structpb.Struct, error) {
inputs, err := plugin.UnmarshalProperties(props, plugin.MarshalOptions{KeepUnknowns: true, SkipNulls: true})

if err != nil {
return "", nil, err
}
Expand All @@ -101,16 +104,9 @@ func (p *dockerNativeProvider) dockerBuild(ctx context.Context,
if err != nil {
return "", nil, err
}
cache, err := marshalCachedImages(inputs["build"])
if err != nil {
return "", nil, err
}

build.CachedImages = cache
img.Build = build

docker, err := configureDockerClient(p.config, true)

if err != nil {
return "", nil, err
}
Expand Down Expand Up @@ -232,18 +228,20 @@ func (p *dockerNativeProvider) dockerBuild(ctx context.Context,

// make the build options
opts := types.ImageBuildOptions{
Dockerfile: replaceDockerfile,
Tags: []string{img.Name}, // this should build the image locally, sans registry info
CacheFrom: img.Build.CachedImages,
BuildArgs: build.Args,
Version: build.BuilderVersion,
Platform: build.Platform,
Target: build.Target,
Dockerfile: replaceDockerfile,
Tags: []string{img.Name}, // this should build the image locally, sans registry info
CacheFrom: img.Build.CachedImages,
BuildArgs: build.Args,
Version: build.BuilderVersion,
Platform: build.Platform,
Target: build.Target,
ExtraHosts: build.ExtraHosts,
NetworkMode: build.Network,

AuthConfigs: authConfigs,
}

//Start a session for BuildKit
// Start a session for BuildKit
if build.BuilderVersion == defaultBuilder {
sess, err := session.NewSession(ctx, "pulumi-docker", identity.NewID())
if err != nil {
Expand Down Expand Up @@ -305,6 +303,7 @@ func (p *dockerNativeProvider) dockerBuild(ctx context.Context,
"baseImageName": img.Name,
"registryServer": img.Registry.Server,
"imageName": img.Name,
"platform": img.Build.Platform,
}

imageName, err := reference.ParseNormalizedNamed(img.Name)
Expand All @@ -331,7 +330,6 @@ func (p *dockerNativeProvider) dockerBuild(ctx context.Context,
_ = p.host.LogStatus(ctx, "info", urn, "Pushing Image to the registry")

authConfigBytes, err := json.Marshal(regAuth)

if err != nil {
return "", nil, fmt.Errorf("error parsing authConfig: %v", err)
}
Expand All @@ -341,7 +339,6 @@ func (p *dockerNativeProvider) dockerBuild(ctx context.Context,

// By default, we push our image with the qualified image name from the input, without extra tagging.
pushOutput, err := docker.ImagePush(ctx, img.Name, pushOpts)

if err != nil {
return "", nil, err
}
Expand Down Expand Up @@ -406,7 +403,8 @@ func (p *dockerNativeProvider) dockerBuild(ctx context.Context,
// If the image is not found in the local store, it returns an error.
func (p *dockerNativeProvider) getRepoDigest(
ctx context.Context, docker *client.Client, imageID string,
img Image, urn resource.URN) (reference.Reference, error) {
img Image, urn resource.URN,
) (reference.Reference, error) {
dist, _, err := docker.ImageInspectWithRaw(ctx, imageID)
if err != nil {
return nil, err
Expand All @@ -420,7 +418,6 @@ func (p *dockerNativeProvider) getRepoDigest(
var repoDigest reference.Reference
for _, d := range dist.RepoDigests {
ref, err := reference.ParseNormalizedNamed(d)

if err != nil {
_ = p.host.Log(ctx, "warning", urn, fmt.Sprintf("Error parsing digest %q: %v", d, err))
continue
Expand Down Expand Up @@ -456,7 +453,8 @@ func (p *dockerNativeProvider) getRepoDigest(
// 4. We only return an imageID if the image in the store matches both (1.) and (2.)
func (p *dockerNativeProvider) runImageBuild(
ctx context.Context, docker *client.Client, tar io.Reader,
opts types.ImageBuildOptions, urn resource.URN, name string) (string, error) {
opts types.ImageBuildOptions, urn resource.URN, name string,
) (string, error) {
if opts.Labels == nil {
opts.Labels = make(map[string]string)
}
Expand Down Expand Up @@ -543,7 +541,8 @@ func (p *dockerNativeProvider) runImageBuild(
}

func pullDockerImage(ctx context.Context, p *dockerNativeProvider, urn resource.URN,
docker *client.Client, authConfig types.AuthConfig, cachedImage string, platform string) error {
docker *client.Client, authConfig types.AuthConfig, cachedImage string, platform string,
) error {
if cachedImage != "" {
_ = p.host.LogStatus(ctx, "info", urn, fmt.Sprintf("Pulling cached image %s", cachedImage))

Expand Down Expand Up @@ -572,7 +571,6 @@ func pullDockerImage(ctx context.Context, p *dockerNativeProvider, urn resource.
}

func marshalBuildAndApplyDefaults(b resource.PropertyValue) (Build, error) {

// build can be nil, a string or an object; we will also use reasonable defaults here.
var build Build
if b.IsNull() {
Expand Down Expand Up @@ -601,7 +599,6 @@ func marshalBuildAndApplyDefaults(b resource.PropertyValue) (Build, error) {
}
// BuildKit
version, err := marshalBuilder(buildObject["builderVersion"])

if err != nil {
return build, err
}
Expand All @@ -615,13 +612,48 @@ func marshalBuildAndApplyDefaults(b resource.PropertyValue) (Build, error) {
build.Target = buildObject["target"].StringValue()
}

// CacheFrom
cache, err := marshalCachedImages(b)
if err != nil {
return build, err
}
build.CachedImages = cache

// AddHosts
hosts, err := marshalExtraHosts(b)
if err != nil {
return build, err
}
build.ExtraHosts = hosts

// Network
if !buildObject["network"].IsNull() {
build.Network = buildObject["network"].StringValue()
}

// Platform
if !buildObject["platform"].IsNull() {
build.Platform = buildObject["platform"].StringValue()
}
return build, nil
}

func marshalExtraHosts(b resource.PropertyValue) ([]string, error) {
var extraHosts []string
if b.IsNull() || b.ObjectValue()["addHosts"].IsNull() {
return extraHosts, nil
}
hosts := b.ObjectValue()["addHosts"].ArrayValue()

for _, host := range hosts {
if !host.IsString() {
continue
}
extraHosts = append(extraHosts, host.StringValue())
}
return extraHosts, nil
}

func marshalCachedImages(b resource.PropertyValue) ([]string, error) {
var cacheImages []string
if b.IsNull() {
Expand Down Expand Up @@ -694,7 +726,7 @@ func marshalBuilder(builder resource.PropertyValue) (types.BuilderVersion, error
var version types.BuilderVersion

if builder.IsNull() {
//set default
// set default
return defaultBuilder, nil
}
// verify valid input
Expand Down Expand Up @@ -858,7 +890,6 @@ func processLogLine(jm jsonmessage.JSONMessage,
info += jm.Status + " " + jm.Progress.String()
} else if jm.Stream != "" {
info += jm.Stream

} else {
info += jm.Status
}
Expand Down Expand Up @@ -888,7 +919,6 @@ func processLogLine(jm jsonmessage.JSONMessage,
}
for _, log := range resp.Logs {
info += fmt.Sprintf("%s\n", string(log.Msg))

}
for _, warn := range resp.Warnings {
info += fmt.Sprintf("%s\n", string(warn.Short))
Expand Down Expand Up @@ -925,7 +955,6 @@ func processLogLine(jm jsonmessage.JSONMessage,
// instead of the system-wide one.
// `verify` is a testing affordance and will always be true in production.
func configureDockerClient(configs map[string]string, verify bool) (*client.Client, error) {

host, isExplicitHost := configs["host"]

if !isExplicitHost {
Expand Down
Loading

0 comments on commit b2f645e

Please sign in to comment.