github.com/kubevela/workflow@v0.6.0/pkg/stdlib/packages.go (about) 1 /* 2 Copyright 2022 The KubeVela Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package stdlib 18 19 import ( 20 "embed" 21 "fmt" 22 "os" 23 "path/filepath" 24 "strings" 25 26 "cuelang.org/go/cue/ast" 27 "cuelang.org/go/cue/build" 28 "cuelang.org/go/cue/parser" 29 "k8s.io/klog/v2" 30 ) 31 32 func init() { 33 var err error 34 pkgs, err := GetPackages() 35 if err != nil { 36 klog.ErrorS(err, "Unable to init builtin packages for imports") 37 os.Exit(1) 38 } 39 builtinImport, err = InitBuiltinImports(pkgs) 40 if err != nil { 41 klog.ErrorS(err, "Unable to init builtin imports") 42 os.Exit(1) 43 } 44 } 45 46 var ( 47 //go:embed actions 48 fs embed.FS 49 // builtinImport is the builtin import for cue 50 builtinImport []*build.Instance 51 ) 52 53 const ( 54 builtinPackageName = "vela/op" 55 builtinActionPath = "actions" 56 packagePath = "pkgs" 57 defaultVersion = "v1" 58 ) 59 60 // SetupBuiltinImports setup builtin imports 61 func SetupBuiltinImports(pkgs map[string]string) error { 62 builtin, err := GetPackages() 63 if err != nil { 64 return err 65 } 66 for k, v := range pkgs { 67 file, err := parser.ParseFile("-", v, parser.ParseComments) 68 if err != nil { 69 return err 70 } 71 if original, ok := builtin[k]; ok { 72 builtin[k] = mergeFiles(original, file) 73 } else { 74 builtin[k] = file 75 } 76 } 77 builtinImport, err = InitBuiltinImports(builtin) 78 if err != nil { 79 return err 80 } 81 return nil 82 } 83 84 // GetPackages Get Stdlib packages 85 func GetPackages() (map[string]*ast.File, error) { 86 versions, err := fs.ReadDir(builtinActionPath) 87 if err != nil { 88 return nil, err 89 } 90 ret := make(map[string]*ast.File) 91 92 for _, dirs := range versions { 93 pathPrefix := fmt.Sprintf("%s/%s", builtinActionPath, dirs.Name()) 94 files, err := fs.ReadDir(fmt.Sprintf("%s/%s", pathPrefix, packagePath)) 95 if err != nil { 96 return nil, err 97 } 98 opBytes, err := fs.ReadFile(fmt.Sprintf("%s/%s", pathPrefix, "op.cue")) 99 if err != nil { 100 return nil, err 101 } 102 opContent := string(opBytes) + "\n" 103 for _, file := range files { 104 body, err := fs.ReadFile(fmt.Sprintf("%s/%s/%s", pathPrefix, packagePath, file.Name())) 105 if err != nil { 106 return nil, err 107 } 108 pkgContent := fmt.Sprintf("%s: {\n%s\n}\n", strings.TrimSuffix(file.Name(), ".cue"), string(body)) 109 opContent += pkgContent 110 } 111 f, err := parser.ParseFile("-", opContent, parser.ParseComments) 112 if err != nil { 113 return nil, err 114 } 115 if dirs.Name() == defaultVersion { 116 ret[builtinPackageName] = f 117 } 118 ret[filepath.Join(builtinPackageName, dirs.Name())] = f 119 } 120 return ret, nil 121 } 122 123 // AddImportsFor install imports for build.Instance. 124 func AddImportsFor(inst *build.Instance, tagTempl string) error { 125 inst.Imports = append(inst.Imports, builtinImport...) 126 if tagTempl != "" { 127 p := &build.Instance{ 128 PkgName: filepath.Base("vela/custom"), 129 ImportPath: "vela/custom", 130 } 131 file, err := parser.ParseFile("-", tagTempl, parser.ParseComments) 132 if err != nil { 133 return err 134 } 135 if err := p.AddSyntax(file); err != nil { 136 return err 137 } 138 inst.Imports = append(inst.Imports, p) 139 } 140 return nil 141 } 142 143 // InitBuiltinImports init built in imports 144 func InitBuiltinImports(pkgs map[string]*ast.File) ([]*build.Instance, error) { 145 imports := make([]*build.Instance, 0) 146 for path, content := range pkgs { 147 p := &build.Instance{ 148 PkgName: filepath.Base(path), 149 ImportPath: path, 150 } 151 if err := p.AddSyntax(content); err != nil { 152 return nil, err 153 } 154 imports = append(imports, p) 155 } 156 return imports, nil 157 } 158 159 func mergeFiles(base, file *ast.File) *ast.File { 160 base.Decls = append(base.Decls, file.Decls...) 161 return base 162 }