mirror of https://github.com/docker/compose.git
implement publish
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
805541be9d
commit
5ca35c88be
|
@ -18,24 +18,136 @@ package compose
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/compose-spec/compose-go/types"
|
"github.com/compose-spec/compose-go/types"
|
||||||
"github.com/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
|
"github.com/docker/buildx/util/imagetools"
|
||||||
"github.com/docker/compose/v2/pkg/api"
|
"github.com/docker/compose/v2/pkg/api"
|
||||||
|
"github.com/docker/compose/v2/pkg/progress"
|
||||||
|
"github.com/opencontainers/go-digest"
|
||||||
|
"github.com/opencontainers/image-spec/specs-go"
|
||||||
|
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *composeService) Publish(ctx context.Context, project *types.Project, repository string, options api.PublishOptions) error {
|
func (s *composeService) Publish(ctx context.Context, project *types.Project, repository string, options api.PublishOptions) error {
|
||||||
|
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
|
||||||
|
return s.publish(ctx, project, repository, options)
|
||||||
|
}, s.stdinfo(), "Publishing")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *composeService) publish(ctx context.Context, project *types.Project, repository string, options api.PublishOptions) error {
|
||||||
err := s.Push(ctx, project, api.PushOptions{})
|
err := s.Push(ctx, project, api.PushOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = reference.ParseDockerRef(repository)
|
w := progress.ContextWriter(ctx)
|
||||||
|
|
||||||
|
named, err := reference.ParseDockerRef(repository)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO publish project.ComposeFiles
|
resolver := imagetools.New(imagetools.Opt{
|
||||||
|
Auth: s.configFile(),
|
||||||
|
})
|
||||||
|
|
||||||
return api.ErrNotImplemented
|
var layers []v1.Descriptor
|
||||||
|
for _, file := range project.ComposeFiles {
|
||||||
|
f, err := os.ReadFile(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Event(progress.Event{
|
||||||
|
ID: file,
|
||||||
|
Text: "publishing",
|
||||||
|
Status: progress.Working,
|
||||||
|
})
|
||||||
|
layer := v1.Descriptor{
|
||||||
|
MediaType: "application/vnd.docker.compose.file+yaml",
|
||||||
|
Digest: digest.FromString(string(f)),
|
||||||
|
Size: int64(len(f)),
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"com.docker.compose": api.ComposeVersion,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
layers = append(layers, layer)
|
||||||
|
err = resolver.Push(ctx, named, layer, f)
|
||||||
|
if err != nil {
|
||||||
|
w.Event(progress.Event{
|
||||||
|
ID: file,
|
||||||
|
Text: "publishing",
|
||||||
|
Status: progress.Error,
|
||||||
|
})
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Event(progress.Event{
|
||||||
|
ID: file,
|
||||||
|
Text: "published",
|
||||||
|
Status: progress.Done,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
emptyConfig, err := json.Marshal(v1.ImageConfig{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
configDescriptor := v1.Descriptor{
|
||||||
|
MediaType: "application/vnd.docker.compose.project",
|
||||||
|
Digest: digest.FromBytes(emptyConfig),
|
||||||
|
Size: int64(len(emptyConfig)),
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"com.docker.compose.version": api.ComposeVersion,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
err = resolver.Push(ctx, named, configDescriptor, emptyConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
imageManifest, err := json.Marshal(v1.Manifest{
|
||||||
|
Versioned: specs.Versioned{SchemaVersion: 2},
|
||||||
|
MediaType: v1.MediaTypeImageManifest,
|
||||||
|
ArtifactType: "application/vnd.docker.compose.project",
|
||||||
|
Config: configDescriptor,
|
||||||
|
Layers: layers,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Event(progress.Event{
|
||||||
|
ID: repository,
|
||||||
|
Text: "publishing",
|
||||||
|
Status: progress.Working,
|
||||||
|
})
|
||||||
|
|
||||||
|
err = resolver.Push(ctx, named, v1.Descriptor{
|
||||||
|
MediaType: v1.MediaTypeImageManifest,
|
||||||
|
Digest: digest.FromString(string(imageManifest)),
|
||||||
|
Size: int64(len(imageManifest)),
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"com.docker.compose.version": api.ComposeVersion,
|
||||||
|
},
|
||||||
|
ArtifactType: "application/vnd.docker.compose.project",
|
||||||
|
}, imageManifest)
|
||||||
|
if err != nil {
|
||||||
|
w.Event(progress.Event{
|
||||||
|
ID: repository,
|
||||||
|
Text: "publishing",
|
||||||
|
Status: progress.Error,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
w.Event(progress.Event{
|
||||||
|
ID: repository,
|
||||||
|
Text: "published",
|
||||||
|
Status: progress.Done,
|
||||||
|
})
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ type ociRemoteLoader struct {
|
||||||
offline bool
|
offline bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const prefix = "oci:"
|
const prefix = "oci://"
|
||||||
|
|
||||||
func (g ociRemoteLoader) Accept(path string) bool {
|
func (g ociRemoteLoader) Accept(path string) bool {
|
||||||
return strings.HasPrefix(path, prefix)
|
return strings.HasPrefix(path, prefix)
|
||||||
|
@ -117,6 +117,11 @@ func (g ociRemoteLoader) Load(ctx context.Context, path string) (string, error)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if descriptor.Config.MediaType != "application/vnd.docker.compose.project" {
|
||||||
|
return "", fmt.Errorf("%s is not a compose project OCI artifact, but %s", ref.String(), descriptor.Config.MediaType)
|
||||||
|
}
|
||||||
|
|
||||||
for i, layer := range descriptor.Layers {
|
for i, layer := range descriptor.Layers {
|
||||||
digested, err := reference.WithDigest(ref, layer.Digest)
|
digested, err := reference.WithDigest(ref, layer.Digest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue