Skip to content

Commit d48bfc1

Browse files
authored
fix the index append (#156)
the index append introduced in #155 created a valid index but didn't properly append the image contents to it. instead it was simply appending an index manifest to the index 🤦 this PR fixes that and adds another test to catch it (I think?). ideally I'd like the test to push up a platform specific image(s) but I can't figure out how to do that with `random.Image`. I've at least tested this locally and it appears to be generating a proper index: ``` { "schemaVersion": 2, "mediaType": "application/vnd.oci.image.index.v1+json", "manifests": [ { "mediaType": "application/vnd.oci.image.manifest.v1+json", "size": 562, "digest": "sha256:c5316b34c4564257960ce18e73b6f421cae0e67c5e3cf18a97cd755947c071c4", "platform": { "architecture": "amd64", "os": "linux" } }, { "mediaType": "application/vnd.oci.image.manifest.v1+json", "size": 561, "digest": "sha256:dad0b65b0a055bcee31b5888d5435c5f73e25785f0e92be473996fb060bb62eb", "platform": { "architecture": "arm64", "os": "linux" } } ] } ```
1 parent f0a5474 commit d48bfc1

File tree

2 files changed

+83
-8
lines changed

2 files changed

+83
-8
lines changed

internal/provider/append_resource.go

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
"github.com/google/go-containerregistry/pkg/name"
1111
v1 "github.com/google/go-containerregistry/pkg/v1"
12+
"github.com/google/go-containerregistry/pkg/v1/empty"
1213
"github.com/google/go-containerregistry/pkg/v1/mutate"
1314
"github.com/google/go-containerregistry/pkg/v1/remote"
1415
"github.com/google/go-containerregistry/pkg/v1/tarball"
@@ -266,9 +267,11 @@ func (r *AppendResource) doAppend(ctx context.Context, data *AppendResourceModel
266267
return nil, []diag.Diagnostic{diag.NewErrorDiagnostic("Unable to read image index manifest", fmt.Sprintf("Unable to read image index manifest for ref %q, got error: %s", data.BaseImage.ValueString(), err))}
267268
}
268269

269-
// get the image for each platform
270-
for _, p := range baseimf.Manifests {
271-
baseimg, err := baseidx.Image(p.Digest)
270+
var idx v1.ImageIndex = empty.Index
271+
272+
// append to each manifest in the index
273+
for _, manifest := range baseimf.Manifests {
274+
baseimg, err := baseidx.Image(manifest.Digest)
272275
if err != nil {
273276
return nil, []diag.Diagnostic{diag.NewErrorDiagnostic("Unable to load image", fmt.Sprintf("Unable to load image for ref %q, got error: %s", data.BaseImage.ValueString(), err))}
274277
}
@@ -278,17 +281,36 @@ func (r *AppendResource) doAppend(ctx context.Context, data *AppendResourceModel
278281
return nil, []diag.Diagnostic{diag.NewErrorDiagnostic("Unable to append layers", fmt.Sprintf("Unable to append layers, got error: %s", err))}
279282
}
280283

281-
baseidx = mutate.AppendManifests(baseidx, mutate.IndexAddendum{Add: img, Descriptor: p})
282-
283-
dig, err := baseidx.Digest()
284+
imgdig, err := img.Digest()
284285
if err != nil {
285286
return nil, []diag.Diagnostic{diag.NewErrorDiagnostic("Unable to get image digest", fmt.Sprintf("Unable to get image digest, got error: %s", err))}
286287
}
287288

288-
d = baseref.Context().Digest(dig.String())
289-
if err := remote.WriteIndex(d, baseidx, r.popts.withContext(ctx)...); err != nil {
289+
if err := remote.Write(baseref.Context().Digest(imgdig.String()), img, ropts...); err != nil {
290290
return nil, []diag.Diagnostic{diag.NewErrorDiagnostic("Unable to push image", fmt.Sprintf("Unable to push image, got error: %s", err))}
291291
}
292+
293+
// Update the index with the new image
294+
idx = mutate.AppendManifests(idx, mutate.IndexAddendum{
295+
Add: img,
296+
Descriptor: v1.Descriptor{
297+
MediaType: manifest.MediaType,
298+
URLs: manifest.URLs,
299+
Annotations: manifest.Annotations,
300+
Platform: manifest.Platform,
301+
ArtifactType: manifest.ArtifactType,
302+
},
303+
})
304+
}
305+
306+
dig, err := idx.Digest()
307+
if err != nil {
308+
return nil, []diag.Diagnostic{diag.NewErrorDiagnostic("Unable to get index digest", fmt.Sprintf("Unable to get index digest, got error: %s", err))}
309+
}
310+
311+
d = baseref.Context().Digest(dig.String())
312+
if err := remote.WriteIndex(d, idx, ropts...); err != nil {
313+
return nil, []diag.Diagnostic{diag.NewErrorDiagnostic("Unable to push index", fmt.Sprintf("Unable to push index, got error: %s", err))}
292314
}
293315

294316
} else if desc.MediaType.IsImage() {

internal/provider/append_resource_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import (
88
ocitesting "github.com/chainguard-dev/terraform-provider-oci/testing"
99
"github.com/google/go-containerregistry/pkg/crane"
1010
"github.com/google/go-containerregistry/pkg/name"
11+
v1 "github.com/google/go-containerregistry/pkg/v1"
12+
"github.com/google/go-containerregistry/pkg/v1/empty"
13+
"github.com/google/go-containerregistry/pkg/v1/mutate"
1114
"github.com/google/go-containerregistry/pkg/v1/random"
1215
"github.com/google/go-containerregistry/pkg/v1/remote"
1316
"github.com/google/go-containerregistry/pkg/v1/validate"
@@ -138,4 +141,54 @@ func TestAccAppendResource(t *testing.T) {
138141
},
139142
},
140143
})
144+
145+
ref4 := repo.Tag("4")
146+
var idx2 v1.ImageIndex = empty.Index
147+
148+
idx2 = mutate.AppendManifests(idx2, mutate.IndexAddendum{Add: img1})
149+
idx2 = mutate.AppendManifests(idx2, mutate.IndexAddendum{Add: img1})
150+
151+
if err := remote.WriteIndex(ref4, idx2); err != nil {
152+
t.Fatalf("failed to write index: %v", err)
153+
}
154+
155+
resource.Test(t, resource.TestCase{
156+
PreCheck: func() { testAccPreCheck(t) },
157+
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
158+
Steps: []resource.TestStep{
159+
// Create and Read testing
160+
{
161+
Config: fmt.Sprintf(`
162+
resource "oci_append" "test" {
163+
base_image = %q
164+
layers = [{
165+
files = {
166+
"/usr/local/test.txt" = { contents = "hello world" }
167+
}
168+
}]
169+
}
170+
`, ref4),
171+
Check: resource.ComposeAggregateTestCheckFunc(
172+
resource.TestCheckResourceAttr("oci_append.test", "base_image", ref4.String()),
173+
resource.TestMatchResourceAttr("oci_append.test", "id", regexp.MustCompile(`/test@sha256:[0-9a-f]{64}$`)),
174+
resource.TestCheckFunc(func(s *terraform.State) error {
175+
rs := s.RootModule().Resources["oci_append.test"]
176+
ref, err := name.ParseReference(rs.Primary.Attributes["image_ref"])
177+
if err != nil {
178+
return fmt.Errorf("failed to parse reference: %v", err)
179+
}
180+
idx, err := remote.Index(ref)
181+
if err != nil {
182+
return fmt.Errorf("failed to pull index: %v", err)
183+
}
184+
if err := validate.Index(idx); err != nil {
185+
return fmt.Errorf("failed to validate index: %v", err)
186+
}
187+
188+
return nil
189+
}),
190+
),
191+
},
192+
},
193+
})
141194
}

0 commit comments

Comments
 (0)