diff --git a/pkg/buildcontext/buildcontext.go b/pkg/buildcontext/buildcontext.go index 08d8a7c98..6e40ece8f 100644 --- a/pkg/buildcontext/buildcontext.go +++ b/pkg/buildcontext/buildcontext.go @@ -61,7 +61,7 @@ func GetBuildContext(srcContext string, opts BuildOptions) (BuildContext, error) if util.ValidAzureBlobStorageHost(srcContext) { return &AzureBlob{context: srcContext}, nil } - return nil, errors.New("url provided for https context is not in a supported format, please use the https url for Azure Blob Storage") + return &HTTPSTar{context: srcContext}, nil case TarBuildContextPrefix: return &Tar{context: context}, nil } diff --git a/pkg/buildcontext/https.go b/pkg/buildcontext/https.go new file mode 100644 index 000000000..6293bc72d --- /dev/null +++ b/pkg/buildcontext/https.go @@ -0,0 +1,79 @@ +/* +Copyright 2018 Google LLC + +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 buildcontext + +import ( + "fmt" + "io" + "net/http" + "os" + "path/filepath" + + "github.com/GoogleContainerTools/kaniko/pkg/constants" + "github.com/GoogleContainerTools/kaniko/pkg/util" + "github.com/sirupsen/logrus" +) + +// HTTPSTar struct for https tar.gz files processing +type HTTPSTar struct { + context string +} + +// UnpackTarFromBuildContext downloads context file from https server +func (h *HTTPSTar) UnpackTarFromBuildContext() (directory string, err error) { + + logrus.Info("Retrieving https tar file") + + // Create directory and target file for downloading the context file + directory = constants.BuildContextDir + tarPath := filepath.Join(directory, constants.ContextTar) + file, err := util.CreateTargetTarfile(tarPath) + if err != nil { + return + } + + // Download tar file from remote https server + // and save it into the target tar file + resp, err := http.Get(h.context) + if err != nil { + return + } + defer func() { + if closeErr := resp.Body.Close(); err == nil && closeErr != nil { + err = closeErr + } + }() + + if resp.StatusCode != http.StatusOK { + return directory, fmt.Errorf("HTTPSTar bad status from server: %s", resp.Status) + } + + if _, err = io.Copy(file, resp.Body); err != nil { + return tarPath, err + } + + logrus.Info("Retrieved https tar file") + + if err = util.UnpackCompressedTar(tarPath, directory); err != nil { + return + } + + logrus.Info("Extracted https tar file") + + // Remove the tar so it doesn't interfere with subsequent commands + return directory, os.Remove(tarPath) +} diff --git a/pkg/buildcontext/https_test.go b/pkg/buildcontext/https_test.go new file mode 100644 index 000000000..e7b07624c --- /dev/null +++ b/pkg/buildcontext/https_test.go @@ -0,0 +1,68 @@ +/* +Copyright 2018 Google LLC + +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 buildcontext + +import ( + "net/http" + "net/http/httptest" + "testing" +) + +func TestBuildWithHttpsTar(t *testing.T) { + + tests := []struct { + name string + serverHandler http.HandlerFunc + }{ + { + name: "test http bad status", + serverHandler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusBadRequest) + _, err := w.Write([]byte("corrupted message")) + if err != nil { + t.Fatalf("Error sending response: %v", err) + } + }), + }, + { + name: "test http bad data", + serverHandler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + _, err := w.Write([]byte("corrupted message")) + if err != nil { + t.Fatalf("Error sending response: %v", err) + } + }), + }, + } + + for _, tcase := range tests { + t.Run(tcase.name, func(t *testing.T) { + server := httptest.NewServer(tcase.serverHandler) + defer server.Close() + + context := &HTTPSTar{ + context: server.URL + "/data.tar.gz", + } + + _, err := context.UnpackTarFromBuildContext() + if err == nil { + t.Fatalf("Error expected but not returned: %s", err) + } + }) + } +}