func loadBrickMetadata(context *pongo2.Context, baseDir *string, brick *string) (*data.BrickMetadata, *string, error) { // Check if simple metadata file exists brickMetadataFile := filepath.Join(*baseDir, fmt.Sprintf("%s.%s", *brick, brickExt)) log.Debug(" Search brick metadata file:\n %s", brickMetadataFile) if exists, _ := util.FileExists(brickMetadataFile); !exists { // Check if complex module metadata file exists brickMetadataFile = filepath.Join(*baseDir, *brick, brickModuleName) log.Debug(" Search brick metadata file:\n %s", brickMetadataFile) if exists, _ := util.FileExists(brickMetadataFile); !exists { return nil, nil, errors.New(fmt.Sprintf("Could not load brick module:\n %s\nfrom path:\n %s", *brick, brickMetadataFile)) } } log.Debug(" Loading brick metadata from file:\n %s", brickMetadataFile) brickBaseDir := filepath.Dir(brickMetadataFile) log.Debug(" Brick base dir:\n %s", brickMetadataFile) // Compile template if compiled, err := compileTemplateFromFile(context, &brickMetadataFile); err == nil { var metadata data.BrickMetadata if err := util.LoadYAMLFromString(*compiled, &metadata); err != nil { return nil, nil, err } return &metadata, &brickBaseDir, nil } else { return nil, nil, err } }
func processMetadataUnits(context *pongo2.Context, metadata *data.BrickMetadata, brickBaseDir *string) (*data.Unit, error) { metaUnit := metadata.Unit // Create the initial Unit unit := &data.Unit{ Name: metaUnit.Name, Command: metaUnit.Command, } // Check if we have a template to process for the unit if len(metaUnit.Template) > 0 { templateFile := filepath.Join(*brickBaseDir, metaUnit.Template) if exists, _ := util.FileExists(templateFile); !exists { return nil, errors.New(fmt.Sprintf("Could not find brick module:\n %s", templateFile)) } // Compile template if compiled, err := compileTemplateFromFile(context, &templateFile); err != nil { return nil, err } else { unit.Content = *compiled } } for _, d := range metaUnit.DropIns { dropIn := &data.UnitDropIn{ Name: d.Name, } // Check if we have a template to process for the drop-in if len(d.Template) > 0 { templateFile := filepath.Join(*brickBaseDir, d.Template) if exists, _ := util.FileExists(templateFile); !exists { return nil, errors.New(fmt.Sprintf("Could not find brick module:\n %s", templateFile)) } // Compile template if compiled, err := compileTemplateFromFile(context, &templateFile); err != nil { return nil, err } else { dropIn.Content = *compiled } } unit.AddDropIn(dropIn) } // Add the unit to the user data if len(unit.Name) > 0 { return unit, nil } return nil, nil }
func processMetadataFiles(context *pongo2.Context, metadata *data.BrickMetadata, brickBaseDir *string) ([]data.WriteFile, error) { writeFiles := make([]data.WriteFile, 0, 10) for _, f := range metadata.Files { // Create the initial WriteFile writeFile := &data.WriteFile{ Path: f.Path, Permissions: f.Permissions, } // Check if we have a template to process if len(f.Template) > 0 { templateFile := filepath.Join(*brickBaseDir, f.Template) if exists, _ := util.FileExists(templateFile); !exists { return nil, errors.New(fmt.Sprintf("Could not find brick module:\n %s", templateFile)) } // Compile template if compiled, err := compileTemplateFromFile(context, &templateFile); err != nil { return nil, err } else { writeFile.Content = *compiled } } writeFiles = append(writeFiles, *writeFile) } return writeFiles, nil }
func compileArtifact(context *pongo2.Context, artifact *data.Artifact, providerName string, baseDir *string, workDir *string) error { outputFile := filepath.Join(*workDir, "build", providerName, artifact.Name, "user-data") outputDir := filepath.Dir(outputFile) // Create output directory if missing if exists, _ := util.FileExists(outputDir); !exists { if err := os.MkdirAll(outputDir, 0755); err != nil { return errors.New(fmt.Sprintf("Could not create output directory:\n %s\n\nnested error:\n %s", outputDir, err.Error())) } } log.Notice("▶ Compiling artifact [%s] to:\n %s", artifact.Name, outputFile) log.Debug(" Setting artifact name to the context") c := pongo2.Context{ "env": map[string]interface{}{ "provider": providerName, "artifact": artifact.Name, }, } if err := mergo.MergeWithOverwrite(context, c); err != nil { return err } printContextData(context, true) // Create the initial user data objects buffer := bytes.NewBufferString("#cloud-config\n---\n") writeFiles := make([]data.WriteFile, 0, 10) units := make([]data.Unit, 0, 10) // Process bricks bricks := artifact.Bricks for _, brick := range bricks { log.Info(" Processing brick:\n %s", brick) // Load metadata if metadata, brickBaseDir, err := loadBrickMetadata(context, baseDir, &brick); err == nil { // Process brick files log.Debug(" Processing brick files") if brickWriteFiles, err := processMetadataFiles(context, metadata, brickBaseDir); err != nil { return err } else { writeFiles = append(writeFiles, brickWriteFiles...) } // Process brick units log.Debug(" Processing brick unit") if brickUnit, err := processMetadataUnits(context, metadata, brickBaseDir); err != nil { return err } else if brickUnit != nil { units = append(units, *brickUnit) } } else { return err } } // Write compiled write-files section if len(writeFiles) > 0 { writeFilesMap := make(map[string]interface{}) writeFilesMap["write-files"] = writeFiles if output, err := yaml.Marshal(writeFilesMap); err != nil { return err } else { buffer.Write(output) } } // Write rest of config file cloudConfig := artifact.CloudConfig // Custom CoreOS if cloudConfig.CoreOS != nil { coreOs := cloudConfig.CoreOS // Add units // if coreOs["units"] != nil { coreOs["units"] = units // } // Write CoreOS section coreOsMap := make(map[string]interface{}) coreOsMap["coreos"] = coreOs if output, err := yaml.Marshal(coreOsMap); err != nil { return err } else { buffer.Write(output) } } // Append everything else to the end of the file if cloudConfig.Generic != nil { if output, err := yaml.Marshal(cloudConfig.Generic); err != nil { return err } else { buffer.Write(output) } } log.Info(" Writing output file to:\n %s", outputFile) if err := ioutil.WriteFile(outputFile, buffer.Bytes(), 0755); err != nil { return err } return nil }