diff --git a/.gitignore b/.gitignore
index 39a879e5a..51ac57cdb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,3 +25,4 @@ Thumbs.db
csrf_headers.txt
/dashboard
+/build-maker
diff --git a/base/200-clusterrole-tenant.yaml b/base/200-clusterrole-tenant.yaml
index 8d0fa445d..49ce70963 100644
--- a/base/200-clusterrole-tenant.yaml
+++ b/base/200-clusterrole-tenant.yaml
@@ -33,7 +33,20 @@ rules:
- apiGroups:
- dashboard.tekton.dev
resources:
+ - builds
+ - builds/status
- extensions
+ - projects
+ - projects/status
+ verbs:
+ - get
+ - list
+ - watch
+ - apiGroups:
+ - extensions
+ - apps
+ resources:
+ - ingresses
verbs:
- get
- list
diff --git a/base/202-build-crd.yaml b/base/202-build-crd.yaml
new file mode 100644
index 000000000..e45bdf0f2
--- /dev/null
+++ b/base/202-build-crd.yaml
@@ -0,0 +1,59 @@
+# Copyright 2019 The Tekton 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.
+
+---
+apiVersion: apiextensions.k8s.io/v1beta1
+kind: CustomResourceDefinition
+metadata:
+ name: builds.dashboard.tekton.dev
+ labels:
+ app.kubernetes.io/component: dashboard
+ app.kubernetes.io/instance: default
+ app.kubernetes.io/part-of: tekton-dashboard
+spec:
+ group: dashboard.tekton.dev
+ versions:
+ - name: v1alpha1
+ served: true
+ storage: true
+ preserveUnknownFields: false
+ validation:
+ openAPIV3Schema:
+ type: object
+ # One can use x-kubernetes-preserve-unknown-fields: true at the root
+ # of the schema (and inside any properties, additionalProperties)
+ # to get the traditional CRD behaviour that nothing is pruned, despite
+ # setting spec.preserveUnknownProperties: false.
+ #
+ # See https://kubernetes.io/blog/2019/06/20/crd-structural-schema/
+ # See issue: https://github.com/knative/serving/issues/912
+ x-kubernetes-preserve-unknown-fields: true
+ names:
+ kind: Build
+ plural: builds
+ categories:
+ - tekton
+ - tekton-dashboard
+ scope: Namespaced
+ # additionalPrinterColumns:
+ # - name: Repository URL
+ # type: string
+ # JSONPath: .spec.repositoryUrl
+ # - name: Age
+ # type: date
+ # JSONPath: .metadata.creationTimestamp
+ # Opt into the status subresource so metadata.generation
+ # starts to increment
+ subresources:
+ status: {}
diff --git a/base/202-project-crd.yaml b/base/202-project-crd.yaml
new file mode 100644
index 000000000..2ea337fa2
--- /dev/null
+++ b/base/202-project-crd.yaml
@@ -0,0 +1,64 @@
+# Copyright 2019 The Tekton 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.
+
+---
+apiVersion: apiextensions.k8s.io/v1beta1
+kind: CustomResourceDefinition
+metadata:
+ name: projects.dashboard.tekton.dev
+ labels:
+ app.kubernetes.io/component: dashboard
+ app.kubernetes.io/instance: default
+ app.kubernetes.io/part-of: tekton-dashboard
+spec:
+ group: dashboard.tekton.dev
+ versions:
+ - name: v1alpha1
+ served: true
+ storage: true
+ preserveUnknownFields: false
+ validation:
+ openAPIV3Schema:
+ type: object
+ # One can use x-kubernetes-preserve-unknown-fields: true at the root
+ # of the schema (and inside any properties, additionalProperties)
+ # to get the traditional CRD behaviour that nothing is pruned, despite
+ # setting spec.preserveUnknownProperties: false.
+ #
+ # See https://kubernetes.io/blog/2019/06/20/crd-structural-schema/
+ # See issue: https://github.com/knative/serving/issues/912
+ x-kubernetes-preserve-unknown-fields: true
+ names:
+ kind: Project
+ plural: projects
+ categories:
+ - tekton
+ - tekton-dashboard
+ shortNames:
+ - project
+ scope: Namespaced
+ additionalPrinterColumns:
+ - name: Service account
+ type: string
+ JSONPath: .spec.serviceAccountName
+ - name: Ingress URL
+ type: string
+ JSONPath: .spec.ingress.host
+ - name: Age
+ type: date
+ JSONPath: .metadata.creationTimestamp
+ # Opt into the status subresource so metadata.generation
+ # starts to increment
+ subresources:
+ status: {}
diff --git a/cmd/build-maker/Dockerfile b/cmd/build-maker/Dockerfile
new file mode 100644
index 000000000..fd1ad50fc
--- /dev/null
+++ b/cmd/build-maker/Dockerfile
@@ -0,0 +1,16 @@
+
+FROM golang as goBuilder
+
+ARG GOARCH=amd64
+
+USER root
+WORKDIR /work
+COPY . .
+RUN GO111MODULE=on CGO_ENABLED=0 GOOS=linux GOARCH=$GOARCH go build ./cmd/build-maker
+
+FROM alpine
+
+WORKDIR /work
+COPY --from=goBuilder /work/build-maker .
+
+ENTRYPOINT ["./build-maker"]
diff --git a/cmd/build-maker/main.go b/cmd/build-maker/main.go
new file mode 100644
index 000000000..916456cad
--- /dev/null
+++ b/cmd/build-maker/main.go
@@ -0,0 +1,147 @@
+/*
+Copyright 2019-2020 The Tekton 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 main
+
+import (
+ "os"
+ "strings"
+
+ "github.com/spf13/pflag"
+ dashboardv1alpha1 "github.com/tektoncd/dashboard/pkg/apis/dashboard/v1alpha1"
+ dashboardclientset "github.com/tektoncd/dashboard/pkg/client/clientset/versioned"
+ "github.com/tektoncd/dashboard/pkg/logging"
+ pipelinev1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
+ resourcev1alpha1 "github.com/tektoncd/pipeline/pkg/apis/resource/v1alpha1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/types"
+ "k8s.io/apimachinery/pkg/util/yaml"
+ "k8s.io/client-go/rest"
+ "k8s.io/client-go/tools/clientcmd"
+)
+
+var (
+ kubeConfigPath = pflag.String("kube-config", "", "Path to kube config file")
+ file = pflag.String("file", "", "PipelineRun spec file")
+ namespace = pflag.String("namespace", "", "Target namespace")
+ ownerName = pflag.String("owner-name", "", "Owner project name")
+ ownerUid = pflag.String("owner-uid", "", "Owner project UID")
+ url = pflag.String("url", "", "Repository url")
+ revision = pflag.String("revision", "", "Revision")
+ logLevel = pflag.String("log-level", "info", "Minimum log level output by the logger")
+ logFormat = pflag.String("log-format", "json", "Format for log output (json or console)")
+ params = pflag.StringArray("param", nil, "Param int the form name=value")
+)
+
+func main() {
+ pflag.Parse()
+
+ logging.InitLogger(*logLevel, *logFormat)
+
+ if *file == "" {
+ logging.Log.Panic("file must be provided")
+ }
+
+ if *namespace == "" {
+ logging.Log.Panic("namespace must be provided")
+ }
+
+ if *url == "" {
+ logging.Log.Panic("url must be provided")
+ }
+
+ if *revision == "" {
+ logging.Log.Panic("revision must be provided")
+ }
+
+ if f, err := os.Open(*file); err != nil {
+ logging.Log.Panicf("Error loading file (%s): %s", *file, err.Error())
+ } else {
+ decoder := yaml.NewYAMLOrJSONDecoder(f, 4096)
+
+ var pipelineSpec pipelinev1beta1.PipelineSpec
+
+ if err := decoder.Decode(&pipelineSpec); err != nil {
+ logging.Log.Panicf("Error decoding file: %s", err.Error())
+ }
+
+ var cfg *rest.Config
+
+ if *kubeConfigPath != "" {
+ cfg, err = clientcmd.BuildConfigFromFlags("", *kubeConfigPath)
+ if err != nil {
+ logging.Log.Panicf("Error building kubeconfig from %s: %s", *kubeConfigPath, err.Error())
+ }
+ } else {
+ if cfg, err = rest.InClusterConfig(); err != nil {
+ logging.Log.Panicf("Error building kubeconfig: %s", err.Error())
+ }
+ }
+
+ dashboardClient, err := dashboardclientset.NewForConfig(cfg)
+ if err != nil {
+ logging.Log.Panicf("Error building dashboard clientset: %s", err.Error())
+ }
+
+ build := &dashboardv1alpha1.Build{
+ Spec: dashboardv1alpha1.BuildSpec{
+ PipelineSpec: pipelineSpec,
+ PipelineResourceSpec: resourcev1alpha1.PipelineResourceSpec{
+ Type: "git",
+ Params: []resourcev1alpha1.ResourceParam{
+ {
+ Name: "url",
+ Value: *url,
+ },
+ {
+ Name: "revision",
+ Value: *revision,
+ },
+ },
+ },
+ },
+ }
+
+ if params != nil {
+ for _, param := range *params {
+ nameValue := strings.Split(param, "=")
+ if len(nameValue) == 2 {
+ build.Spec.Params = append(build.Spec.Params, pipelinev1beta1.Param{
+ Name: nameValue[0],
+ Value: pipelinev1beta1.NewArrayOrString(nameValue[1]),
+ })
+ }
+ }
+ }
+
+ build.GenerateName = "build-"
+
+ if *ownerName != "" && *ownerUid != "" {
+ trueHelper := true
+ build.OwnerReferences = append(build.OwnerReferences, metav1.OwnerReference{
+ APIVersion: "dashboard.tekton.dev/v1alpha1",
+ Kind: "Project",
+ Name: *ownerName,
+ UID: types.UID(*ownerUid),
+ Controller: &trueHelper,
+ BlockOwnerDeletion: &trueHelper,
+ })
+ }
+
+ if build, err := dashboardClient.DashboardV1alpha1().Builds(*namespace).Create(build); err != nil {
+ logging.Log.Panicf("Error creating build: %s", err.Error())
+ } else {
+ logging.Log.Infof("Created build %s in namespace %s", build.Name, build.Namespace)
+ }
+ }
+}
diff --git a/cmd/dashboard/main.go b/cmd/dashboard/main.go
index cea27b5be..b84592cfe 100644
--- a/cmd/dashboard/main.go
+++ b/cmd/dashboard/main.go
@@ -31,6 +31,7 @@ import (
"github.com/tektoncd/dashboard/pkg/router"
pipelineclientset "github.com/tektoncd/pipeline/pkg/client/clientset/versioned"
resourceclientset "github.com/tektoncd/pipeline/pkg/client/resource/clientset/versioned"
+ triggersclientset "github.com/tektoncd/triggers/pkg/client/clientset/versioned"
k8sclientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
@@ -102,6 +103,11 @@ func main() {
logging.Log.Errorf("Error building pipeline clientset: %s", err.Error())
}
+ triggersClient, err := triggersclientset.NewForConfig(cfg)
+ if err != nil {
+ logging.Log.Errorf("Error building triggers clientset: %s", err.Error())
+ }
+
dashboardClient, err := dashboardclientset.NewForConfig(cfg)
if err != nil {
logging.Log.Errorf("Error building dashboard clientset: %s", err.Error())
@@ -147,6 +153,7 @@ func main() {
DashboardClient: dashboardClient,
PipelineClient: pipelineClient,
PipelineResourceClient: pipelineResourceClient,
+ TriggersClient: triggersClient,
K8sClient: k8sClient,
RouteClient: routeClient,
Options: options,
@@ -160,7 +167,9 @@ func main() {
resyncDur := time.Second * 30
controllers.StartTektonControllers(resource.PipelineClient, resource.PipelineResourceClient, *tenantNamespace, resyncDur, ctx.Done())
controllers.StartKubeControllers(resource.K8sClient, resyncDur, *tenantNamespace, *readOnly, routerHandler, ctx.Done())
- controllers.StartDashboardControllers(resource.DashboardClient, resyncDur, *tenantNamespace, ctx.Done())
+ controllers.StartDashboardControllers(resource.DashboardClient, resource.TriggersClient, resource.K8sClient, resyncDur, *tenantNamespace, ctx.Done())
+
+ controllers.StartRuntimeControllers(cfg)
logging.Log.Infof("Creating server and entering wait loop")
CSRF := csrf.Protect(
diff --git a/go.mod b/go.mod
index 5afb031a8..507d477a5 100644
--- a/go.mod
+++ b/go.mod
@@ -12,20 +12,21 @@ replace (
)
require (
- github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible
github.com/emicklei/go-restful v2.12.0+incompatible
github.com/google/go-cmp v0.4.0
github.com/gorilla/csrf v1.7.0
github.com/gorilla/websocket v1.4.2
github.com/openshift/api v3.9.0+incompatible // indirect
github.com/openshift/client-go v0.0.0-20191125132246-f6563a70e19a
+ github.com/spf13/pflag v1.0.5
github.com/tektoncd/pipeline v0.12.1
github.com/tektoncd/plumbing v0.0.0-20200430135134-e53521e1d887
+ github.com/tektoncd/triggers v0.6.0
go.uber.org/zap v1.15.0
- k8s.io/api v0.17.6
- k8s.io/apimachinery v0.17.6
+ k8s.io/api v0.18.2
+ k8s.io/apimachinery v0.18.2
k8s.io/client-go v11.0.1-0.20190805182717-6502b5e7b1b5+incompatible
k8s.io/code-generator v0.18.0
knative.dev/pkg v0.0.0-20200529164702-389d28f9b67a
- sigs.k8s.io/yaml v1.2.0 // indirect
+ sigs.k8s.io/controller-runtime v0.5.0
)
diff --git a/go.sum b/go.sum
index d06d139f2..134edc537 100644
--- a/go.sum
+++ b/go.sum
@@ -42,6 +42,8 @@ contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e
contrib.go.opencensus.io/exporter/stackdriver v0.12.8/go.mod h1:XyyafDnFOsqoxHJgTFycKZMrRUrPThLh2iYTJF6uoO0=
contrib.go.opencensus.io/exporter/stackdriver v0.12.9-0.20191108183826-59d068f8d8ff h1:g4QkFNN0ak+sCs/jqbhYLNkQaF1NVaKVoQ4Xm1RV3wM=
contrib.go.opencensus.io/exporter/stackdriver v0.12.9-0.20191108183826-59d068f8d8ff/go.mod h1:XyyafDnFOsqoxHJgTFycKZMrRUrPThLh2iYTJF6uoO0=
+contrib.go.opencensus.io/exporter/stackdriver v0.12.9 h1:ZRVpDigsb+nVI/yps/NLDOYzYjFFmm3OCsBhmYocxR0=
+contrib.go.opencensus.io/exporter/stackdriver v0.12.9/go.mod h1:XyyafDnFOsqoxHJgTFycKZMrRUrPThLh2iYTJF6uoO0=
contrib.go.opencensus.io/exporter/zipkin v0.1.1/go.mod h1:GMvdSl3eJ2gapOaLKzTKE3qDgUkJ86k9k3yY2eqwkzc=
contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE=
contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcigGlFvXwEGEnkRLA=
@@ -143,6 +145,7 @@ github.com/andybalholm/brotli v0.0.0-20190621154722-5f990b63d2d6/go.mod h1:+lx6/
github.com/andygrunwald/go-gerrit v0.0.0-20190120104749-174420ebee6c/go.mod h1:0iuRQp6WJ44ts+iihy5E/WlPqfg5RNeQxOmzRkxCdtk=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q=
+github.com/antlr/antlr4 v0.0.0-20190819145818-b43a4c3a8015/go.mod h1:T7PbCXFs94rrTttyxjbyT5+/1V8T2TYDejxUfHJjw1Y=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg=
@@ -204,6 +207,7 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp
github.com/clarketm/json v1.13.4/go.mod h1:ynr2LRfb0fQU34l07csRNBTcivjySLLiY1YzQqKVfdo=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudevents/sdk-go v0.0.0-20190509003705-56931988abe3/go.mod h1:j1nZWMLGg3om8SswStBoY6/SHvcLM19MuZqwDtMtmzs=
+github.com/cloudevents/sdk-go v1.0.0/go.mod h1:3TkmM0cFqkhCHOq5JzzRU/RxRkwzoS8TZ+G448qVTog=
github.com/cloudevents/sdk-go v1.1.2/go.mod h1:ss+jWJ88wypiewnPEzChSBzTYXGpdcILoN9YHk8uhTQ=
github.com/cloudevents/sdk-go/v2 v2.0.0-preview8/go.mod h1:akZr/joO3DfDft2KZnI91LEs15NSKIBNPYcAMBQ1xbk=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
@@ -336,6 +340,7 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
github.com/go-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk=
+github.com/go-logr/zapr v0.1.1 h1:qXBXPDdNncunGs7XeEpsJt8wCjYBygluzfdLO0G5baE=
github.com/go-logr/zapr v0.1.1/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk=
github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
@@ -410,6 +415,7 @@ github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaL
github.com/gobuffalo/envy v1.6.5/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ=
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w=
+github.com/gobuffalo/envy v1.9.0/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
@@ -458,6 +464,8 @@ github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Z
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/cel-go v0.4.2/go.mod h1:0pIisECLUDurNyQcYRcNjhGp0j/yM6v617EmXsBJE3A=
+github.com/google/cel-spec v0.4.0/go.mod h1:2pBM5cU4UKjbPDXBgwWkiwBsVgnxknuEJ7C5TDWwORQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -469,6 +477,7 @@ github.com/google/go-containerregistry v0.0.0-20200123184029-53ce695e4179/go.mod
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-github/v27 v27.0.6/go.mod h1:/0Gr8pJ55COkmv+S/yPKCczSkUPIM/LnFyubufRNIS0=
github.com/google/go-github/v29 v29.0.3/go.mod h1:CHKiKKPHJ0REzfwc14QMklvtHwCveD0PxlMjLlzAM5E=
+github.com/google/go-github/v31 v31.0.0/go.mod h1:NQPZol8/1sMoWYGN2yaALIBytu17gAWfhbweiEed3pM=
github.com/google/go-licenses v0.0.0-20191112164736-212ea350c932/go.mod h1:16wa6pRqNDUIhOtwF0GcROVqMeXHZJ7H6eGDFUh5Pfk=
github.com/google/go-licenses v0.0.0-20200227160636-0fa8c766a591/go.mod h1:JWeTIGPLQ9gF618ZOdlUitd1gRR/l99WOkHOlmR/UVA=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
@@ -546,6 +555,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.4/go.mod h1:vNeuVxBJEsws4ogUvrchl83t
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.12.1 h1:zCy2xE9ablevUOrUZc3Dl72Dt+ya2FNAvC2yLYMHzi4=
github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c=
+github.com/grpc-ecosystem/grpc-gateway v1.13.0 h1:sBDQoHXrOlfPobnKw69FIKa1wg9qsLLvvQ/Y19WtFgI=
+github.com/grpc-ecosystem/grpc-gateway v1.13.0/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c=
github.com/h2non/gock v1.0.9/go.mod h1:CZMcB0Lg5IWnr9bF79pPMg9WeV6WumxQiUJ1UvdO1iE=
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
@@ -905,6 +916,7 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/tektoncd/pipeline v0.8.0/go.mod h1:IZzJdiX9EqEMuUcgdnElozdYYRh0/ZRC+NKMLj1K3Yw=
github.com/tektoncd/pipeline v0.10.1/go.mod h1:D2X0exT46zYx95BU7ByM8+erpjoN7thmUBvlKThOszU=
+github.com/tektoncd/pipeline v0.11.3/go.mod h1:hlkH32S92+/UODROH0dmxzyuMxfRFp/Nc3e29MewLn8=
github.com/tektoncd/pipeline v0.12.1 h1:x+3f0ScP9vmIcGQLzKbwPwBTcrqgDFfWEIaRqDN/doo=
github.com/tektoncd/pipeline v0.12.1/go.mod h1:FLppx3k2Xlk8bsEYvlnp/wz3SK07rMFk4vaSAI6aTCM=
github.com/tektoncd/plumbing v0.0.0-20191216083742-847dcf196de9/go.mod h1:QZHgU07PRBTRF6N57w4+ApRu8OgfYLFNqCDlfEZaD9Y=
@@ -912,7 +924,12 @@ github.com/tektoncd/plumbing v0.0.0-20200217163359-cd0db6e567d2/go.mod h1:QZHgU0
github.com/tektoncd/plumbing v0.0.0-20200430135134-e53521e1d887 h1:crv70CBAJ2gZFSbf13aRVwdbjR2GYwTms/ZEok/SnFM=
github.com/tektoncd/plumbing v0.0.0-20200430135134-e53521e1d887/go.mod h1:cZPJIeTIoP7UPTxQyTQLs7VE1TiXJSNj0te+If4Q+jI=
github.com/tektoncd/plumbing/pipelinerun-logs v0.0.0-20191206114338-712d544c2c21/go.mod h1:S62EUWtqmejjJgUMOGB1CCCHRp6C706laH06BoALkzU=
+github.com/tektoncd/triggers v0.6.0 h1:a2/SUTkkuEDd0M2Uo0pe/x0cjc+9aWauccN8IIBowT0=
+github.com/tektoncd/triggers v0.6.0/go.mod h1:59Cz77wfFpPYXhzyx5IRqXw1JvX8Oja29/DkA4ivPPI=
+github.com/tidwall/gjson v1.3.5/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls=
+github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/tidwall/sjson v1.0.4/go.mod h1:bURseu1nuBkFpIES5cz6zBtjmYeOQmEESshn7VpF15Y=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tsenart/vegeta v12.7.1-0.20190725001342-b5f4fca92137+incompatible/go.mod h1:Smz/ZWfhKRcyDDChZkG3CyTHdj87lHzio/HOCkbndXM=
@@ -1300,6 +1317,7 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200317114155-1f3552e48f24/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200326112834-f447254575fd h1:DVCc2PgW9UrvHGZGEv4Mt3uSeQtUrrs7r8pUw+bVwWI=
google.golang.org/genproto v0.0.0-20200326112834-f447254575fd/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
@@ -1429,6 +1447,7 @@ k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH
k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc=
k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
+k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29 h1:NeQXVJ2XFSkRoPzRo8AId01ZER+j8oV4SZADT4iBOXQ=
k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29/go.mod h1:F+5wygcW0wmRTnM3cOgIqGivxkwSWIWT5YdsDbeAOaU=
k8s.io/kubectl v0.17.2 h1:QZR8Q6lWiVRjwKslekdbN5WPMp53dS/17j5e+oi5XVU=
@@ -1449,11 +1468,16 @@ k8s.io/utils v0.0.0-20190907131718-3d4f5b7dea0b/go.mod h1:sZAwmy6armz5eXlNoLmJcl
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20200124190032-861946025e34 h1:HjlUD6M0K3P8nRXmr2B9o4F9dUy9TCj/aEpReeyi6+k=
k8s.io/utils v0.0.0-20200124190032-861946025e34/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
+k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89 h1:d4vVOjXm687F1iLSP2q3lyPPuyvTUt3aVoBpi2DqRsU=
+k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
knative.dev/caching v0.0.0-20190719140829-2032732871ff/go.mod h1:dHXFU6CGlLlbzaWc32g80cR92iuBSpsslDNBWI8C7eg=
knative.dev/caching v0.0.0-20200116200605-67bca2c83dfa/go.mod h1:dHXFU6CGlLlbzaWc32g80cR92iuBSpsslDNBWI8C7eg=
+knative.dev/caching v0.0.0-20200228235451-13d271455c74/go.mod h1:dHXFU6CGlLlbzaWc32g80cR92iuBSpsslDNBWI8C7eg=
knative.dev/eventing-contrib v0.6.1-0.20190723221543-5ce18048c08b/go.mod h1:SnXZgSGgMSMLNFTwTnpaOH7hXDzTFtw0J8OmHflNx3g=
+knative.dev/eventing-contrib v0.11.2/go.mod h1:SnXZgSGgMSMLNFTwTnpaOH7hXDzTFtw0J8OmHflNx3g=
knative.dev/pkg v0.0.0-20191101194912-56c2594e4f11/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
knative.dev/pkg v0.0.0-20191111150521-6d806b998379/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
+knative.dev/pkg v0.0.0-20200207155214-fef852970f43/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
knative.dev/pkg v0.0.0-20200306230727-a56a6ea3fa56/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
knative.dev/pkg v0.0.0-20200428194351-90fc61bae7f7/go.mod h1:o+e8OVEJKIuvXPsGVPIautjXgs05xbos7G+QMRjuUps=
knative.dev/pkg v0.0.0-20200505191044-3da93ebb24c2/go.mod h1:Q6sL35DdGs8hIQZKdaCXJGgY8f90BmNBKSb8z6d/BTM=
@@ -1489,6 +1513,7 @@ sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1
sigs.k8s.io/structured-merge-diff v1.0.1 h1:LOs1LZWMsz1xs77Phr/pkB4LFaavH7IVq/3+WTN9XTA=
sigs.k8s.io/structured-merge-diff v1.0.1/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA=
sigs.k8s.io/structured-merge-diff/v2 v2.0.1/go.mod h1:Wb7vfKAodbKgf6tn1Kl0VvGj7mRH6DGaRcixXEJXTsE=
+sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
sigs.k8s.io/testing_frameworks v0.1.1/go.mod h1:VVBKrHmJ6Ekkfz284YKhQePcdycOzNH9qL6ht1zEr/U=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
diff --git a/overlays/installer/base/kustomization.yaml b/overlays/installer/base/kustomization.yaml
index 3eb1a33ce..3d8ca7f63 100644
--- a/overlays/installer/base/kustomization.yaml
+++ b/overlays/installer/base/kustomization.yaml
@@ -23,7 +23,9 @@ resources:
- ../../../base/200-clusterrole-tenant.yaml
- ../../../base/200-clusterrole-triggers.yaml
- ../../../base/201-clusterrolebinding-backend.yaml
+ - ../../../base/202-build-crd.yaml
- ../../../base/202-extension-crd.yaml
+ - ../../../base/202-project-crd.yaml
- ../../../base/203-serviceaccount.yaml
- ../../../base/300-deployment.yaml
- ../../../base/300-service.yaml
diff --git a/overlays/patches/read-write/clusterrole-tenant-patch.yaml b/overlays/patches/read-write/clusterrole-tenant-patch.yaml
index 3a2d49785..2dc6d6725 100644
--- a/overlays/patches/read-write/clusterrole-tenant-patch.yaml
+++ b/overlays/patches/read-write/clusterrole-tenant-patch.yaml
@@ -75,3 +75,32 @@
- delete
- patch
- add
+- op: add
+ path: /rules/-
+ value:
+ apiGroups:
+ - dashboard.tekton.dev
+ resources:
+ - builds
+ - builds/status
+ - extensions
+ - projects
+ - projects/status
+ verbs:
+ - create
+ - update
+ - delete
+ - patch
+- op: add
+ path: /rules/-
+ value:
+ apiGroups:
+ - extensions
+ - apps
+ resources:
+ - ingresses
+ verbs:
+ - create
+ - update
+ - delete
+ - patch
diff --git a/packages/utils/src/utils/router.js b/packages/utils/src/utils/router.js
index 688261927..0eb35f7c1 100644
--- a/packages/utils/src/utils/router.js
+++ b/packages/utils/src/utils/router.js
@@ -20,6 +20,19 @@ export const paths = {
about() {
return '/about';
},
+ builds: {
+ all() {
+ return '/builds';
+ },
+ byName() {
+ return byNamespace({
+ path: '/builds/:buildName'
+ });
+ },
+ byNamespace() {
+ return byNamespace({ path: '/builds' });
+ }
+ },
byNamespace,
clusterTasks: {
all() {
@@ -66,6 +79,19 @@ export const paths = {
return `/extensions/${name}`;
}
},
+ projects: {
+ all() {
+ return '/projects';
+ },
+ byName() {
+ return byNamespace({
+ path: '/projects/:projectName'
+ });
+ },
+ byNamespace() {
+ return byNamespace({ path: '/projects' });
+ }
+ },
importResources() {
return '/importresources';
},
diff --git a/pkg/apis/dashboard/v1alpha1/build_types.go b/pkg/apis/dashboard/v1alpha1/build_types.go
new file mode 100644
index 000000000..dd9fa31f5
--- /dev/null
+++ b/pkg/apis/dashboard/v1alpha1/build_types.go
@@ -0,0 +1,41 @@
+package v1alpha1
+
+import (
+ pipelinev1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
+ resourcev1alpha1 "github.com/tektoncd/pipeline/pkg/apis/resource/v1alpha1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// +genclient
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// +k8s:openapi-gen=true
+type Build struct {
+ metav1.TypeMeta `json:",inline"`
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+ // +optional
+ Spec BuildSpec `json:"spec,omitempty"`
+ // +optional
+ Status BuildStatus `json:"status,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+type BuildList struct {
+ metav1.TypeMeta `json:",inline"`
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+ Items []Build `json:"items"`
+}
+
+type BuildSpec struct {
+ ServiceAccountName string `json:"serviceAccountName"`
+ PipelineResourceSpec resourcev1alpha1.PipelineResourceSpec `json:"pipelineResourceSpec"`
+ PipelineSpec pipelinev1beta1.PipelineSpec `json:"pipelineSpec"`
+ Params []pipelinev1beta1.Param `json:"params"`
+}
+
+type BuildStatus struct {
+ PipelineRun *pipelinev1beta1.PipelineRunStatus `json:"pipelineRun"`
+}
diff --git a/pkg/apis/dashboard/v1alpha1/project_types.go b/pkg/apis/dashboard/v1alpha1/project_types.go
new file mode 100644
index 000000000..037f6e47b
--- /dev/null
+++ b/pkg/apis/dashboard/v1alpha1/project_types.go
@@ -0,0 +1,56 @@
+package v1alpha1
+
+import (
+ pipelinev1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
+ triggersv1alpha1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1"
+ extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// +genclient
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// +k8s:openapi-gen=true
+type Project struct {
+ metav1.TypeMeta `json:",inline"`
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+ // +optional
+ Spec ProjectSpec `json:"spec,omitempty"`
+ // +optional
+ Status ProjectStatus `json:"status,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+type ProjectList struct {
+ metav1.TypeMeta `json:",inline"`
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+ Items []Project `json:"items"`
+}
+
+type ProjectSpec struct {
+ ServiceAccountName string `json:"serviceAccountName"`
+ Ingress *Ingress `json:"ingress"`
+ TriggerTemplate triggersv1alpha1.TriggerTemplateSpec `json:"triggerTemplate"`
+ TriggerBinding triggersv1alpha1.TriggerBindingSpec `json:"triggerBinding"`
+ Interceptors []*triggersv1alpha1.EventInterceptor `json:"interceptors"`
+}
+
+type ProjectStatus struct {
+ TriggerTemplate *triggersv1alpha1.TriggerTemplateStatus `json:"triggerTemplate"`
+ TriggerBinding *triggersv1alpha1.TriggerBindingStatus `json:"triggerBinding"`
+ EventListener *triggersv1alpha1.EventListenerStatus `json:"eventListener"`
+ Ingress *extensionsv1beta1.IngressStatus `json:"ingress"`
+ TaskRuns map[string]*pipelinev1beta1.TaskRunStatus `json:"taskRuns"`
+ Builds map[string]*BuildStatus `json:"builds,omitempty"`
+}
+
+type Ingress struct {
+ Host string `json:"host"`
+ Annotations map[string]string `json:"annotations"`
+ Labels map[string]string `json:"labels"`
+}
+
+// project -> taskrun -> build -> taskrun -> pipelinerun
diff --git a/pkg/apis/dashboard/v1alpha1/register.go b/pkg/apis/dashboard/v1alpha1/register.go
index 31f19be0f..5fe289c29 100644
--- a/pkg/apis/dashboard/v1alpha1/register.go
+++ b/pkg/apis/dashboard/v1alpha1/register.go
@@ -46,8 +46,12 @@ var (
// Adds the list of known types to Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
+ &Build{},
+ &BuildList{},
&Extension{},
&ExtensionList{},
+ &Project{},
+ &ProjectList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
diff --git a/pkg/apis/dashboard/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/dashboard/v1alpha1/zz_generated.deepcopy.go
index 06d42965e..c5e0090b8 100644
--- a/pkg/apis/dashboard/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/dashboard/v1alpha1/zz_generated.deepcopy.go
@@ -21,9 +21,119 @@ limitations under the License.
package v1alpha1
import (
+ v1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
+ triggersv1alpha1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1"
+ extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
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 *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 *BuildList) DeepCopyInto(out *BuildList) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ListMeta.DeepCopyInto(&out.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
+ in.PipelineResourceSpec.DeepCopyInto(&out.PipelineResourceSpec)
+ in.PipelineSpec.DeepCopyInto(&out.PipelineSpec)
+ if in.Params != nil {
+ in, out := &in.Params, &out.Params
+ *out = make([]v1beta1.Param, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+ 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.PipelineRun != nil {
+ in, out := &in.PipelineRun, &out.PipelineRun
+ *out = new(v1beta1.PipelineRunStatus)
+ (*in).DeepCopyInto(*out)
+ }
+ 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 *Extension) DeepCopyInto(out *Extension) {
*out = *in
@@ -99,3 +209,194 @@ func (in *ExtensionSpec) DeepCopy() *ExtensionSpec {
in.DeepCopyInto(out)
return out
}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Ingress) DeepCopyInto(out *Ingress) {
+ *out = *in
+ if in.Annotations != nil {
+ in, out := &in.Annotations, &out.Annotations
+ *out = make(map[string]string, len(*in))
+ for key, val := range *in {
+ (*out)[key] = val
+ }
+ }
+ if in.Labels != nil {
+ in, out := &in.Labels, &out.Labels
+ *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 Ingress.
+func (in *Ingress) DeepCopy() *Ingress {
+ if in == nil {
+ return nil
+ }
+ out := new(Ingress)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Project) DeepCopyInto(out *Project) {
+ *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 Project.
+func (in *Project) DeepCopy() *Project {
+ if in == nil {
+ return nil
+ }
+ out := new(Project)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *Project) 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 *ProjectList) DeepCopyInto(out *ProjectList) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ListMeta.DeepCopyInto(&out.ListMeta)
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]Project, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProjectList.
+func (in *ProjectList) DeepCopy() *ProjectList {
+ if in == nil {
+ return nil
+ }
+ out := new(ProjectList)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ProjectList) 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 *ProjectSpec) DeepCopyInto(out *ProjectSpec) {
+ *out = *in
+ if in.Ingress != nil {
+ in, out := &in.Ingress, &out.Ingress
+ *out = new(Ingress)
+ (*in).DeepCopyInto(*out)
+ }
+ in.TriggerTemplate.DeepCopyInto(&out.TriggerTemplate)
+ in.TriggerBinding.DeepCopyInto(&out.TriggerBinding)
+ if in.Interceptors != nil {
+ in, out := &in.Interceptors, &out.Interceptors
+ *out = make([]*triggersv1alpha1.EventInterceptor, len(*in))
+ for i := range *in {
+ if (*in)[i] != nil {
+ in, out := &(*in)[i], &(*out)[i]
+ *out = new(triggersv1alpha1.EventInterceptor)
+ (*in).DeepCopyInto(*out)
+ }
+ }
+ }
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProjectSpec.
+func (in *ProjectSpec) DeepCopy() *ProjectSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(ProjectSpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ProjectStatus) DeepCopyInto(out *ProjectStatus) {
+ *out = *in
+ if in.TriggerTemplate != nil {
+ in, out := &in.TriggerTemplate, &out.TriggerTemplate
+ *out = new(triggersv1alpha1.TriggerTemplateStatus)
+ **out = **in
+ }
+ if in.TriggerBinding != nil {
+ in, out := &in.TriggerBinding, &out.TriggerBinding
+ *out = new(triggersv1alpha1.TriggerBindingStatus)
+ **out = **in
+ }
+ if in.EventListener != nil {
+ in, out := &in.EventListener, &out.EventListener
+ *out = new(triggersv1alpha1.EventListenerStatus)
+ (*in).DeepCopyInto(*out)
+ }
+ if in.Ingress != nil {
+ in, out := &in.Ingress, &out.Ingress
+ *out = new(extensionsv1beta1.IngressStatus)
+ (*in).DeepCopyInto(*out)
+ }
+ if in.TaskRuns != nil {
+ in, out := &in.TaskRuns, &out.TaskRuns
+ *out = make(map[string]*v1beta1.TaskRunStatus, len(*in))
+ for key, val := range *in {
+ var outVal *v1beta1.TaskRunStatus
+ if val == nil {
+ (*out)[key] = nil
+ } else {
+ in, out := &val, &outVal
+ *out = new(v1beta1.TaskRunStatus)
+ (*in).DeepCopyInto(*out)
+ }
+ (*out)[key] = outVal
+ }
+ }
+ if in.Builds != nil {
+ in, out := &in.Builds, &out.Builds
+ *out = make(map[string]*BuildStatus, len(*in))
+ for key, val := range *in {
+ var outVal *BuildStatus
+ if val == nil {
+ (*out)[key] = nil
+ } else {
+ in, out := &val, &outVal
+ *out = new(BuildStatus)
+ (*in).DeepCopyInto(*out)
+ }
+ (*out)[key] = outVal
+ }
+ }
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProjectStatus.
+func (in *ProjectStatus) DeepCopy() *ProjectStatus {
+ if in == nil {
+ return nil
+ }
+ out := new(ProjectStatus)
+ in.DeepCopyInto(out)
+ return out
+}
diff --git a/pkg/broadcaster/broadcaster.go b/pkg/broadcaster/broadcaster.go
index fea181ffd..249a2a397 100644
--- a/pkg/broadcaster/broadcaster.go
+++ b/pkg/broadcaster/broadcaster.go
@@ -56,6 +56,12 @@ const (
ServiceAccountCreated MessageType = "ServiceAccountCreated"
ServiceAccountDeleted MessageType = "ServiceAccountDeleted"
ServiceAccountUpdated MessageType = "ServiceAccountUpdated"
+ ProjectCreated MessageType = "ProjectCreated"
+ ProjectDeleted MessageType = "ProjectDeleted"
+ ProjectUpdated MessageType = "ProjectUpdated"
+ BuildCreated MessageType = "BuildCreated"
+ BuildDeleted MessageType = "BuildDeleted"
+ BuildUpdated MessageType = "BuildUpdated"
)
type SocketData struct {
diff --git a/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/build.go b/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/build.go
new file mode 100644
index 000000000..12a664e25
--- /dev/null
+++ b/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/build.go
@@ -0,0 +1,191 @@
+/*
+Copyright 2020 The Tekton 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+ "time"
+
+ v1alpha1 "github.com/tektoncd/dashboard/pkg/apis/dashboard/v1alpha1"
+ scheme "github.com/tektoncd/dashboard/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)
+ UpdateStatus(*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 *DashboardV1alpha1Client, 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) {
+ var timeout time.Duration
+ if opts.TimeoutSeconds != nil {
+ timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+ }
+ result = &v1alpha1.BuildList{}
+ err = c.client.Get().
+ Namespace(c.ns).
+ Resource("builds").
+ VersionedParams(&opts, scheme.ParameterCodec).
+ Timeout(timeout).
+ Do().
+ Into(result)
+ return
+}
+
+// Watch returns a watch.Interface that watches the requested builds.
+func (c *builds) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ var timeout time.Duration
+ if opts.TimeoutSeconds != nil {
+ timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+ }
+ opts.Watch = true
+ return c.client.Get().
+ Namespace(c.ns).
+ Resource("builds").
+ VersionedParams(&opts, scheme.ParameterCodec).
+ Timeout(timeout).
+ 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
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+
+func (c *builds) UpdateStatus(build *v1alpha1.Build) (result *v1alpha1.Build, err error) {
+ result = &v1alpha1.Build{}
+ err = c.client.Put().
+ Namespace(c.ns).
+ Resource("builds").
+ Name(build.Name).
+ SubResource("status").
+ 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 {
+ var timeout time.Duration
+ if listOptions.TimeoutSeconds != nil {
+ timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
+ }
+ return c.client.Delete().
+ Namespace(c.ns).
+ Resource("builds").
+ VersionedParams(&listOptions, scheme.ParameterCodec).
+ Timeout(timeout).
+ 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/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/dashboard_client.go b/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/dashboard_client.go
index 40d7aa490..53a6eeb6b 100644
--- a/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/dashboard_client.go
+++ b/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/dashboard_client.go
@@ -26,7 +26,9 @@ import (
type DashboardV1alpha1Interface interface {
RESTClient() rest.Interface
+ BuildsGetter
ExtensionsGetter
+ ProjectsGetter
}
// DashboardV1alpha1Client is used to interact with features provided by the dashboard.tekton.dev group.
@@ -34,10 +36,18 @@ type DashboardV1alpha1Client struct {
restClient rest.Interface
}
+func (c *DashboardV1alpha1Client) Builds(namespace string) BuildInterface {
+ return newBuilds(c, namespace)
+}
+
func (c *DashboardV1alpha1Client) Extensions(namespace string) ExtensionInterface {
return newExtensions(c, namespace)
}
+func (c *DashboardV1alpha1Client) Projects(namespace string) ProjectInterface {
+ return newProjects(c, namespace)
+}
+
// NewForConfig creates a new DashboardV1alpha1Client for the given config.
func NewForConfig(c *rest.Config) (*DashboardV1alpha1Client, error) {
config := *c
diff --git a/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/fake/fake_build.go b/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/fake/fake_build.go
new file mode 100644
index 000000000..c20c3e9f0
--- /dev/null
+++ b/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/fake/fake_build.go
@@ -0,0 +1,140 @@
+/*
+Copyright 2020 The Tekton 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1alpha1 "github.com/tektoncd/dashboard/pkg/apis/dashboard/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeBuilds implements BuildInterface
+type FakeBuilds struct {
+ Fake *FakeDashboardV1alpha1
+ ns string
+}
+
+var buildsResource = schema.GroupVersionResource{Group: "dashboard.tekton.dev", Version: "v1alpha1", Resource: "builds"}
+
+var buildsKind = schema.GroupVersionKind{Group: "dashboard.tekton.dev", Version: "v1alpha1", Kind: "Build"}
+
+// Get takes name of the build, and returns the corresponding build object, and an error if there is any.
+func (c *FakeBuilds) Get(name string, options v1.GetOptions) (result *v1alpha1.Build, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(buildsResource, c.ns, name), &v1alpha1.Build{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.Build), err
+}
+
+// List takes label and field selectors, and returns the list of Builds that match those selectors.
+func (c *FakeBuilds) List(opts v1.ListOptions) (result *v1alpha1.BuildList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(buildsResource, buildsKind, c.ns, opts), &v1alpha1.BuildList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1alpha1.BuildList{ListMeta: obj.(*v1alpha1.BuildList).ListMeta}
+ for _, item := range obj.(*v1alpha1.BuildList).Items {
+ if label.Matches(labels.Set(item.Labels)) {
+ list.Items = append(list.Items, item)
+ }
+ }
+ return list, err
+}
+
+// Watch returns a watch.Interface that watches the requested builds.
+func (c *FakeBuilds) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(buildsResource, c.ns, opts))
+
+}
+
+// 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 *FakeBuilds) Create(build *v1alpha1.Build) (result *v1alpha1.Build, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(buildsResource, c.ns, build), &v1alpha1.Build{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.Build), err
+}
+
+// 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 *FakeBuilds) Update(build *v1alpha1.Build) (result *v1alpha1.Build, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(buildsResource, c.ns, build), &v1alpha1.Build{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.Build), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeBuilds) UpdateStatus(build *v1alpha1.Build) (*v1alpha1.Build, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(buildsResource, "status", c.ns, build), &v1alpha1.Build{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.Build), err
+}
+
+// Delete takes name of the build and deletes it. Returns an error if one occurs.
+func (c *FakeBuilds) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(buildsResource, c.ns, name), &v1alpha1.Build{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeBuilds) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(buildsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1alpha1.BuildList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched build.
+func (c *FakeBuilds) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Build, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(buildsResource, c.ns, name, pt, data, subresources...), &v1alpha1.Build{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.Build), err
+}
diff --git a/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/fake/fake_dashboard_client.go b/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/fake/fake_dashboard_client.go
index 549e099ab..72dd60cc0 100644
--- a/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/fake/fake_dashboard_client.go
+++ b/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/fake/fake_dashboard_client.go
@@ -28,10 +28,18 @@ type FakeDashboardV1alpha1 struct {
*testing.Fake
}
+func (c *FakeDashboardV1alpha1) Builds(namespace string) v1alpha1.BuildInterface {
+ return &FakeBuilds{c, namespace}
+}
+
func (c *FakeDashboardV1alpha1) Extensions(namespace string) v1alpha1.ExtensionInterface {
return &FakeExtensions{c, namespace}
}
+func (c *FakeDashboardV1alpha1) Projects(namespace string) v1alpha1.ProjectInterface {
+ return &FakeProjects{c, namespace}
+}
+
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *FakeDashboardV1alpha1) RESTClient() rest.Interface {
diff --git a/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/fake/fake_project.go b/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/fake/fake_project.go
new file mode 100644
index 000000000..455704a5c
--- /dev/null
+++ b/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/fake/fake_project.go
@@ -0,0 +1,140 @@
+/*
+Copyright 2020 The Tekton 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ v1alpha1 "github.com/tektoncd/dashboard/pkg/apis/dashboard/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeProjects implements ProjectInterface
+type FakeProjects struct {
+ Fake *FakeDashboardV1alpha1
+ ns string
+}
+
+var projectsResource = schema.GroupVersionResource{Group: "dashboard.tekton.dev", Version: "v1alpha1", Resource: "projects"}
+
+var projectsKind = schema.GroupVersionKind{Group: "dashboard.tekton.dev", Version: "v1alpha1", Kind: "Project"}
+
+// Get takes name of the project, and returns the corresponding project object, and an error if there is any.
+func (c *FakeProjects) Get(name string, options v1.GetOptions) (result *v1alpha1.Project, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(projectsResource, c.ns, name), &v1alpha1.Project{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.Project), err
+}
+
+// List takes label and field selectors, and returns the list of Projects that match those selectors.
+func (c *FakeProjects) List(opts v1.ListOptions) (result *v1alpha1.ProjectList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(projectsResource, projectsKind, c.ns, opts), &v1alpha1.ProjectList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1alpha1.ProjectList{ListMeta: obj.(*v1alpha1.ProjectList).ListMeta}
+ for _, item := range obj.(*v1alpha1.ProjectList).Items {
+ if label.Matches(labels.Set(item.Labels)) {
+ list.Items = append(list.Items, item)
+ }
+ }
+ return list, err
+}
+
+// Watch returns a watch.Interface that watches the requested projects.
+func (c *FakeProjects) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(projectsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a project and creates it. Returns the server's representation of the project, and an error, if there is any.
+func (c *FakeProjects) Create(project *v1alpha1.Project) (result *v1alpha1.Project, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(projectsResource, c.ns, project), &v1alpha1.Project{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.Project), err
+}
+
+// Update takes the representation of a project and updates it. Returns the server's representation of the project, and an error, if there is any.
+func (c *FakeProjects) Update(project *v1alpha1.Project) (result *v1alpha1.Project, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(projectsResource, c.ns, project), &v1alpha1.Project{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.Project), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeProjects) UpdateStatus(project *v1alpha1.Project) (*v1alpha1.Project, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(projectsResource, "status", c.ns, project), &v1alpha1.Project{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.Project), err
+}
+
+// Delete takes name of the project and deletes it. Returns an error if one occurs.
+func (c *FakeProjects) Delete(name string, options *v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteAction(projectsResource, c.ns, name), &v1alpha1.Project{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeProjects) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(projectsResource, c.ns, listOptions)
+
+ _, err := c.Fake.Invokes(action, &v1alpha1.ProjectList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched project.
+func (c *FakeProjects) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Project, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(projectsResource, c.ns, name, pt, data, subresources...), &v1alpha1.Project{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.Project), err
+}
diff --git a/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/generated_expansion.go b/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/generated_expansion.go
index ed63f52a8..1e885c8fc 100644
--- a/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/generated_expansion.go
+++ b/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/generated_expansion.go
@@ -18,4 +18,8 @@ limitations under the License.
package v1alpha1
+type BuildExpansion interface{}
+
type ExtensionExpansion interface{}
+
+type ProjectExpansion interface{}
diff --git a/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/project.go b/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/project.go
new file mode 100644
index 000000000..00e46c67a
--- /dev/null
+++ b/pkg/client/clientset/versioned/typed/dashboard/v1alpha1/project.go
@@ -0,0 +1,191 @@
+/*
+Copyright 2020 The Tekton 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+ "time"
+
+ v1alpha1 "github.com/tektoncd/dashboard/pkg/apis/dashboard/v1alpha1"
+ scheme "github.com/tektoncd/dashboard/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"
+)
+
+// ProjectsGetter has a method to return a ProjectInterface.
+// A group's client should implement this interface.
+type ProjectsGetter interface {
+ Projects(namespace string) ProjectInterface
+}
+
+// ProjectInterface has methods to work with Project resources.
+type ProjectInterface interface {
+ Create(*v1alpha1.Project) (*v1alpha1.Project, error)
+ Update(*v1alpha1.Project) (*v1alpha1.Project, error)
+ UpdateStatus(*v1alpha1.Project) (*v1alpha1.Project, error)
+ Delete(name string, options *v1.DeleteOptions) error
+ DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
+ Get(name string, options v1.GetOptions) (*v1alpha1.Project, error)
+ List(opts v1.ListOptions) (*v1alpha1.ProjectList, error)
+ Watch(opts v1.ListOptions) (watch.Interface, error)
+ Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Project, err error)
+ ProjectExpansion
+}
+
+// projects implements ProjectInterface
+type projects struct {
+ client rest.Interface
+ ns string
+}
+
+// newProjects returns a Projects
+func newProjects(c *DashboardV1alpha1Client, namespace string) *projects {
+ return &projects{
+ client: c.RESTClient(),
+ ns: namespace,
+ }
+}
+
+// Get takes name of the project, and returns the corresponding project object, and an error if there is any.
+func (c *projects) Get(name string, options v1.GetOptions) (result *v1alpha1.Project, err error) {
+ result = &v1alpha1.Project{}
+ err = c.client.Get().
+ Namespace(c.ns).
+ Resource("projects").
+ Name(name).
+ VersionedParams(&options, scheme.ParameterCodec).
+ Do().
+ Into(result)
+ return
+}
+
+// List takes label and field selectors, and returns the list of Projects that match those selectors.
+func (c *projects) List(opts v1.ListOptions) (result *v1alpha1.ProjectList, err error) {
+ var timeout time.Duration
+ if opts.TimeoutSeconds != nil {
+ timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+ }
+ result = &v1alpha1.ProjectList{}
+ err = c.client.Get().
+ Namespace(c.ns).
+ Resource("projects").
+ VersionedParams(&opts, scheme.ParameterCodec).
+ Timeout(timeout).
+ Do().
+ Into(result)
+ return
+}
+
+// Watch returns a watch.Interface that watches the requested projects.
+func (c *projects) Watch(opts v1.ListOptions) (watch.Interface, error) {
+ var timeout time.Duration
+ if opts.TimeoutSeconds != nil {
+ timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+ }
+ opts.Watch = true
+ return c.client.Get().
+ Namespace(c.ns).
+ Resource("projects").
+ VersionedParams(&opts, scheme.ParameterCodec).
+ Timeout(timeout).
+ Watch()
+}
+
+// Create takes the representation of a project and creates it. Returns the server's representation of the project, and an error, if there is any.
+func (c *projects) Create(project *v1alpha1.Project) (result *v1alpha1.Project, err error) {
+ result = &v1alpha1.Project{}
+ err = c.client.Post().
+ Namespace(c.ns).
+ Resource("projects").
+ Body(project).
+ Do().
+ Into(result)
+ return
+}
+
+// Update takes the representation of a project and updates it. Returns the server's representation of the project, and an error, if there is any.
+func (c *projects) Update(project *v1alpha1.Project) (result *v1alpha1.Project, err error) {
+ result = &v1alpha1.Project{}
+ err = c.client.Put().
+ Namespace(c.ns).
+ Resource("projects").
+ Name(project.Name).
+ Body(project).
+ Do().
+ Into(result)
+ return
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+
+func (c *projects) UpdateStatus(project *v1alpha1.Project) (result *v1alpha1.Project, err error) {
+ result = &v1alpha1.Project{}
+ err = c.client.Put().
+ Namespace(c.ns).
+ Resource("projects").
+ Name(project.Name).
+ SubResource("status").
+ Body(project).
+ Do().
+ Into(result)
+ return
+}
+
+// Delete takes name of the project and deletes it. Returns an error if one occurs.
+func (c *projects) Delete(name string, options *v1.DeleteOptions) error {
+ return c.client.Delete().
+ Namespace(c.ns).
+ Resource("projects").
+ Name(name).
+ Body(options).
+ Do().
+ Error()
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *projects) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+ var timeout time.Duration
+ if listOptions.TimeoutSeconds != nil {
+ timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
+ }
+ return c.client.Delete().
+ Namespace(c.ns).
+ Resource("projects").
+ VersionedParams(&listOptions, scheme.ParameterCodec).
+ Timeout(timeout).
+ Body(options).
+ Do().
+ Error()
+}
+
+// Patch applies the patch and returns the patched project.
+func (c *projects) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Project, err error) {
+ result = &v1alpha1.Project{}
+ err = c.client.Patch(pt).
+ Namespace(c.ns).
+ Resource("projects").
+ SubResource(subresources...).
+ Name(name).
+ Body(data).
+ Do().
+ Into(result)
+ return
+}
diff --git a/pkg/client/informers/externalversions/dashboard/v1alpha1/build.go b/pkg/client/informers/externalversions/dashboard/v1alpha1/build.go
new file mode 100644
index 000000000..fff86fbf0
--- /dev/null
+++ b/pkg/client/informers/externalversions/dashboard/v1alpha1/build.go
@@ -0,0 +1,89 @@
+/*
+Copyright 2020 The Tekton 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.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+ time "time"
+
+ dashboardv1alpha1 "github.com/tektoncd/dashboard/pkg/apis/dashboard/v1alpha1"
+ versioned "github.com/tektoncd/dashboard/pkg/client/clientset/versioned"
+ internalinterfaces "github.com/tektoncd/dashboard/pkg/client/informers/externalversions/internalinterfaces"
+ v1alpha1 "github.com/tektoncd/dashboard/pkg/client/listers/dashboard/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ runtime "k8s.io/apimachinery/pkg/runtime"
+ watch "k8s.io/apimachinery/pkg/watch"
+ cache "k8s.io/client-go/tools/cache"
+)
+
+// BuildInformer provides access to a shared informer and lister for
+// Builds.
+type BuildInformer interface {
+ Informer() cache.SharedIndexInformer
+ Lister() v1alpha1.BuildLister
+}
+
+type buildInformer struct {
+ factory internalinterfaces.SharedInformerFactory
+ tweakListOptions internalinterfaces.TweakListOptionsFunc
+ namespace string
+}
+
+// NewBuildInformer constructs a new informer for Build type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewBuildInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
+ return NewFilteredBuildInformer(client, namespace, resyncPeriod, indexers, nil)
+}
+
+// NewFilteredBuildInformer constructs a new informer for Build type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewFilteredBuildInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
+ return cache.NewSharedIndexInformer(
+ &cache.ListWatch{
+ ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
+ if tweakListOptions != nil {
+ tweakListOptions(&options)
+ }
+ return client.DashboardV1alpha1().Builds(namespace).List(options)
+ },
+ WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
+ if tweakListOptions != nil {
+ tweakListOptions(&options)
+ }
+ return client.DashboardV1alpha1().Builds(namespace).Watch(options)
+ },
+ },
+ &dashboardv1alpha1.Build{},
+ resyncPeriod,
+ indexers,
+ )
+}
+
+func (f *buildInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
+ return NewFilteredBuildInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
+}
+
+func (f *buildInformer) Informer() cache.SharedIndexInformer {
+ return f.factory.InformerFor(&dashboardv1alpha1.Build{}, f.defaultInformer)
+}
+
+func (f *buildInformer) Lister() v1alpha1.BuildLister {
+ return v1alpha1.NewBuildLister(f.Informer().GetIndexer())
+}
diff --git a/pkg/client/informers/externalversions/dashboard/v1alpha1/interface.go b/pkg/client/informers/externalversions/dashboard/v1alpha1/interface.go
index 275b96ad9..965f2ccd4 100644
--- a/pkg/client/informers/externalversions/dashboard/v1alpha1/interface.go
+++ b/pkg/client/informers/externalversions/dashboard/v1alpha1/interface.go
@@ -24,8 +24,12 @@ import (
// Interface provides access to all the informers in this group version.
type Interface interface {
+ // Builds returns a BuildInformer.
+ Builds() BuildInformer
// Extensions returns a ExtensionInformer.
Extensions() ExtensionInformer
+ // Projects returns a ProjectInformer.
+ Projects() ProjectInformer
}
type version struct {
@@ -39,7 +43,17 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
+// Builds returns a BuildInformer.
+func (v *version) Builds() BuildInformer {
+ return &buildInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
+}
+
// Extensions returns a ExtensionInformer.
func (v *version) Extensions() ExtensionInformer {
return &extensionInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}
+
+// Projects returns a ProjectInformer.
+func (v *version) Projects() ProjectInformer {
+ return &projectInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
+}
diff --git a/pkg/client/informers/externalversions/dashboard/v1alpha1/project.go b/pkg/client/informers/externalversions/dashboard/v1alpha1/project.go
new file mode 100644
index 000000000..2b1e81c01
--- /dev/null
+++ b/pkg/client/informers/externalversions/dashboard/v1alpha1/project.go
@@ -0,0 +1,89 @@
+/*
+Copyright 2020 The Tekton 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.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+ time "time"
+
+ dashboardv1alpha1 "github.com/tektoncd/dashboard/pkg/apis/dashboard/v1alpha1"
+ versioned "github.com/tektoncd/dashboard/pkg/client/clientset/versioned"
+ internalinterfaces "github.com/tektoncd/dashboard/pkg/client/informers/externalversions/internalinterfaces"
+ v1alpha1 "github.com/tektoncd/dashboard/pkg/client/listers/dashboard/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ runtime "k8s.io/apimachinery/pkg/runtime"
+ watch "k8s.io/apimachinery/pkg/watch"
+ cache "k8s.io/client-go/tools/cache"
+)
+
+// ProjectInformer provides access to a shared informer and lister for
+// Projects.
+type ProjectInformer interface {
+ Informer() cache.SharedIndexInformer
+ Lister() v1alpha1.ProjectLister
+}
+
+type projectInformer struct {
+ factory internalinterfaces.SharedInformerFactory
+ tweakListOptions internalinterfaces.TweakListOptionsFunc
+ namespace string
+}
+
+// NewProjectInformer constructs a new informer for Project type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewProjectInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
+ return NewFilteredProjectInformer(client, namespace, resyncPeriod, indexers, nil)
+}
+
+// NewFilteredProjectInformer constructs a new informer for Project type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewFilteredProjectInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
+ return cache.NewSharedIndexInformer(
+ &cache.ListWatch{
+ ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
+ if tweakListOptions != nil {
+ tweakListOptions(&options)
+ }
+ return client.DashboardV1alpha1().Projects(namespace).List(options)
+ },
+ WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
+ if tweakListOptions != nil {
+ tweakListOptions(&options)
+ }
+ return client.DashboardV1alpha1().Projects(namespace).Watch(options)
+ },
+ },
+ &dashboardv1alpha1.Project{},
+ resyncPeriod,
+ indexers,
+ )
+}
+
+func (f *projectInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
+ return NewFilteredProjectInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
+}
+
+func (f *projectInformer) Informer() cache.SharedIndexInformer {
+ return f.factory.InformerFor(&dashboardv1alpha1.Project{}, f.defaultInformer)
+}
+
+func (f *projectInformer) Lister() v1alpha1.ProjectLister {
+ return v1alpha1.NewProjectLister(f.Informer().GetIndexer())
+}
diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go
index 4a4ab00f2..cbca6f5db 100644
--- a/pkg/client/informers/externalversions/generic.go
+++ b/pkg/client/informers/externalversions/generic.go
@@ -53,8 +53,12 @@ func (f *genericInformer) Lister() cache.GenericLister {
func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
switch resource {
// Group=dashboard.tekton.dev, Version=v1alpha1
+ case v1alpha1.SchemeGroupVersion.WithResource("builds"):
+ return &genericInformer{resource: resource.GroupResource(), informer: f.Dashboard().V1alpha1().Builds().Informer()}, nil
case v1alpha1.SchemeGroupVersion.WithResource("extensions"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Dashboard().V1alpha1().Extensions().Informer()}, nil
+ case v1alpha1.SchemeGroupVersion.WithResource("projects"):
+ return &genericInformer{resource: resource.GroupResource(), informer: f.Dashboard().V1alpha1().Projects().Informer()}, nil
}
diff --git a/pkg/client/listers/dashboard/v1alpha1/build.go b/pkg/client/listers/dashboard/v1alpha1/build.go
new file mode 100644
index 000000000..6a2819385
--- /dev/null
+++ b/pkg/client/listers/dashboard/v1alpha1/build.go
@@ -0,0 +1,94 @@
+/*
+Copyright 2020 The Tekton 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.
+*/
+
+// Code generated by lister-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+ v1alpha1 "github.com/tektoncd/dashboard/pkg/apis/dashboard/v1alpha1"
+ "k8s.io/apimachinery/pkg/api/errors"
+ "k8s.io/apimachinery/pkg/labels"
+ "k8s.io/client-go/tools/cache"
+)
+
+// BuildLister helps list Builds.
+type BuildLister interface {
+ // List lists all Builds in the indexer.
+ List(selector labels.Selector) (ret []*v1alpha1.Build, err error)
+ // Builds returns an object that can list and get Builds.
+ Builds(namespace string) BuildNamespaceLister
+ BuildListerExpansion
+}
+
+// buildLister implements the BuildLister interface.
+type buildLister struct {
+ indexer cache.Indexer
+}
+
+// NewBuildLister returns a new BuildLister.
+func NewBuildLister(indexer cache.Indexer) BuildLister {
+ return &buildLister{indexer: indexer}
+}
+
+// List lists all Builds in the indexer.
+func (s *buildLister) List(selector labels.Selector) (ret []*v1alpha1.Build, err error) {
+ err = cache.ListAll(s.indexer, selector, func(m interface{}) {
+ ret = append(ret, m.(*v1alpha1.Build))
+ })
+ return ret, err
+}
+
+// Builds returns an object that can list and get Builds.
+func (s *buildLister) Builds(namespace string) BuildNamespaceLister {
+ return buildNamespaceLister{indexer: s.indexer, namespace: namespace}
+}
+
+// BuildNamespaceLister helps list and get Builds.
+type BuildNamespaceLister interface {
+ // List lists all Builds in the indexer for a given namespace.
+ List(selector labels.Selector) (ret []*v1alpha1.Build, err error)
+ // Get retrieves the Build from the indexer for a given namespace and name.
+ Get(name string) (*v1alpha1.Build, error)
+ BuildNamespaceListerExpansion
+}
+
+// buildNamespaceLister implements the BuildNamespaceLister
+// interface.
+type buildNamespaceLister struct {
+ indexer cache.Indexer
+ namespace string
+}
+
+// List lists all Builds in the indexer for a given namespace.
+func (s buildNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.Build, err error) {
+ err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
+ ret = append(ret, m.(*v1alpha1.Build))
+ })
+ return ret, err
+}
+
+// Get retrieves the Build from the indexer for a given namespace and name.
+func (s buildNamespaceLister) Get(name string) (*v1alpha1.Build, error) {
+ obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
+ if err != nil {
+ return nil, err
+ }
+ if !exists {
+ return nil, errors.NewNotFound(v1alpha1.Resource("build"), name)
+ }
+ return obj.(*v1alpha1.Build), nil
+}
diff --git a/pkg/client/listers/dashboard/v1alpha1/expansion_generated.go b/pkg/client/listers/dashboard/v1alpha1/expansion_generated.go
index 3125f9e3f..22994ebff 100644
--- a/pkg/client/listers/dashboard/v1alpha1/expansion_generated.go
+++ b/pkg/client/listers/dashboard/v1alpha1/expansion_generated.go
@@ -18,6 +18,14 @@ limitations under the License.
package v1alpha1
+// BuildListerExpansion allows custom methods to be added to
+// BuildLister.
+type BuildListerExpansion interface{}
+
+// BuildNamespaceListerExpansion allows custom methods to be added to
+// BuildNamespaceLister.
+type BuildNamespaceListerExpansion interface{}
+
// ExtensionListerExpansion allows custom methods to be added to
// ExtensionLister.
type ExtensionListerExpansion interface{}
@@ -25,3 +33,11 @@ type ExtensionListerExpansion interface{}
// ExtensionNamespaceListerExpansion allows custom methods to be added to
// ExtensionNamespaceLister.
type ExtensionNamespaceListerExpansion interface{}
+
+// ProjectListerExpansion allows custom methods to be added to
+// ProjectLister.
+type ProjectListerExpansion interface{}
+
+// ProjectNamespaceListerExpansion allows custom methods to be added to
+// ProjectNamespaceLister.
+type ProjectNamespaceListerExpansion interface{}
diff --git a/pkg/client/listers/dashboard/v1alpha1/project.go b/pkg/client/listers/dashboard/v1alpha1/project.go
new file mode 100644
index 000000000..3da953ef7
--- /dev/null
+++ b/pkg/client/listers/dashboard/v1alpha1/project.go
@@ -0,0 +1,94 @@
+/*
+Copyright 2020 The Tekton 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.
+*/
+
+// Code generated by lister-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+ v1alpha1 "github.com/tektoncd/dashboard/pkg/apis/dashboard/v1alpha1"
+ "k8s.io/apimachinery/pkg/api/errors"
+ "k8s.io/apimachinery/pkg/labels"
+ "k8s.io/client-go/tools/cache"
+)
+
+// ProjectLister helps list Projects.
+type ProjectLister interface {
+ // List lists all Projects in the indexer.
+ List(selector labels.Selector) (ret []*v1alpha1.Project, err error)
+ // Projects returns an object that can list and get Projects.
+ Projects(namespace string) ProjectNamespaceLister
+ ProjectListerExpansion
+}
+
+// projectLister implements the ProjectLister interface.
+type projectLister struct {
+ indexer cache.Indexer
+}
+
+// NewProjectLister returns a new ProjectLister.
+func NewProjectLister(indexer cache.Indexer) ProjectLister {
+ return &projectLister{indexer: indexer}
+}
+
+// List lists all Projects in the indexer.
+func (s *projectLister) List(selector labels.Selector) (ret []*v1alpha1.Project, err error) {
+ err = cache.ListAll(s.indexer, selector, func(m interface{}) {
+ ret = append(ret, m.(*v1alpha1.Project))
+ })
+ return ret, err
+}
+
+// Projects returns an object that can list and get Projects.
+func (s *projectLister) Projects(namespace string) ProjectNamespaceLister {
+ return projectNamespaceLister{indexer: s.indexer, namespace: namespace}
+}
+
+// ProjectNamespaceLister helps list and get Projects.
+type ProjectNamespaceLister interface {
+ // List lists all Projects in the indexer for a given namespace.
+ List(selector labels.Selector) (ret []*v1alpha1.Project, err error)
+ // Get retrieves the Project from the indexer for a given namespace and name.
+ Get(name string) (*v1alpha1.Project, error)
+ ProjectNamespaceListerExpansion
+}
+
+// projectNamespaceLister implements the ProjectNamespaceLister
+// interface.
+type projectNamespaceLister struct {
+ indexer cache.Indexer
+ namespace string
+}
+
+// List lists all Projects in the indexer for a given namespace.
+func (s projectNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.Project, err error) {
+ err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
+ ret = append(ret, m.(*v1alpha1.Project))
+ })
+ return ret, err
+}
+
+// Get retrieves the Project from the indexer for a given namespace and name.
+func (s projectNamespaceLister) Get(name string) (*v1alpha1.Project, error) {
+ obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
+ if err != nil {
+ return nil, err
+ }
+ if !exists {
+ return nil, errors.NewNotFound(v1alpha1.Resource("project"), name)
+ }
+ return obj.(*v1alpha1.Project), nil
+}
diff --git a/pkg/controllers/controller.go b/pkg/controllers/controller.go
index 3217bb38c..aba7f1aef 100644
--- a/pkg/controllers/controller.go
+++ b/pkg/controllers/controller.go
@@ -16,19 +16,27 @@ package controllers
import (
"time"
+ dashboardv1alpha1 "github.com/tektoncd/dashboard/pkg/apis/dashboard/v1alpha1"
dashboardclientset "github.com/tektoncd/dashboard/pkg/client/clientset/versioned"
dashboardinformers "github.com/tektoncd/dashboard/pkg/client/informers/externalversions"
dashboardcontroller "github.com/tektoncd/dashboard/pkg/controllers/dashboard"
kubecontroller "github.com/tektoncd/dashboard/pkg/controllers/kubernetes"
+ runtimecontroller "github.com/tektoncd/dashboard/pkg/controllers/runtime"
tektoncontroller "github.com/tektoncd/dashboard/pkg/controllers/tekton"
"github.com/tektoncd/dashboard/pkg/logging"
"github.com/tektoncd/dashboard/pkg/router"
+ pipelinev1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
tektonclientset "github.com/tektoncd/pipeline/pkg/client/clientset/versioned"
tektoninformers "github.com/tektoncd/pipeline/pkg/client/informers/externalversions"
resourceclientset "github.com/tektoncd/pipeline/pkg/client/resource/clientset/versioned"
resourceinformers "github.com/tektoncd/pipeline/pkg/client/resource/informers/externalversions"
+ triggersv1alpha1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1"
+ triggersclientset "github.com/tektoncd/triggers/pkg/client/clientset/versioned"
k8sinformers "k8s.io/client-go/informers"
k8sclientset "k8s.io/client-go/kubernetes"
+ "k8s.io/client-go/rest"
+ "sigs.k8s.io/controller-runtime/pkg/manager"
+ runtimesignals "sigs.k8s.io/controller-runtime/pkg/manager/signals"
)
// StartTektonControllers creates and starts Tekton controllers
@@ -74,11 +82,31 @@ func StartKubeControllers(clientset k8sclientset.Interface, resyncDur time.Durat
}
// StartDashboardControllers creates and starts Dashboard controllers
-func StartDashboardControllers(clientset dashboardclientset.Interface, resyncDur time.Duration, tenantNamespace string, stopCh <-chan struct{}) {
+func StartDashboardControllers(clientset dashboardclientset.Interface, triggersClient triggersclientset.Interface, k8sClient k8sclientset.Interface, resyncDur time.Duration, tenantNamespace string, stopCh <-chan struct{}) {
logging.Log.Info("Creating Dashboard controllers")
tenantInformerFactory := dashboardinformers.NewSharedInformerFactoryWithOptions(clientset, resyncDur, dashboardinformers.WithNamespace(tenantNamespace))
+ dashboardcontroller.NewBuildController(tenantInformerFactory)
dashboardcontroller.NewExtensionController(tenantInformerFactory)
+ dashboardcontroller.NewProjectController(tenantInformerFactory)
// Started once all controllers have been registered
logging.Log.Info("Starting Dashboard controllers")
tenantInformerFactory.Start(stopCh)
}
+
+func StartRuntimeControllers(config *rest.Config) {
+ // Setup a Manager
+ mgr, _ := manager.New(config, manager.Options{})
+
+ // Register scheme
+ dashboardv1alpha1.AddToScheme(mgr.GetScheme())
+ pipelinev1beta1.AddToScheme(mgr.GetScheme())
+ triggersv1alpha1.AddToScheme(mgr.GetScheme())
+
+ runtimecontroller.ForProjects(mgr)
+ runtimecontroller.ForBuilds(mgr)
+
+ go func() {
+ mgr.Start(runtimesignals.SetupSignalHandler())
+ }()
+
+}
diff --git a/pkg/controllers/dashboard/build.go b/pkg/controllers/dashboard/build.go
new file mode 100644
index 000000000..218233ca0
--- /dev/null
+++ b/pkg/controllers/dashboard/build.go
@@ -0,0 +1,36 @@
+/*
+Copyright 2020 The Tekton 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 dashboard
+
+import (
+ "github.com/tektoncd/dashboard/pkg/broadcaster"
+ dashboardinformer "github.com/tektoncd/dashboard/pkg/client/informers/externalversions"
+ "github.com/tektoncd/dashboard/pkg/controllers/utils"
+ "github.com/tektoncd/dashboard/pkg/logging"
+)
+
+// NewNamespaceController registers the K8s shared informer that reacts to
+// create and delete events for namespaces
+func NewBuildController(sharedDashboardInformerFactory dashboardinformer.SharedInformerFactory) {
+ logging.Log.Debug("In NewBuildController")
+
+ utils.NewController(
+ "build",
+ sharedDashboardInformerFactory.Dashboard().V1alpha1().Builds().Informer(),
+ broadcaster.BuildCreated,
+ broadcaster.BuildUpdated,
+ broadcaster.BuildDeleted,
+ nil,
+ )
+}
diff --git a/pkg/controllers/dashboard/project.go b/pkg/controllers/dashboard/project.go
new file mode 100644
index 000000000..d8baa6357
--- /dev/null
+++ b/pkg/controllers/dashboard/project.go
@@ -0,0 +1,36 @@
+/*
+Copyright 2020 The Tekton 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 dashboard
+
+import (
+ "github.com/tektoncd/dashboard/pkg/broadcaster"
+ dashboardinformer "github.com/tektoncd/dashboard/pkg/client/informers/externalversions"
+ "github.com/tektoncd/dashboard/pkg/controllers/utils"
+ "github.com/tektoncd/dashboard/pkg/logging"
+)
+
+// NewNamespaceController registers the K8s shared informer that reacts to
+// create and delete events for namespaces
+func NewProjectController(sharedDashboardInformerFactory dashboardinformer.SharedInformerFactory) {
+ logging.Log.Debug("In NewProjectController")
+
+ utils.NewController(
+ "project",
+ sharedDashboardInformerFactory.Dashboard().V1alpha1().Projects().Informer(),
+ broadcaster.ProjectCreated,
+ broadcaster.ProjectUpdated,
+ broadcaster.ProjectDeleted,
+ nil,
+ )
+}
diff --git a/pkg/controllers/runtime/build.go b/pkg/controllers/runtime/build.go
new file mode 100644
index 000000000..0ed14b53f
--- /dev/null
+++ b/pkg/controllers/runtime/build.go
@@ -0,0 +1,74 @@
+/*
+Copyright 2020 The Tekton 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 runtimecontroller
+
+import (
+ "context"
+
+ dashboardv1alpha1 "github.com/tektoncd/dashboard/pkg/apis/dashboard/v1alpha1"
+ "github.com/tektoncd/dashboard/pkg/logging"
+ pipelinev1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
+ apierrors "k8s.io/apimachinery/pkg/api/errors"
+ ctrl "sigs.k8s.io/controller-runtime"
+ "sigs.k8s.io/controller-runtime/pkg/manager"
+ "sigs.k8s.io/controller-runtime/pkg/reconcile"
+)
+
+func ForBuilds(mgr manager.Manager) {
+ ctrl.NewControllerManagedBy(mgr).
+ For(&dashboardv1alpha1.Build{}).
+ Owns(&pipelinev1beta1.PipelineRun{}).
+ Complete(reconcile.Func(func(request ctrl.Request) (ctrl.Result, error) {
+ ctx := context.Background()
+ client := mgr.GetClient()
+ scheme := mgr.GetScheme()
+
+ logging.Log.Infof("Reconcile Build %+v", request)
+
+ var build dashboardv1alpha1.Build
+ if err := client.Get(ctx, request.NamespacedName, &build); err != nil {
+ if !apierrors.IsNotFound(err) {
+ return ctrl.Result{}, nil
+ }
+ logging.Log.Errorf("unable to get Build: %s", err)
+ return ctrl.Result{}, err
+ }
+
+ pipelineRun := &pipelinev1beta1.PipelineRun{ObjectMeta: objectMeta(request)}
+ if err := r(ctx, "TriggerTemplate", client, scheme, &build, pipelineRun, func() error {
+ pipelineRun.Spec = pipelinev1beta1.PipelineRunSpec{
+ PipelineSpec: &build.Spec.PipelineSpec,
+ Resources: []pipelinev1beta1.PipelineResourceBinding{
+ {
+ Name: "source",
+ ResourceSpec: &build.Spec.PipelineResourceSpec,
+ },
+ },
+ Params: build.Spec.Params,
+ }
+ return nil
+ }); err != nil {
+ return ctrl.Result{}, err
+ }
+
+ build.Status.PipelineRun = &pipelineRun.Status
+
+ if err := client.Status().Update(ctx, &build); err != nil {
+ logging.Log.Errorf("failed to update Build status: %s", err)
+ return ctrl.Result{}, err
+ }
+
+ return ctrl.Result{}, nil
+ }))
+}
diff --git a/pkg/controllers/runtime/project.go b/pkg/controllers/runtime/project.go
new file mode 100644
index 000000000..db54481be
--- /dev/null
+++ b/pkg/controllers/runtime/project.go
@@ -0,0 +1,208 @@
+/*
+Copyright 2020 The Tekton 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 runtimecontroller
+
+import (
+ "context"
+
+ dashboardv1alpha1 "github.com/tektoncd/dashboard/pkg/apis/dashboard/v1alpha1"
+ "github.com/tektoncd/dashboard/pkg/logging"
+ pipelinev1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
+ triggersv1alpha1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1"
+ extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
+ apierrors "k8s.io/apimachinery/pkg/api/errors"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/util/intstr"
+ ctrl "sigs.k8s.io/controller-runtime"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/manager"
+ "sigs.k8s.io/controller-runtime/pkg/reconcile"
+)
+
+const projectOwnerKey = ".metadata.controller"
+
+var apiGVStr = dashboardv1alpha1.SchemeGroupVersion.String()
+
+func ForProjects(mgr manager.Manager) {
+ if err := mgr.GetFieldIndexer().IndexField(&pipelinev1beta1.TaskRun{}, projectOwnerKey, func(rawObj runtime.Object) []string {
+ obj := rawObj.(*pipelinev1beta1.TaskRun)
+ owner := metav1.GetControllerOf(obj)
+ if owner == nil {
+ return nil
+ }
+ if owner.APIVersion != apiGVStr || owner.Kind != "Project" {
+ return nil
+ }
+ return []string{owner.Name}
+ }); err != nil {
+ logging.Log.Errorf("failed to register indexer: %s", err)
+ }
+
+ if err := mgr.GetFieldIndexer().IndexField(&dashboardv1alpha1.Build{}, projectOwnerKey, func(rawObj runtime.Object) []string {
+ obj := rawObj.(*dashboardv1alpha1.Build)
+ owner := metav1.GetControllerOf(obj)
+ if owner == nil {
+ return nil
+ }
+ if owner.APIVersion != apiGVStr || owner.Kind != "Project" {
+ return nil
+ }
+ return []string{owner.Name}
+ }); err != nil {
+ logging.Log.Errorf("failed to register indexer: %s", err)
+ }
+
+ ctrl.NewControllerManagedBy(mgr).
+ For(&dashboardv1alpha1.Project{}).
+ Owns(&triggersv1alpha1.TriggerBinding{}).
+ Owns(&triggersv1alpha1.TriggerTemplate{}).
+ Owns(&triggersv1alpha1.EventListener{}).
+ Owns(&extensionsv1beta1.Ingress{}).
+ Owns(&dashboardv1alpha1.Build{}).
+ Owns(&pipelinev1beta1.TaskRun{}).
+ Complete(reconcile.Func(func(request ctrl.Request) (ctrl.Result, error) {
+ ctx := context.Background()
+ c := mgr.GetClient()
+ scheme := mgr.GetScheme()
+
+ logging.Log.Infof("Reconcile Project %+v", request)
+
+ var project dashboardv1alpha1.Project
+ if err := c.Get(ctx, request.NamespacedName, &project); err != nil {
+ if !apierrors.IsNotFound(err) {
+ return ctrl.Result{}, nil
+ }
+ logging.Log.Errorf("unable to get Project: %s", err)
+ return ctrl.Result{}, err
+ }
+
+ triggerTemplate := &triggersv1alpha1.TriggerTemplate{ObjectMeta: objectMeta(request)}
+ if err := r(ctx, "TriggerTemplate", c, scheme, &project, triggerTemplate, func() error {
+ triggerTemplate.Spec = project.Spec.TriggerTemplate
+ return nil
+ }); err != nil {
+ return ctrl.Result{}, err
+ }
+
+ triggerBinding := &triggersv1alpha1.TriggerBinding{ObjectMeta: objectMeta(request)}
+ if err := r(ctx, "TriggerBinding", c, scheme, &project, triggerBinding, func() error {
+ project.Spec.TriggerBinding.DeepCopyInto(&triggerBinding.Spec)
+ triggerBinding.Spec.Params = append(
+ triggerBinding.Spec.Params,
+ triggersv1alpha1.Param{
+ Name: "ownername",
+ Value: project.Name,
+ },
+ triggersv1alpha1.Param{
+ Name: "owneruid",
+ Value: string(project.UID),
+ },
+ )
+ return nil
+ }); err != nil {
+ return ctrl.Result{}, err
+ }
+
+ eventListener := &triggersv1alpha1.EventListener{ObjectMeta: objectMeta(request)}
+ if err := r(ctx, "EventListener", c, scheme, &project, eventListener, func() error {
+ eventListener.Spec = triggersv1alpha1.EventListenerSpec{
+ ServiceAccountName: project.Spec.ServiceAccountName,
+ Triggers: []triggersv1alpha1.EventListenerTrigger{
+ {
+ Interceptors: project.Spec.Interceptors,
+ Bindings: []*triggersv1alpha1.EventListenerBinding{
+ {
+ Ref: project.GetName(),
+ },
+ },
+ Template: triggersv1alpha1.EventListenerTemplate{
+ Name: triggerTemplate.Name,
+ },
+ },
+ },
+ }
+ return nil
+ }); err != nil {
+ return ctrl.Result{}, err
+ }
+
+ if project.Spec.Ingress != nil {
+ ingress := &extensionsv1beta1.Ingress{ObjectMeta: objectMeta(request)}
+ if err := r(ctx, "Ingress", c, scheme, &project, ingress, func() error {
+ ingress.Annotations = project.Spec.Ingress.Annotations
+ ingress.Labels = project.Spec.Ingress.Labels
+ ingress.Spec = extensionsv1beta1.IngressSpec{
+ Rules: []extensionsv1beta1.IngressRule{
+ {
+ Host: project.Spec.Ingress.Host,
+ IngressRuleValue: extensionsv1beta1.IngressRuleValue{
+ HTTP: &extensionsv1beta1.HTTPIngressRuleValue{
+ Paths: []extensionsv1beta1.HTTPIngressPath{
+ {
+ Backend: extensionsv1beta1.IngressBackend{
+ ServiceName: "el-" + eventListener.GetName(),
+ ServicePort: intstr.FromInt(8080),
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+ return nil
+ }); err != nil {
+ return ctrl.Result{}, err
+ }
+
+ project.Status.Ingress = &ingress.Status
+ }
+
+ project.Status.EventListener = &eventListener.Status
+ project.Status.TriggerBinding = &triggerBinding.Status
+ project.Status.TriggerTemplate = &triggerTemplate.Status
+
+ var taskRunList pipelinev1beta1.TaskRunList
+ if err := c.List(ctx, &taskRunList, client.InNamespace(request.Namespace), client.MatchingFields{projectOwnerKey: request.Name}); err != nil {
+ logging.Log.Errorf("failed to reconcile TaskRuns status: %s", err)
+ }
+
+ taskRuns := make(map[string]*pipelinev1beta1.TaskRunStatus)
+ for _, taskRun := range taskRunList.Items {
+ ref := taskRun
+ taskRuns[taskRun.Name] = &ref.Status
+ }
+ project.Status.TaskRuns = taskRuns
+
+ var buildList dashboardv1alpha1.BuildList
+ if err := c.List(ctx, &buildList, client.InNamespace(request.Namespace), client.MatchingFields{projectOwnerKey: request.Name}); err != nil {
+ logging.Log.Errorf("failed to reconcile Builds status: %s", err)
+ }
+
+ builds := make(map[string]*dashboardv1alpha1.BuildStatus)
+ for _, build := range buildList.Items {
+ ref := build
+ builds[build.Name] = &ref.Status
+ }
+ project.Status.Builds = builds
+
+ if err := c.Status().Update(ctx, &project); err != nil {
+ logging.Log.Errorf("failed to update Project status: %s", err)
+ return ctrl.Result{}, err
+ }
+
+ return ctrl.Result{}, nil
+ }))
+}
diff --git a/pkg/controllers/runtime/utils.go b/pkg/controllers/runtime/utils.go
new file mode 100644
index 000000000..7a4553014
--- /dev/null
+++ b/pkg/controllers/runtime/utils.go
@@ -0,0 +1,48 @@
+/*
+Copyright 2020 The Tekton 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 runtimecontroller
+
+import (
+ "context"
+
+ "github.com/tektoncd/dashboard/pkg/logging"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ ctrl "sigs.k8s.io/controller-runtime"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
+)
+
+func r(ctx context.Context, kind string, c client.Client, scheme *runtime.Scheme, owner metav1.Object, obj runtime.Object, f controllerutil.MutateFn) error {
+ op, err := ctrl.CreateOrUpdate(ctx, c, obj, func() error {
+ if err := ctrl.SetControllerReference(owner, obj.(metav1.Object), scheme); err != nil {
+ logging.Log.Errorf("failed to set %s's owner reference: %s", kind, err)
+ return err
+ }
+ return f()
+ })
+ if err != nil {
+ logging.Log.Errorf("failed to reconcile %s: %s", kind, err)
+ } else {
+ logging.Log.Infof("successfully reconciled %s: %s", kind, op)
+ }
+ return err
+}
+
+func objectMeta(request ctrl.Request) metav1.ObjectMeta {
+ return metav1.ObjectMeta{
+ Name: request.Name,
+ Namespace: request.Namespace,
+ }
+}
diff --git a/pkg/endpoints/types.go b/pkg/endpoints/types.go
index 4bd897c29..6f2fb645b 100644
--- a/pkg/endpoints/types.go
+++ b/pkg/endpoints/types.go
@@ -7,6 +7,7 @@ import (
dashboardclientset "github.com/tektoncd/dashboard/pkg/client/clientset/versioned"
pipelineclientset "github.com/tektoncd/pipeline/pkg/client/clientset/versioned"
resourceclientset "github.com/tektoncd/pipeline/pkg/client/resource/clientset/versioned"
+ triggersclientset "github.com/tektoncd/triggers/pkg/client/clientset/versioned"
k8sclientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
@@ -50,6 +51,7 @@ type Resource struct {
DashboardClient dashboardclientset.Interface
PipelineClient pipelineclientset.Interface
PipelineResourceClient resourceclientset.Interface
+ TriggersClient triggersclientset.Interface
K8sClient k8sclientset.Interface
RouteClient routeclientset.Interface
Options Options
diff --git a/rbac.yaml b/rbac.yaml
new file mode 100644
index 000000000..f5adb3078
--- /dev/null
+++ b/rbac.yaml
@@ -0,0 +1,42 @@
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: github-project
+ labels:
+ app.kubernetes.io/component: dashboard
+ app.kubernetes.io/instance: default
+ app.kubernetes.io/part-of: tekton-dashboard
+
+---
+kind: Role
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+ name: github-project
+ labels:
+ app.kubernetes.io/component: dashboard
+ app.kubernetes.io/instance: default
+ app.kubernetes.io/part-of: tekton-dashboard
+rules:
+ - apiGroups:
+ - '*'
+ resources:
+ - '*'
+ verbs:
+ - '*'
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ labels:
+ app.kubernetes.io/component: dashboard
+ app.kubernetes.io/instance: default
+ app.kubernetes.io/part-of: tekton-dashboard
+ name: github-project
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: github-project
+subjects:
+ - kind: ServiceAccount
+ name: github-project
diff --git a/scripts/prepare-kind-cluster b/scripts/prepare-kind-cluster
index 2e624c38b..bb59f6ccd 100755
--- a/scripts/prepare-kind-cluster
+++ b/scripts/prepare-kind-cluster
@@ -44,13 +44,13 @@ install_ingress_nginx() {
}
install_pipelines() {
- kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml
+ kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/previous/v0.14.3/release.yaml
sleep 10
kubectl wait -n tekton-pipelines --for=condition=ready pod --selector=app.kubernetes.io/part-of=tekton-pipelines,app.kubernetes.io/component=controller --timeout=90s
}
install_triggers() {
- kubectl apply --filename https://storage.googleapis.com/tekton-releases/triggers/latest/release.yaml
+ kubectl apply --filename https://storage.googleapis.com/tekton-releases/triggers/previous/v0.6.1/release.yaml
sleep 10
kubectl wait -n tekton-pipelines --for=condition=ready pod --selector=app.kubernetes.io/part-of=tekton-triggers,app.kubernetes.io/component=controller --timeout=90s
}
@@ -66,7 +66,11 @@ case $1 in
install_ingress_nginx
install_pipelines
install_triggers
- ./scripts/installer install --log-format console $@
+ ./scripts/installer install $@ --ingress-url tekton-dashboard.127.0.0.1.nip.io --log-format console
+ ;;
+ 'update'|u)
+ shift
+ ./scripts/installer install $@ --ingress-url tekton-dashboard.127.0.0.1.nip.io --log-format console
;;
'delete'|d)
delete_cluster
diff --git a/src/actions/builds.js b/src/actions/builds.js
new file mode 100644
index 000000000..240d91973
--- /dev/null
+++ b/src/actions/builds.js
@@ -0,0 +1,32 @@
+/*
+Copyright 2020 The Tekton 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.
+*/
+
+import { getBuild, getBuilds } from '../api';
+import {
+ fetchNamespacedCollection,
+ fetchNamespacedResource
+} from './actionCreators';
+
+export function fetchBuild({ name, namespace }) {
+ return fetchNamespacedResource('Build', getBuild, {
+ name,
+ namespace
+ });
+}
+
+export function fetchBuilds({ filters, namespace } = {}) {
+ return fetchNamespacedCollection('Build', getBuilds, {
+ filters,
+ namespace
+ });
+}
diff --git a/src/actions/projects.js b/src/actions/projects.js
new file mode 100644
index 000000000..44446defb
--- /dev/null
+++ b/src/actions/projects.js
@@ -0,0 +1,32 @@
+/*
+Copyright 2020 The Tekton 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.
+*/
+
+import { getProject, getProjects } from '../api';
+import {
+ fetchNamespacedCollection,
+ fetchNamespacedResource
+} from './actionCreators';
+
+export function fetchProject({ name, namespace }) {
+ return fetchNamespacedResource('Project', getProject, {
+ name,
+ namespace
+ });
+}
+
+export function fetchProjects({ filters, namespace } = {}) {
+ return fetchNamespacedCollection('Project', getProjects, {
+ filters,
+ namespace
+ });
+}
diff --git a/src/api/index.js b/src/api/index.js
index a25fc994a..df647a91d 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -305,6 +305,178 @@ export function getCondition({ name, namespace }) {
return get(uri);
}
+export function getProjects({ filters = [], namespace } = {}) {
+ const uri = getTektonAPI(
+ 'projects',
+ { group: dashboardAPIGroup, namespace, version: 'v1alpha1' },
+ getQueryParams(filters)
+ );
+ return get(uri).then(checkData);
+}
+
+export function getProject({ name, namespace }) {
+ const uri = getTektonAPI('projects', {
+ group: dashboardAPIGroup,
+ name,
+ namespace,
+ version: 'v1alpha1'
+ });
+ return get(uri);
+}
+
+export function createProject({
+ name,
+ namespace,
+ ingress,
+ ingressLabels,
+ ingressAnnotations,
+ bindings,
+ interceptors,
+ serviceAccount
+}) {
+ const payload = {
+ apiVersion: 'dashboard.tekton.dev/v1alpha1',
+ kind: 'Project',
+ metadata: {
+ name,
+ namespace
+ },
+ spec: {
+ serviceAccountName: serviceAccount,
+ interceptors,
+ triggerBinding: {
+ params: [
+ ...Object.keys(bindings).map(x => ({ name: x, value: bindings[x] }))
+ ]
+ },
+ triggerTemplate: {
+ params: [
+ ...Object.keys(bindings).map(x => ({ name: x })),
+ {
+ name: 'ownername'
+ },
+ {
+ name: 'owneruid'
+ }
+ ],
+ resourcetemplates: [
+ {
+ apiVersion: 'tekton.dev/v1beta1',
+ kind: 'TaskRun',
+ metadata: {
+ generateName: `${name}-`,
+ ownerReferences: [
+ {
+ apiVersion: 'dashboard.tekton.dev/v1alpha1',
+ kind: 'Project',
+ name: '$(tt.params.ownername)',
+ uid: '$(tt.params.owneruid)',
+ controller: true,
+ blockOwnerDeletion: true
+ }
+ ]
+ },
+ spec: {
+ serviceAccountName: serviceAccount,
+ resources: {
+ inputs: [
+ {
+ name: 'source',
+ resourceSpec: {
+ type: 'git',
+ params: [
+ {
+ name: 'revision',
+ value: '$(tt.params.gitrevision)'
+ },
+ {
+ name: 'url',
+ value: '$(tt.params.gitrepositoryurl)'
+ }
+ ]
+ }
+ }
+ ]
+ },
+ taskSpec: {
+ resources: {
+ inputs: [
+ {
+ name: 'source',
+ type: 'git'
+ }
+ ]
+ },
+ steps: [
+ {
+ image: 'eddycharly/build-maker:test-4',
+ command: ['/work/build-maker'],
+ args: [
+ `--namespace=${namespace}`,
+ '--file=$(resources.inputs.source.path)/.tekton.yaml',
+ '--url=$(tt.params.gitrepositoryurl)',
+ '--revision=$(tt.params.gitrevision)',
+ '--owner-name=$(tt.params.ownername)',
+ '--owner-uid=$(tt.params.owneruid)',
+ ...Object.keys(bindings).map(
+ x => `--param=${x}=$(tt.params.${x})`
+ )
+ ]
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ }
+ };
+
+ if (ingress) {
+ payload.spec.ingress = {
+ host: ingress,
+ annotations: ingressAnnotations,
+ labels: ingressLabels
+ };
+ }
+
+ const uri = getTektonAPI('projects', {
+ group: dashboardAPIGroup,
+ namespace,
+ version: 'v1alpha1'
+ });
+ return post(uri, payload);
+}
+
+export function deleteProject({ name, namespace }) {
+ const uri = getTektonAPI('projects', {
+ group: dashboardAPIGroup,
+ name,
+ namespace,
+ version: 'v1alpha1'
+ });
+ return deleteRequest(uri);
+}
+
+export function getBuilds({ filters = [], namespace } = {}) {
+ const uri = getTektonAPI(
+ 'builds',
+ { group: dashboardAPIGroup, namespace, version: 'v1alpha1' },
+ getQueryParams(filters)
+ );
+ return get(uri).then(checkData);
+}
+
+export function getBuild({ name, namespace }) {
+ const uri = getTektonAPI('builds', {
+ group: dashboardAPIGroup,
+ name,
+ namespace,
+ version: 'v1alpha1'
+ });
+ return get(uri);
+}
+
export function getPodLogURL({ container, name, namespace }) {
let queryParams;
if (container) {
diff --git a/src/containers/App/App.js b/src/containers/App/App.js
index 9d450c475..738f7a129 100644
--- a/src/containers/App/App.js
+++ b/src/containers/App/App.js
@@ -34,6 +34,8 @@ import { getErrorMessage, paths, urls } from '@tektoncd/dashboard-utils';
import {
About,
+ Build,
+ Builds,
ClusterTasks,
ClusterTriggerBinding,
ClusterTriggerBindings,
@@ -52,6 +54,8 @@ import {
PipelineRun,
PipelineRuns,
Pipelines,
+ Project,
+ Projects,
ReadWriteRoute,
ResourceList,
Secret,
@@ -300,6 +304,24 @@ export /* istanbul ignore next */ class App extends Component {
path={paths.conditions.byName()}
component={Condition}
/>
+