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 }