github.com/joshdk/godel@v0.0.0-20170529232908-862138a45aee/apps/distgo/pkg/slsspec/sls.go (about) 1 // Copyright 2016 Palantir Technologies, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package slsspec 16 17 import ( 18 "fmt" 19 "io/ioutil" 20 "os" 21 "path" 22 "path/filepath" 23 "strings" 24 25 "github.com/palantir/pkg/matcher" 26 "github.com/palantir/pkg/specdir" 27 "github.com/pkg/errors" 28 "gopkg.in/yaml.v2" 29 ) 30 31 const ( 32 Deployment = "deployment" 33 Manifest = "manifest" 34 Service = "service" 35 ServiceBin = "service/bin" 36 InitSh = "init.sh" 37 serviceNameTemplate = "ServiceName" 38 serviceVersionTemplate = "ServiceVersion" 39 ) 40 41 func New() specdir.LayoutSpec { 42 return specdir.NewLayoutSpec( 43 specdir.Dir(specdir.CompositeName(specdir.TemplateName(serviceNameTemplate), specdir.LiteralName("-"), specdir.TemplateName(serviceVersionTemplate)), "", 44 specdir.Dir(specdir.LiteralName("deployment"), Deployment, 45 specdir.File(specdir.LiteralName("manifest.yml"), Manifest), 46 ), 47 specdir.Dir(specdir.LiteralName("service"), Service, 48 specdir.Dir(specdir.LiteralName("bin"), ServiceBin, 49 specdir.File(specdir.LiteralName("init.sh"), InitSh), 50 ), 51 ), 52 ), 53 true, 54 ) 55 } 56 57 func TemplateValues(product, version string) specdir.TemplateValues { 58 return specdir.TemplateValues{ 59 serviceNameTemplate: product, 60 serviceVersionTemplate: version, 61 } 62 } 63 64 func Validate(rootDir string, values specdir.TemplateValues, excludeYML matcher.Matcher) error { 65 _, err := specdir.New(rootDir, New(), values, specdir.Validate) 66 if err != nil { 67 return err 68 } 69 // check validity of all YML files except those in service directory (binaries may contain invalid YML) 70 invalidYMLFiles, err := invalidYMLFiles(rootDir, func(path string) bool { 71 relPath, err := filepath.Rel(rootDir, path) 72 return err == nil && excludeYML != nil && excludeYML.Match(relPath) 73 }) 74 if err != nil { 75 return errors.Wrapf(err, "failed to determine validity of YML files") 76 } 77 if len(invalidYMLFiles) > 0 { 78 msg := fmt.Sprintf("invalid YML files: %v\n", invalidYMLFiles) 79 msg += "If these files are known to be correct, exclude them from validation using the SLS YML validation exclude matcher." 80 return errors.Errorf(msg) 81 } 82 return nil 83 } 84 85 func invalidYMLFiles(rootDir string, skip func(path string) bool) ([]string, error) { 86 var invalidYMLFiles []string 87 if err := filepath.Walk(rootDir, func(currFile string, info os.FileInfo, err error) error { 88 if err != nil { 89 return err 90 } 91 if info.IsDir() || skip(currFile) { 92 return nil 93 } 94 if strings.HasSuffix(info.Name(), ".yml") || strings.HasSuffix(info.Name(), ".yaml") { 95 bytes, err := ioutil.ReadFile(currFile) 96 if err != nil { 97 return err 98 } 99 var m interface{} 100 if err := yaml.Unmarshal(bytes, &m); err != nil { 101 rootRelPath := currFile 102 if relPath, err := filepath.Rel(rootDir, currFile); err == nil { 103 rootRelPath = path.Join(path.Base(rootDir), relPath) 104 } 105 // if YML file fails unmarshal, treat it as invalid 106 invalidYMLFiles = append(invalidYMLFiles, rootRelPath) 107 } 108 } 109 return nil 110 }); err != nil { 111 return nil, err 112 } 113 return invalidYMLFiles, nil 114 }