Skip to content

Commit

Permalink
manifest push using yaml file
Browse files Browse the repository at this point in the history
Instead of:
manifest create list image1 image2
manifest annotate list image1
manifest push list

You can do:
manifiest push --filename myfile.yaml

Signed-off-by: Christy Norman Perez <christy@linux.vnet.ibm.com>
  • Loading branch information
clnperez committed Jun 1, 2018
1 parent 31d99ba commit 4c2bba3
Show file tree
Hide file tree
Showing 10 changed files with 366 additions and 38 deletions.
136 changes: 130 additions & 6 deletions cli/command/manifest/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"

"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
Expand All @@ -14,14 +16,17 @@ import (
"github.com/docker/distribution/manifest/schema2"
"github.com/docker/distribution/reference"
"github.com/docker/docker/registry"

"github.com/pkg/errors"
"github.com/spf13/cobra"
yaml "gopkg.in/yaml.v2"
)

type pushOpts struct {
insecure bool
purge bool
target string
file string
}

type mountRequest struct {
Expand All @@ -42,32 +47,56 @@ type pushRequest struct {
insecure bool
}

type yamlManifestList struct {
Image string
Manifests []yamlManifest
}

type yamlManifest struct {
Image string
Platform manifestlist.PlatformSpec
}

func newPushListCommand(dockerCli command.Cli) *cobra.Command {
opts := pushOpts{}

cmd := &cobra.Command{
Use: "push [OPTIONS] MANIFEST_LIST",
Use: "push [OPTIONS] [MANIFEST_LIST]",
Short: "Push a manifest list to a repository",
Args: cli.ExactArgs(1),
Args: cli.RequiresRangeArgs(0, 1),
RunE: func(cmd *cobra.Command, args []string) error {
opts.target = args[0]
if len(args) == 1 {
opts.target = args[0]
}
return runPush(dockerCli, opts)
},
}

flags := cmd.Flags()
flags.BoolVarP(&opts.purge, "purge", "p", false, "Remove the local manifest list after push")
flags.BoolVar(&opts.insecure, "insecure", false, "Allow push to an insecure registry")
flags.BoolVarP(&opts.purge, "purge", "p", false, "remove the local manifest list after push")
flags.BoolVar(&opts.insecure, "insecure", false, "allow push to an insecure registry")
flags.StringVar(&opts.file, "filename", "", "create, annotate, and push using a yaml file")
return cmd
}

func runPush(dockerCli command.Cli, opts pushOpts) error {

if opts.target == "" && opts.file == "" {
return errors.New("please specify either a file or local manifest name")
}

if opts.file != "" { // just pass opts??
return pushListFromYaml(dockerCli, opts.file, opts.insecure)
}

return pushListFromStore(dockerCli, opts)
}

func pushListFromStore(dockerCli command.Cli, opts pushOpts) error {
targetRef, err := normalizeReference(opts.target)
if err != nil {
return err
}

manifests, err := dockerCli.ManifestStore().GetList(targetRef)
if err != nil {
return err
Expand Down Expand Up @@ -271,3 +300,98 @@ func mountBlobs(ctx context.Context, client registryclient.RegistryClient, ref r
}
return nil
}

func pushListFromYaml(dockerCli command.Cli, file string, insecure_registry bool) error {

yamlInput, err := getYamlManifestList(dockerCli, file)
if err != nil {
return err
}
targetRef, err := normalizeReference(yamlInput.Image)
if err != nil {
return err
}

ctx := context.Background()
var manifests []types.ImageManifest
for _, manifest := range yamlInput.Manifests {
imageRef, err := normalizeReference(manifest.Image)
if err != nil {
return err
}
im, err := dockerCli.RegistryClient(insecure_registry).GetManifest(ctx, imageRef)
if err != nil {
return err
}
addYamlAnnotations(&im, manifest)
manifests = append(manifests, im)
}
if len(manifests) == 0 { // @TODO: move up
return errors.Errorf("no manifests specified in file input")
}

pushRequest, err := buildPushRequest(manifests, targetRef, insecure_registry)
if err != nil {
return err
}
if err := pushList(ctx, dockerCli, pushRequest); err != nil {
return err
}
return nil

}

func addYamlAnnotations(manifest *types.ImageManifest, ym yamlManifest) {

/*
@TODO: Delete me. Here for reference.
type ImageManifest struct {
Ref *SerializableNamed
Digest digest.Digest
SchemaV2Manifest *schema2.DeserializedManifest `json:",omitempty"`
Platform manifestlist.PlatformSpec
}
type yamlManifest struct {
Image string
Platform manifestlist.PlatformSpec
}
return {
target: yaml.Image,
image: manifest.Image,
variant: manifest.Platform.Variant,
os: manifest.Platform.OS,
arch: manifest.Platform.Architecture,
osFeatures: manifest.Platform.OSFeatures,
}
*/

if ym.Platform.Variant != "" {
manifest.Platform.Variant = ym.Platform.Variant
}
if ym.Platform.OS != "" {
manifest.Platform.OS = ym.Platform.OS
}
if ym.Platform.Architecture != "" {
manifest.Platform.Architecture = ym.Platform.Architecture
}
if len(ym.Platform.OSFeatures) != 0 {
manifest.Platform.OSFeatures = ym.Platform.OSFeatures
}
}

func getYamlManifestList(dockerCli command.Cli, yamlFile string) (yamlManifestList, error) {
var yamlInput yamlManifestList

if _, err := os.Stat(yamlFile); err != nil {
return yamlManifestList{}, err
}
yamlBuf, err := ioutil.ReadFile(yamlFile)
if err != nil {
return yamlManifestList{}, err
}
if err := yaml.UnmarshalStrict(yamlBuf, &yamlInput); err != nil {
return yamlManifestList{}, err
}
return yamlInput, nil
}
2 changes: 1 addition & 1 deletion vendor.conf
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ golang.org/x/time a4bde12657593d5e90d0533a3e4fd95e635124cb
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
google.golang.org/grpc v1.3.0
gopkg.in/inf.v0 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
gopkg.in/yaml.v2 4c78c975fe7c825c6d1466c42be594d1d6f3aba6
gopkg.in/yaml.v2 d670f9405373e636a5a2765eea47fac0c9bc91a4
k8s.io/api kubernetes-1.8.2
k8s.io/apimachinery kubernetes-1.8.2
k8s.io/client-go kubernetes-1.8.2
Expand Down
Loading

0 comments on commit 4c2bba3

Please sign in to comment.