2021-09-19 12:00:00 +00:00
|
|
|
// Copyright (c) 2019, Drone IO Inc.
|
|
|
|
// Copyright (c) 2021, Robert Kaussow <mail@thegeeklab.de>
|
2019-02-10 19:00:16 +00:00
|
|
|
|
2019-01-22 23:44:17 +00:00
|
|
|
package yaml
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"bytes"
|
2019-05-30 15:14:47 +00:00
|
|
|
"errors"
|
2019-01-22 23:44:17 +00:00
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
|
2022-03-30 20:42:06 +00:00
|
|
|
"gopkg.in/yaml.v2"
|
2019-01-22 23:44:17 +00:00
|
|
|
)
|
|
|
|
|
2023-02-08 09:14:20 +00:00
|
|
|
var ErrMissingKind = errors.New("yaml: missing kind attribute")
|
2019-05-30 15:14:47 +00:00
|
|
|
|
2019-01-22 23:44:17 +00:00
|
|
|
// Parse parses the configuration from io.Reader r.
|
|
|
|
func Parse(r io.Reader) (*Manifest, error) {
|
|
|
|
resources, err := ParseRaw(r)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2023-02-08 09:14:20 +00:00
|
|
|
|
2019-01-22 23:44:17 +00:00
|
|
|
manifest := new(Manifest)
|
2023-02-08 09:14:20 +00:00
|
|
|
|
2019-01-22 23:44:17 +00:00
|
|
|
for _, raw := range resources {
|
|
|
|
if raw == nil {
|
|
|
|
continue
|
|
|
|
}
|
2023-02-08 09:14:20 +00:00
|
|
|
|
2019-01-22 23:44:17 +00:00
|
|
|
resource, err := parseRaw(raw)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2023-02-08 09:14:20 +00:00
|
|
|
|
2019-05-30 15:14:47 +00:00
|
|
|
if resource.GetKind() == "" {
|
2023-02-08 09:14:20 +00:00
|
|
|
return nil, ErrMissingKind
|
2019-05-30 15:14:47 +00:00
|
|
|
}
|
2023-02-08 09:14:20 +00:00
|
|
|
|
2019-01-22 23:44:17 +00:00
|
|
|
manifest.Resources = append(
|
|
|
|
manifest.Resources,
|
|
|
|
resource,
|
|
|
|
)
|
|
|
|
}
|
2023-02-08 09:14:20 +00:00
|
|
|
|
2019-01-22 23:44:17 +00:00
|
|
|
return manifest, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ParseBytes parses the configuration from bytes b.
|
|
|
|
func ParseBytes(b []byte) (*Manifest, error) {
|
|
|
|
return Parse(
|
|
|
|
bytes.NewBuffer(b),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ParseString parses the configuration from string s.
|
|
|
|
func ParseString(s string) (*Manifest, error) {
|
|
|
|
return ParseBytes(
|
|
|
|
[]byte(s),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ParseFile parses the configuration from path p.
|
|
|
|
func ParseFile(p string) (*Manifest, error) {
|
|
|
|
f, err := os.Open(p)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer f.Close()
|
2023-02-08 09:14:20 +00:00
|
|
|
|
2019-01-22 23:44:17 +00:00
|
|
|
return Parse(f)
|
|
|
|
}
|
|
|
|
|
2023-02-08 09:14:20 +00:00
|
|
|
func parseRaw(r *RawResource) (Resource, error) { //nolint:ireturn
|
2019-01-22 23:44:17 +00:00
|
|
|
var obj Resource
|
2023-02-08 09:14:20 +00:00
|
|
|
|
2019-01-22 23:44:17 +00:00
|
|
|
switch r.Kind {
|
|
|
|
case "cron":
|
|
|
|
obj = new(Cron)
|
|
|
|
case "secret":
|
|
|
|
obj = new(Secret)
|
|
|
|
case "signature":
|
|
|
|
obj = new(Signature)
|
|
|
|
case "registry":
|
|
|
|
obj = new(Registry)
|
|
|
|
default:
|
|
|
|
obj = new(Pipeline)
|
|
|
|
}
|
2023-02-08 09:14:20 +00:00
|
|
|
|
2019-01-22 23:44:17 +00:00
|
|
|
err := yaml.Unmarshal(r.Data, obj)
|
2023-02-08 09:14:20 +00:00
|
|
|
|
2019-01-22 23:44:17 +00:00
|
|
|
return obj, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// ParseRaw parses the multi-document yaml from the
|
|
|
|
// io.Reader and returns a slice of raw resources.
|
|
|
|
func ParseRaw(r io.Reader) ([]*RawResource, error) {
|
|
|
|
const newline = '\n'
|
2023-02-08 09:14:20 +00:00
|
|
|
|
|
|
|
var (
|
|
|
|
resources []*RawResource
|
|
|
|
resource *RawResource
|
|
|
|
)
|
2019-01-22 23:44:17 +00:00
|
|
|
|
|
|
|
scanner := bufio.NewScanner(r)
|
|
|
|
for scanner.Scan() {
|
|
|
|
line := scanner.Text()
|
|
|
|
if isSeparator(line) {
|
|
|
|
resource = nil
|
|
|
|
}
|
2023-02-08 09:14:20 +00:00
|
|
|
|
2019-01-22 23:44:17 +00:00
|
|
|
if resource == nil {
|
|
|
|
resource = &RawResource{}
|
|
|
|
resources = append(resources, resource)
|
|
|
|
}
|
2023-02-08 09:14:20 +00:00
|
|
|
|
2019-01-22 23:44:17 +00:00
|
|
|
if isSeparator(line) {
|
|
|
|
continue
|
|
|
|
}
|
2023-02-08 09:14:20 +00:00
|
|
|
|
2019-01-22 23:44:17 +00:00
|
|
|
if isTerminator(line) {
|
|
|
|
break
|
|
|
|
}
|
2023-02-08 09:14:20 +00:00
|
|
|
|
|
|
|
if errors.Is(scanner.Err(), io.EOF) {
|
2019-01-22 23:44:17 +00:00
|
|
|
break
|
|
|
|
}
|
2023-02-08 09:14:20 +00:00
|
|
|
|
2019-01-22 23:44:17 +00:00
|
|
|
resource.Data = append(
|
|
|
|
resource.Data,
|
|
|
|
line...,
|
|
|
|
)
|
2023-02-08 09:14:20 +00:00
|
|
|
|
2019-01-22 23:44:17 +00:00
|
|
|
resource.Data = append(
|
|
|
|
resource.Data,
|
|
|
|
newline,
|
|
|
|
)
|
|
|
|
}
|
2023-02-08 09:14:20 +00:00
|
|
|
|
2019-01-22 23:44:17 +00:00
|
|
|
for _, resource := range resources {
|
|
|
|
err := yaml.Unmarshal(resource.Data, resource)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
2023-02-08 09:14:20 +00:00
|
|
|
|
2019-01-22 23:44:17 +00:00
|
|
|
return resources, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ParseRawString parses the multi-document yaml from s
|
|
|
|
// and returns a slice of raw resources.
|
|
|
|
func ParseRawString(s string) ([]*RawResource, error) {
|
|
|
|
return ParseRaw(
|
|
|
|
strings.NewReader(s),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ParseRawBytes parses the multi-document yaml from b
|
|
|
|
// and returns a slice of raw resources.
|
|
|
|
func ParseRawBytes(b []byte) ([]*RawResource, error) {
|
|
|
|
return ParseRaw(
|
|
|
|
bytes.NewReader(b),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ParseRawFile parses the multi-document yaml from path p
|
|
|
|
// and returns a slice of raw resources.
|
|
|
|
func ParseRawFile(p string) ([]*RawResource, error) {
|
|
|
|
f, err := os.Open(p)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer f.Close()
|
2023-02-08 09:14:20 +00:00
|
|
|
|
2019-01-22 23:44:17 +00:00
|
|
|
return ParseRaw(f)
|
|
|
|
}
|
|
|
|
|
|
|
|
func isSeparator(s string) bool {
|
|
|
|
return strings.HasPrefix(s, "---")
|
|
|
|
}
|
|
|
|
|
|
|
|
func isTerminator(s string) bool {
|
|
|
|
return strings.HasPrefix(s, "...")
|
|
|
|
}
|