github.com/drone/runner-go@v1.12.0/manifest/parse.go (about)

     1  // Copyright 2019 Drone.IO Inc. All rights reserved.
     2  // Use of this source code is governed by the Polyform License
     3  // that can be found in the LICENSE file.
     4  
     5  package manifest
     6  
     7  import (
     8  	"bufio"
     9  	"bytes"
    10  	"io"
    11  	"os"
    12  	"strings"
    13  
    14  	"github.com/buildkite/yaml"
    15  )
    16  
    17  // Parse parses the configuration from io.Reader r.
    18  func Parse(r io.Reader) (*Manifest, error) {
    19  	resources, err := ParseRaw(r)
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  	manifest := new(Manifest)
    24  	for _, raw := range resources {
    25  		if raw == nil {
    26  			continue
    27  		}
    28  		resource, err := parseRaw(raw)
    29  		if err != nil {
    30  			return nil, err
    31  		}
    32  		if resource == nil {
    33  			continue
    34  		}
    35  		manifest.Resources = append(
    36  			manifest.Resources,
    37  			resource,
    38  		)
    39  	}
    40  	return manifest, nil
    41  }
    42  
    43  // ParseBytes parses the configuration from bytes b.
    44  func ParseBytes(b []byte) (*Manifest, error) {
    45  	return Parse(
    46  		bytes.NewBuffer(b),
    47  	)
    48  }
    49  
    50  // ParseString parses the configuration from string s.
    51  func ParseString(s string) (*Manifest, error) {
    52  	return ParseBytes(
    53  		[]byte(s),
    54  	)
    55  }
    56  
    57  // ParseFile parses the configuration from path p.
    58  func ParseFile(p string) (*Manifest, error) {
    59  	f, err := os.Open(p)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  	defer f.Close()
    64  	return Parse(f)
    65  }
    66  
    67  func parseRaw(r *RawResource) (Resource, error) {
    68  	for _, fn := range drivers {
    69  		res, ok, err := fn(r)
    70  		if ok {
    71  			return res, err
    72  		}
    73  	}
    74  	return nil, nil
    75  }
    76  
    77  // ParseRaw parses the multi-document yaml from the
    78  // io.Reader and returns a slice of raw resources.
    79  func ParseRaw(r io.Reader) ([]*RawResource, error) {
    80  	const newline = '\n'
    81  	var resources []*RawResource
    82  	var resource *RawResource
    83  
    84  	scanner := bufio.NewScanner(r)
    85  	for scanner.Scan() {
    86  		line := scanner.Text()
    87  		if isSeparator(line) {
    88  			resource = nil
    89  		}
    90  		if resource == nil {
    91  			resource = &RawResource{}
    92  			resources = append(resources, resource)
    93  		}
    94  		if isSeparator(line) {
    95  			continue
    96  		}
    97  		if isTerminator(line) {
    98  			break
    99  		}
   100  		if scanner.Err() == io.EOF {
   101  			break
   102  		}
   103  		resource.Data = append(
   104  			resource.Data,
   105  			line...,
   106  		)
   107  		resource.Data = append(
   108  			resource.Data,
   109  			newline,
   110  		)
   111  	}
   112  	for _, resource := range resources {
   113  		err := yaml.Unmarshal(resource.Data, resource)
   114  		if err != nil {
   115  			return nil, err
   116  		}
   117  	}
   118  	return resources, nil
   119  }
   120  
   121  // ParseRawString parses the multi-document yaml from s
   122  // and returns a slice of raw resources.
   123  func ParseRawString(s string) ([]*RawResource, error) {
   124  	return ParseRaw(
   125  		strings.NewReader(s),
   126  	)
   127  }
   128  
   129  // ParseRawBytes parses the multi-document yaml from b
   130  // and returns a slice of raw resources.
   131  func ParseRawBytes(b []byte) ([]*RawResource, error) {
   132  	return ParseRaw(
   133  		bytes.NewReader(b),
   134  	)
   135  }
   136  
   137  // ParseRawFile parses the multi-document yaml from path p
   138  // and returns a slice of raw resources.
   139  func ParseRawFile(p string) ([]*RawResource, error) {
   140  	f, err := os.Open(p)
   141  	if err != nil {
   142  		return nil, err
   143  	}
   144  	defer f.Close()
   145  	return ParseRaw(f)
   146  }
   147  
   148  func isSeparator(s string) bool {
   149  	return strings.HasPrefix(s, "---")
   150  }
   151  
   152  func isTerminator(s string) bool {
   153  	return strings.HasPrefix(s, "...")
   154  }