diff --git a/cli/catalogue/generate.go b/cli/catalogue/generate.go index d4490af4..95233ec7 100644 --- a/cli/catalogue/generate.go +++ b/cli/catalogue/generate.go @@ -134,6 +134,15 @@ A new catalogue copy can be published to the recipes repository by passing the logrus.Fatal(err) } + isClean, err := gitPkg.IsClean(rm.Name) + if err != nil { + logrus.Fatal(err) + } + + if !isClean { + logrus.Fatalf("'%s' has locally unstaged changes", rm.Name) + } + if err := gitPkg.EnsureUpToDate(recipeDir); err != nil { logrus.Fatal(err) } @@ -165,6 +174,11 @@ A new catalogue copy can be published to the recipes repository by passing the logrus.Fatal(err) } + features, category, err := catalogue.GetRecipeFeaturesAndCategory(recipeMeta.Name) + if err != nil { + logrus.Fatal(err) + } + catl[recipeMeta.Name] = catalogue.RecipeMeta{ Name: recipeMeta.Name, Repository: recipeMeta.CloneURL, @@ -173,8 +187,8 @@ A new catalogue copy can be published to the recipes repository by passing the Description: recipeMeta.Description, Website: recipeMeta.Website, Versions: versions, - // Category: ..., // FIXME: parse & load - // Features: ..., // FIXME: parse & load + Category: category, + Features: features, } catlBar.Add(1) } diff --git a/pkg/catalogue/catalogue.go b/pkg/catalogue/catalogue.go index b3a85700..233ec048 100644 --- a/pkg/catalogue/catalogue.go +++ b/pkg/catalogue/catalogue.go @@ -45,6 +45,7 @@ type features struct { Image image `json:"image"` Status int `json:"status"` Tests string `json:"tests"` + SSO string `json:"sso"` } // tag represents a git tag. @@ -373,6 +374,127 @@ func ReadReposMetadata() (RepoCatalogue, error) { return reposMeta, nil } +func GetStringInBetween(str, start, end string) (result string, err error) { + // GetStringInBetween returns empty string if no start or end string found + s := strings.Index(str, start) + if s == -1 { + return "", fmt.Errorf("marker string '%s' not found", start) + } + s += len(start) + e := strings.Index(str[s:], end) + if e == -1 { + return "", fmt.Errorf("end marker '%s' not found", end) + } + return str[s : s+e], nil +} + +func GetImageMetadata(imageRowString string) (image, error) { + img := image{} + + imgFields := strings.Split(imageRowString, ",") + + for i, elem := range imgFields { + imgFields[i] = strings.TrimSpace(elem) + } + + if len(imgFields) < 3 { + logrus.Warnf("image string has incorrect format: %s", imageRowString) + return img, nil + } + + img.Rating = imgFields[1] + img.Source = imgFields[2] + + imgString := imgFields[0] + + imageName, err := GetStringInBetween(imgString, "[", "]") + if err != nil { + logrus.Fatal(err) + } + img.Image = imageName + + imageURL, err := GetStringInBetween(imgString, "(", ")") + if err != nil { + logrus.Fatal(err) + } + img.URL = imageURL + + return img, nil +} + +func GetRecipeFeaturesAndCategory(recipeName string) (features, string, error) { + feat := features{} + + var category string + + readmePath := path.Join(config.ABRA_DIR, "apps", recipeName, "README.md") + + logrus.Debugf("attempting to open '%s'", readmePath) + + readmeFS, err := ioutil.ReadFile(readmePath) + if err != nil { + return feat, category, err + } + + readmeMetadata, err := GetStringInBetween( // Find text between delimiters + string(readmeFS), + "", "", + ) + if err != nil { + logrus.Fatal(err) + } + + readmeLines := strings.Split( // Array item from lines + strings.ReplaceAll( // Remove \t tabs + readmeMetadata, "\t", "", + ), + "\n") + + for _, val := range readmeLines { + if strings.Contains(val, "**Category**") { + category = strings.TrimSpace( + strings.TrimPrefix(val, "* **Category**:"), + ) + } + if strings.Contains(val, "**Backups**") { + feat.Backups = strings.TrimSpace( + strings.TrimPrefix(val, "* **Backups**:"), + ) + } + if strings.Contains(val, "**Email**") { + feat.Email = strings.TrimSpace( + strings.TrimPrefix(val, "* **Email**:"), + ) + } + if strings.Contains(val, "**SSO**") { + feat.SSO = strings.TrimSpace( + strings.TrimPrefix(val, "* **SSO**:"), + ) + } + if strings.Contains(val, "**Healthcheck**") { + feat.Healthcheck = strings.TrimSpace( + strings.TrimPrefix(val, "* **Healthcheck**:"), + ) + } + if strings.Contains(val, "**Tests**") { + feat.Tests = strings.TrimSpace( + strings.TrimPrefix(val, "* **Tests**:"), + ) + } + if strings.Contains(val, "**Image**") { + imageMetadata, err := GetImageMetadata(strings.TrimSpace( + strings.TrimPrefix(val, "* **Image**:"), + )) + if err != nil { + continue + } + feat.Image = imageMetadata + } + } + + return feat, category, nil +} + // GetRecipeVersions retrieves all recipe versions. func GetRecipeVersions(recipeName string) (RecipeVersions, error) { versions := RecipeVersions{}