github.com/dctrud/umoci@v0.4.3-0.20191016193643-05a1d37de015/cmd/umoci/stat.go (about) 1 /* 2 * umoci: Umoci Modifies Open Containers' Images 3 * Copyright (C) 2016, 2017, 2018 SUSE LLC. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package main 19 20 import ( 21 "encoding/json" 22 "fmt" 23 "os" 24 25 "github.com/openSUSE/umoci" 26 "github.com/openSUSE/umoci/oci/cas/dir" 27 "github.com/openSUSE/umoci/oci/casext" 28 ispec "github.com/opencontainers/image-spec/specs-go/v1" 29 "github.com/pkg/errors" 30 "github.com/urfave/cli" 31 "golang.org/x/net/context" 32 ) 33 34 var statCommand = cli.Command{ 35 Name: "stat", 36 Usage: "displays status information of an image manifest", 37 ArgsUsage: `--image <image-path>[:<tag>] 38 39 Where "<image-path>" is the path to the OCI image, and "<tag>" is the name of 40 the tagged image to stat. 41 42 WARNING: Do not depend on the output of this tool unless you're using --json. 43 The intention of the default formatting of this tool is that it is easy for 44 humans to read, and might change in future versions.`, 45 46 // stat gives information about a manifest. 47 Category: "image", 48 49 Flags: []cli.Flag{ 50 cli.BoolFlag{ 51 Name: "json", 52 Usage: "output the stat information as a JSON encoded blob", 53 }, 54 }, 55 56 Action: stat, 57 } 58 59 func stat(ctx *cli.Context) error { 60 imagePath := ctx.App.Metadata["--image-path"].(string) 61 tagName := ctx.App.Metadata["--image-tag"].(string) 62 63 // Get a reference to the CAS. 64 engine, err := dir.Open(imagePath) 65 if err != nil { 66 return errors.Wrap(err, "open CAS") 67 } 68 engineExt := casext.NewEngine(engine) 69 defer engine.Close() 70 71 manifestDescriptorPaths, err := engineExt.ResolveReference(context.Background(), tagName) 72 if err != nil { 73 return errors.Wrap(err, "get descriptor") 74 } 75 if len(manifestDescriptorPaths) == 0 { 76 return errors.Errorf("tag not found: %s", tagName) 77 } 78 if len(manifestDescriptorPaths) != 1 { 79 // TODO: Handle this more nicely. 80 return errors.Errorf("tag is ambiguous: %s", tagName) 81 } 82 manifestDescriptor := manifestDescriptorPaths[0].Descriptor() 83 84 // FIXME: Implement support for manifest lists. 85 if manifestDescriptor.MediaType != ispec.MediaTypeImageManifest { 86 return errors.Wrap(fmt.Errorf("descriptor does not point to ispec.MediaTypeImageManifest: not implemented: %s", manifestDescriptor.MediaType), "invalid saved from descriptor") 87 } 88 89 // Get stat information. 90 ms, err := umoci.Stat(context.Background(), engineExt, manifestDescriptor) 91 if err != nil { 92 return errors.Wrap(err, "stat") 93 } 94 95 // Output the stat information. 96 if ctx.Bool("json") { 97 // Use JSON. 98 if err := json.NewEncoder(os.Stdout).Encode(ms); err != nil { 99 return errors.Wrap(err, "encoding stat") 100 } 101 } else { 102 if err := ms.Format(os.Stdout); err != nil { 103 return errors.Wrap(err, "format stat") 104 } 105 } 106 107 return nil 108 }