From e17d117a3ef5c64c33eae5d0ed2f045e980d10e1 Mon Sep 17 00:00:00 2001 From: David Gageot Date: Tue, 10 Jul 2018 09:00:00 +0200 Subject: [PATCH] Support Knative Build CRD Currently focused on supporting Docker build artifacts Signed-off-by: David Gageot --- Gopkg.lock | 18 + Gopkg.toml | 10 +- examples/annotated-skaffold.yaml | 9 + pkg/skaffold/build/knative.go | 88 ++++ pkg/skaffold/build/knative/build.go | 156 ++++++ pkg/skaffold/build/knative/crd.go | 36 ++ pkg/skaffold/build/knative/secret.go | 100 ++++ pkg/skaffold/constants/constants.go | 4 + pkg/skaffold/runner/runner.go | 4 + pkg/skaffold/schema/v1alpha2/config.go | 11 + pkg/skaffold/schema/v1alpha2/defaults.go | 51 ++ vendor/github.com/knative/build/AUTHORS | 8 + vendor/github.com/knative/build/LICENSE | 202 ++++++++ .../knative/build/pkg/apis/build/register.go | 19 + .../build/v1alpha1/build_template_types.go | 85 ++++ .../pkg/apis/build/v1alpha1/build_types.go | 239 +++++++++ .../build/pkg/apis/build/v1alpha1/doc.go | 21 + .../build/pkg/apis/build/v1alpha1/register.go | 55 ++ .../build/v1alpha1/zz_generated.deepcopy.go | 479 ++++++++++++++++++ .../client/clientset/versioned/scheme/doc.go | 17 + .../clientset/versioned/scheme/register.go | 51 ++ .../versioned/typed/build/v1alpha1/build.go | 154 ++++++ .../typed/build/v1alpha1/build_client.go | 92 ++++ .../typed/build/v1alpha1/buildtemplate.go | 154 ++++++ .../versioned/typed/build/v1alpha1/doc.go | 17 + .../build/v1alpha1/generated_expansion.go | 20 + .../github.com/knative/build/pkg/logs/logs.go | 243 +++++++++ 27 files changed, 2340 insertions(+), 3 deletions(-) create mode 100644 pkg/skaffold/build/knative.go create mode 100644 pkg/skaffold/build/knative/build.go create mode 100644 pkg/skaffold/build/knative/crd.go create mode 100644 pkg/skaffold/build/knative/secret.go create mode 100644 vendor/github.com/knative/build/AUTHORS create mode 100644 vendor/github.com/knative/build/LICENSE create mode 100644 vendor/github.com/knative/build/pkg/apis/build/register.go create mode 100644 vendor/github.com/knative/build/pkg/apis/build/v1alpha1/build_template_types.go create mode 100644 vendor/github.com/knative/build/pkg/apis/build/v1alpha1/build_types.go create mode 100644 vendor/github.com/knative/build/pkg/apis/build/v1alpha1/doc.go create mode 100644 vendor/github.com/knative/build/pkg/apis/build/v1alpha1/register.go create mode 100644 vendor/github.com/knative/build/pkg/apis/build/v1alpha1/zz_generated.deepcopy.go create mode 100644 vendor/github.com/knative/build/pkg/client/clientset/versioned/scheme/doc.go create mode 100644 vendor/github.com/knative/build/pkg/client/clientset/versioned/scheme/register.go create mode 100644 vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/build.go create mode 100644 vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/build_client.go create mode 100644 vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/buildtemplate.go create mode 100644 vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/doc.go create mode 100644 vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/generated_expansion.go create mode 100644 vendor/github.com/knative/build/pkg/logs/logs.go diff --git a/Gopkg.lock b/Gopkg.lock index 5917fb9ea43..7bcdd0d2dc5 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -451,7 +451,21 @@ version = "0.4" [[projects]] +<<<<<<< HEAD digest = "1:5985ef4caf91ece5d54817c11ea25f182697534f8ae6521eadcd628c142ac4b6" +======= + name = "github.com/knative/build" + packages = [ + "pkg/apis/build", + "pkg/apis/build/v1alpha1", + "pkg/client/clientset/versioned/scheme", + "pkg/client/clientset/versioned/typed/build/v1alpha1", + "pkg/logs" + ] + revision = "dd8f92ed1cc2e49d98c26a94270a40c9ea7da9b8" + +[[projects]] +>>>>>>> 78a16f7e... Support Knative Build CRD name = "github.com/matttproud/golang_protobuf_extensions" packages = ["pbutil"] pruneopts = "NUT" @@ -1127,6 +1141,7 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 +<<<<<<< HEAD input-imports = [ "cloud.google.com/go/storage", "github.com/blang/semver", @@ -1197,5 +1212,8 @@ "k8s.io/client-go/tools/clientcmd", "k8s.io/client-go/tools/clientcmd/api", ] +======= + inputs-digest = "6f145026193c4be573b28250bc90b4bd471a1a3d3f1261bb405a1e386ebdc2cc" +>>>>>>> 78a16f7e... Support Knative Build CRD solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index dbf29c0b092..2bd427f9436 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -39,15 +39,15 @@ name = "github.com/docker/distribution" revision = "83389a148052d74ac602f5f1d62f86ff2f3c4aa5" -[[constraint]] +[[override]] name = "k8s.io/apimachinery" version = "kubernetes-1.11.0" -[[constraint]] +[[override]] name = "k8s.io/client-go" version = "kubernetes-1.11.0" -[[constraint]] +[[override]] name = "k8s.io/api" version = "kubernetes-1.11.0" @@ -74,3 +74,7 @@ [[constraint]] name = "github.com/google/go-github" version = "15.0.0" + +[[constraint]] + name = "github.com/knative/build" + revision = "dd8f92ed1cc2e49d98c26a94270a40c9ea7da9b8" \ No newline at end of file diff --git a/examples/annotated-skaffold.yaml b/examples/annotated-skaffold.yaml index 89c139cc607..d1b19b7f8ad 100644 --- a/examples/annotated-skaffold.yaml +++ b/examples/annotated-skaffold.yaml @@ -104,6 +104,15 @@ build: # namespace: default # timeout: 20m + # Docker artifacts can be built on a Kubernetes cluster with Knative Build CRD. + # Example + # knative: + # gcsBucket: k8s-skaffold + # namespace: default + # secret: "" + # secretName: knative-secret + # serviceAccountName: knative-sa + # The deploy section has all the information needed to deploy. Along with build: # it is a required section. deploy: diff --git a/pkg/skaffold/build/knative.go b/pkg/skaffold/build/knative.go new file mode 100644 index 00000000000..f69f16dbf7b --- /dev/null +++ b/pkg/skaffold/build/knative.go @@ -0,0 +1,88 @@ +/* +Copyright 2018 The Skaffold Authors + +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 ( + "context" + "fmt" + "io" + + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/knative" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/tag" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/constants" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/v1alpha2" + "github.com/pkg/errors" +) + +// KnativeBuilder can build docker artifacts on Kubernetes, using knative build CRD. +type KnativeBuilder struct { + *v1alpha2.KnativeBuild +} + +// NewKnativeBuilder creates a KnativeBuilder. +func NewKnativeBuilder(cfg *v1alpha2.KnativeBuild) *KnativeBuilder { + return &KnativeBuilder{ + KnativeBuild: cfg, + } +} + +// Labels gives labels to be set on artifacts deployed with knative. +func (k *KnativeBuilder) Labels() map[string]string { + return map[string]string{ + constants.Labels.Builder: "knative", + } +} + +// Build builds a list of artifacts with knative. +func (k *KnativeBuilder) Build(ctx context.Context, out io.Writer, tagger tag.Tagger, artifacts []*v1alpha2.Artifact) ([]Artifact, error) { + // TODO(dgageot): parallel builds + var builds []Artifact + + for _, artifact := range artifacts { + fmt.Fprintf(out, "Building [%s]...\n", artifact.ImageName) + + initialTag, err := knative.BuildArtifact(ctx, out, artifact, k.KnativeBuild) + if err != nil { + return nil, errors.Wrapf(err, "kaniko build for [%s]", artifact.ImageName) + } + + digest, err := docker.RemoteDigest(initialTag) + if err != nil { + return nil, errors.Wrap(err, "getting digest") + } + + tag, err := tagger.GenerateFullyQualifiedImageName(artifact.Workspace, &tag.Options{ + ImageName: artifact.ImageName, + Digest: digest, + }) + if err != nil { + return nil, errors.Wrap(err, "generating tag") + } + + if err := docker.AddTag(initialTag, tag); err != nil { + return nil, errors.Wrap(err, "tagging image") + } + + builds = append(builds, Artifact{ + ImageName: artifact.ImageName, + Tag: tag, + }) + } + + return builds, nil +} diff --git a/pkg/skaffold/build/knative/build.go b/pkg/skaffold/build/knative/build.go new file mode 100644 index 00000000000..baf1d19b9b8 --- /dev/null +++ b/pkg/skaffold/build/knative/build.go @@ -0,0 +1,156 @@ +/* +Copyright 2018 The Skaffold Authors + +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 knative + +import ( + "context" + "fmt" + "io" + + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/constants" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/v1alpha2" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" + "github.com/knative/build/pkg/apis/build/v1alpha1" + build_v1alpha1 "github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1" + "github.com/knative/build/pkg/logs" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/tools/clientcmd" +) + +// BuildArtifact builds an artifact with knative Build CRD +func BuildArtifact(ctx context.Context, out io.Writer, a *v1alpha2.Artifact, cfg *v1alpha2.KnativeBuild) (string, error) { + if err := testBuildCRD(); err != nil { + logrus.Errorln("Build CRD is not installed") + logrus.Errorln("Follow the installation guide: https://github.com/knative/build#getting-started") + logrus.Errorln("Usually, it's as simple as: kubectl create -f https://storage.googleapis.com/build-crd/latest/release.yaml") + return "", errors.Wrap(err, "Build CRD is not installed") + } + + loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() + kubeConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{}) + clientConfig, err := kubeConfig.ClientConfig() + if err != nil { + return "", errors.Wrap(err, "getting clientConfig") + } + + deleteSecret, err := setupSecret(clientConfig, cfg) + if err != nil { + return "", errors.Wrap(err, "setting up secret") + } + defer deleteSecret() + + deleteServiceAccount, err := setupServiceAccount(clientConfig, cfg) + if err != nil { + return "", errors.Wrap(err, "setting up service account") + } + defer deleteServiceAccount() + + randomID := util.RandomID() + zipName := fmt.Sprintf("context-%s.tar.gz", randomID) + // TODO(dgageot): delete sources + if err := docker.UploadContextToGCS(ctx, a.Workspace, a.DockerArtifact, cfg.GCSBucket, zipName); err != nil { + return "", errors.Wrap(err, "uploading tar to gcs") + } + + client, err := build_v1alpha1.NewForConfig(clientConfig) + if err != nil { + return "", errors.Wrap(err, "getting build client") + } + + imageDst := fmt.Sprintf("%s:%s", a.ImageName, randomID) + build := buildFor(imageDst, zipName, a, cfg) + + builds := client.Builds(cfg.Namespace) + build, err = builds.Create(build) + if err != nil { + return "", errors.Wrap(err, "creating build") + } + defer func() { + if err := builds.Delete(build.Name, &metav1.DeleteOptions{}); err != nil { + logrus.Debugln("deleting build", err) + } + }() + + if err := logs.Tail(ctx, out, build.Name, build.Namespace); err != nil { + return "", errors.Wrap(err, "streaming logs") + } + + if err := waitForCompletion(builds, build); err != nil { + return "", errors.Wrap(err, "waiting for completion") + } + + return imageDst, nil +} + +func waitForCompletion(builds build_v1alpha1.BuildInterface, build *v1alpha1.Build) error { + for { + done, err := builds.Get(build.Name, metav1.GetOptions{}) + if err != nil { + return errors.Wrap(err, "getting status") + } + + switch buildStatus(done) { + case v1.ConditionFalse: + return errors.New("build failed") + case v1.ConditionTrue: + return nil + } + } +} + +func buildStatus(build *v1alpha1.Build) v1.ConditionStatus { + for _, condition := range build.Status.Conditions { + if condition.Type == v1alpha1.BuildSucceeded { + return condition.Status + } + } + + return v1.ConditionUnknown +} + +func buildFor(imageName, tarName string, a *v1alpha2.Artifact, cfg *v1alpha2.KnativeBuild) *v1alpha1.Build { + return &v1alpha1.Build{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "skaffold-docker-build", + Namespace: cfg.Namespace, + }, + Spec: v1alpha1.BuildSpec{ + ServiceAccountName: cfg.ServiceAccountName, + Source: &v1alpha1.SourceSpec{ + Custom: &v1.Container{ + Image: "gcr.io/cloud-builders/gsutil", // TODO(dgageot) way too big + Command: []string{"sh", "-c"}, + Args: []string{fmt.Sprintf("gsutil cp gs://%s/%s - | tar xvz", cfg.GCSBucket, tarName)}, + }, + }, + Steps: []v1.Container{ + { + Name: "build-and-push", + Image: constants.DefaultKanikoImage, + Args: []string{ + "--dockerfile=/workspace/" + a.ArtifactType.DockerArtifact.DockerfilePath, + "--destination=" + imageName, + }, + }, + }, + }, + } +} diff --git a/pkg/skaffold/build/knative/crd.go b/pkg/skaffold/build/knative/crd.go new file mode 100644 index 00000000000..e9929d0f785 --- /dev/null +++ b/pkg/skaffold/build/knative/crd.go @@ -0,0 +1,36 @@ +/* +Copyright 2018 The Skaffold Authors + +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 knative + +import ( + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes" + "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const buildCRDNamespace = "knative-build" + +// testBuildCRD verifies that the Build CRD is installed. +func testBuildCRD() error { + client, err := kubernetes.GetClientset() + if err != nil { + return errors.Wrap(err, "getting kubernetes client") + } + + _, err = client.CoreV1().Namespaces().Get(buildCRDNamespace, metav1.GetOptions{}) + return err +} diff --git a/pkg/skaffold/build/knative/secret.go b/pkg/skaffold/build/knative/secret.go new file mode 100644 index 00000000000..72b21588b6a --- /dev/null +++ b/pkg/skaffold/build/knative/secret.go @@ -0,0 +1,100 @@ +/* +Copyright 2018 The Skaffold Authors + +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 knative + +import ( + "io/ioutil" + + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/v1alpha2" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + corev1 "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/rest" +) + +// TODO(dgageot): reuse service account? +func setupServiceAccount(clientConfig *rest.Config, cfg *v1alpha2.KnativeBuild) (func(), error) { + core, err := corev1.NewForConfig(clientConfig) + if err != nil { + return nil, errors.Wrap(err, "getting kubernetes client") + } + + sa := &v1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: cfg.ServiceAccountName, + Namespace: cfg.Namespace, + }, + Secrets: []v1.ObjectReference{{ + Name: cfg.SecretName, + }}, + } + + serviceAccounts := core.ServiceAccounts(cfg.Namespace) + if _, err := serviceAccounts.Create(sa); err != nil { + return nil, errors.Wrapf(err, "creating service account: %s", err) + } + + return func() { + if err := serviceAccounts.Delete(cfg.ServiceAccountName, &metav1.DeleteOptions{}); err != nil { + logrus.Warnf("deleting service account: %s", cfg.ServiceAccountName) + } + }, nil +} + +func setupSecret(clientConfig *rest.Config, cfg *v1alpha2.KnativeBuild) (func(), error) { + if cfg.Secret == "" { + return nil, errors.New("no pull secret specified") + } + + core, err := corev1.NewForConfig(clientConfig) + if err != nil { + return nil, errors.Wrap(err, "getting kubernetes client") + } + + secretData, err := ioutil.ReadFile(cfg.Secret) + if err != nil { + return nil, errors.Wrap(err, "reading secret") + } + + secret := &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: cfg.SecretName, + Namespace: cfg.Namespace, + Annotations: map[string]string{ + "build.knative.dev/docker-0": "https://gcr.io", // TODO + }, + }, + Type: "kubernetes.io/basic-auth", + Data: map[string][]byte{ + "username": []byte("_json_key"), + "password": secretData, + }, + } + + secrets := core.Secrets(cfg.Namespace) + if _, err := secrets.Create(secret); err != nil { + return nil, errors.Wrapf(err, "creating secret: %s", err) + } + + return func() { + if err := secrets.Delete(cfg.SecretName, &metav1.DeleteOptions{}); err != nil { + logrus.Warnf("deleting secret: %s", cfg.SecretName) + } + }, nil +} diff --git a/pkg/skaffold/constants/constants.go b/pkg/skaffold/constants/constants.go index 30ad591c408..02474bb68ac 100644 --- a/pkg/skaffold/constants/constants.go +++ b/pkg/skaffold/constants/constants.go @@ -53,6 +53,10 @@ const ( UpdateCheckEnvironmentVariable = "SKAFFOLD_UPDATE_CHECK" DefaultCloudBuildDockerImage = "gcr.io/cloud-builders/docker" + + DefaultKnativeBuild = "build.yaml" + DefaultKnativeSecretName = "knative-secret" + DefaultKnativeServiceAccountName = "knative-sa" ) var DefaultKubectlManifests = []string{"k8s/*.yaml"} diff --git a/pkg/skaffold/runner/runner.go b/pkg/skaffold/runner/runner.go index ba94c8509b6..9c2197b3c30 100644 --- a/pkg/skaffold/runner/runner.go +++ b/pkg/skaffold/runner/runner.go @@ -110,6 +110,10 @@ func getBuilder(cfg *v1alpha2.BuildConfig, kubeContext string) (build.Builder, e logrus.Debugf("Using builder: kaniko") return kaniko.NewBuilder(cfg.KanikoBuild), nil + case cfg.KnativeBuild != nil: + logrus.Debugf("Using builder: knative") + return build.NewKnativeBuilder(cfg.KnativeBuild), nil + default: return nil, fmt.Errorf("Unknown builder for config %+v", cfg) } diff --git a/pkg/skaffold/schema/v1alpha2/config.go b/pkg/skaffold/schema/v1alpha2/config.go index c2b2fea0b69..c97f823654f 100644 --- a/pkg/skaffold/schema/v1alpha2/config.go +++ b/pkg/skaffold/schema/v1alpha2/config.go @@ -74,6 +74,7 @@ type BuildType struct { LocalBuild *LocalBuild `yaml:"local"` GoogleCloudBuild *GoogleCloudBuild `yaml:"googleCloudBuild"` KanikoBuild *KanikoBuild `yaml:"kaniko"` + KnativeBuild *KnativeBuild `yaml:"knative"` } // LocalBuild contains the fields needed to do a build on the local docker daemon @@ -104,6 +105,16 @@ type KanikoBuild struct { Timeout string `yaml:"timeout,omitempty"` } +// KnativeBuild contains the fields needed to do a on-cluster build using +// the knative build CRD +type KnativeBuild struct { + GCSBucket string `yaml:"gcsBucket,omitempty"` + Secret string `yaml:"secret,omitempty"` + SecretName string `yaml:"secretName,omitempty"` + ServiceAccountName string `yaml:"serviceAccountName,omitempty"` + Namespace string `yaml:"namespace,omitempty"` +} + // DeployConfig contains all the configuration needed by the deploy steps type DeployConfig struct { DeployType `yaml:",inline"` diff --git a/pkg/skaffold/schema/v1alpha2/defaults.go b/pkg/skaffold/schema/v1alpha2/defaults.go index 5824b204249..c63c8e08152 100644 --- a/pkg/skaffold/schema/v1alpha2/defaults.go +++ b/pkg/skaffold/schema/v1alpha2/defaults.go @@ -33,12 +33,19 @@ func (c *SkaffoldConfig) setDefaultValues() error { c.setDefaultKustomizePath() c.setDefaultKubectlManifests() c.setDefaultKanikoTimeout() + if err := c.setDefaultKanikoNamespace(); err != nil { return err } if err := c.setDefaultKanikoSecret(); err != nil { return err } + if err := c.setDefaultKnativeNamespace(); err != nil { + return err + } + if err := c.setDefaultKnativeSecret(); err != nil { + return err + } for _, a := range c.Build.Artifacts { c.defaultToDockerArtifact(a) @@ -138,6 +145,24 @@ func (c *SkaffoldConfig) setDefaultKanikoTimeout() { } } +func (c *SkaffoldConfig) setDefaultKnativeNamespace() error { + knative := c.Build.KnativeBuild + if knative == nil { + return nil + } + + if knative.Namespace == "" { + ns, err := currentNamespace() + if err != nil { + return errors.Wrap(err, "getting current namespace") + } + + knative.Namespace = ns + } + + return nil +} + func (c *SkaffoldConfig) setDefaultKanikoSecret() error { kaniko := c.Build.KanikoBuild if kaniko == nil { @@ -161,6 +186,32 @@ func (c *SkaffoldConfig) setDefaultKanikoSecret() error { return nil } +func (c *SkaffoldConfig) setDefaultKnativeSecret() error { + knative := c.Build.KnativeBuild + if knative == nil { + return nil + } + + if knative.SecretName == "" { + knative.SecretName = constants.DefaultKnativeSecretName + } + if knative.ServiceAccountName == "" { + knative.SecretName = constants.DefaultKnativeServiceAccountName + } + + if knative.Secret != "" { + absPath, err := homedir.Expand(knative.Secret) + if err != nil { + return fmt.Errorf("unable to expand pullSecret %s", knative.Secret) + } + + knative.Secret = absPath + return nil + } + + return nil +} + func currentNamespace() (string, error) { cfg, err := kubectx.CurrentConfig() if err != nil { diff --git a/vendor/github.com/knative/build/AUTHORS b/vendor/github.com/knative/build/AUTHORS new file mode 100644 index 00000000000..9c2b57e2ca4 --- /dev/null +++ b/vendor/github.com/knative/build/AUTHORS @@ -0,0 +1,8 @@ +# This is the list of Knative authors for copyright purposes. +# +# This does not necessarily list everyone who has contributed code, since in +# some cases, their employer may be the copyright holder. To see the full list +# of contributors, see the revision history in source control. +Google LLC +Pivotal Software, Inc. +Red Hat, Inc. \ No newline at end of file diff --git a/vendor/github.com/knative/build/LICENSE b/vendor/github.com/knative/build/LICENSE new file mode 100644 index 00000000000..d6456956733 --- /dev/null +++ b/vendor/github.com/knative/build/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. diff --git a/vendor/github.com/knative/build/pkg/apis/build/register.go b/vendor/github.com/knative/build/pkg/apis/build/register.go new file mode 100644 index 00000000000..ec8299fe8c2 --- /dev/null +++ b/vendor/github.com/knative/build/pkg/apis/build/register.go @@ -0,0 +1,19 @@ +/* +Copyright 2018 The Knative Authors + +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 + +const GroupName = "build.knative.dev" diff --git a/vendor/github.com/knative/build/pkg/apis/build/v1alpha1/build_template_types.go b/vendor/github.com/knative/build/pkg/apis/build/v1alpha1/build_template_types.go new file mode 100644 index 00000000000..7d63ea4b722 --- /dev/null +++ b/vendor/github.com/knative/build/pkg/apis/build/v1alpha1/build_template_types.go @@ -0,0 +1,85 @@ +/* +Copyright 2018 The Knative Authors + +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 v1alpha1 + +import ( + "encoding/json" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +genclient:noStatus +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// BuildTemplate is a template that can used to easily create Builds. +type BuildTemplate struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec BuildTemplateSpec `json:"spec"` +} + +// BuildTemplateSpec is the spec for a BuildTemplate. +type BuildTemplateSpec struct { + // TODO: Generation does not work correctly with CRD. They are scrubbed + // by the APIserver (https://github.com/kubernetes/kubernetes/issues/58778) + // So, we add Generation here. Once that gets fixed, remove this and use + // ObjectMeta.Generation instead. + // +optional + Generation int64 `json:"generation,omitempty"` + + // Parameters defines the parameters that can be populated in a template. + Parameters []ParameterSpec `json:"parameters,omitempty"` + + // Steps are the steps of the build; each step is run sequentially with the + // source mounted into /workspace. + Steps []corev1.Container `json:"steps"` + + // Volumes is a collection of volumes that are available to mount into the + // steps of the build. + Volumes []corev1.Volume `json:"volumes"` +} + +// ParameterSpec defines the possible parameters that can be populated in a +// template. +type ParameterSpec struct { + // Name is the unique name of this template parameter. + Name string `json:"name"` + + // Description is a human-readable explanation of this template parameter. + Description string `json:"description,omitempty"` + + // Default, if specified, defines the default value that should be applied if + // the build does not specify the value for this parameter. + Default *string `json:"default,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// BuildTemplateList is a list of BuildTemplate resources. +type BuildTemplateList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []BuildTemplate `json:"items"` +} + +func (bt *BuildTemplate) GetGeneration() int64 { return bt.Spec.Generation } +func (bt *BuildTemplate) SetGeneration(generation int64) { bt.Spec.Generation = generation } +func (bt *BuildTemplate) GetSpecJSON() ([]byte, error) { return json.Marshal(bt.Spec) } diff --git a/vendor/github.com/knative/build/pkg/apis/build/v1alpha1/build_types.go b/vendor/github.com/knative/build/pkg/apis/build/v1alpha1/build_types.go new file mode 100644 index 00000000000..f6334241a10 --- /dev/null +++ b/vendor/github.com/knative/build/pkg/apis/build/v1alpha1/build_types.go @@ -0,0 +1,239 @@ +/* +Copyright 2018 The Knative Authors + +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 v1alpha1 + +import ( + "encoding/json" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +genclient:noStatus +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Build represents a build of a container image. A Build is made up of a +// source, and a set of steps. Steps can mount volumes to share data between +// themselves. A build may be created by instantiating a BuildTemplate. +type Build struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec BuildSpec `json:"spec"` + Status BuildStatus `json:"status"` +} + +// BuildSpec is the spec for a Build resource. +type BuildSpec struct { + // TODO: Generation does not work correctly with CRD. They are scrubbed + // by the APIserver (https://github.com/kubernetes/kubernetes/issues/58778) + // So, we add Generation here. Once that gets fixed, remove this and use + // ObjectMeta.Generation instead. + // +optional + Generation int64 `json:"generation,omitempty"` + + // Source specifies the input to the build. + Source *SourceSpec `json:"source,omitempty"` + + // Steps are the steps of the build; each step is run sequentially with the + // source mounted into /workspace. + Steps []corev1.Container `json:"steps,omitempty"` + + // Volumes is a collection of volumes that are available to mount into the + // steps of the build. + Volumes []corev1.Volume `json:"volumes,omitempty"` + + // The name of the service account as which to run this build. + ServiceAccountName string `json:"serviceAccountName,omitempty"` + + // Template, if specified, references a BuildTemplate resource to use to + // populate fields in the build, and optional Arguments to pass to the + // template. + Template *TemplateInstantiationSpec `json:"template,omitempty"` + + // NodeSelector is a selector which must be true for the pod to fit on a node. + // Selector which must match a node's labels for the pod to be scheduled on that node. + // More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + // +optional + NodeSelector map[string]string `json:"nodeSelector,omitempty"` +} + +// TemplateInstantiationSpec specifies how a BuildTemplate is instantiated into +// a Build. +type TemplateInstantiationSpec struct { + // Name references the BuildTemplate resource to use. + // + // The template is assumed to exist in the Build's namespace. + Name string `json:"name"` + + // Arguments, if specified, lists values that should be applied to the + // parameters specified by the template. + Arguments []ArgumentSpec `json:"arguments,omitempty"` + + // Env, if specified will provide variables to all build template steps. + // This will override any of the template's steps environment variables. + Env []corev1.EnvVar `json:"env,omitempty"` +} + +// ArgumentSpec defines the actual values to use to populate a template's +// parameters. +type ArgumentSpec struct { + Name string `json:"name"` + Value string `json:"value"` + // TODO(jasonhall): ValueFrom? +} + +// SourceSpec defines the input to the Build +type SourceSpec struct { + Git *GitSourceSpec `json:"git,omitempty"` + GCS *GCSSourceSpec `json:"gcs,omitempty"` + Custom *corev1.Container `json:"custom,omitempty"` +} + +// GitSourceSpec describes a Git repo source input to the Build. +type GitSourceSpec struct { + // URL of the Git repository to clone from. + Url string `json:"url"` + + // Git revision (branch, tag, commit SHA or ref) to clone. See + // https://git-scm.com/docs/gitrevisions#_specifying_revisions for more + // information. + Revision string `json:"revision"` +} + +// GCSSourceSpec describes source input to the Build in the form of an archive, +// or a source manifest describing files to fetch. +type GCSSourceSpec struct { + Type GCSSourceType `json:"type,omitempty"` + Location string `json:"location,omitempty"` +} + +type GCSSourceType string + +const ( + GCSArchive GCSSourceType = "Archive" + GCSManifest GCSSourceType = "Manifest" +) + +type BuildProvider string + +const ( + // GoogleBuildProvider indicates that this build was performed with Google Container Builder. + GoogleBuildProvider BuildProvider = "Google" + // ClusterBuildProvider indicates that this build was performed on-cluster. + ClusterBuildProvider BuildProvider = "Cluster" +) + +// BuildStatus is the status for a Build resource +type BuildStatus struct { + Builder BuildProvider `json:"builder,omitempty"` + + // Additional information based on the Builder executing this build. + Cluster *ClusterSpec `json:"cluster,omitempty"` + Google *GoogleSpec `json:"google,omitempty"` + + // Information about the execution of the build. + StartTime metav1.Time `json:"startTime,omitEmpty"` + CompletionTime metav1.Time `json:"completionTime,omitEmpty"` + + // Parallel list to spec.Containers + StepStates []corev1.ContainerState `json:"stepStates,omitEmpty"` + Conditions []BuildCondition `json:"conditions,omitempty"` +} + +type ClusterSpec struct { + Namespace string `json:"namespace"` + PodName string `json:"podName"` +} + +type GoogleSpec struct { + Operation string `json:"operation"` +} + +type BuildConditionType string + +const ( + // BuildSucceeded is set when the build is running, and becomes True + // when the build finishes successfully. + // + // If the build is ongoing, its status will be Unknown. If it fails, + // its status will be False. + BuildSucceeded BuildConditionType = "Succeeded" +) + +// BuildCondition defines a readiness condition for a Build. +// See: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#typical-status-properties +type BuildCondition struct { + Type BuildConditionType `json:"state"` + + Status corev1.ConditionStatus `json:"status" description:"status of the condition, one of True, False, Unknown"` + + // +optional + Reason string `json:"reason,omitempty" description:"one-word CamelCase reason for the condition's last transition"` + // +optional + Message string `json:"message,omitempty" description:"human-readable message indicating details about last transition"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// BuildList is a list of Build resources +type BuildList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []Build `json:"items"` +} + +func (bs *BuildStatus) GetCondition(t BuildConditionType) *BuildCondition { + for _, cond := range bs.Conditions { + if cond.Type == t { + return &cond + } + } + return nil +} + +func (b *BuildStatus) SetCondition(newCond *BuildCondition) { + if newCond == nil { + return + } + + t := newCond.Type + var conditions []BuildCondition + for _, cond := range b.Conditions { + if cond.Type != t { + conditions = append(conditions, cond) + } + } + conditions = append(conditions, *newCond) + b.Conditions = conditions +} + +func (b *BuildStatus) RemoveCondition(t BuildConditionType) { + var conditions []BuildCondition + for _, cond := range b.Conditions { + if cond.Type != t { + conditions = append(conditions, cond) + } + } + b.Conditions = conditions +} + +func (b *Build) GetGeneration() int64 { return b.Spec.Generation } +func (b *Build) SetGeneration(generation int64) { b.Spec.Generation = generation } +func (b *Build) GetSpecJSON() ([]byte, error) { return json.Marshal(b.Spec) } diff --git a/vendor/github.com/knative/build/pkg/apis/build/v1alpha1/doc.go b/vendor/github.com/knative/build/pkg/apis/build/v1alpha1/doc.go new file mode 100644 index 00000000000..df551590c00 --- /dev/null +++ b/vendor/github.com/knative/build/pkg/apis/build/v1alpha1/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2018 The Knative Authors + +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. +*/ + +// +k8s:deepcopy-gen=package + +// Package v1alpha1 is the v1alpha1 version of the API. +// +groupName=build.knative.dev +package v1alpha1 diff --git a/vendor/github.com/knative/build/pkg/apis/build/v1alpha1/register.go b/vendor/github.com/knative/build/pkg/apis/build/v1alpha1/register.go new file mode 100644 index 00000000000..95c900c26ee --- /dev/null +++ b/vendor/github.com/knative/build/pkg/apis/build/v1alpha1/register.go @@ -0,0 +1,55 @@ +/* +Copyright 2018 The Knative Authors + +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 v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + + "github.com/knative/build/pkg/apis/build" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: build.GroupName, Version: "v1alpha1"} + +// Kind takes an unqualified kind and returns back a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &Build{}, + &BuildList{}, + &BuildTemplate{}, + &BuildTemplateList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/vendor/github.com/knative/build/pkg/apis/build/v1alpha1/zz_generated.deepcopy.go b/vendor/github.com/knative/build/pkg/apis/build/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..36d62a66e31 --- /dev/null +++ b/vendor/github.com/knative/build/pkg/apis/build/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,479 @@ +// +build !ignore_autogenerated + +/* +Copyright 2018 The Knative Authors + +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. +*/ + +// This file was autogenerated by deepcopy-gen. Do not edit it manually! + +package v1alpha1 + +import ( + v1 "k8s.io/api/core/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ArgumentSpec) DeepCopyInto(out *ArgumentSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArgumentSpec. +func (in *ArgumentSpec) DeepCopy() *ArgumentSpec { + if in == nil { + return nil + } + out := new(ArgumentSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Build) DeepCopyInto(out *Build) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Build. +func (in *Build) DeepCopy() *Build { + if in == nil { + return nil + } + out := new(Build) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Build) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BuildCondition) DeepCopyInto(out *BuildCondition) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BuildCondition. +func (in *BuildCondition) DeepCopy() *BuildCondition { + if in == nil { + return nil + } + out := new(BuildCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BuildList) DeepCopyInto(out *BuildList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Build, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BuildList. +func (in *BuildList) DeepCopy() *BuildList { + if in == nil { + return nil + } + out := new(BuildList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BuildList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BuildSpec) DeepCopyInto(out *BuildSpec) { + *out = *in + if in.Source != nil { + in, out := &in.Source, &out.Source + if *in == nil { + *out = nil + } else { + *out = new(SourceSpec) + (*in).DeepCopyInto(*out) + } + } + if in.Steps != nil { + in, out := &in.Steps, &out.Steps + *out = make([]v1.Container, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Volumes != nil { + in, out := &in.Volumes, &out.Volumes + *out = make([]v1.Volume, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Template != nil { + in, out := &in.Template, &out.Template + if *in == nil { + *out = nil + } else { + *out = new(TemplateInstantiationSpec) + (*in).DeepCopyInto(*out) + } + } + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BuildSpec. +func (in *BuildSpec) DeepCopy() *BuildSpec { + if in == nil { + return nil + } + out := new(BuildSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BuildStatus) DeepCopyInto(out *BuildStatus) { + *out = *in + if in.Cluster != nil { + in, out := &in.Cluster, &out.Cluster + if *in == nil { + *out = nil + } else { + *out = new(ClusterSpec) + **out = **in + } + } + if in.Google != nil { + in, out := &in.Google, &out.Google + if *in == nil { + *out = nil + } else { + *out = new(GoogleSpec) + **out = **in + } + } + in.StartTime.DeepCopyInto(&out.StartTime) + in.CompletionTime.DeepCopyInto(&out.CompletionTime) + if in.StepStates != nil { + in, out := &in.StepStates, &out.StepStates + *out = make([]v1.ContainerState, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]BuildCondition, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BuildStatus. +func (in *BuildStatus) DeepCopy() *BuildStatus { + if in == nil { + return nil + } + out := new(BuildStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BuildTemplate) DeepCopyInto(out *BuildTemplate) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BuildTemplate. +func (in *BuildTemplate) DeepCopy() *BuildTemplate { + if in == nil { + return nil + } + out := new(BuildTemplate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BuildTemplate) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BuildTemplateList) DeepCopyInto(out *BuildTemplateList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]BuildTemplate, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BuildTemplateList. +func (in *BuildTemplateList) DeepCopy() *BuildTemplateList { + if in == nil { + return nil + } + out := new(BuildTemplateList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BuildTemplateList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BuildTemplateSpec) DeepCopyInto(out *BuildTemplateSpec) { + *out = *in + if in.Parameters != nil { + in, out := &in.Parameters, &out.Parameters + *out = make([]ParameterSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Steps != nil { + in, out := &in.Steps, &out.Steps + *out = make([]v1.Container, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Volumes != nil { + in, out := &in.Volumes, &out.Volumes + *out = make([]v1.Volume, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BuildTemplateSpec. +func (in *BuildTemplateSpec) DeepCopy() *BuildTemplateSpec { + if in == nil { + return nil + } + out := new(BuildTemplateSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterSpec. +func (in *ClusterSpec) DeepCopy() *ClusterSpec { + if in == nil { + return nil + } + out := new(ClusterSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GCSSourceSpec) DeepCopyInto(out *GCSSourceSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GCSSourceSpec. +func (in *GCSSourceSpec) DeepCopy() *GCSSourceSpec { + if in == nil { + return nil + } + out := new(GCSSourceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GitSourceSpec) DeepCopyInto(out *GitSourceSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitSourceSpec. +func (in *GitSourceSpec) DeepCopy() *GitSourceSpec { + if in == nil { + return nil + } + out := new(GitSourceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GoogleSpec) DeepCopyInto(out *GoogleSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GoogleSpec. +func (in *GoogleSpec) DeepCopy() *GoogleSpec { + if in == nil { + return nil + } + out := new(GoogleSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ParameterSpec) DeepCopyInto(out *ParameterSpec) { + *out = *in + if in.Default != nil { + in, out := &in.Default, &out.Default + if *in == nil { + *out = nil + } else { + *out = new(string) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ParameterSpec. +func (in *ParameterSpec) DeepCopy() *ParameterSpec { + if in == nil { + return nil + } + out := new(ParameterSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SourceSpec) DeepCopyInto(out *SourceSpec) { + *out = *in + if in.Git != nil { + in, out := &in.Git, &out.Git + if *in == nil { + *out = nil + } else { + *out = new(GitSourceSpec) + **out = **in + } + } + if in.GCS != nil { + in, out := &in.GCS, &out.GCS + if *in == nil { + *out = nil + } else { + *out = new(GCSSourceSpec) + **out = **in + } + } + if in.Custom != nil { + in, out := &in.Custom, &out.Custom + if *in == nil { + *out = nil + } else { + *out = new(v1.Container) + (*in).DeepCopyInto(*out) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SourceSpec. +func (in *SourceSpec) DeepCopy() *SourceSpec { + if in == nil { + return nil + } + out := new(SourceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TemplateInstantiationSpec) DeepCopyInto(out *TemplateInstantiationSpec) { + *out = *in + if in.Arguments != nil { + in, out := &in.Arguments, &out.Arguments + *out = make([]ArgumentSpec, len(*in)) + copy(*out, *in) + } + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]v1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TemplateInstantiationSpec. +func (in *TemplateInstantiationSpec) DeepCopy() *TemplateInstantiationSpec { + if in == nil { + return nil + } + out := new(TemplateInstantiationSpec) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/github.com/knative/build/pkg/client/clientset/versioned/scheme/doc.go b/vendor/github.com/knative/build/pkg/client/clientset/versioned/scheme/doc.go new file mode 100644 index 00000000000..52627884652 --- /dev/null +++ b/vendor/github.com/knative/build/pkg/client/clientset/versioned/scheme/doc.go @@ -0,0 +1,17 @@ +/* +Copyright 2018 The Knative Authors + +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. +*/ +// This package contains the scheme of the automatically generated clientset. +package scheme diff --git a/vendor/github.com/knative/build/pkg/client/clientset/versioned/scheme/register.go b/vendor/github.com/knative/build/pkg/client/clientset/versioned/scheme/register.go new file mode 100644 index 00000000000..3faf6378693 --- /dev/null +++ b/vendor/github.com/knative/build/pkg/client/clientset/versioned/scheme/register.go @@ -0,0 +1,51 @@ +/* +Copyright 2018 The Knative Authors + +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 scheme + +import ( + buildv1alpha1 "github.com/knative/build/pkg/apis/build/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" +) + +var Scheme = runtime.NewScheme() +var Codecs = serializer.NewCodecFactory(Scheme) +var ParameterCodec = runtime.NewParameterCodec(Scheme) + +func init() { + v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + AddToScheme(Scheme) +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +func AddToScheme(scheme *runtime.Scheme) { + buildv1alpha1.AddToScheme(scheme) +} diff --git a/vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/build.go b/vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/build.go new file mode 100644 index 00000000000..7d73648cab3 --- /dev/null +++ b/vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/build.go @@ -0,0 +1,154 @@ +/* +Copyright 2018 The Knative Authors + +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 v1alpha1 + +import ( + v1alpha1 "github.com/knative/build/pkg/apis/build/v1alpha1" + scheme "github.com/knative/build/pkg/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// BuildsGetter has a method to return a BuildInterface. +// A group's client should implement this interface. +type BuildsGetter interface { + Builds(namespace string) BuildInterface +} + +// BuildInterface has methods to work with Build resources. +type BuildInterface interface { + Create(*v1alpha1.Build) (*v1alpha1.Build, error) + Update(*v1alpha1.Build) (*v1alpha1.Build, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.Build, error) + List(opts v1.ListOptions) (*v1alpha1.BuildList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Build, err error) + BuildExpansion +} + +// builds implements BuildInterface +type builds struct { + client rest.Interface + ns string +} + +// newBuilds returns a Builds +func newBuilds(c *BuildV1alpha1Client, namespace string) *builds { + return &builds{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the build, and returns the corresponding build object, and an error if there is any. +func (c *builds) Get(name string, options v1.GetOptions) (result *v1alpha1.Build, err error) { + result = &v1alpha1.Build{} + err = c.client.Get(). + Namespace(c.ns). + Resource("builds"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of Builds that match those selectors. +func (c *builds) List(opts v1.ListOptions) (result *v1alpha1.BuildList, err error) { + result = &v1alpha1.BuildList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("builds"). + VersionedParams(&opts, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested builds. +func (c *builds) Watch(opts v1.ListOptions) (watch.Interface, error) { + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("builds"). + VersionedParams(&opts, scheme.ParameterCodec). + Watch() +} + +// Create takes the representation of a build and creates it. Returns the server's representation of the build, and an error, if there is any. +func (c *builds) Create(build *v1alpha1.Build) (result *v1alpha1.Build, err error) { + result = &v1alpha1.Build{} + err = c.client.Post(). + Namespace(c.ns). + Resource("builds"). + Body(build). + Do(). + Into(result) + return +} + +// Update takes the representation of a build and updates it. Returns the server's representation of the build, and an error, if there is any. +func (c *builds) Update(build *v1alpha1.Build) (result *v1alpha1.Build, err error) { + result = &v1alpha1.Build{} + err = c.client.Put(). + Namespace(c.ns). + Resource("builds"). + Name(build.Name). + Body(build). + Do(). + Into(result) + return +} + +// Delete takes name of the build and deletes it. Returns an error if one occurs. +func (c *builds) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("builds"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *builds) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("builds"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched build. +func (c *builds) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Build, err error) { + result = &v1alpha1.Build{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("builds"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/build_client.go b/vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/build_client.go new file mode 100644 index 00000000000..ff83df4b968 --- /dev/null +++ b/vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/build_client.go @@ -0,0 +1,92 @@ +/* +Copyright 2018 The Knative Authors + +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 v1alpha1 + +import ( + v1alpha1 "github.com/knative/build/pkg/apis/build/v1alpha1" + "github.com/knative/build/pkg/client/clientset/versioned/scheme" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + rest "k8s.io/client-go/rest" +) + +type BuildV1alpha1Interface interface { + RESTClient() rest.Interface + BuildsGetter + BuildTemplatesGetter +} + +// BuildV1alpha1Client is used to interact with features provided by the build.knative.dev group. +type BuildV1alpha1Client struct { + restClient rest.Interface +} + +func (c *BuildV1alpha1Client) Builds(namespace string) BuildInterface { + return newBuilds(c, namespace) +} + +func (c *BuildV1alpha1Client) BuildTemplates(namespace string) BuildTemplateInterface { + return newBuildTemplates(c, namespace) +} + +// NewForConfig creates a new BuildV1alpha1Client for the given config. +func NewForConfig(c *rest.Config) (*BuildV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &BuildV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new BuildV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *BuildV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new BuildV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *BuildV1alpha1Client { + return &BuildV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *BuildV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/buildtemplate.go b/vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/buildtemplate.go new file mode 100644 index 00000000000..4236a729658 --- /dev/null +++ b/vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/buildtemplate.go @@ -0,0 +1,154 @@ +/* +Copyright 2018 The Knative Authors + +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 v1alpha1 + +import ( + v1alpha1 "github.com/knative/build/pkg/apis/build/v1alpha1" + scheme "github.com/knative/build/pkg/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// BuildTemplatesGetter has a method to return a BuildTemplateInterface. +// A group's client should implement this interface. +type BuildTemplatesGetter interface { + BuildTemplates(namespace string) BuildTemplateInterface +} + +// BuildTemplateInterface has methods to work with BuildTemplate resources. +type BuildTemplateInterface interface { + Create(*v1alpha1.BuildTemplate) (*v1alpha1.BuildTemplate, error) + Update(*v1alpha1.BuildTemplate) (*v1alpha1.BuildTemplate, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.BuildTemplate, error) + List(opts v1.ListOptions) (*v1alpha1.BuildTemplateList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.BuildTemplate, err error) + BuildTemplateExpansion +} + +// buildTemplates implements BuildTemplateInterface +type buildTemplates struct { + client rest.Interface + ns string +} + +// newBuildTemplates returns a BuildTemplates +func newBuildTemplates(c *BuildV1alpha1Client, namespace string) *buildTemplates { + return &buildTemplates{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the buildTemplate, and returns the corresponding buildTemplate object, and an error if there is any. +func (c *buildTemplates) Get(name string, options v1.GetOptions) (result *v1alpha1.BuildTemplate, err error) { + result = &v1alpha1.BuildTemplate{} + err = c.client.Get(). + Namespace(c.ns). + Resource("buildtemplates"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of BuildTemplates that match those selectors. +func (c *buildTemplates) List(opts v1.ListOptions) (result *v1alpha1.BuildTemplateList, err error) { + result = &v1alpha1.BuildTemplateList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("buildtemplates"). + VersionedParams(&opts, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested buildTemplates. +func (c *buildTemplates) Watch(opts v1.ListOptions) (watch.Interface, error) { + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("buildtemplates"). + VersionedParams(&opts, scheme.ParameterCodec). + Watch() +} + +// Create takes the representation of a buildTemplate and creates it. Returns the server's representation of the buildTemplate, and an error, if there is any. +func (c *buildTemplates) Create(buildTemplate *v1alpha1.BuildTemplate) (result *v1alpha1.BuildTemplate, err error) { + result = &v1alpha1.BuildTemplate{} + err = c.client.Post(). + Namespace(c.ns). + Resource("buildtemplates"). + Body(buildTemplate). + Do(). + Into(result) + return +} + +// Update takes the representation of a buildTemplate and updates it. Returns the server's representation of the buildTemplate, and an error, if there is any. +func (c *buildTemplates) Update(buildTemplate *v1alpha1.BuildTemplate) (result *v1alpha1.BuildTemplate, err error) { + result = &v1alpha1.BuildTemplate{} + err = c.client.Put(). + Namespace(c.ns). + Resource("buildtemplates"). + Name(buildTemplate.Name). + Body(buildTemplate). + Do(). + Into(result) + return +} + +// Delete takes name of the buildTemplate and deletes it. Returns an error if one occurs. +func (c *buildTemplates) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("buildtemplates"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *buildTemplates) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("buildtemplates"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched buildTemplate. +func (c *buildTemplates) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.BuildTemplate, err error) { + result = &v1alpha1.BuildTemplate{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("buildtemplates"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/doc.go b/vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/doc.go new file mode 100644 index 00000000000..10ede9da2f0 --- /dev/null +++ b/vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/doc.go @@ -0,0 +1,17 @@ +/* +Copyright 2018 The Knative Authors + +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. +*/ +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/generated_expansion.go b/vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/generated_expansion.go new file mode 100644 index 00000000000..d74db3e3647 --- /dev/null +++ b/vendor/github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1/generated_expansion.go @@ -0,0 +1,20 @@ +/* +Copyright 2018 The Knative Authors + +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 v1alpha1 + +type BuildExpansion interface{} + +type BuildTemplateExpansion interface{} diff --git a/vendor/github.com/knative/build/pkg/logs/logs.go b/vendor/github.com/knative/build/pkg/logs/logs.go new file mode 100644 index 00000000000..a1309c66cbd --- /dev/null +++ b/vendor/github.com/knative/build/pkg/logs/logs.go @@ -0,0 +1,243 @@ +/* +Copyright 2018 Knative Authors 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 logs + +import ( + "bufio" + "context" + "errors" + "fmt" + "io" + "time" + + buildv1alpha1 "github.com/knative/build/pkg/client/clientset/versioned/typed/build/v1alpha1" + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" + corev1 "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" +) + +const buildExecuteFailed = "BuildExecuteFailed" + +// Tail tails the logs for a build. +func Tail(ctx context.Context, out io.Writer, buildName, namespace string) error { + loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() + kubeConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{}) + + cfg, err := kubeConfig.ClientConfig() + if err != nil { + return fmt.Errorf("getting clientConfig: %v", err) + } + + podName, err := podName(cfg, out, buildName, namespace) + if err != nil { + return fmt.Errorf("getting build pod: %v", err) + } + + client, err := corev1.NewForConfig(cfg) + if err != nil { + return fmt.Errorf("getting kubernetes client: %v", err) + } + + pods := client.Pods(namespace) + watcher := podWatcher{ + pods: pods, + name: podName, + } + if err := watcher.start(ctx); err != nil { + return fmt.Errorf("watching pod: %v", err) + } + + pod, err := watcher.waitForPod(ctx, func(p *v1.Pod) bool { + return len(p.Status.InitContainerStatuses) > 0 + }) + if err != nil { + return err + } + + for i, container := range pod.Status.InitContainerStatuses { + pod, err := watcher.waitForPod(ctx, func(p *v1.Pod) bool { + waiting := p.Status.InitContainerStatuses[i].State.Waiting + if waiting == nil { + return true + } + + if waiting.Message != "" { + fmt.Fprintln(out, red(fmt.Sprintf("[%s] %s", container.Name, waiting.Message))) + } + + return false + }) + if err != nil { + return fmt.Errorf("waiting for container: %v", err) + } + + container := pod.Status.InitContainerStatuses[i] + followContainer := container.State.Terminated == nil + if err := printContainerLogs(ctx, out, pods, podName, container.Name, followContainer); err != nil { + return fmt.Errorf("printing logs: %v", err) + } + + pod, err = watcher.waitForPod(ctx, func(p *v1.Pod) bool { + return p.Status.InitContainerStatuses[i].State.Terminated != nil + }) + if err != nil { + return fmt.Errorf("waiting for container termination: %v", err) + } + + container = pod.Status.InitContainerStatuses[i] + terminated := container.State.Terminated + if terminated.ExitCode != 0 { + message := "Build Failed" + if terminated.Message != "" { + message += ": " + terminated.Message + } + + fmt.Fprintln(out, red(fmt.Sprintf("[%s] %s", container.Name, message))) + return nil + } + } + + return nil +} + +type podWatcher struct { + pods corev1.PodInterface + name string + + versions chan *v1.Pod + last *v1.Pod +} + +func (w *podWatcher) start(ctx context.Context) error { + w.versions = make(chan *v1.Pod, 100) + + watcher, err := w.pods.Watch(metav1.ListOptions{ + IncludeUninitialized: true, + FieldSelector: fields.OneTermEqualSelector("metadata.name", w.name).String(), + }) + if err != nil { + return fmt.Errorf("watching pod: %v", err) + } + + go func() { + for { + select { + case <-ctx.Done(): + watcher.Stop() + return + case evt, ok := <-watcher.ResultChan(): + if !ok { + // TODO: reconnect watch + } + + w.versions <- evt.Object.(*v1.Pod) + } + } + }() + + return nil +} + +func (w *podWatcher) waitForPod(ctx context.Context, predicate func(pod *v1.Pod) bool) (*v1.Pod, error) { + if w.last != nil && predicate(w.last) { + return w.last, nil + } + + for { + select { + case <-ctx.Done(): + return nil, errors.New("watch cancelled") + case w.last = <-w.versions: + if predicate(w.last) { + return w.last, nil + } + } + } +} + +func printContainerLogs(ctx context.Context, out io.Writer, pods corev1.PodExpansion, podName, containerName string, follow bool) error { + rc, err := pods.GetLogs(podName, &v1.PodLogOptions{ + Container: containerName, + Follow: follow, + }).Stream() + if err != nil { + return err + } + defer rc.Close() + + return streamLogs(ctx, out, containerName, rc) +} + +func streamLogs(ctx context.Context, out io.Writer, containerName string, rc io.Reader) error { + prefix := green(fmt.Sprintf("[%s]", containerName)) + " " + + r := bufio.NewReader(rc) + for { + select { + case <-ctx.Done(): + return nil + default: + } + + line, err := r.ReadBytes('\n') + if err == io.EOF { + if len(line) > 0 { + fmt.Fprintf(out, "%s%s\n", prefix, line) + } + return nil + } + if err != nil { + return err + } + + fmt.Fprintf(out, "%s%s", prefix, line) + } +} + +// podName finds the pod name for a given build. +func podName(cfg *rest.Config, out io.Writer, buildName, namespace string) (string, error) { + client, err := buildv1alpha1.NewForConfig(cfg) + if err != nil { + return "", fmt.Errorf("getting build client: %v", err) + } + + for ; ; time.Sleep(time.Second) { + b, err := client.Builds(namespace).Get(buildName, metav1.GetOptions{IncludeUninitialized: true}) + if err != nil { + return "", fmt.Errorf("getting build: %v", err) + } + + cluster := b.Status.Cluster + if cluster != nil && cluster.PodName != "" { + return cluster.PodName, nil + } + + for _, condition := range b.Status.Conditions { + if condition.Reason == buildExecuteFailed { + return "", fmt.Errorf("build failed: %s", condition.Message) + } + } + } +} + +func green(text string) string { + return fmt.Sprintf("\033[%dm%s\033[0m", 32, text) +} + +func red(text string) string { + return fmt.Sprintf("\033[%dm%s\033[0m", 31, text) +}