diff --git a/Gopkg.lock b/Gopkg.lock index b2954b3..4b062bd 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -34,11 +34,10 @@ [[projects]] branch = "master" - digest = "1:68307cc2c794b04c44d6487d01755169f981f4f7b1b7994dafa299c94fcb2523" + digest = "1:4d735a4f0b7f0e98c6b60939bae9553ba801e40d324d3e8b70c95d05656b5cb1" name = "github.com/google/go-containerregistry" packages = [ "pkg/authn", - "pkg/ko/build", "pkg/name", "pkg/v1", "pkg/v1/empty", @@ -55,6 +54,14 @@ pruneopts = "UT" revision = "68537023cae86a3267a37354535baa614ad29924" +[[projects]] + digest = "1:dc103a2b0c588c87eaae0ba653b36c6bf79f0cd2d5914fa6d9e0fa2d7ee4219f" + name = "github.com/google/ko" + packages = ["pkg/build"] + pruneopts = "UT" + revision = "021e392d3a3d2c318c79f34c4dd15da2402afce9" + version = "v0.1" + [[projects]] digest = "1:e04cc716992a302cacf6d726409a05aa9546241998b24356d6dd0f01bc5a374e" name = "github.com/googleapis/gax-go" @@ -252,11 +259,12 @@ analyzer-version = 1 input-imports = [ "cloud.google.com/go/storage", - "github.com/google/go-containerregistry/pkg/ko/build", "github.com/google/go-containerregistry/pkg/name", "github.com/google/go-containerregistry/pkg/v1", "github.com/google/go-containerregistry/pkg/v1/random", "github.com/google/go-containerregistry/pkg/v1/remote", + "github.com/google/ko/pkg/build", + "google.golang.org/api/googleapi", ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/README.md b/README.md index d3b88fd..94eaf7e 100644 --- a/README.md +++ b/README.md @@ -11,14 +11,14 @@ bytes each. `docker pull kontain.me/ko/[import path]` serves an image containing a Go binary fetched using `go get` and built into a container image using -[`ko`](https://github.com/google/go-containerregistry/blob/master/cmd/ko/README.md). -For example, `docker pull -kontain.me/ko/github.com/google/go-containerregistry/cmd/ko` will fetch, build -and (eventually) serve a Docker image containing `ko` itself. _Koception!_ +[`ko`](https://github.com/google/ko/). For example, `docker pull +kontain.me/ko/github.com/google/ko/cmd/ko` will fetch, build and (eventually) +serve a Docker image containing `ko` itself. _Koception!_ The registry does not accept pushes and does not handle requests for images by digest. This is a silly hack and probably isn't stable. Don't rely on it for -anything serious. +anything serious. It could probably do a lot of smart things to be a lot +faster. ## How it works diff --git a/main.go b/main.go index eab134b..9a8f046 100644 --- a/main.go +++ b/main.go @@ -29,11 +29,11 @@ import ( "time" "cloud.google.com/go/storage" - "github.com/google/go-containerregistry/pkg/ko/build" "github.com/google/go-containerregistry/pkg/name" "github.com/google/go-containerregistry/pkg/v1" "github.com/google/go-containerregistry/pkg/v1/random" "github.com/google/go-containerregistry/pkg/v1/remote" + "github.com/google/ko/pkg/build" "google.golang.org/api/googleapi" ) diff --git a/vendor/github.com/google/ko/LICENSE b/vendor/github.com/google/ko/LICENSE new file mode 100644 index 0000000..7a4a3ea --- /dev/null +++ b/vendor/github.com/google/ko/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. \ No newline at end of file diff --git a/vendor/github.com/google/ko/cmd/ko/test/kodata/kenobi b/vendor/github.com/google/ko/cmd/ko/test/kodata/kenobi new file mode 120000 index 0000000..5d7eddc --- /dev/null +++ b/vendor/github.com/google/ko/cmd/ko/test/kodata/kenobi @@ -0,0 +1 @@ +../kenobi \ No newline at end of file diff --git a/vendor/github.com/google/go-containerregistry/pkg/ko/build/build.go b/vendor/github.com/google/ko/pkg/build/build.go similarity index 95% rename from vendor/github.com/google/go-containerregistry/pkg/ko/build/build.go rename to vendor/github.com/google/ko/pkg/build/build.go index 1ef4313..06c33c6 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/ko/build/build.go +++ b/vendor/github.com/google/ko/pkg/build/build.go @@ -15,7 +15,7 @@ package build import ( - "github.com/google/go-containerregistry/pkg/v1" + v1 "github.com/google/go-containerregistry/pkg/v1" ) // Interface abstracts different methods for turning a supported importpath diff --git a/vendor/github.com/google/go-containerregistry/pkg/ko/build/doc.go b/vendor/github.com/google/ko/pkg/build/doc.go similarity index 100% rename from vendor/github.com/google/go-containerregistry/pkg/ko/build/doc.go rename to vendor/github.com/google/ko/pkg/build/doc.go diff --git a/vendor/github.com/google/ko/pkg/build/future.go b/vendor/github.com/google/ko/pkg/build/future.go new file mode 100644 index 0000000..8f66fbb --- /dev/null +++ b/vendor/github.com/google/ko/pkg/build/future.go @@ -0,0 +1,75 @@ +// 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 build + +import ( + "sync" + + v1 "github.com/google/go-containerregistry/pkg/v1" +) + +func newFuture(work func() (v1.Image, error)) *future { + // Create a channel on which to send the result. + ch := make(chan *result) + // Initiate the actual work, sending its result + // along the above channel. + go func() { + img, err := work() + ch <- &result{img: img, err: err} + }() + // Return a future for the above work. Callers should + // call .Get() on this result (as many times as needed). + // One of these calls will receive the result, store it, + // and close the channel so that the rest of the callers + // can consume it. + return &future{ + promise: ch, + } +} + +type result struct { + img v1.Image + err error +} + +type future struct { + m sync.RWMutex + + result *result + promise chan *result +} + +// Get blocks on the result of the future. +func (f *future) Get() (v1.Image, error) { + // Block on the promise of a result until we get one. + result, ok := <-f.promise + if ok { + func() { + f.m.Lock() + defer f.m.Unlock() + // If we got the result, then store it so that + // others may access it. + f.result = result + // Close the promise channel so that others + // are signaled that the result is available. + close(f.promise) + }() + } + + f.m.RLock() + defer f.m.RUnlock() + + return f.result.img, f.result.err +} diff --git a/vendor/github.com/google/go-containerregistry/pkg/ko/build/gobuild.go b/vendor/github.com/google/ko/pkg/build/gobuild.go similarity index 81% rename from vendor/github.com/google/go-containerregistry/pkg/ko/build/gobuild.go rename to vendor/github.com/google/ko/pkg/build/gobuild.go index c2b31da..7300f5e 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/ko/build/gobuild.go +++ b/vendor/github.com/google/ko/pkg/build/gobuild.go @@ -26,13 +26,17 @@ import ( "os/exec" "path/filepath" - "github.com/google/go-containerregistry/pkg/v1" + v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/google/go-containerregistry/pkg/v1/mutate" "github.com/google/go-containerregistry/pkg/v1/tarball" ) -const appPath = "/ko-app" +const ( + appDir = "/ko-app" + defaultAppFilename = "ko-app" +) +// GetBase takes an importpath and returns a base v1.Image. type GetBase func(string) (v1.Image, error) type builder func(string) (string, error) @@ -42,6 +46,7 @@ type gobuild struct { build builder } +// Option is a functional option for NewGo. type Option func(*gobuildOpener) error type gobuildOpener struct { @@ -52,7 +57,7 @@ type gobuildOpener struct { func (gbo *gobuildOpener) Open() (Interface, error) { if gbo.getBase == nil { - return nil, errors.New("a way of providing base images must be specified, see build.WithBaseImages.") + return nil, errors.New("a way of providing base images must be specified, see build.WithBaseImages") } return &gobuild{ getBase: gbo.getBase, @@ -106,6 +111,7 @@ func build(ip string) (string, error) { cmd.Stderr = &output cmd.Stdout = &output + log.Printf("Building %s", ip) if err := cmd.Run(); err != nil { os.RemoveAll(tmpDir) log.Printf("Unexpected error running \"go build\": %v\n%v", err, output.String()) @@ -114,11 +120,53 @@ func build(ip string) (string, error) { return file, nil } -func tarBinary(binary string) (*bytes.Buffer, error) { +func appFilename(importpath string) string { + base := filepath.Base(importpath) + + // If we fail to determine a good name from the importpath then use a + // safe default. + if base == "." || base == string(filepath.Separator) { + return defaultAppFilename + } + + return base +} + +func tarAddDirectories(tw *tar.Writer, dir string) error { + if dir == "." || dir == string(filepath.Separator) { + return nil + } + + // Write parent directories first + if err := tarAddDirectories(tw, filepath.Dir(dir)); err != nil { + return err + } + + // write the directory header to the tarball archive + if err := tw.WriteHeader(&tar.Header{ + Name: dir, + Typeflag: tar.TypeDir, + // Use a fixed Mode, so that this isn't sensitive to the directory and umask + // under which it was created. Additionally, windows can only set 0222, + // 0444, or 0666, none of which are executable. + Mode: 0555, + }); err != nil { + return err + } + + return nil +} + +func tarBinary(name, binary string) (*bytes.Buffer, error) { buf := bytes.NewBuffer(nil) tw := tar.NewWriter(buf) defer tw.Close() + // write the parent directories to the tarball archive + if err := tarAddDirectories(tw, filepath.Dir(name)); err != nil { + return nil, err + } + file, err := os.Open(binary) if err != nil { return nil, err @@ -129,7 +177,7 @@ func tarBinary(binary string) (*bytes.Buffer, error) { return nil, err } header := &tar.Header{ - Name: appPath, + Name: name, Size: stat.Size(), Typeflag: tar.TypeReg, // Use a fixed Mode, so that this isn't sensitive to the directory and umask @@ -246,8 +294,10 @@ func (gb *gobuild) Build(s string) (v1.Image, error) { } layers = append(layers, dataLayer) + appPath := filepath.Join(appDir, appFilename(s)) + // Construct a tarball with the binary and produce a layer. - binaryLayerBuf, err := tarBinary(file) + binaryLayerBuf, err := tarBinary(appPath, file) if err != nil { return nil, err } diff --git a/vendor/github.com/google/go-containerregistry/pkg/ko/build/options.go b/vendor/github.com/google/ko/pkg/build/options.go similarity index 96% rename from vendor/github.com/google/go-containerregistry/pkg/ko/build/options.go rename to vendor/github.com/google/ko/pkg/build/options.go index 10f3ac1..df6eb40 100644 --- a/vendor/github.com/google/go-containerregistry/pkg/ko/build/options.go +++ b/vendor/github.com/google/ko/pkg/build/options.go @@ -15,7 +15,7 @@ package build import ( - "github.com/google/go-containerregistry/pkg/v1" + v1 "github.com/google/go-containerregistry/pkg/v1" ) // WithBaseImages is a functional option for overriding the base images diff --git a/vendor/github.com/google/ko/pkg/build/recorder.go b/vendor/github.com/google/ko/pkg/build/recorder.go new file mode 100644 index 0000000..3694eaa --- /dev/null +++ b/vendor/github.com/google/ko/pkg/build/recorder.go @@ -0,0 +1,46 @@ +// 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 build + +import ( + "sync" + + v1 "github.com/google/go-containerregistry/pkg/v1" +) + +// Recorder composes with another Interface to record the built import paths. +type Recorder struct { + m sync.Mutex + ImportPaths []string + Builder Interface +} + +// Recorder implements Interface +var _ Interface = (*Recorder)(nil) + +// IsSupportedReference implements Interface +func (r *Recorder) IsSupportedReference(ip string) bool { + return r.Builder.IsSupportedReference(ip) +} + +// Build implements Interface +func (r *Recorder) Build(ip string) (v1.Image, error) { + func() { + r.m.Lock() + defer r.m.Unlock() + r.ImportPaths = append(r.ImportPaths, ip) + }() + return r.Builder.Build(ip) +} diff --git a/vendor/github.com/google/ko/pkg/build/shared.go b/vendor/github.com/google/ko/pkg/build/shared.go new file mode 100644 index 0000000..72d0d3a --- /dev/null +++ b/vendor/github.com/google/ko/pkg/build/shared.go @@ -0,0 +1,79 @@ +// 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 build + +import ( + "sync" + + v1 "github.com/google/go-containerregistry/pkg/v1" +) + +// Caching wraps a builder implementation in a layer that shares build results +// for the same inputs using a simple "future" implementation. Cached results +// may be invalidated by calling Invalidate with the same input passed to Build. +type Caching struct { + inner Interface + + m sync.Mutex + results map[string]*future +} + +// Caching implements Interface +var _ Interface = (*Caching)(nil) + +// NewCaching wraps the provided build.Interface in an implementation that +// shares build results for a given path until the result has been invalidated. +func NewCaching(inner Interface) (*Caching, error) { + return &Caching{ + inner: inner, + results: make(map[string]*future), + }, nil +} + +// Build implements Interface +func (c *Caching) Build(ip string) (v1.Image, error) { + f := func() *future { + // Lock the map of futures. + c.m.Lock() + defer c.m.Unlock() + + // If a future for "ip" exists, then return it. + f, ok := c.results[ip] + if ok { + return f + } + // Otherwise create and record a future for a Build of "ip". + f = newFuture(func() (v1.Image, error) { + return c.inner.Build(ip) + }) + c.results[ip] = f + return f + }() + + return f.Get() +} + +// IsSupportedReference implements Interface +func (c *Caching) IsSupportedReference(ip string) bool { + return c.inner.IsSupportedReference(ip) +} + +// Invalidate removes an import path's cached results. +func (c *Caching) Invalidate(ip string) { + c.m.Lock() + defer c.m.Unlock() + + delete(c.results, ip) +}