// Copyright 2018 Google LLC All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package crane import ( "archive/tar" "bytes" "io" "sort" v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/google/go-containerregistry/pkg/v1/empty" "github.com/google/go-containerregistry/pkg/v1/mutate" "github.com/google/go-containerregistry/pkg/v1/tarball" ) // Layer creates a layer from a single file map. These layers are reproducible and consistent. // A filemap is a path -> file content map representing a file system. func Layer(filemap map[string][]byte) (v1.Layer, error) { b := &bytes.Buffer{} w := tar.NewWriter(b) fn := []string{} for f := range filemap { fn = append(fn, f) } sort.Strings(fn) for _, f := range fn { c := filemap[f] if err := w.WriteHeader(&tar.Header{ Name: f, Size: int64(len(c)), }); err != nil { return nil, err } if _, err := w.Write(c); err != nil { return nil, err } } if err := w.Close(); err != nil { return nil, err } // Return a new copy of the buffer each time it's opened. return tarball.LayerFromOpener(func() (io.ReadCloser, error) { return io.NopCloser(bytes.NewBuffer(b.Bytes())), nil }) } // Image creates a image with the given filemaps as its contents. These images are reproducible and consistent. // A filemap is a path -> file content map representing a file system. func Image(filemap map[string][]byte) (v1.Image, error) { y, err := Layer(filemap) if err != nil { return nil, err } return mutate.AppendLayers(empty.Image, y) }