Skip to content

Commit

Permalink
add oci support (#6)
Browse files Browse the repository at this point in the history
add required HTTP request headers to support OCI manifests and image indices

Signed-off-by: Stefan Hoffmeister <stefan@hoffmeister.biz>
  • Loading branch information
DizTortion committed Oct 18, 2022
1 parent 9b57d8c commit 43ed80d
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 5 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/generate-test-images.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: generate-test-images
on:
workflow_dispatch:
jobs:
generate-test-images:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Log in to ghcr.io
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- run: make generate-test-images
6 changes: 6 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,10 @@ jobs:
with:
go-version: 1.17.x
- uses: actions/checkout@v2
- name: Log in to ghcr.io
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- run: make test
35 changes: 35 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,38 @@ build:

release:
goreleaser release --rm-dist


generate-test-images: REPOSITORY=ghcr.io/airfocusio/git-ops-update-test
generate-test-images:
# docker v2 manifest
echo "FROM scratch\nLABEL version=0.0.1\nLABEL foo=bar" | podman build -f - --format=docker --timestamp=0 --no-cache --tag $(REPOSITORY):docker-v2-manifest-v0.0.1
echo "FROM scratch\nLABEL version=0.0.2\nLABEL foo=bar" | podman build -f - --format=docker --timestamp=0 --no-cache --tag $(REPOSITORY):docker-v2-manifest-v0.0.2
podman push $(REPOSITORY):docker-v2-manifest-v0.0.1
podman push $(REPOSITORY):docker-v2-manifest-v0.0.2
podman image rm $(REPOSITORY):docker-v2-manifest-v0.0.1
podman image rm $(REPOSITORY):docker-v2-manifest-v0.0.2

# oci v1 manifest
echo "FROM scratch\nLABEL version=0.0.1\nLABEL foo=bar" | podman build -f - --format=oci --timestamp=0 --no-cache --tag $(REPOSITORY):oci-v1-manifest-v0.0.1
echo "FROM scratch\nLABEL version=0.0.2\nLABEL foo=bar" | podman build -f - --format=oci --timestamp=0 --no-cache --tag $(REPOSITORY):oci-v1-manifest-v0.0.2
podman push $(REPOSITORY):oci-v1-manifest-v0.0.1
podman push $(REPOSITORY):oci-v1-manifest-v0.0.2
podman image rm $(REPOSITORY):oci-v1-manifest-v0.0.1
podman image rm $(REPOSITORY):oci-v1-manifest-v0.0.2

# docker v2 manifest list
echo "FROM scratch\nLABEL version=0.0.1\nLABEL foo=bar" | podman build -f - --no-cache --timestamp=0 --platform=linux/amd64 --manifest $(REPOSITORY):docker-v2-manifest-list-v0.0.1
echo "FROM scratch\nLABEL version=0.0.2\nLABEL foo=bar" | podman build -f - --no-cache --timestamp=0 --platform=linux/amd64 --manifest $(REPOSITORY):docker-v2-manifest-list-v0.0.2
podman manifest push --format=v2s2 --all $(REPOSITORY):docker-v2-manifest-list-v0.0.1 docker://$(REPOSITORY):docker-v2-manifest-list-v0.0.1
podman manifest push --format=v2s2 --all $(REPOSITORY):docker-v2-manifest-list-v0.0.2 docker://$(REPOSITORY):docker-v2-manifest-list-v0.0.2
podman manifest rm $(REPOSITORY):docker-v2-manifest-list-v0.0.1
podman manifest rm $(REPOSITORY):docker-v2-manifest-list-v0.0.2

# oci v1 image index
echo "FROM scratch\nLABEL version=0.0.1\nLABEL foo=bar" | podman build -f - --no-cache --timestamp=0 --platform=linux/amd64 --manifest $(REPOSITORY):oci-v1-image-index-v0.0.1
echo "FROM scratch\nLABEL version=0.0.2\nLABEL foo=bar" | podman build -f - --no-cache --timestamp=0 --platform=linux/amd64 --manifest $(REPOSITORY):oci-v1-image-index-v0.0.2
podman manifest push --format=oci --all $(REPOSITORY):oci-v1-image-index-v0.0.1 docker://$(REPOSITORY):oci-v1-image-index-v0.0.1
podman manifest push --format=oci --all $(REPOSITORY):oci-v1-image-index-v0.0.2 docker://$(REPOSITORY):oci-v1-image-index-v0.0.2
podman manifest rm $(REPOSITORY):oci-v1-image-index-v0.0.1
podman manifest rm $(REPOSITORY):oci-v1-image-index-v0.0.2
9 changes: 4 additions & 5 deletions internal/registry_docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func (r DockerRegistry) RetrieveMetadata(repository string, version string) (map
if err != nil {
return nil, err
}
req.Header.Add("Accept", "application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.docker.distribution.manifest.v2+json")
req.Header.Add("Accept", "application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.index.v1+json, application/vnd.oci.image.manifest.v1+json")
resp, err := client.Do(req)
if err != nil {
return nil, err
Expand All @@ -117,14 +117,14 @@ func (r DockerRegistry) RetrieveMetadata(repository string, version string) (map

manifests := []manifestJson{}

if resp.Header.Get("content-type") == "application/vnd.docker.distribution.manifest.v2+json" {
if resp.Header.Get("content-type") == "application/vnd.docker.distribution.manifest.v2+json" || resp.Header.Get("content-type") == "application/vnd.oci.image.manifest.v1+json" {
var manifest manifestJson
err = json.Unmarshal(respBody, &manifest)
if err != nil {
return nil, err
}
manifests = append(manifests, manifest)
} else if resp.Header.Get("content-type") == "application/vnd.docker.distribution.manifest.list.v2+json" {
} else if resp.Header.Get("content-type") == "application/vnd.docker.distribution.manifest.list.v2+json" || resp.Header.Get("content-type") == "application/vnd.oci.image.index.v1+json" {
var manifestList manifestListJson
err = json.Unmarshal(respBody, &manifestList)
if err != nil {
Expand All @@ -135,7 +135,7 @@ func (r DockerRegistry) RetrieveMetadata(repository string, version string) (map
if err != nil {
return nil, err
}
req2.Header.Add("Accept", "application/vnd.docker.distribution.manifest.v2+json")
req2.Header.Add("Accept", "application/vnd.docker.distribution.manifest.v2+json, application/vnd.oci.image.manifest.v1+json")
resp2, err := client.Do(req2)
if err != nil {
return nil, err
Expand Down Expand Up @@ -178,7 +178,6 @@ func (r DockerRegistry) RetrieveMetadata(repository string, version string) (map
if err != nil {
return nil, err
}

for k, v := range config.Config.Labels {
result[k] = v
}
Expand Down
40 changes: 40 additions & 0 deletions internal/registry_docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,43 @@ func TestDockerRetrieveMetadata(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, map[string]string{}, output2)
}

func TestDockerRetrieveDockerV2ManifestMetadata(t *testing.T) {
reg := DockerRegistry{
Url: "https://ghcr.io",
}
output, err := reg.RetrieveMetadata("airfocusio/git-ops-update-test", "docker-v2-manifest-v0.0.1")
assert.NoError(t, err)
assert.Contains(t, output, "foo")
assert.Equal(t, "bar", output["foo"])
}

func TestDockerRetrieveDockerV2ManifestListMetadata(t *testing.T) {
reg := DockerRegistry{
Url: "https://ghcr.io",
}
output, err := reg.RetrieveMetadata("airfocusio/git-ops-update-test", "docker-v2-manifest-list-v0.0.1")
assert.NoError(t, err)
assert.Contains(t, output, "foo")
assert.Equal(t, "bar", output["foo"])
}

func TestDockerRetrieveOciV1ManifestMetadata(t *testing.T) {
reg := DockerRegistry{
Url: "https://ghcr.io",
}
output, err := reg.RetrieveMetadata("airfocusio/git-ops-update-test", "oci-v1-manifest-v0.0.1")
assert.NoError(t, err)
assert.Contains(t, output, "foo")
assert.Equal(t, "bar", output["foo"])
}

func TestDockerRetrieveOciV1ImageIndexMetadata(t *testing.T) {
reg := DockerRegistry{
Url: "https://ghcr.io",
}
output, err := reg.RetrieveMetadata("airfocusio/git-ops-update-test", "oci-v1-image-index-v0.0.1")
assert.NoError(t, err)
assert.Contains(t, output, "foo")
assert.Equal(t, "bar", output["foo"])
}

0 comments on commit 43ed80d

Please sign in to comment.