Skip to content

Commit

Permalink
Add proxy to [Tekton Results](https://github.com/tektoncd/results)
Browse files Browse the repository at this point in the history
  • Loading branch information
xinnjie committed Jul 22, 2023
1 parent 15dee28 commit a640c58
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 20 deletions.
4 changes: 4 additions & 0 deletions base/200-clusterrole-backend.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,7 @@ rules:
- get
- list
- watch
# Dashboard needs to be able to query existing results.
- apiGroups: ["results.tekton.dev"]
resources: ["logs", "results", "records"]
verbs: ["get", "list"]
1 change: 1 addition & 0 deletions base/300-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,4 @@ spec:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
volumeMounts: []
59 changes: 49 additions & 10 deletions cmd/dashboard/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ package main
import (
"flag"
"fmt"
"os"

"github.com/tektoncd/dashboard/pkg/endpoints"
"github.com/tektoncd/dashboard/pkg/logging"
"github.com/tektoncd/dashboard/pkg/router"
k8sclientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
certutil "k8s.io/client-go/util/cert"
"os"
)

var (
Expand All @@ -40,6 +40,9 @@ var (
streamLogs = flag.Bool("stream-logs", true, "Enable log streaming instead of polling")
externalLogs = flag.String("external-logs", "", "External logs provider url")
xFrameOptions = flag.String("x-frame-options", "DENY", "Value for the X-Frame-Options response header, set '' to omit it")
resultsApiAddr = flag.String("results-api-addr", "tekton-results-api-service.tekton-pipelines.svc.cluster.local:8080", "Address of Results API server")
enableResultsTLS = flag.Bool("enable-results-tls", false, "Enable TLS verification when connecting to Results API server")
resultsTLSCertPath = flag.String("results-tls-cert-path", "/etc/tls/tls.crt", "TLS certs to the Results API server.")
)

func main() {
Expand All @@ -60,24 +63,29 @@ func main() {

logging.InitLogger(*logLevel, *logFormat)

var cfg *rest.Config
var kubeCfg *rest.Config
var err error
if *kubeConfigPath != "" {
cfg, err = clientcmd.BuildConfigFromFlags("", *kubeConfigPath)
kubeCfg, err = clientcmd.BuildConfigFromFlags("", *kubeConfigPath)
if err != nil {
logging.Log.Errorf("Error building kubeconfig from %s: %s", *kubeConfigPath, err.Error())
}
} else {
if cfg, err = rest.InClusterConfig(); err != nil {
if kubeCfg, err = rest.InClusterConfig(); err != nil {
logging.Log.Errorf("Error building kubeconfig: %s", err.Error())
}
}

k8sClient, err := k8sclientset.NewForConfig(cfg)
k8sClient, err := k8sclientset.NewForConfig(kubeCfg)
if err != nil {
logging.Log.Errorf("Error building k8s clientset: %s", err.Error())
}

resultsCfg, err := resultsConfig(*enableResultsTLS, *resultsTLSCertPath)
if err != nil {
logging.Log.Errorf("Error building results config: %s", err.Error())
}

options := endpoints.Options{
InstallNamespace: installNamespace,
PipelinesNamespace: *pipelinesNamespace,
Expand All @@ -91,12 +99,13 @@ func main() {
}

resource := endpoints.Resource{
Config: cfg,
K8sClient: k8sClient,
Options: options,
Config: kubeCfg,
K8sClient: k8sClient,
Options: options,
ResultsConfig: resultsCfg,
}

server, err := router.Register(resource, cfg)
server, err := router.Register(resource, kubeCfg, resultsCfg)

if err != nil {
logging.Log.Errorf("Error creating proxy: %s", err.Error())
Expand All @@ -113,3 +122,33 @@ func main() {
logging.Log.Infof("Starting to serve on %s", l.Addr().String())
logging.Log.Fatal(server.ServeOnListener(l))
}

func resultsConfig(enableResultsTLS bool, resultsTLSCertPath string) (*rest.Config, error) {
var cfg *rest.Config
var err error
// use kube config first and replace some configuration. Need the default bearer token.
if *kubeConfigPath != "" {
cfg, err = clientcmd.BuildConfigFromFlags("", *kubeConfigPath)
if err != nil {
logging.Log.Errorf("Error building kubeconfig from %s: %s", *kubeConfigPath, err.Error())
return nil, err
}
} else {
if cfg, err = rest.InClusterConfig(); err != nil {
logging.Log.Errorf("Error building kubeconfig: %s", err.Error())
return nil, err
}
}
if enableResultsTLS {
if _, err := certutil.NewPool(resultsTLSCertPath); err != nil {
logging.Log.Errorf("Expected to load root CA config from %s, but got err: %v", resultsTLSCertPath, err)
} else {
cfg.TLSClientConfig.CAFile = resultsTLSCertPath
}
} else {
cfg.TLSClientConfig.Insecure = true
cfg.TLSClientConfig.CAFile = ""
}
cfg.Host = "https://" + *resultsApiAddr
return cfg, nil
}
16 changes: 16 additions & 0 deletions docs/dev/results.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Tekton Dashboard - [Tekton Results](https://github.com/tektoncd/results) API support

Tekton Results aims to help users logically group CI/CD workload history and separate out long term result storage away
from the Pipeline controller. For more info information, please
see [Tekton Results](https://github.com/tektoncd/results)

Note: Dashboard for [Tekton Results](https://github.com/tektoncd/results) API support is still at early stage.

## [Tekton Results](https://github.com/tektoncd/results) supporting set-up

1. follow Tekton Results [installation instructions](https://github.com/tektoncd/results/blob/main/docs/install.md)
2. append `--enable-results` arguments to install, note that `--enable-results` override `--read-write`.

```bash
./scripts/installer install --enable-results
```
27 changes: 27 additions & 0 deletions overlays/installer/results/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Copyright 2020-2023 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: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../read-only
patches:
- path: ../../patches/results/deployment-tls-patch.yaml
target:
group: apps
kind: Deployment
name: tekton-dashboard
namespace: tekton-pipelines
version: v1
35 changes: 35 additions & 0 deletions overlays/patches/results/deployment-tls-patch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Copyright 2020-2021 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.

---
- op: add
path: /spec/template/spec/volumes/-
value:
name: tls
secret:
secretName: tekton-results-tls
- op: add
path: /spec/template/spec/containers/0/volumeMounts/-
value:
name: tls
mountPath: "/etc/tls"
readOnly: true
- op: add
path: /spec/template/spec/containers/0/args/-
value:
--enable-results-tls=1
- op: add
path: /spec/template/spec/containers/0/args/-
value:
--results-tls-cert-path=/etc/tls/tls.crt
7 changes: 4 additions & 3 deletions pkg/endpoints/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ func (o Options) GetTriggersNamespace() string {

// Resource is a wrapper around all necessary clients and config used for endpoints
type Resource struct {
Config *rest.Config
K8sClient k8sclientset.Interface
Options Options
Config *rest.Config
K8sClient k8sclientset.Interface
Options Options
ResultsConfig *rest.Config
}
23 changes: 17 additions & 6 deletions pkg/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ func makeUpgradeTransport(config *rest.Config, keepalive time.Duration) (proxy.U
}

// Register returns a HTTP handler with the Dashboard and Kubernetes APIs registered
func Register(r endpoints.Resource, cfg *rest.Config) (*Server, error) {
func Register(r endpoints.Resource, cfg *rest.Config, resultsCfg *rest.Config) (*Server, error) {
logging.Log.Info("Adding Kube API")
apiProxyPrefix := "/api/"
apisProxyPrefix := "/apis/"
Expand All @@ -134,6 +134,14 @@ func Register(r endpoints.Resource, cfg *rest.Config) (*Server, error) {
mux.Handle(apiProxyPrefix, proxyHandler)
mux.Handle(apisProxyPrefix, proxyHandler)

logging.Log.Info("Adding Results API")
resultsApiProxyPrefix := "/apis/results.tekton.dev/"
resultsProxyHandler, err := NewProxyHandler(resultsCfg, 30*time.Second)
if err != nil {
return nil, err
}
mux.Handle(resultsApiProxyPrefix, resultsProxyHandler)

logging.Log.Info("Adding Dashboard APIs")
registerWeb(r, mux)
registerPropertiesEndpoint(r, mux)
Expand All @@ -158,14 +166,17 @@ func NewProxyHandler(cfg *rest.Config, keepalive time.Duration) (http.Handler, e
responder := &responder{}
transport, err := rest.TransportFor(cfg)
if err != nil {
return nil, err
}
upgradeTransport, err := makeUpgradeTransport(cfg, keepalive)
if err != nil {
logging.Log.Error(err)
return nil, err
}
proxy := proxy.NewUpgradeAwareHandler(target, transport, false, false, responder)
proxy.UpgradeTransport = upgradeTransport
if !cfg.TLSClientConfig.Insecure {
upgradeTransport, err := makeUpgradeTransport(cfg, keepalive)
if err != nil {
return nil, err
}
proxy.UpgradeTransport = upgradeTransport
}
proxy.UseRequestLocation = true
proxy.UseLocationHost = true

Expand Down
9 changes: 8 additions & 1 deletion scripts/installer
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

# dashboard flavour
READONLY="true"
RESULTS_SUPPORT="false"

# configuration default values
DEBUG="false"
Expand Down Expand Up @@ -90,7 +91,9 @@ debug() {
compile() {
local overlay="overlays/installer"

if [ "$READONLY" == "true" ]; then
if [ "$RESULTS_SUPPORT" == "true" ]; then
overlay="$overlay/results"
elif [ "$READONLY" == "true" ]; then
overlay="$overlay/read-only"
else
overlay="$overlay/read-write"
Expand Down Expand Up @@ -425,6 +428,7 @@ help () {
echo -e "\t[--tenant-namespace <namespace>]\tWill limit the visibility to the specified namespace only"
echo -e "\t[--triggers-namespace <namespace>]\tOverride the namespace where Tekton Triggers is installed (defaults to Dashboard install namespace)"
echo -e "\t[--version <version>]\t\t\tWill download manifests for specified version or build everything using kustomize/ko"
echo -e "\t[--enable-results]\t\t\tWill build manifests that enable Tekton Results support"
}

# cleanup temporary files
Expand Down Expand Up @@ -550,6 +554,9 @@ while [[ $# -gt 0 ]]; do
shift
KO_RESOLVE_OPTIONS="$KO_RESOLVE_OPTIONS -t ${1}"
;;
'--enable-results')
RESULTS_SUPPORT="true"
;;
*)
echo "ERROR: Unknown option $1"
help
Expand Down

0 comments on commit a640c58

Please sign in to comment.