forked from toolshed/abra
@ -5,6 +5,7 @@ import (
|
||||
|
||||
"coopcloud.tech/abra/pkg/config"
|
||||
"coopcloud.tech/abra/pkg/recipe"
|
||||
"coopcloud.tech/abra/pkg/runtime"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
@ -27,7 +28,12 @@ func AppNameComplete(c *cli.Context) {
|
||||
|
||||
// RecipeNameComplete completes recipe names.
|
||||
func RecipeNameComplete(c *cli.Context) {
|
||||
catl, err := recipe.ReadRecipeCatalogue()
|
||||
// defaults since we can't take arguments here... this means auto-completion
|
||||
// of recipe names always access the network if e.g. the catalogue needs
|
||||
// cloning / updating
|
||||
conf := runtime.New()
|
||||
|
||||
catl, err := recipe.ReadRecipeCatalogue(conf)
|
||||
if err != nil {
|
||||
logrus.Warn(err)
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
|
||||
"coopcloud.tech/abra/pkg/config"
|
||||
gitPkg "coopcloud.tech/abra/pkg/git"
|
||||
"coopcloud.tech/abra/pkg/runtime"
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@ -52,9 +53,13 @@ var CatalogueSkipList = map[string]bool{
|
||||
}
|
||||
|
||||
// EnsureCatalogue ensures that the catalogue is cloned locally & present.
|
||||
func EnsureCatalogue() error {
|
||||
func EnsureCatalogue(conf *runtime.Config) error {
|
||||
catalogueDir := path.Join(config.ABRA_DIR, "catalogue")
|
||||
if _, err := os.Stat(catalogueDir); err != nil && os.IsNotExist(err) {
|
||||
if conf.Offline {
|
||||
return fmt.Errorf("no local copy of the catalogue available, network access required")
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, config.CATALOGUE_JSON_REPO_NAME)
|
||||
if err := gitPkg.Clone(catalogueDir, url); err != nil {
|
||||
return err
|
||||
@ -68,7 +73,7 @@ func EnsureCatalogue() error {
|
||||
|
||||
// EnsureUpToDate ensures that the local catalogue has no unstaged changes as
|
||||
// is up to date. This is useful to run before doing catalogue generation.
|
||||
func EnsureUpToDate() error {
|
||||
func EnsureUpToDate(conf *runtime.Config) error {
|
||||
isClean, err := gitPkg.IsClean(config.CATALOGUE_DIR)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -79,6 +84,11 @@ func EnsureUpToDate() error {
|
||||
return fmt.Errorf(msg, config.CATALOGUE_DIR)
|
||||
}
|
||||
|
||||
if conf.Offline {
|
||||
logrus.Debug("attempting to use local catalogue without access network (\"--offline\")")
|
||||
return nil
|
||||
}
|
||||
|
||||
repo, err := git.PlainOpen(config.CATALOGUE_DIR)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"coopcloud.tech/abra/pkg/config"
|
||||
"coopcloud.tech/abra/pkg/recipe"
|
||||
recipePkg "coopcloud.tech/abra/pkg/recipe"
|
||||
"coopcloud.tech/abra/pkg/runtime"
|
||||
"coopcloud.tech/tagcmp"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/go-git/go-git/v5"
|
||||
@ -333,7 +334,11 @@ func LintImagePresent(recipe recipe.Recipe) (bool, error) {
|
||||
}
|
||||
|
||||
func LintHasPublishedVersion(recipe recipe.Recipe) (bool, error) {
|
||||
catl, err := recipePkg.ReadRecipeCatalogue()
|
||||
// defaults since we can't take arguments here... this means this lint rule
|
||||
// always access the network if e.g. the catalogue needs cloning / updating
|
||||
conf := runtime.New()
|
||||
|
||||
catl, err := recipePkg.ReadRecipeCatalogue(conf)
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
@ -252,13 +252,13 @@ func Get(recipeName string, conf *runtime.Config) (Recipe, error) {
|
||||
|
||||
// EnsureExists ensures that a recipe is locally cloned
|
||||
func EnsureExists(recipeName string, conf *runtime.Config) error {
|
||||
if !conf.EnsureRecipeExists {
|
||||
return nil
|
||||
}
|
||||
|
||||
recipeDir := path.Join(config.RECIPES_DIR, recipeName)
|
||||
|
||||
if _, err := os.Stat(recipeDir); os.IsNotExist(err) {
|
||||
if conf.Offline {
|
||||
return fmt.Errorf("no local copy of %s available, network access required", recipeName)
|
||||
}
|
||||
|
||||
logrus.Debugf("%s does not exist, attemmpting to clone", recipeDir)
|
||||
url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, recipeName)
|
||||
if err := gitPkg.Clone(recipeDir, url); err != nil {
|
||||
@ -339,10 +339,6 @@ func EnsureVersion(recipeName, version string) error {
|
||||
|
||||
// EnsureLatest makes sure the latest commit is checked out for a local recipe repository
|
||||
func EnsureLatest(recipeName string, conf *runtime.Config) error {
|
||||
if !conf.EnsureRecipeLatest {
|
||||
return nil
|
||||
}
|
||||
|
||||
recipeDir := path.Join(config.RECIPES_DIR, recipeName)
|
||||
|
||||
isClean, err := gitPkg.IsClean(recipeDir)
|
||||
@ -588,10 +584,6 @@ func GetStringInBetween(recipeName, str, start, end string) (result string, err
|
||||
|
||||
// EnsureUpToDate ensures that the local repo is synced to the remote
|
||||
func EnsureUpToDate(recipeName string, conf *runtime.Config) error {
|
||||
if !conf.EnsureRecipeLatest {
|
||||
return nil
|
||||
}
|
||||
|
||||
recipeDir := path.Join(config.RECIPES_DIR, recipeName)
|
||||
|
||||
isClean, err := gitPkg.IsClean(recipeDir)
|
||||
@ -604,6 +596,11 @@ func EnsureUpToDate(recipeName string, conf *runtime.Config) error {
|
||||
return fmt.Errorf(msg, recipeName, recipeDir)
|
||||
}
|
||||
|
||||
if conf.Offline {
|
||||
logrus.Debug("attempting to use local recipe without access network (\"--offline\")")
|
||||
return nil
|
||||
}
|
||||
|
||||
repo, err := git.PlainOpen(recipeDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to open %s: %s", recipeDir, err)
|
||||
@ -659,14 +656,14 @@ func EnsureUpToDate(recipeName string, conf *runtime.Config) error {
|
||||
}
|
||||
|
||||
// ReadRecipeCatalogue reads the recipe catalogue.
|
||||
func ReadRecipeCatalogue() (RecipeCatalogue, error) {
|
||||
func ReadRecipeCatalogue(conf *runtime.Config) (RecipeCatalogue, error) {
|
||||
recipes := make(RecipeCatalogue)
|
||||
|
||||
if err := catalogue.EnsureCatalogue(); err != nil {
|
||||
if err := catalogue.EnsureCatalogue(conf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := catalogue.EnsureUpToDate(); err != nil {
|
||||
if err := catalogue.EnsureUpToDate(conf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -694,10 +691,10 @@ func readRecipeCatalogueFS(target interface{}) error {
|
||||
}
|
||||
|
||||
// VersionsOfService lists the version of a service.
|
||||
func VersionsOfService(recipe, serviceName string) ([]string, error) {
|
||||
func VersionsOfService(recipe, serviceName string, conf *runtime.Config) ([]string, error) {
|
||||
var versions []string
|
||||
|
||||
catalogue, err := ReadRecipeCatalogue()
|
||||
catalogue, err := ReadRecipeCatalogue(conf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -724,7 +721,7 @@ func VersionsOfService(recipe, serviceName string) ([]string, error) {
|
||||
|
||||
// GetRecipeMeta retrieves the recipe metadata from the recipe catalogue.
|
||||
func GetRecipeMeta(recipeName string, conf *runtime.Config) (RecipeMeta, error) {
|
||||
catl, err := ReadRecipeCatalogue()
|
||||
catl, err := ReadRecipeCatalogue(conf)
|
||||
if err != nil {
|
||||
return RecipeMeta{}, err
|
||||
}
|
||||
@ -821,7 +818,11 @@ type InternalTracker struct {
|
||||
type RepoCatalogue map[string]RepoMeta
|
||||
|
||||
// ReadReposMetadata retrieves coop-cloud/... repo metadata from Gitea.
|
||||
func ReadReposMetadata() (RepoCatalogue, error) {
|
||||
func ReadReposMetadata(conf *runtime.Config) (RepoCatalogue, error) {
|
||||
if conf.Offline {
|
||||
return nil, fmt.Errorf("network access required to query recipes metadata")
|
||||
}
|
||||
|
||||
reposMeta := make(RepoCatalogue)
|
||||
|
||||
pageIdx := 1
|
||||
@ -1002,6 +1003,10 @@ func GetRecipeCatalogueVersions(recipeName string, catl RecipeCatalogue) ([]stri
|
||||
|
||||
// UpdateRepositories clones and updates all recipe repositories locally.
|
||||
func UpdateRepositories(repos RepoCatalogue, recipeName string, conf *runtime.Config) error {
|
||||
if conf.Offline {
|
||||
return fmt.Errorf("network access required to update recipes")
|
||||
}
|
||||
|
||||
var barLength int
|
||||
if recipeName != "" {
|
||||
barLength = 1
|
||||
|
28
pkg/runtime/config.go
Normal file
28
pkg/runtime/config.go
Normal file
@ -0,0 +1,28 @@
|
||||
package runtime
|
||||
|
||||
import "github.com/sirupsen/logrus"
|
||||
|
||||
type Config struct {
|
||||
Offline bool
|
||||
}
|
||||
|
||||
type Option func(c *Config)
|
||||
|
||||
func New(opts ...Option) *Config {
|
||||
conf := &Config{Offline: false}
|
||||
|
||||
for _, optFunc := range opts {
|
||||
optFunc(conf)
|
||||
}
|
||||
|
||||
return conf
|
||||
}
|
||||
|
||||
func WithOffline(offline bool) Option {
|
||||
return func(c *Config) {
|
||||
if offline {
|
||||
logrus.Debugf("runtime config: attempting to run in offline mode")
|
||||
}
|
||||
c.Offline = offline
|
||||
}
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
package runtime
|
||||
|
||||
import "github.com/sirupsen/logrus"
|
||||
|
||||
// Config is an internal configuration modifier. It can be instantiated on a
|
||||
// command call and can be changed on the fly to help make decisions further
|
||||
// down in the internals, e.g. whether or not to clone the recipe locally or
|
||||
// not.
|
||||
type Config struct {
|
||||
EnsureRecipeExists bool // ensure that the recipe is cloned locally
|
||||
EnsureRecipeLatest bool // ensure the local recipe has latest changes
|
||||
}
|
||||
|
||||
// Option modifies a Config. The convention for passing an Option to a function
|
||||
// is so far, only used in internal/validate.go. A Config is then constructed
|
||||
// and passed down further into the code. This may change in the future but
|
||||
// this is at least the abstraction so far.
|
||||
type Option func(c *Config)
|
||||
|
||||
// New instantiates a Config.
|
||||
func New(opts ...Option) *Config {
|
||||
conf := &Config{
|
||||
EnsureRecipeExists: true,
|
||||
EnsureRecipeLatest: true,
|
||||
}
|
||||
|
||||
for _, optFunc := range opts {
|
||||
optFunc(conf)
|
||||
}
|
||||
|
||||
return conf
|
||||
}
|
||||
|
||||
// WithEnsureRecipeExists determines whether or not we should be cloning the
|
||||
// local recipe or not. This can be useful for being more adaptable to offline
|
||||
// scenarios.
|
||||
func WithEnsureRecipeExists(ensureRecipeExists bool) Option {
|
||||
return func(c *Config) {
|
||||
if ensureRecipeExists {
|
||||
logrus.Debugf("runtime config: EnsureRecipeExists = %v, ensuring recipes are cloned", ensureRecipeExists)
|
||||
} else {
|
||||
logrus.Debugf("runtime config: EnsureRecipeExists = %v, not cloning recipes", ensureRecipeExists)
|
||||
}
|
||||
|
||||
c.EnsureRecipeExists = ensureRecipeExists
|
||||
}
|
||||
}
|
||||
|
||||
// WithEnsureRecipeLatest determines whether we should update the local recipes
|
||||
// remotely via Git. This can be useful when e.g. ensuring we have the latest
|
||||
// changes before making new ones.
|
||||
func WithEnsureRecipeLatest(ensureRecipeLatest bool) Option {
|
||||
return func(c *Config) {
|
||||
if ensureRecipeLatest {
|
||||
logrus.Debugf("runtime config: EnsureRecipeLatest = %v, ensuring recipes have latest changes", ensureRecipeLatest)
|
||||
} else {
|
||||
logrus.Debugf("runtime config: EnsureRecipeLatest = %v, leaving recipes alone", ensureRecipeLatest)
|
||||
}
|
||||
|
||||
c.EnsureRecipeLatest = ensureRecipeLatest
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user