get.porter.sh/porter@v1.3.0/pkg/storage/parameter_store.go (about)

     1  package storage
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"slices"
     7  	"strings"
     8  
     9  	"get.porter.sh/porter/pkg/secrets"
    10  	hostSecrets "get.porter.sh/porter/pkg/secrets/plugins/host"
    11  	"get.porter.sh/porter/pkg/tracing"
    12  	"github.com/cnabio/cnab-go/secrets/host"
    13  	"github.com/hashicorp/go-multierror"
    14  )
    15  
    16  var _ ParameterSetProvider = &ParameterStore{}
    17  
    18  const (
    19  	CollectionParameters = "parameters"
    20  )
    21  
    22  // ParameterStore provides access to parameter sets by instantiating plugins that
    23  // implement CRUD storage.
    24  type ParameterStore struct {
    25  	Documents   Store
    26  	Secrets     secrets.Store
    27  	HostSecrets hostSecrets.Store
    28  }
    29  
    30  func NewParameterStore(storage Store, secrets secrets.Store) *ParameterStore {
    31  	return &ParameterStore{
    32  		Documents:   storage,
    33  		Secrets:     secrets,
    34  		HostSecrets: hostSecrets.NewStore(),
    35  	}
    36  }
    37  
    38  // EnsureParameterIndices creates indices on the parameters collection.
    39  func EnsureParameterIndices(ctx context.Context, store Store) error {
    40  	ctx, span := tracing.StartSpan(ctx)
    41  	defer span.EndSpan()
    42  
    43  	span.Debug("Initializing parameter collection indices")
    44  	indices := EnsureIndexOptions{
    45  		Indices: []Index{
    46  			// query parameters by namespace + name
    47  			{Collection: CollectionParameters, Keys: []string{"namespace", "name"}, Unique: true},
    48  		},
    49  	}
    50  	err := store.EnsureIndex(ctx, indices)
    51  	return span.Error(err)
    52  }
    53  
    54  func (s ParameterStore) GetDataStore() Store {
    55  	return s.Documents
    56  }
    57  
    58  func (s ParameterStore) ResolveAll(ctx context.Context, params ParameterSet, keys []string) (secrets.Set, error) {
    59  	resolvedParams := make(secrets.Set)
    60  	var resolveErrors error
    61  
    62  	for _, param := range params.Parameters {
    63  		if !slices.Contains(keys, param.Name) {
    64  			continue
    65  		}
    66  
    67  		var value string
    68  		var err error
    69  		if isHandledByHostPlugin(param.Source.Strategy) {
    70  			value, err = s.HostSecrets.Resolve(ctx, param.Source.Strategy, param.Source.Hint)
    71  		} else {
    72  			value, err = s.Secrets.Resolve(ctx, param.Source.Strategy, param.Source.Hint)
    73  		}
    74  		if err != nil {
    75  			resolveErrors = multierror.Append(resolveErrors, fmt.Errorf("unable to resolve parameter %s.%s from %s %s: %w", params.Name, param.Name, param.Source.Strategy, param.Source.Hint, err))
    76  		}
    77  
    78  		resolvedParams[param.Name] = value
    79  	}
    80  
    81  	return resolvedParams, resolveErrors
    82  }
    83  
    84  func (s ParameterStore) Validate(ctx context.Context, params ParameterSet) error {
    85  	validSources := []string{secrets.SourceSecret, host.SourceValue, host.SourceEnv, host.SourcePath, host.SourceCommand}
    86  	var errors error
    87  
    88  	for _, cs := range params.Parameters {
    89  		valid := false
    90  		for _, validSource := range validSources {
    91  			if cs.Source.Strategy == validSource {
    92  				valid = true
    93  				break
    94  			}
    95  		}
    96  		if !valid {
    97  			errors = multierror.Append(errors, fmt.Errorf(
    98  				"%s is not a valid source. Valid sources are: %s",
    99  				cs.Source.Strategy,
   100  				strings.Join(validSources, ", "),
   101  			))
   102  		}
   103  	}
   104  
   105  	return errors
   106  }
   107  
   108  func (s ParameterStore) InsertParameterSet(ctx context.Context, params ParameterSet) error {
   109  	params.SchemaVersion = DefaultParameterSetSchemaVersion
   110  	opts := InsertOptions{
   111  		Documents: []interface{}{params},
   112  	}
   113  	return s.Documents.Insert(ctx, CollectionParameters, opts)
   114  }
   115  
   116  func (s ParameterStore) ListParameterSets(ctx context.Context, listOptions ListOptions) ([]ParameterSet, error) {
   117  	var out []ParameterSet
   118  	err := s.Documents.Find(ctx, CollectionParameters, listOptions.ToFindOptions(), &out)
   119  	return out, err
   120  }
   121  
   122  func (s ParameterStore) GetParameterSet(ctx context.Context, namespace string, name string) (ParameterSet, error) {
   123  	var out ParameterSet
   124  	opts := FindOptions{
   125  		Filter: map[string]interface{}{
   126  			"namespace": namespace,
   127  			"name":      name,
   128  		},
   129  	}
   130  	err := s.Documents.FindOne(ctx, CollectionParameters, opts, &out)
   131  	return out, err
   132  }
   133  
   134  func (s ParameterStore) UpdateParameterSet(ctx context.Context, params ParameterSet) error {
   135  	params.SchemaVersion = DefaultParameterSetSchemaVersion
   136  	opts := UpdateOptions{
   137  		Document: params,
   138  	}
   139  	return s.Documents.Update(ctx, CollectionParameters, opts)
   140  }
   141  
   142  func (s ParameterStore) UpsertParameterSet(ctx context.Context, params ParameterSet) error {
   143  	params.SchemaVersion = DefaultParameterSetSchemaVersion
   144  	opts := UpdateOptions{
   145  		Document: params,
   146  		Upsert:   true,
   147  	}
   148  	return s.Documents.Update(ctx, CollectionParameters, opts)
   149  }
   150  
   151  func (s ParameterStore) RemoveParameterSet(ctx context.Context, namespace string, name string) error {
   152  	opts := RemoveOptions{
   153  		Namespace: namespace,
   154  		Name:      name,
   155  	}
   156  	return s.Documents.Remove(ctx, CollectionParameters, opts)
   157  }