github.com/TNTworks/flogo-cli@v0.9.1-0.20220522183836-60b8a963ae00/api/shim.go (about) 1 package api 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "os/exec" 8 "path" 9 "path/filepath" 10 "regexp" 11 "strings" 12 13 "github.com/TNTworks/flogo-cli/common" 14 "github.com/TNTworks/flogo-cli/util" 15 ) 16 17 const ( 18 fileShimSupportGo string = "shim_support.go" 19 fileShimGo string = "shim.go" 20 fileBuildGo string = "build.go" 21 fileMakefile string = "Makefile" 22 dirShim string = "shim" 23 ) 24 25 var fileSampleShimSupport = filepath.Join("examples", "engine", "shim", fileShimSupportGo) 26 27 var flogoImportPattern = regexp.MustCompile(`^(([^ ]*)[ ]+)?([^@:]*)@?([^:]*)?:?(.*)?$`) 28 29 30 type ShimBuilder struct { 31 appBuilder common.Builder 32 shim string 33 } 34 35 func (sb *ShimBuilder) Build(project common.AppProject) error { 36 37 err := backupMain(project) 38 if err != nil { 39 return err 40 } 41 42 defer shimCleanup(project) 43 44 err = createShimSupportGoFile(project) 45 if err != nil { 46 return err 47 } 48 49 if Verbose() { 50 fmt.Println("Preparing shim...") 51 } 52 built, err := prepareShim(project, sb.shim) 53 if err != nil { 54 return err 55 } 56 57 if !built { 58 fmt.Println("Using go build to build shim...") 59 60 err := simpleGoBuild(project) 61 if err != nil { 62 return err 63 } 64 } 65 66 return nil 67 } 68 69 func prepareShim(project common.AppProject, shim string) (bool, error) { 70 71 buf, err := ioutil.ReadFile(filepath.Join(project.Dir(), fileFlogoJson)) 72 if err != nil { 73 return false, err 74 } 75 76 flogoJSON := string(buf) 77 78 descriptor, err := util.ParseAppDescriptor(flogoJSON) 79 if err != nil { 80 return false, err 81 } 82 83 err = registerImports(project, descriptor) 84 if err != nil { 85 return false, err 86 } 87 88 for _, trgCfg := range descriptor.Triggers { 89 if trgCfg.Id == shim { 90 91 ref := trgCfg.Ref 92 93 if trgCfg.Ref != "" { 94 found := false 95 ref, found = GetAliasRef("flogo:trigger", trgCfg.Ref) 96 if !found { 97 return false, fmt.Errorf("unable to determine ref for trigger: %s", trgCfg.Id) 98 } 99 } 100 101 refImport, err := util.NewFlogoImportFromPath(ref) 102 if err != nil { 103 return false, err 104 } 105 106 impPath, err := project.GetPath(refImport) 107 if err != nil { 108 return false, err 109 } 110 111 var shimFilePath string 112 113 shimFilePath = filepath.Join(impPath, dirShim, fileShimGo) 114 115 if _, err := os.Stat(shimFilePath); err == nil { 116 117 err = util.CopyFile(shimFilePath, filepath.Join(project.SrcDir(), fileShimGo)) 118 if err != nil { 119 return false, err 120 } 121 122 // Check if this shim based trigger has a gobuild file. If the trigger has a gobuild 123 // execute that file, otherwise check if there is a Makefile to execute 124 goBuildFilePath := filepath.Join(impPath, dirShim, fileBuildGo) 125 126 makefilePath := filepath.Join(shimFilePath, dirShim, fileMakefile) 127 128 if _, err := os.Stat(goBuildFilePath); err == nil { 129 fmt.Println("Using build.go to build shim......") 130 131 err = util.CopyFile(goBuildFilePath, filepath.Join(project.SrcDir(), fileBuildGo)) 132 if err != nil { 133 return false, err 134 } 135 136 // Execute go run gobuild.go 137 err = util.ExecCmd(exec.Command("go", "run", fileBuildGo), project.SrcDir()) 138 if err != nil { 139 return false, err 140 } 141 142 return true, nil 143 } else if _, err := os.Stat(makefilePath); err == nil { 144 //look for Makefile and execute it 145 fmt.Println("Using make file to build shim...") 146 147 err = util.CopyFile(makefilePath, filepath.Join(project.SrcDir(), fileMakefile)) 148 if err != nil { 149 return false, err 150 } 151 152 if Verbose() { 153 fmt.Println("Make File:", makefilePath) 154 } 155 156 // Execute make 157 cmd := exec.Command("make", "-C", project.SrcDir()) 158 cmd.Stdout = os.Stdout 159 cmd.Stderr = os.Stderr 160 cmd.Env = util.ReplaceEnvValue(os.Environ(), "GOPATH", project.Dir()) 161 162 err = cmd.Run() 163 if err != nil { 164 return false, err 165 } 166 167 return true, nil 168 } else { 169 return false, nil 170 } 171 } 172 173 break 174 } 175 } 176 177 return false, fmt.Errorf("unable to to find shim trigger: %s", shim) 178 } 179 180 func shimCleanup(project common.AppProject) { 181 182 if Verbose() { 183 fmt.Println("Cleaning up shim support files...") 184 } 185 186 err := util.DeleteFile(filepath.Join(project.SrcDir(), fileShimSupportGo)) 187 if err != nil { 188 fmt.Printf("Unable to delete: %s", fileShimSupportGo) 189 } 190 err = util.DeleteFile(filepath.Join(project.SrcDir(), fileShimGo)) 191 if err != nil { 192 fmt.Printf("Unable to delete: %s", fileShimGo) 193 } 194 err = util.DeleteFile(filepath.Join(project.SrcDir(), fileBuildGo)) 195 if err != nil { 196 fmt.Printf("Unable to delete: %s", fileBuildGo) 197 } 198 } 199 200 func createShimSupportGoFile(project common.AppProject) error { 201 202 shimSrcPath := filepath.Join(project.SrcDir(), fileShimSupportGo) 203 204 if Verbose() { 205 fmt.Println("Creating shim support files...") 206 } 207 208 flogoCoreImport, err := util.NewFlogoImportFromPath(flogoCoreRepo) 209 if err != nil { 210 return err 211 } 212 213 corePath, err := project.GetPath(flogoCoreImport) 214 if err != nil { 215 return err 216 } 217 218 bytes, err := ioutil.ReadFile(filepath.Join(corePath, fileSampleShimSupport)) 219 if err != nil { 220 return err 221 } 222 223 err = ioutil.WriteFile(shimSrcPath, bytes, 0644) 224 if err != nil { 225 return err 226 } 227 228 return nil 229 } 230 231 func registerImports(project common.AppProject, appDesc *util.FlogoAppDescriptor) error { 232 233 for _, anImport := range appDesc.Imports { 234 err := registerImport(project, anImport) 235 if err != nil { 236 return err 237 } 238 } 239 240 return nil 241 } 242 243 func registerImport(project common.AppProject, anImport string) error { 244 245 matches := flogoImportPattern.FindStringSubmatch(anImport) 246 247 parts := strings.Split(matches[3], " ") 248 249 var alias string 250 var ref string 251 numParts := len(parts) 252 if numParts == 1 { 253 ref = parts[0] 254 alias = path.Base(ref) 255 256 } else if numParts == 2 { 257 alias = parts[0] 258 ref = parts[1] 259 } else { 260 return fmt.Errorf("invalid import %s", anImport) 261 } 262 263 if alias == "" || ref == "" { 264 return fmt.Errorf("invalid import %s", anImport) 265 } 266 267 ct, err := util.GetContribType(project.DepManager(), ref) 268 if err != nil { 269 return err 270 } 271 272 if ct != "" { 273 RegisterAlias(ct, alias, ref) 274 } 275 276 return nil 277 } 278 279 var aliases = make(map[string]map[string]string) 280 281 func RegisterAlias(contribType string, alias, ref string) { 282 283 aliasToRefMap, exists := aliases[contribType] 284 if !exists { 285 aliasToRefMap = make(map[string]string) 286 aliases[contribType] = aliasToRefMap 287 } 288 289 aliasToRefMap[alias] = ref 290 } 291 292 func GetAliasRef(contribType string, alias string) (string, bool) { 293 if alias == "" { 294 return "", false 295 } 296 297 if alias[0] == '#' { 298 alias = alias[1:] 299 } 300 aliasToRefMap, exists := aliases[contribType] 301 if !exists { 302 return "", false 303 } 304 305 ref, exists := aliasToRefMap[alias] 306 if !exists { 307 return "", false 308 } 309 310 return ref, true 311 }