-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
enable releasing and deploying OCI artefacts
- Loading branch information
Showing
7 changed files
with
189 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package main | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"fmt" | ||
"io" | ||
"os/exec" | ||
"strings" | ||
|
||
"github.com/function61/deployer/pkg/oci" | ||
"github.com/function61/gokit/jsonfile" | ||
) | ||
|
||
type ociArtefactDownloader struct { | ||
imageRef string | ||
imageRefWithoutTag string | ||
manifest oci.Manifest | ||
} | ||
|
||
func newOCIArtefactDownloader(ctx context.Context, imageRef string) (artefactDownloader, error) { | ||
withErr := func(err error) (artefactDownloader, error) { | ||
return nil, fmt.Errorf("newOCIArtefactDownloader: %w", err) | ||
} | ||
|
||
orasFetchOutput := &bytes.Buffer{} | ||
stderr := &bytes.Buffer{} | ||
|
||
orasFetch := exec.CommandContext(ctx, "oras", "manifest", "fetch", imageRef) | ||
orasFetch.Stdout = orasFetchOutput | ||
orasFetch.Stderr = stderr | ||
|
||
if err := orasFetch.Run(); err != nil { | ||
return withErr(fmt.Errorf("oras manifest fetch %s: %w: stdout[%s] stderr[%s]", imageRef, err, orasFetchOutput.String(), stderr.String())) | ||
} | ||
|
||
manifest := oci.Manifest{} | ||
if err := jsonfile.Unmarshal(orasFetchOutput, &manifest, false); err != nil { | ||
return withErr(err) | ||
} | ||
|
||
// "redis:latest" => ["redis", "latest"] | ||
imageRefWithoutTag := strings.Split(imageRef, ":") | ||
if len(imageRefWithoutTag) != 2 { | ||
return withErr(fmt.Errorf("expected imageRef to be <something>:<tag>; got %s", imageRef)) | ||
} | ||
|
||
return &ociArtefactDownloader{imageRef, imageRefWithoutTag[0], manifest}, nil | ||
} | ||
|
||
func (o *ociArtefactDownloader) DownloadArtefact(ctx context.Context, filename string) (io.ReadCloser, error) { | ||
withErr := func(err error) (io.ReadCloser, error) { | ||
return nil, fmt.Errorf("ociArtefactDownloader.DownloadArtefact: %w", err) | ||
} | ||
|
||
layer, found := func() (*oci.Layer, bool) { | ||
for _, layer := range o.manifest.Layers { | ||
if layer.Annotations["org.opencontainers.image.title"] == filename { | ||
return &layer, true | ||
} | ||
} | ||
|
||
return nil, false | ||
}() | ||
if !found { | ||
return withErr(fmt.Errorf("%s not found from manifest of %s", filename, o.imageRef)) | ||
} | ||
|
||
// "redis" => "redis@sha256:..." | ||
blobRef := o.imageRefWithoutTag + "@" + layer.Digest | ||
|
||
// blobReader, blobWriter := io.Pipe() | ||
|
||
blobReader := &bytes.Buffer{} | ||
|
||
orasBlobFetch := exec.CommandContext(ctx, "oras", "blob", "fetch", "--output=-", blobRef) | ||
orasBlobFetch.Stdout = blobReader | ||
// orasBlobFetch.Stdout = blobWriter | ||
|
||
if err := orasBlobFetch.Run(); err != nil { | ||
return withErr(err) | ||
} | ||
|
||
return io.NopCloser(blobReader), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package main | ||
|
||
// OCI image releaser | ||
|
||
import ( | ||
"context" | ||
"log" | ||
"time" | ||
|
||
"github.com/function61/deployer/pkg/ddomain" | ||
"github.com/function61/deployer/pkg/dstate" | ||
"github.com/function61/deployer/pkg/githubminiclient" | ||
"github.com/function61/eventhorizon/pkg/ehevent" | ||
"github.com/function61/gokit/cryptorandombytes" | ||
) | ||
|
||
func createOCIImageRelease( | ||
ctx context.Context, | ||
imageRef string, | ||
owner string, | ||
repoName string, | ||
releaseName string, | ||
revisionId string, | ||
logger *log.Logger, | ||
) error { | ||
repo := githubminiclient.NewRepoRef(owner, repoName) | ||
|
||
app, err := mkApp(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if app.State.HasRevisionId(revisionId) { // should not be considered an error | ||
logger.Printf("WARN: already have revision %s", revisionId) | ||
return nil | ||
} | ||
|
||
releaseCreated := ddomain.NewReleaseCreated( | ||
cryptorandombytes.Base64UrlWithoutLeadingDash(4), | ||
ownerSlashRepo(repo), // function61/coolproduct | ||
releaseName, | ||
revisionId, | ||
"docker://"+imageRef, | ||
"", | ||
ehevent.MetaSystemUser(time.Now())) // TODO: time of commit? | ||
|
||
_, err = app.Writer.Append( | ||
ctx, | ||
app.TenantCtx.Tenant.Stream(dstate.Stream), | ||
[]string{ehevent.Serialize(releaseCreated)}) | ||
return err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package oci | ||
|
||
type Manifest struct { | ||
SchemaVersion int `json:"schemaVersion"` | ||
MediaType string `json:"mediaType"` | ||
ArtifactType string `json:"artifactType"` | ||
Config Config `json:"config"` | ||
Layers []Layer `json:"layers"` | ||
Annotations map[string]string `json:"annotations"` | ||
} | ||
|
||
type Config struct { | ||
MediaType string `json:"mediaType"` | ||
Digest string `json:"digest"` | ||
Size int `json:"size"` | ||
Data string `json:"data"` | ||
} | ||
|
||
type Layer struct { | ||
MediaType string `json:"mediaType"` | ||
Digest string `json:"digest"` | ||
Size int `json:"size"` | ||
Annotations map[string]string `json:"annotations"` | ||
} |