mirror of
https://github.com/gravitational/teleport
synced 2024-10-20 17:23:22 +00:00
0e37917155
* dronegen: Fix nesting of slack template parameter When generating a GitHub Actions pipeline, put the slack message template under `step.settings` instead of `step`, as the template is a parameter to the plugin, not a configuration item of the step. The `Template` field (now unused) has not been removed from the `step` struct as it needs to be there to unmarshal the existing `.drone.yml` file. Once that has been regenerated, we can remove the field. * drone: Regenerate .drone.yml with correct templates Regenerate `.drone.yml` with the correct template setting for the slack plugin. * dronegen: Remove unused Template field from step Remove the unused `step.Template` field as it is no longer used. It could not be removed earlier as it was needed to be able to unmarshal the existing `.drone.yml` file. Now that has been done in a previous commit, the field can be removed.
264 lines
7.4 KiB
Go
264 lines
7.4 KiB
Go
// Copyright 2021 Gravitational, Inc
|
|
//
|
|
// 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 (
|
|
"errors"
|
|
"fmt"
|
|
"runtime"
|
|
"strings"
|
|
|
|
"k8s.io/apimachinery/pkg/api/resource"
|
|
)
|
|
|
|
// Types to mirror the YAML fields of the drone config.
|
|
// See https://docs.drone.io/pipeline/kubernetes/syntax/ and https://docs.drone.io/pipeline/exec/syntax/.
|
|
|
|
type pipeline struct {
|
|
comment string
|
|
|
|
Kind string `yaml:"kind"`
|
|
Type string `yaml:"type"`
|
|
Name string `yaml:"name"`
|
|
Environment map[string]value `yaml:"environment,omitempty"`
|
|
Trigger trigger `yaml:"trigger"`
|
|
Workspace workspace `yaml:"workspace,omitempty"`
|
|
Platform platform `yaml:"platform,omitempty"`
|
|
Node map[string]value `yaml:"node,omitempty"`
|
|
Clone clone `yaml:"clone,omitempty"`
|
|
DependsOn []string `yaml:"depends_on,omitempty"`
|
|
Concurrency concurrency `yaml:"concurrency,omitempty"`
|
|
Steps []step `yaml:"steps"`
|
|
Services []service `yaml:"services,omitempty"`
|
|
Volumes []volume `yaml:"volumes,omitempty"`
|
|
ImagePullSecrets []string `yaml:"image_pull_secrets,omitempty"`
|
|
}
|
|
|
|
func newKubePipeline(name string) pipeline {
|
|
return pipeline{
|
|
comment: generatedComment(),
|
|
Kind: "pipeline",
|
|
Type: "kubernetes",
|
|
Name: name,
|
|
Clone: clone{Disable: true},
|
|
}
|
|
}
|
|
|
|
func newExecPipeline(name string) pipeline {
|
|
return pipeline{
|
|
comment: generatedComment(),
|
|
Kind: "pipeline",
|
|
Type: "exec",
|
|
Name: name,
|
|
Clone: clone{Disable: true},
|
|
}
|
|
}
|
|
|
|
func generatedComment() string {
|
|
c := `################################################
|
|
# Generated using dronegen, do not edit by hand!
|
|
# Use 'make dronegen' to update.
|
|
`
|
|
pc, file, line, ok := runtime.Caller(2)
|
|
if ok {
|
|
// Trim off the local path to the repo.
|
|
i := strings.LastIndex(file, "dronegen")
|
|
if i > 0 {
|
|
file = file[i:]
|
|
}
|
|
|
|
info := fmt.Sprintf("line %d", line)
|
|
fn := runtime.FuncForPC(pc)
|
|
if fn != nil {
|
|
info = fn.Name()
|
|
}
|
|
c += fmt.Sprintf("# Generated at %s (%s)\n", file, info)
|
|
}
|
|
c += "################################################\n\n"
|
|
return c
|
|
}
|
|
|
|
type trigger struct {
|
|
Event triggerRef `yaml:"event,omitempty"`
|
|
Cron triggerRef `yaml:"cron,omitempty"`
|
|
Target triggerRef `yaml:"target,omitempty"`
|
|
Ref triggerRef `yaml:"ref,omitempty"`
|
|
Repo triggerRef `yaml:"repo"`
|
|
Branch triggerRef `yaml:"branch,omitempty"`
|
|
}
|
|
|
|
type triggerRef struct {
|
|
Include []string `yaml:"include,omitempty"`
|
|
Exclude []string `yaml:"exclude,omitempty"`
|
|
}
|
|
|
|
// UnmarshalYAML parses trigger references as either a list of strings, or as
|
|
// include/exclude lists. Both are allowed by drone.
|
|
func (v *triggerRef) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
var rawItems []string
|
|
if err := unmarshal(&rawItems); err == nil {
|
|
v.Include = rawItems
|
|
return nil
|
|
}
|
|
var regular struct {
|
|
Include []string `yaml:"include,omitempty"`
|
|
Exclude []string `yaml:"exclude,omitempty"`
|
|
}
|
|
if err := unmarshal(®ular); err == nil {
|
|
v.Include = regular.Include
|
|
v.Exclude = regular.Exclude
|
|
return nil
|
|
}
|
|
return errors.New("can't unmarshal the value as either string or from_secret reference")
|
|
}
|
|
|
|
type workspace struct {
|
|
Path string `yaml:"path"`
|
|
}
|
|
|
|
type clone struct {
|
|
Disable bool `yaml:"disable"`
|
|
}
|
|
|
|
type platform struct {
|
|
OS string `yaml:"os"`
|
|
Arch string `yaml:"arch"`
|
|
}
|
|
|
|
type concurrency struct {
|
|
Limit int `yaml:"limit"`
|
|
}
|
|
|
|
type volume struct {
|
|
Name string `yaml:"name"`
|
|
Temp *volumeTemp `yaml:"temp,omitempty"`
|
|
Claim *volumeClaim `yaml:"claim,omitempty"`
|
|
}
|
|
|
|
type volumeTemp struct {
|
|
Medium string `yaml:"medium,omitempty"`
|
|
}
|
|
|
|
type volumeClaim struct {
|
|
Name string `yaml:"name"`
|
|
}
|
|
|
|
type service struct {
|
|
Name string `yaml:"name"`
|
|
Image string `yaml:"image"`
|
|
Privileged bool `yaml:"privileged"`
|
|
Volumes []volumeRef `yaml:"volumes"`
|
|
}
|
|
|
|
type volumeRef struct {
|
|
Name string `yaml:"name"`
|
|
Path string `yaml:"path"`
|
|
}
|
|
|
|
type step struct {
|
|
Name string `yaml:"name"`
|
|
Image string `yaml:"image,omitempty"`
|
|
Pull string `yaml:"pull,omitempty"`
|
|
Commands []string `yaml:"commands,omitempty"`
|
|
Environment map[string]value `yaml:"environment,omitempty"`
|
|
Volumes []volumeRef `yaml:"volumes,omitempty"`
|
|
Settings map[string]value `yaml:"settings,omitempty"`
|
|
When *condition `yaml:"when,omitempty"`
|
|
Failure string `yaml:"failure,omitempty"`
|
|
Resources *containerResources `yaml:"resources,omitempty"`
|
|
DependsOn []string `yaml:"depends_on,omitempty"`
|
|
}
|
|
|
|
type condition struct {
|
|
Status []string `yaml:"status,omitempty"`
|
|
}
|
|
|
|
// value is a string value for key:value pairs like "environment" or
|
|
// "settings". Values can be either inline strings (raw) or references to
|
|
// secrets stored in Drone (fromSecret).
|
|
type value struct {
|
|
raw string
|
|
fromSecret string
|
|
}
|
|
|
|
type valueFromSecret struct {
|
|
FromSecret string `yaml:"from_secret"`
|
|
}
|
|
|
|
func (v value) MarshalYAML() (interface{}, error) {
|
|
if v.raw != "" && v.fromSecret != "" {
|
|
return nil, fmt.Errorf("value %+v has both raw and fromSecret set, can only have one", v)
|
|
}
|
|
if v.raw != "" {
|
|
return v.raw, nil
|
|
}
|
|
if v.fromSecret != "" {
|
|
return valueFromSecret{FromSecret: v.fromSecret}, nil
|
|
}
|
|
return nil, fmt.Errorf("value has neither raw nor fromSecret set, need one")
|
|
}
|
|
|
|
func (v *value) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
if err := unmarshal(&v.raw); err == nil {
|
|
return nil
|
|
}
|
|
var fs valueFromSecret
|
|
if err := unmarshal(&fs); err == nil {
|
|
v.fromSecret = fs.FromSecret
|
|
return nil
|
|
}
|
|
return errors.New("can't unmarshal the value as either string or from_secret reference")
|
|
}
|
|
|
|
type containerResources struct {
|
|
Limits *resourceSet `yaml:"limits,omitempty"`
|
|
// Not currently supported
|
|
// Requests *resourceSet `yaml:"requests,omitempty"`
|
|
}
|
|
|
|
type resourceSet struct {
|
|
// Drone does not strictly follow the k8s CRD format for resources here
|
|
// See link for details:
|
|
// https://docs.drone.io/pipeline/kubernetes/syntax/steps/#resources
|
|
// CPU *resourceQuantity `yaml:"cpu,omitempty"`
|
|
|
|
CPU float64 `yaml:"cpu,omitempty"`
|
|
Memory *resourceQuantity `yaml:"memory,omitempty"`
|
|
}
|
|
|
|
// This is a workaround to get resource.Quantity to unmarshal correctly
|
|
type resourceQuantity resource.Quantity
|
|
|
|
func (rq *resourceQuantity) MarshalYAML() (interface{}, error) {
|
|
return ((*resource.Quantity)(rq)).String(), nil
|
|
}
|
|
|
|
func (rq *resourceQuantity) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
var value string
|
|
if err := unmarshal(&value); err != nil {
|
|
return errors.New("failed to unmarshal the value into a string")
|
|
}
|
|
|
|
parsedValue, err := resource.ParseQuantity(value)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to unmarshal string %q into resource quantity", value)
|
|
}
|
|
|
|
q := ((*resource.Quantity)(rq))
|
|
q.Add(parsedValue)
|
|
|
|
return nil
|
|
}
|