kubesphere / ks-devops

This is a cloud-native application that focuses on the DevOps area.
https://kubesphere.io/devops/
Apache License 2.0
159 stars 89 forks source link

Support using tekton to create pipelines #81

Open wujiahao15 opened 3 years ago

wujiahao15 commented 3 years ago

Add support for using tekton to create pipelines in ks-devops.

/label ospp-2021

wujiahao15 commented 3 years ago

/label ospp-2021

LinuxSuRen commented 3 years ago

/label ospp-2021

wujiahao15 commented 3 years ago

API design is here.

wujiahao15 commented 3 years ago

CLI basic design can be seen here.

wujiahao15 commented 3 years ago

To simplify the usage of Tekton in ks-devops, I decide to create a new syntax for using devops referring to Github Actions.

TODO

What I am going to do is as follows:

  1. create a new crd named Pipeline with another version v2alpha1.
  2. create the controller of the crd Pipeline to translate it to tekton crds and run the tekton-based pipeline.

Syntax design

Here, I will describe the example of the new devops syntax first to give you a blueprint of it.

Overview

┌─────────────────────────────────┐   ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
│         Pipeline                │                          
│  ┌─────────────────────────┐    │   │name: "pipeline name"│
│  │      Task               │    │                          
│  │ ┌─────────────────────┐ │    │   │tasks:               │
│  │ │    Step             │ │    │                          
│  │ └─────────────────────┘ │──┐ │   │  - name: "task1"    │
│  │ ┌─────────────────────┐ │  │ │        steps:            
│  │ │    Step             │ │  │ │   │      - step1        │
│  │ └─────────────────────┘ │  │ │          - step2         
│  └─────────────────────────┘  │ │   │                     │
│  ┌─────────────────────────┐  │ │                          
│  │      Task               │  │ │   │                     │
│  │ ┌─────────────────────┐ │  │ │      - name: "task2"     
│  │ │    Step             │ │  │ │   │    need:            │
│  │ └─────────────────────┘ │◀─┘ │          - task1         
│  │ ┌─────────────────────┐ │    │   │    steps:           │
│  │ │    Step             │ │    │          - step1         
│  │ └─────────────────────┘ │    │   │      - step2        │
│  └─────────────────────────┘    │                          
└─────────────────────────────────┘   └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘                              

Details of syntax

The detailed syntax can be describe by the following yaml file:

name: "pipeline name" # required, description: specify the pipeline name
tasks: # required, description: tasks contains a lot of task
  - name: "task name 1" # required, description: specify the task name
    need: [""] # optional, description: names of tasks which must be done before the current task
    uses: "template name of task" # optional, description: the name of template task
    with: # optional, description: params passed to the template task
      - key: value
    env: # optional, description: environment variable settings
      - env_key: env_value
    steps: # optional, description: for self defined task steps
      - name: "step name 1" # required, description: the name of the step
        image: "gcr.io/image:tag" # optional, default: ubuntu, description: the image url of the container
        workspace: "/path/to/execute/scripts" # optional, description: set the workspace of the step
        command: ["echo"] # optional, description: entry point of the container image
        args: ["hello", "step 1"] # optional, description: arguments of the entry point
        script: | # optional, description: command line scripts
          # command line scripts
          # e.g.
          ls
          echo "hello step 1"

Use cases

hello world

The following pipeline will print hello world.

name: "Hello world"
tasks:
  - name: "echo-hello-world-task"
    steps:
      - name: "echo-hello-world-step"
        image: "ubuntu:16.04"
        command: ["/bin/bash"]
        args: ["-c", "echo hello world"]

Using git task template

This example is about how to use predefined task template.

name: "Git clone"
tasks:
  - name: "git-clone-task"
    uses: "git-cli"
    with:
      - name: "GIT_URL"
        value: "https://github.com/kubesphere/ks-devops"
      - name: "GIT_REVISION"
        value: "master"
      - name: "GIT_SECRET"
        value: "${GIT_TOKEN}"
    env:
      - name: "GIT_TOKEN"
        value: "token"

Depending on the above examples, we can briefly describe the usage of an image-based task and a template-based task.

wujiahao15 commented 3 years ago

Based on the above syntax design, we can create a new crd called action.

We can define the following structs in /api/devops/v2alpha1/action_types.go and using make manifests in command line to generate CRD yaml files called devops.kubesphere.io_actions.yaml.

import (
    corev1 "k8s.io/api/core/v1"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// Step defines the content of the step
type Step struct {
    corev1.Container `json:",inline"`

    // This is an alpha field. You must set the "enable-api-fields" feature flag to "alpha"
    // for this field to be supported.
    //
    // Workspaces is a list of workspaces from the Task that this Step wants
    // exclusive access to. Adding a workspace to this list means that any
    // other Step or Sidecar that does not also request this Workspace will
    // not have access to it.
    // +optional
    Workspace string `json:"workspace,omitempty" description:"the path to execute step operations"`

    // Script is the contents of an executable file to execute.
    //
    // If Script is not empty, the Step cannot have an Command and the Args will be passed to the Script.
    // +optional
    Script string `json:"script,omitempty"`
}

// TaskSpec defines the content of the task
type TaskSpec struct {
    // Name is the task name for reference.
    Name string `json:"name" description:"the name of the task"`

    // Need is to define the execution order
    // +optional
    Need []string `json:"need,omitempty" description:"tasks which should run before the current task"`

    // Steps define executing steps
    // +optional
    Steps []Step `json:"steps,omitempty" description:"steps within the current task"`

    // Uses is the task template name, which is predefined in the cluster
    // +optional
    Uses string `json:"uses,omitempty" description:"task template name"`

    // With is params passed to the task template
    // +optional
    With map[string]string `json:"with,omitempty" description:"params list of the using template"`
}

// PipelineSpec defines the desired state of Pipeline
type PipelineSpec struct {
    // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
    // Important: Run "make" to regenerate code after modifying this file

    // Name is the pipeline name for reference.
    Name string `json:"name" description:"the name of the pipeline"`

    // Tasks is the content definition of the pipeline.
    Tasks []TaskSpec `json:"tasks,omitempty" description:"tasks defails"`
}

// PipelineStatus defines the observed state of Pipeline
type PipelineStatus struct {
    // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
    // Important: Run "make" to regenerate code after modifying this file
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status

// Pipeline is the Schema for the pipelines API
type Pipeline struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec   PipelineSpec   `json:"spec,omitempty"`
    Status PipelineStatus `json:"status,omitempty"`
}
wujiahao15 commented 3 years ago

@LinuxSuRen Any questions about the above syntax design and the crd implementation are welcome. 😊

LinuxSuRen commented 3 years ago

create a new crd named action (pipeline crd has already been used by Jenkins).

I prefer to use Pipeline. It's not a problem because they have a different version.

And one more question, how users can trigger the Pipeline? For example, do we have a CRD names PipelineRun?

wujiahao15 commented 3 years ago

create a new crd named action (pipeline crd has already been used by Jenkins).

I prefer to use Pipeline. It's not a problem because they have a different version.

And one more question, how users can trigger the Pipeline? For example, do we have a CRD names PipelineRun?

wujiahao15 commented 3 years ago

In addition, trigger mechanism is also provided by Tekton. The trigger uses the webhook to get messages sent from other git repositories. That is, i.e. we can trigger the git clone repository to run our pipeline. Just like the keyword on in Github Actions.

However, trigger is another project of Tekton. The tekton-helm-chart does not include trigger components. If we need to support trigger, we need to install it additionally. This can be done in the future work:

LinuxSuRen commented 3 years ago

The word trigger has multiple means here.

LinuxSuRen commented 3 years ago

Please don't forget the following potential features of the PipelineRun

wujiahao15 commented 3 years ago

According to the design described in the above comment, I would like to explain the details of implementation of creating new CRDs and their controller.

Pipeline

CRD Design

Implementation

PipelineRun

CRD Design

name: pipeline-name
description: run-for-first-time

Implementation