Skip to content

Commit 70c3a81

Browse files
committed
remove tag/repository config, create digest file
a repository name and tag aren't necessary for building an image, and baking them into the image kind of feels like a legacy practice. the OCI format has no place for the repository to be stored. in order to continue supporting 'docker load' and identifying the loaded image, we can instead just write the image's digest to a separate file in the output. this digest can then be tagged to give it a name: docker load -i image.tar docker tag $(cat digest) my-name this feels like a much cleaner split: repository/tag naming is a concern of pushing to a registry, not of image building, so it should be limited to the registry-pushing resource (i.e. registry-image) instead of having to configure it in both. Signed-off-by: Alex Suraci <[email protected]>
1 parent 69b06d3 commit 70c3a81

File tree

7 files changed

+39
-44
lines changed

7 files changed

+39
-44
lines changed

ci/tasks/build-image.yml

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ outputs:
1515
- name: image
1616

1717
params:
18-
REPOSITORY: concourse/builder-task
1918
CONTEXT: builder-task
2019

2120
run:

integration_test.go

+11-8
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@ func (s *TaskSuite) SetupTest() {
2727

2828
s.req = task.Request{
2929
ResponsePath: filepath.Join(s.outputsDir, "response.json"),
30-
Config: task.Config{
31-
Repository: "builder-task-test",
32-
},
30+
Config: task.Config{},
3331
}
3432
}
3533

@@ -38,18 +36,23 @@ func (s *TaskSuite) TearDownTest() {
3836
s.NoError(err)
3937
}
4038

41-
func (s *TaskSuite) TestMissingRepositoryValidation() {
42-
s.req.Config.Repository = ""
39+
func (s *TaskSuite) TestBasicBuild() {
40+
s.req.Config.ContextDir = "testdata/basic"
4341

4442
_, err := task.Build(s.outputsDir, s.req)
45-
s.EqualError(err, "config: repository must be specified")
43+
s.NoError(err)
4644
}
4745

48-
func (s *TaskSuite) TestBasicBuild() {
49-
s.req.Config.ContextDir = "testdata/basic"
46+
func (s *TaskSuite) TestDigestFile() {
47+
s.req.Config.ContextDir = "testdata/digest"
5048

5149
_, err := task.Build(s.outputsDir, s.req)
5250
s.NoError(err)
51+
52+
digest, err := ioutil.ReadFile(s.imagePath("digest"))
53+
s.NoError(err)
54+
55+
s.Equal(string(digest), "sha256:725c9a9e7bbd75b2081c0ca92788a4d29d4d728e4efeec52a1da5f91a3d600b8")
5356
}
5457

5558
func (s *TaskSuite) TestDockerfilePath() {

task.go

+21-25
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ func Build(outputsDir string, req Request) (Response, error) {
5353
return Response{}, errors.Wrap(err, "spawn buildkitd")
5454
}
5555

56-
ociImagePath := filepath.Join(imageDir, "image.tar")
56+
imagePath := filepath.Join(imageDir, "image.tar")
57+
digestPath := filepath.Join(imageDir, "digest")
5758

5859
dockerfileDir := filepath.Dir(cfg.DockerfilePath)
5960
dockerfileName := filepath.Base(cfg.DockerfilePath)
@@ -65,7 +66,7 @@ func Build(outputsDir string, req Request) (Response, error) {
6566
"--local", "dockerfile=" + dockerfileDir,
6667
"--opt", "filename=" + dockerfileName,
6768
"--export-cache", "type=local,mode=min,dest=" + cacheDir,
68-
"--output", "type=docker,dest=" + ociImagePath,
69+
"--output", "type=docker,dest=" + imagePath,
6970
}
7071

7172
if _, err := os.Stat(filepath.Join(cacheDir, "index.json")); err == nil {
@@ -95,8 +96,23 @@ func Build(outputsDir string, req Request) (Response, error) {
9596
return Response{}, errors.Wrap(err, "build")
9697
}
9798

99+
image, err := tarball.ImageFromPath(imagePath, nil)
100+
if err != nil {
101+
return Response{}, errors.Wrap(err, "open oci image")
102+
}
103+
104+
manifest, err := image.Manifest()
105+
if err != nil {
106+
return Response{}, errors.Wrap(err, "get image digest")
107+
}
108+
109+
err = ioutil.WriteFile(digestPath, []byte(manifest.Config.Digest.String()), 0644)
110+
if err != nil {
111+
return Response{}, errors.Wrap(err, "write digest")
112+
}
113+
98114
if req.Config.UnpackRootfs {
99-
err = unpackRootfs(imageDir, ociImagePath, cfg)
115+
err = unpackRootfs(imageDir, image, cfg)
100116
if err != nil {
101117
return Response{}, errors.Wrap(err, "unpack rootfs")
102118
}
@@ -105,18 +121,13 @@ func Build(outputsDir string, req Request) (Response, error) {
105121
return res, nil
106122
}
107123

108-
func unpackRootfs(dest string, ociImagePath string, cfg Config) error {
124+
func unpackRootfs(dest string, image v1.Image, cfg Config) error {
109125
rootfsDir := filepath.Join(dest, "rootfs")
110126
metadataPath := filepath.Join(dest, "metadata.json")
111127

112-
image, err := tarball.ImageFromPath(ociImagePath, nil)
113-
if err != nil {
114-
return errors.Wrap(err, "open oci image")
115-
}
116-
117128
logrus.Info("unpacking image")
118129

119-
err = unpackImage(rootfsDir, image, cfg.Debug)
130+
err := unpackImage(rootfsDir, image, cfg.Debug)
120131
if err != nil {
121132
return errors.Wrap(err, "unpack image")
122133
}
@@ -167,10 +178,6 @@ func writeImageMetadata(metadataPath string, image v1.Image) error {
167178
}
168179

169180
func sanitize(cfg *Config) error {
170-
if cfg.Repository == "" {
171-
return errors.New("repository must be specified")
172-
}
173-
174181
if cfg.ContextDir == "" {
175182
cfg.ContextDir = "."
176183
}
@@ -179,17 +186,6 @@ func sanitize(cfg *Config) error {
179186
cfg.DockerfilePath = filepath.Join(cfg.ContextDir, "Dockerfile")
180187
}
181188

182-
if cfg.TagFile != "" {
183-
target, err := ioutil.ReadFile(cfg.TagFile)
184-
if err != nil {
185-
return errors.Wrap(err, "read target file")
186-
}
187-
188-
cfg.Tag = strings.TrimSpace(string(target))
189-
} else if cfg.Tag == "" {
190-
cfg.Tag = "latest"
191-
}
192-
193189
if cfg.TargetFile != "" {
194190
target, err := ioutil.ReadFile(cfg.TargetFile)
195191
if err != nil {

testdata/basic/Dockerfile

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
FROM scratch
2+
COPY Dockerfile /

testdata/digest/Dockerfile

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
FROM scratch
2+
3+
# nothing; just need an image with a fixed digest
4+
COPY Dockerfile /
+2-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
FROM scratch
1+
FROM busybox
2+
RUN true

types.go

-9
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,8 @@ type Response struct {
4444
// For now, and for backwards-compatibility, we will also support taking values
4545
// from task params (i.e. env), hence the use of `envconfig:`.
4646
type Config struct {
47-
Repository string `json:"repository"`
48-
4947
Debug bool `json:"debug" envconfig:"optional"`
5048

51-
Tag string `json:"tag" envconfig:"optional"`
52-
TagFile string `json:"tag_file" envconfig:"optional"`
53-
5449
ContextDir string `json:"context" envconfig:"CONTEXT,optional"`
5550
DockerfilePath string `json:"dockerfile,omitempty" envconfig:"DOCKERFILE,optional"`
5651

@@ -66,10 +61,6 @@ type Config struct {
6661
UnpackRootfs bool `json:"unpack_rootfs" envconfig:"optional"`
6762
}
6863

69-
func (cfg Config) ImageName() string {
70-
return cfg.Repository + ":" + cfg.Tag
71-
}
72-
7364
// ImageMetadata is the schema written to manifest.json when producing the
7465
// legacy Concourse image format (rootfs/..., metadata.json).
7566
type ImageMetadata struct {

0 commit comments

Comments
 (0)