1 // Copyright 2018 Google LLC All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package crane 16 17 import ( 18 "io" 19 20 v1 "github.com/google/go-containerregistry/pkg/v1" 21 "github.com/google/go-containerregistry/pkg/v1/mutate" 22 ) 23 24 // Export writes the filesystem contents (as a tarball) of img to w. 25 // If img has a single layer, just write the (uncompressed) contents to w so 26 // that this "just works" for images that just wrap a single blob. 27 func Export(img v1.Image, w io.Writer) error { 28 layers, err := img.Layers() 29 if err != nil { 30 return err 31 } 32 if len(layers) == 1 { 33 // If it's a single layer... 34 l := layers[0] 35 mt, err := l.MediaType() 36 if err != nil { 37 return err 38 } 39 40 if !mt.IsLayer() { 41 // ...and isn't an OCI mediaType, we don't have to flatten it. 42 // This lets export work for single layer, non-tarball images. 43 rc, err := l.Uncompressed() 44 if err != nil { 45 return err 46 } 47 _, err = io.Copy(w, rc) 48 return err 49 } 50 } 51 fs := mutate.Extract(img) 52 _, err = io.Copy(w, fs) 53 return err 54 } 55