From 1187d6bfd517a62d41d6ad9662d6af1b815de399 Mon Sep 17 00:00:00 2001
From: decentral1se <lukewm@riseup.net>
Date: Wed, 28 Jul 2021 22:10:13 +0200
Subject: [PATCH] refactor: move catalogue logic into own package

---
 catalogue/catalogue.go | 149 +++++++++++++++++++++++++++++++++++++
 catalogue/common.go    |  17 +++++
 cli/app.go             |   1 +
 cli/recipe.go          | 164 ++---------------------------------------
 4 files changed, 173 insertions(+), 158 deletions(-)
 create mode 100644 catalogue/catalogue.go
 create mode 100644 catalogue/common.go

diff --git a/catalogue/catalogue.go b/catalogue/catalogue.go
new file mode 100644
index 000000000..b2ac73b29
--- /dev/null
+++ b/catalogue/catalogue.go
@@ -0,0 +1,149 @@
+package catalogue
+
+import (
+	"encoding/json"
+	"io/ioutil"
+	"net/http"
+	"os"
+	"strings"
+	"time"
+
+	"coopcloud.tech/abra/config"
+)
+
+type Image struct {
+	Image  string `json:"image"`
+	Rating string `json:"rating"`
+	Source string `json:"source"`
+	URL    string `json:"url"`
+}
+
+type Feature struct {
+	Backups     string `json:"backups"`
+	Email       string `json:"email"`
+	Healthcheck string `json:"healthcheck"`
+	Image       Image  `json:"image"`
+	Status      int    `json:"status"`
+	Tests       string `json:"tests"`
+}
+
+type Tag = string
+type Service = string
+type ServiceMeta struct {
+	Digest string `json:"digest"`
+	Image  string `json:"image"`
+	Tag    string `json:"tag"`
+}
+
+type App struct {
+	Category      string                          `json:"category"`
+	DefaultBranch string                          `json:"default_branch"`
+	Description   string                          `json:"description"`
+	Features      Feature                         `json:"features"`
+	Icon          string                          `json:"icon"`
+	Name          string                          `json:"name"`
+	Repository    string                          `json:"repository"`
+	Versions      map[Tag]map[Service]ServiceMeta `json:"versions"`
+	Website       string                          `json:"website"`
+}
+
+type Name = string
+type AppsCatalogue map[Name]App
+
+func (a AppsCatalogue) Flatten() []App {
+	apps := make([]App, 0, len(a))
+	for name := range a {
+		apps = append(apps, a[name])
+	}
+	return apps
+}
+
+type ByAppName []App
+
+func (a ByAppName) Len() int      { return len(a) }
+func (a ByAppName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a ByAppName) Less(i, j int) bool {
+	return strings.ToLower(a[i].Name) < strings.ToLower(a[j].Name)
+}
+
+var AppsCatalogueURL = "https://apps.coopcloud.tech"
+
+func AppsCatalogueFSIsLatest() (bool, error) {
+	httpClient := &http.Client{Timeout: 5 * time.Second}
+	res, err := httpClient.Head(AppsCatalogueURL)
+	if err != nil {
+		return false, err
+	}
+
+	lastModified := res.Header["Last-Modified"][0]
+	parsed, err := time.Parse(time.RFC1123, lastModified)
+	if err != nil {
+		return false, err
+	}
+	info, err := os.Stat(config.APPS_JSON)
+	if err != nil {
+		if os.IsNotExist(err) {
+			return false, nil
+		}
+		return false, err
+	}
+
+	localModifiedTime := info.ModTime().Unix()
+	remoteModifiedTime := parsed.Unix()
+
+	if localModifiedTime < remoteModifiedTime {
+		return false, nil
+	}
+
+	return true, nil
+}
+
+func ReadAppsCatalogue() (AppsCatalogue, error) {
+	apps := make(AppsCatalogue)
+
+	appsFSIsLatest, err := AppsCatalogueFSIsLatest()
+	if err != nil {
+		return nil, err
+	}
+
+	if !appsFSIsLatest {
+		if err := ReadAppsCatalogueWeb(&apps); err != nil {
+			return nil, err
+		}
+		return apps, nil
+	}
+
+	if err := ReadAppsCatalogueFS(&apps); err != nil {
+		return nil, err
+	}
+
+	return apps, nil
+}
+
+func ReadAppsCatalogueFS(target interface{}) error {
+	appsJsonFS, err := ioutil.ReadFile(config.APPS_JSON)
+	if err != nil {
+		return err
+	}
+	if err := json.Unmarshal(appsJsonFS, &target); err != nil {
+		return err
+	}
+	return nil
+}
+
+func ReadAppsCatalogueWeb(target interface{}) error {
+	if err := readJson(AppsCatalogueURL, &target); err != nil {
+		return err
+	}
+
+	appsJson, err := json.MarshalIndent(target, "", "    ")
+	if err != nil {
+		return err
+	}
+
+	if err := ioutil.WriteFile(config.APPS_JSON, appsJson, 0644); err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/catalogue/common.go b/catalogue/common.go
new file mode 100644
index 000000000..d2b22cb0b
--- /dev/null
+++ b/catalogue/common.go
@@ -0,0 +1,17 @@
+package catalogue
+
+import (
+	"encoding/json"
+	"net/http"
+	"time"
+)
+
+func readJson(url string, target interface{}) error {
+	httpClient := &http.Client{Timeout: 5 * time.Second}
+	res, err := httpClient.Get(url)
+	if err != nil {
+		return err
+	}
+	defer res.Body.Close()
+	return json.NewDecoder(res.Body).Decode(target)
+}
diff --git a/cli/app.go b/cli/app.go
index 766b7a681..398245b23 100644
--- a/cli/app.go
+++ b/cli/app.go
@@ -6,6 +6,7 @@ import (
 	"sort"
 	"strings"
 
+	"coopcloud.tech/abra/catalogue"
 	"coopcloud.tech/abra/client"
 	"coopcloud.tech/abra/config"
 
diff --git a/cli/recipe.go b/cli/recipe.go
index e3eb5177d..7c5289c93 100644
--- a/cli/recipe.go
+++ b/cli/recipe.go
@@ -1,17 +1,13 @@
 package cli
 
 import (
-	"encoding/json"
 	"fmt"
-	"io/ioutil"
-	"net/http"
 	"os"
 	"path"
 	"sort"
-	"strings"
 	"text/template"
-	"time"
 
+	"coopcloud.tech/abra/catalogue"
 	"coopcloud.tech/abra/config"
 
 	"github.com/go-git/go-git/v5"
@@ -19,165 +15,17 @@ import (
 	"github.com/urfave/cli/v2"
 )
 
-type Image struct {
-	Image  string `json:"image"`
-	Rating string `json:"rating"`
-	Source string `json:"source"`
-	URL    string `json:"url"`
-}
-
-type Feature struct {
-	Backups     string `json:"backups"`
-	Email       string `json:"email"`
-	Healthcheck string `json:"healthcheck"`
-	Image       Image  `json:"image"`
-	Status      int    `json:"status"`
-	Tests       string `json:"tests"`
-}
-
-type Tag = string
-type Service = string
-type ServiceMeta struct {
-	Digest string `json:"digest"`
-	Image  string `json:"image"`
-	Tag    string `json:"tag"`
-}
-
-type App struct {
-	Category      string                          `json:"category"`
-	DefaultBranch string                          `json:"default_branch"`
-	Description   string                          `json:"description"`
-	Features      Feature                         `json:"features"`
-	Icon          string                          `json:"icon"`
-	Name          string                          `json:"name"`
-	Repository    string                          `json:"repository"`
-	Versions      map[Tag]map[Service]ServiceMeta `json:"versions"`
-	Website       string                          `json:"website"`
-}
-
-type Name = string
-type AppsCatalogue map[Name]App
-
-func (a AppsCatalogue) Flatten() []App {
-	apps := make([]App, 0, len(a))
-	for name := range a {
-		apps = append(apps, a[name])
-	}
-	return apps
-}
-
-type ByAppName []App
-
-func (a ByAppName) Len() int      { return len(a) }
-func (a ByAppName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
-func (a ByAppName) Less(i, j int) bool {
-	return strings.ToLower(a[i].Name) < strings.ToLower(a[j].Name)
-}
-
-var httpClient = &http.Client{Timeout: 5 * time.Second}
-
-var AppsCatalogueURL = "https://apps.coopcloud.tech"
-
-func readJson(url string, target interface{}) error {
-	res, err := httpClient.Get(url)
-	if err != nil {
-		return err
-	}
-	defer res.Body.Close()
-	return json.NewDecoder(res.Body).Decode(target)
-}
-
-func AppsCatalogueFSIsLatest() (bool, error) {
-	res, err := httpClient.Head(AppsCatalogueURL)
-	if err != nil {
-		return false, err
-	}
-
-	lastModified := res.Header["Last-Modified"][0]
-	parsed, err := time.Parse(time.RFC1123, lastModified)
-	if err != nil {
-		return false, err
-	}
-
-	info, err := os.Stat(config.APPS_JSON)
-	if err != nil {
-		if os.IsNotExist(err) {
-			return false, nil
-		}
-		return false, err
-	}
-
-	localModifiedTime := info.ModTime().Unix()
-	remoteModifiedTime := parsed.Unix()
-
-	if localModifiedTime < remoteModifiedTime {
-		return false, nil
-	}
-
-	return true, nil
-}
-
-func ReadAppsCatalogue() (AppsCatalogue, error) {
-	apps := make(AppsCatalogue)
-
-	appsFSIsLatest, err := AppsCatalogueFSIsLatest()
-	if err != nil {
-		return nil, err
-	}
-
-	if !appsFSIsLatest {
-		if err := ReadAppsCatalogueWeb(&apps); err != nil {
-			return nil, err
-		}
-		return apps, nil
-	}
-
-	if err := ReadAppsCatalogueFS(&apps); err != nil {
-		return nil, err
-	}
-
-	return apps, nil
-}
-
-func ReadAppsCatalogueFS(target interface{}) error {
-	appsJsonFS, err := ioutil.ReadFile(config.APPS_JSON)
-	if err != nil {
-		return err
-	}
-	if err := json.Unmarshal(appsJsonFS, &target); err != nil {
-		return err
-	}
-	return nil
-}
-
-func ReadAppsCatalogueWeb(target interface{}) error {
-	if err := readJson(AppsCatalogueURL, &target); err != nil {
-		return err
-	}
-
-	appsJson, err := json.MarshalIndent(target, "", "    ")
-	if err != nil {
-		return err
-	}
-
-	if err := ioutil.WriteFile(config.APPS_JSON, appsJson, 0644); err != nil {
-		return err
-	}
-
-	return nil
-}
-
 var recipeListCommand = &cli.Command{
 	Name:    "list",
 	Usage:   "List all available recipes",
 	Aliases: []string{"ls"},
 	Action: func(c *cli.Context) error {
-		catalogue, err := ReadAppsCatalogue()
+		catl, err := catalogue.ReadAppsCatalogue()
 		if err != nil {
 			logrus.Fatal(err.Error())
 		}
-		apps := catalogue.Flatten()
-		sort.Sort(ByAppName(apps))
+		apps := catl.Flatten()
+		sort.Sort(catalogue.ByAppName(apps))
 		tableCol := []string{"Name", "Category", "Status"}
 		table := createTable(tableCol)
 		for _, app := range apps {
@@ -201,13 +49,13 @@ var recipeVersionCommand = &cli.Command{
 			return nil
 		}
 
-		apps, err := ReadAppsCatalogue()
+		catalogue, err := catalogue.ReadAppsCatalogue()
 		if err != nil {
 			logrus.Fatal(err)
 			return nil
 		}
 
-		if app, ok := apps[recipe]; ok {
+		if app, ok := catalogue[recipe]; ok {
 			tableCol := []string{"Version", "Service", "Image", "Digest"}
 			table := createTable(tableCol)
 			for version := range app.Versions {