Skip to content

Commit a547964

Browse files
authored
force docker linux/amd64 platform (#169)
* force docker platform * set default platform * update imports * add test * temporary fix for arm * log platform event * update known issues
1 parent e84d0ec commit a547964

File tree

11 files changed

+50
-7
lines changed

11 files changed

+50
-7
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,10 @@ tail -F ${HOME}/.local/state/hck/log/hckctl-*.log
280280
just publish <MAJOR.MINOR.PATCH>
281281
```
282282

283+
## Known issues
284+
285+
* Most of the images are built by default only for [`linux/amd64`](https://github.com/hckops/hckctl/pull/169), but they should work also on `linux/arm64`
286+
283287
## Roadmap
284288

285289
* `flow` orchestrate and schedule multistage tasks, collect and output the combined results in multiple formats

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ require (
1414
github.com/google/uuid v1.5.0
1515
github.com/mitchellh/mapstructure v1.5.0
1616
github.com/moby/term v0.5.0
17+
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b
1718
github.com/pkg/errors v0.9.1
1819
github.com/rs/zerolog v1.31.0
1920
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
@@ -91,7 +92,6 @@ require (
9192
github.com/morikuni/aec v1.0.0 // indirect
9293
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
9394
github.com/opencontainers/go-digest v1.0.0 // indirect
94-
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect
9595
github.com/opencontainers/runc v1.1.9 // indirect
9696
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
9797
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect

pkg/box/docker/docker.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ func (box *DockerBoxClient) createBox(opts *boxModel.CreateOptions) (*boxModel.B
136136
ContainerConfig: containerConfig,
137137
HostConfig: hostConfig,
138138
NetworkingConfig: docker.BuildNetworkingConfig(networkName, networkId), // all on the same network
139+
Platform: docker.DefaultPlatform(),
139140
WaitStatus: false,
140141
CaptureInterrupt: false,
141142
OnContainerInterruptCallback: func(string) {},

pkg/client/docker/builder.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/docker/docker/api/types/mount"
1111
"github.com/docker/docker/api/types/network"
1212
"github.com/docker/go-connections/nat"
13+
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
1314

1415
"github.com/hckops/hckctl/pkg/util"
1516
)
@@ -138,3 +139,10 @@ func ContainerNetworkMode(idOrName string) string {
138139
func BuildNetworkingConfig(networkName, networkId string) *network.NetworkingConfig {
139140
return &network.NetworkingConfig{EndpointsConfig: map[string]*network.EndpointSettings{networkName: {NetworkID: networkId}}}
140141
}
142+
143+
func DefaultPlatform() *ocispec.Platform {
144+
return &ocispec.Platform{
145+
Architecture: "amd64",
146+
OS: "linux",
147+
}
148+
}

pkg/client/docker/builder_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/docker/docker/api/types/mount"
1010
"github.com/docker/docker/api/types/network"
1111
"github.com/docker/go-connections/nat"
12+
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
1213
)
1314

1415
func TestBuildContainerConfig(t *testing.T) {
@@ -137,3 +138,8 @@ func TestBuildNetworkingConfig(t *testing.T) {
137138
result := BuildNetworkingConfig("myNetwork", "123")
138139
assert.Equal(t, expected, result)
139140
}
141+
142+
func TestDefaultPlatform(t *testing.T) {
143+
expected := &ocispec.Platform{Architecture: "amd64", OS: "linux"}
144+
assert.Equal(t, expected, DefaultPlatform())
145+
}

pkg/client/docker/client.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func (client *DockerClient) Close() error {
4343

4444
func (client *DockerClient) ImagePull(opts *ImagePullOpts) error {
4545

46-
reader, err := client.docker.ImagePull(client.ctx, opts.ImageName, types.ImagePullOptions{})
46+
reader, err := client.docker.ImagePull(client.ctx, opts.ImageName, types.ImagePullOptions{Platform: opts.PlatformString()})
4747
if err != nil {
4848
return errors.Wrap(err, "error image pull")
4949
}
@@ -90,7 +90,7 @@ func (client *DockerClient) ContainerCreate(opts *ContainerCreateOpts) (string,
9090
opts.ContainerConfig,
9191
opts.HostConfig,
9292
opts.NetworkingConfig,
93-
nil, // platform
93+
opts.Platform, // consistent with ImagePull, on ARM it works also if "nil"
9494
opts.ContainerName)
9595
if err != nil {
9696
return "", errors.Wrap(err, "error container create")

pkg/client/docker/client_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,10 @@ func TestNewContainerDetails(t *testing.T) {
100100
assert.NoError(t, err)
101101
assert.Equal(t, expected, containerDetails)
102102
}
103+
104+
func TestImagePlatform(t *testing.T) {
105+
opts := &ImagePullOpts{
106+
Platform: DefaultPlatform(),
107+
}
108+
assert.Equal(t, "linux/amd64", opts.PlatformString())
109+
}

pkg/client/docker/options.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package docker
22

33
import (
4+
"fmt"
45
"io"
56

67
"github.com/docker/docker/api/types/container"
78
"github.com/docker/docker/api/types/network"
9+
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
810

911
commonModel "github.com/hckops/hckctl/pkg/common/model"
1012
)
@@ -33,9 +35,14 @@ type ContainerPortConfigOpts struct {
3335

3436
type ImagePullOpts struct {
3537
ImageName string
38+
Platform *ocispec.Platform
3639
OnImagePullCallback func()
3740
}
3841

42+
func (o *ImagePullOpts) PlatformString() string {
43+
return fmt.Sprintf("%s/%s", o.Platform.OS, o.Platform.Architecture)
44+
}
45+
3946
type ImageRemoveOpts struct {
4047
OnImageRemoveCallback func(imageId string)
4148
OnImageRemoveErrorCallback func(imageId string, err error)
@@ -46,6 +53,7 @@ type ContainerCreateOpts struct {
4653
ContainerConfig *container.Config
4754
HostConfig *container.HostConfig
4855
NetworkingConfig *network.NetworkingConfig
56+
Platform *ocispec.Platform
4957
WaitStatus bool
5058
CaptureInterrupt bool
5159
OnContainerInterruptCallback func(containerId string)

pkg/common/docker/client.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,18 @@ func (common *DockerCommonClient) Close() error {
4646

4747
func (common *DockerCommonClient) PullImageOffline(imageName string, onImagePullCallback func()) error {
4848

49+
// TODO add support at least for linux/arm64
50+
// temporary solution to force the architecture, ideally:
51+
// - every image should be correctly built for all the architectures
52+
// - the templates should have a field with the list of supported architectures and use the default only as fallback
53+
platform := docker.DefaultPlatform()
54+
4955
imagePullOpts := &docker.ImagePullOpts{
5056
ImageName: imageName,
57+
Platform: platform,
5158
OnImagePullCallback: onImagePullCallback,
5259
}
53-
common.eventBus.Publish(newImagePullDockerEvent(imageName))
60+
common.eventBus.Publish(newImagePullDockerEvent(imageName, imagePullOpts.PlatformString()))
5461
if err := common.client.ImagePull(imagePullOpts); err != nil {
5562
// ignore error and try to use an existing image if exists
5663
if common.clientOpts.IgnoreImagePullError {
@@ -150,6 +157,7 @@ func (common *DockerCommonClient) SidecarVpnInject(opts *commonModel.SidecarVpnI
150157
ContainerName: containerName,
151158
ContainerConfig: containerConfig,
152159
HostConfig: hostConfig,
160+
Platform: docker.DefaultPlatform(),
153161
WaitStatus: false,
154162
CaptureInterrupt: false, // edge case: killing this while creating will leave an orphan sidecar container
155163
OnContainerCreateCallback: func(containerId string) error {

pkg/common/docker/events.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ func newCloseDockerClientEvent() *dockerCommonEvent {
3232
return &dockerCommonEvent{kind: event.LogDebug, value: "close docker client"}
3333
}
3434

35-
func newImagePullDockerEvent(imageName string) *dockerCommonEvent {
36-
return &dockerCommonEvent{kind: event.LogInfo, value: fmt.Sprintf("image pull: imageName=%s", imageName)}
35+
func newImagePullDockerEvent(imageName string, platform string) *dockerCommonEvent {
36+
return &dockerCommonEvent{kind: event.LogInfo, value: fmt.Sprintf("image pull: imageName=%s platform=%s", imageName, platform)}
3737
}
3838

3939
func newImagePullIgnoreDockerEvent(imageName string) *dockerCommonEvent {

pkg/task/docker/docker.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ func (task *DockerTaskClient) runTask(opts *taskModel.RunOptions) error {
101101
ContainerConfig: containerConfig,
102102
HostConfig: hostConfig,
103103
NetworkingConfig: docker.BuildNetworkingConfig(networkName, networkId), // all on the same network
104-
WaitStatus: true, // block
104+
Platform: docker.DefaultPlatform(),
105+
WaitStatus: true, // block
105106
CaptureInterrupt: true,
106107
OnContainerInterruptCallback: func(containerId string) {
107108
// returns control to runTask, it will correctly invoke defer to remove the sidecar

0 commit comments

Comments
 (0)