Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add tekton plugin #2

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions cmd/plugin/tekton/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package main

import (
"github.com/devstream-io/devstream/internal/pkg/plugin/tekton"
"github.com/devstream-io/devstream/pkg/util/log"
)

// NAME is the name of this DevStream plugin.
const NAME = "tekton"

// Plugin is the type used by DevStream core. It's a string.
type Plugin string

// Create implements the create of tekton.
func (p Plugin) Create(options map[string]interface{}) (map[string]interface{}, error) {
return tekton.Create(options)
}

// Update implements the update of tekton.
func (p Plugin) Update(options map[string]interface{}) (map[string]interface{}, error) {
return tekton.Update(options)
}

// Delete implements the delete of tekton.
func (p Plugin) Delete(options map[string]interface{}) (bool, error) {
return tekton.Delete(options)
}

// Read implements the read of tekton.
func (p Plugin) Read(options map[string]interface{}) (map[string]interface{}, error) {
return tekton.Read(options)
}

// DevStreamPlugin is the exported variable used by the DevStream core.
var DevStreamPlugin Plugin

func main() {
log.Infof("%T: %s is a plugin for DevStream. Use it with DevStream.\n", DevStreamPlugin, NAME)
}
43 changes: 43 additions & 0 deletions docs/plugins/tekton.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# tekton Plugin

This plugin installs [Tekton](https://tekton.dev/) in an existing Kubernetes cluster using the Helm chart.

## Usage

```yaml
tools:
# name of the tool
- name: tekton
# id of the tool instance
instanceID: default
# format: name.instanceID; If specified, dtm will make sure the dependency is applied first before handling this tool.
dependsOn: []
# options for the plugin
options:
# need to create the namespace or not, default: false
create_namespace: true
repo:
# name of the Helm repo
name: cdf
# url of the Helm repo
url: https://cdfoundation.github.io/tekton-helm-chart/
# Helm chart information
chart:
# name of the chart
chart_name: cdf/tekton-pipeline
# release name of the chart
release_name: tekton-pipeline
# k8s namespace where Tekton will be installed, don't use `tekton-pipelines`
namespace: tekton
# whether to wait for the release to be deployed or not
wait: true
# the time to wait for any individual Kubernetes operation (like Jobs for hooks). This defaults to 5m0s
timeout: 5m
# whether to perform a CRD upgrade during installation
upgradeCRDs: true
# custom configuration (Optional). You can refer to [Tekton values.yaml](https://github.com/cdfoundation/tekton-helm-chart/blob/master/charts/tekton-pipeline/values.yaml)
values_yaml: null

```

Currently, except for `values_yaml`, all the parameters in the example above are mandatory.
51 changes: 51 additions & 0 deletions internal/pkg/plugin/tekton/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package tekton

import (
"fmt"

"github.com/mitchellh/mapstructure"

. "github.com/devstream-io/devstream/internal/pkg/plugin/common/helm"
"github.com/devstream-io/devstream/pkg/util/log"
)

func Create(options map[string]interface{}) (map[string]interface{}, error) {
var opts Options
if err := mapstructure.Decode(options, &opts); err != nil {
return nil, err
}

if errs := validate(&opts); len(errs) != 0 {
for _, e := range errs {
log.Errorf("Options error: %s.", e)
}
return nil, fmt.Errorf("opts are illegal")
}

// deal with ns
if err := DealWithNsWhenInstall(&opts); err != nil {
return nil, err
}

var retErr error
defer func() {
if retErr == nil {
return
}
if err := DealWithNsWhenInterruption(&opts); err != nil {
log.Errorf("Failed to deal with namespace: %s.", err)
}
log.Debugf("Deal with namespace when interruption succeeded.")
}()

// install or upgrade
if retErr = InstallOrUpgradeChart(&opts); retErr != nil {
return nil, retErr
}

// fill the return map
retMap := GetStaticState().ToStringInterfaceMap()
log.Debugf("Return map: %v", retMap)

return retMap, nil
}
56 changes: 56 additions & 0 deletions internal/pkg/plugin/tekton/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package tekton

import (
"fmt"

"github.com/mitchellh/mapstructure"

. "github.com/devstream-io/devstream/internal/pkg/plugin/common/helm"

"github.com/devstream-io/devstream/pkg/util/helm"
"github.com/devstream-io/devstream/pkg/util/k8s"
"github.com/devstream-io/devstream/pkg/util/log"
)

func Delete(options map[string]interface{}) (bool, error) {
var opts Options
if err := mapstructure.Decode(options, &opts); err != nil {
return false, err
}

if errs := validate(&opts); len(errs) != 0 {
for _, e := range errs {
log.Errorf("Options error: %s.", e)
}
return false, fmt.Errorf("opts are illegal")
}

h, err := helm.NewHelm(opts.GetHelmParam())
if err != nil {
return false, err
}

log.Info("Uninstalling tekton helm chart.")
if err = h.UninstallHelmChartRelease(); err != nil {
return false, err
}

if err := dealWithNsWhenUninstall(&opts); err != nil {
return false, err
}

return true, nil
}

func dealWithNsWhenUninstall(opts *Options) error {
if !opts.CreateNamespace {
return nil
}

kubeClient, err := k8s.NewClient()
if err != nil {
return err
}

return kubeClient.DeleteNamespace(opts.Chart.Namespace)
}
64 changes: 64 additions & 0 deletions internal/pkg/plugin/tekton/read.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package tekton

import (
"fmt"

"github.com/mitchellh/mapstructure"
"k8s.io/utils/strings/slices"

. "github.com/devstream-io/devstream/internal/pkg/plugin/common/helm"
"github.com/devstream-io/devstream/pkg/util/helm"
"github.com/devstream-io/devstream/pkg/util/k8s"
"github.com/devstream-io/devstream/pkg/util/log"
)

const (
TektonDefaultNamespace = "tekton-pipelines"
)

func Read(options map[string]interface{}) (map[string]interface{}, error) {
var opts Options
if err := mapstructure.Decode(options, &opts); err != nil {
return nil, err
}

if errs := validate(&opts); len(errs) != 0 {
for _, e := range errs {
log.Errorf("Options error: %s.", e)
}
return nil, fmt.Errorf("opts are illegal")
}

// namespace := opts.Chart.Namespace
namespace := TektonDefaultNamespace
// if namespace == "" {
// namespace = TektonDefaultNamespace
// }

kubeClient, err := k8s.NewClient()
if err != nil {
return nil, err
}

dps, err := kubeClient.ListDeployments(namespace)
if err != nil {
return nil, err
}

retState := &helm.InstanceState{}
for _, dp := range dps {
dpName := dp.GetName()
if !slices.Contains(DefaultDeploymentList, dpName) {
log.Infof("Found unknown deployment: %s.", dpName)
}

ready := kubeClient.IsDeploymentReady(&dp)
retState.Workflows.AddDeployment(dpName, ready)
log.Debugf("The deployment %s is %t.", dp.GetName(), ready)
}

retMap := retState.ToStringInterfaceMap()
log.Debugf("Return map: %v.", retMap)

return retMap, nil
}
16 changes: 16 additions & 0 deletions internal/pkg/plugin/tekton/state.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package tekton

import "github.com/devstream-io/devstream/pkg/util/helm"

var DefaultDeploymentList = []string{
"tekton-pipelines-controller",
"tekton-pipelines-webhook",
}

func GetStaticState() *helm.InstanceState {
retState := &helm.InstanceState{}
for _, dpName := range DefaultDeploymentList {
retState.Workflows.AddDeployment(dpName, true)
}
return retState
}
1 change: 1 addition & 0 deletions internal/pkg/plugin/tekton/tekton.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package tekton
35 changes: 35 additions & 0 deletions internal/pkg/plugin/tekton/update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package tekton

import (
"fmt"

"github.com/mitchellh/mapstructure"

. "github.com/devstream-io/devstream/internal/pkg/plugin/common/helm"
"github.com/devstream-io/devstream/pkg/util/log"
)

func Update(options map[string]interface{}) (map[string]interface{}, error) {
var opts Options
if err := mapstructure.Decode(options, &opts); err != nil {
return nil, err
}

if errs := validate(&opts); len(errs) != 0 {
for _, e := range errs {
log.Errorf("Options error: %s.", e)
}
return nil, fmt.Errorf("opts are illegal")
}

// install or upgrade
if err := InstallOrUpgradeChart(&opts); err != nil {
return nil, err
}

// fill the return map
retMap := GetStaticState().ToStringInterfaceMap()
log.Debugf("Return map: %v", retMap)

return retMap, nil
}
11 changes: 11 additions & 0 deletions internal/pkg/plugin/tekton/validate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package tekton

import (
. "github.com/devstream-io/devstream/internal/pkg/plugin/common/helm"
"github.com/devstream-io/devstream/pkg/util/helm"
)

// validate validates the options provided by the core.
func validate(opts *Options) []error {
return helm.Validate(opts.GetHelmParam())
}
1 change: 1 addition & 0 deletions internal/pkg/show/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ var pluginDefaultConfigs = map[string]string{
"helm-generic": HelmGenericDefaultConfig,
"gitlab-repo-scaffolding-golang": GitLabRepoScaffoldingGolangDefaultConfig,
"hashicorp-vault": VaultDefaultConfig,
"tekton": TektonDefaultConfig,
}

func Show() error {
Expand Down
3 changes: 3 additions & 0 deletions internal/pkg/show/config/embed.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,7 @@ var (

//go:embed plugins/hashicorp-vault.yaml
VaultDefaultConfig string

//go:embed plugins/tekton.yaml
TektonDefaultConfig string
)
32 changes: 32 additions & 0 deletions internal/pkg/show/config/plugins/tekton.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
tools:
# name of the tool
- name: tekton
# id of the tool instance
instanceID: default
# format: name.instanceID; If specified, dtm will make sure the dependency is applied first before handling this tool.
dependsOn: []
# options for the plugin
options:
# need to create the namespace or not, default: false
create_namespace: true
repo:
# name of the Helm repo
name: cdf
# url of the Helm repo
url: https://cdfoundation.github.io/tekton-helm-chart/
# Helm chart information
chart:
# name of the chart
chart_name: cdf/tekton-pipeline
# release name of the chart
release_name: tekton-pipeline
# k8s namespace where Tekton will be installed, don't use tekton-pipelines
namespace: tekton
# whether to wait for the release to be deployed or not
wait: true
# the time to wait for any individual Kubernetes operation (like Jobs for hooks). This defaults to 5m0s
timeout: 5m
# whether to perform a CRD upgrade during installation
upgradeCRDs: true
# custom configuration (Optional). You can refer to [Tekton values.yaml](https://github.com/cdfoundation/tekton-helm-chart/blob/master/charts/tekton-pipeline/values.yaml)
values_yaml: null