Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions catalog/changesets/update_env_metadata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package changesets

import (
"errors"

cldfdatastore "github.com/smartcontractkit/chainlink-deployments-framework/datastore"
cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment"
cldfops "github.com/smartcontractkit/chainlink-deployments-framework/operations"

"github.com/smartcontractkit/cld-changesets/catalog/operations"
)

// UpdateEnvMetadataChangeset updates existing env metadata entries in the Catalog service.
type UpdateEnvMetadataChangeset struct{}

type UpdateEnvMetadataChangesetInput struct {
EnvMetadata cldfdatastore.EnvMetadata `json:"envMetadata"`
}

// VerifyPreconditions ensures the input is valid.
func (UpdateEnvMetadataChangeset) VerifyPreconditions(e cldf.Environment, input UpdateEnvMetadataChangesetInput) error {
if input.EnvMetadata.Metadata == nil {
return errors.New("missing env metadata input")
}
if e.DataStore == nil {
return errors.New("missing datastore in environment")
}

return nil
}

// Apply executes the changeset, updating the env metadata in the Catalog service.
func (UpdateEnvMetadataChangeset) Apply(
e cldf.Environment, input UpdateEnvMetadataChangesetInput,
) (cldf.ChangesetOutput, error) {
deps := operations.UpdateEnvMetadataDeps{DataStore: e.DataStore}
opInput := operations.UpdateEnvMetadataInput{EnvMetadata: input.EnvMetadata}

report, err := cldfops.ExecuteOperation(e.OperationsBundle, operations.UpdateEnvMetadataOp, deps, opInput)
out := cldf.ChangesetOutput{
DataStore: report.Output.DataStore,
Reports: []cldfops.Report[any, any]{report.ToGenericReport()},
}
if err != nil {
return out, err
}

return out, nil
}
147 changes: 147 additions & 0 deletions catalog/changesets/update_env_metadata_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package changesets

import (
"testing"

"github.com/Masterminds/semver/v3"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/stretchr/testify/require"

cldfdatastore "github.com/smartcontractkit/chainlink-deployments-framework/datastore"
cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment"
cldfoperations "github.com/smartcontractkit/chainlink-deployments-framework/operations"
cldflogger "github.com/smartcontractkit/chainlink-deployments-framework/pkg/logger"

"github.com/smartcontractkit/cld-changesets/catalog/operations"
)

func TestUpdateEnvMetadataChangeset_VerifyPreconditions(t *testing.T) {
t.Parallel()

envMetadata := cldfdatastore.EnvMetadata{Metadata: "value"}

tests := []struct {
name string
env cldf.Environment
input UpdateEnvMetadataChangesetInput
wantErr string
}{
{
name: "success: valid preconditions",
env: cldf.Environment{DataStore: func() cldfdatastore.DataStore {
ds := cldfdatastore.NewMemoryDataStore()
err := ds.EnvMetadata().Set(envMetadata)
require.NoError(t, err)

return ds.Seal()
}()},
input: UpdateEnvMetadataChangesetInput{
EnvMetadata: envMetadata,
},
},
{
name: "failure: missing datastore",
env: cldf.Environment{},
input: UpdateEnvMetadataChangesetInput{
EnvMetadata: envMetadata,
},
wantErr: "missing datastore in environment",
},
{
name: "failure: no env metadata given",
env: cldf.Environment{DataStore: cldfdatastore.NewMemoryDataStore().Seal()},
input: UpdateEnvMetadataChangesetInput{
EnvMetadata: cldfdatastore.EnvMetadata{},
},
wantErr: "missing env metadata input",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

err := UpdateEnvMetadataChangeset{}.VerifyPreconditions(tt.env, tt.input)

if tt.wantErr == "" {
require.NoError(t, err)
} else {
require.ErrorContains(t, err, tt.wantErr)
}
})
}
}

func TestUpdateEnvMetadataChangeset_Apply(t *testing.T) {
t.Parallel()

envMetadata := cldfdatastore.EnvMetadata{Metadata: "value"}
envMetadataUpdated := cldfdatastore.EnvMetadata{Metadata: "updated-value"}

tests := []struct {
name string
env cldf.Environment
input UpdateEnvMetadataChangesetInput
want cldf.ChangesetOutput
wantErr string
}{
{
name: "success: updates env metadata",
env: cldf.Environment{
DataStore: testDataStoreWithEnvMetadata(t, envMetadata).Seal(),
OperationsBundle: cldfoperations.NewBundle(t.Context, cldflogger.Test(t), cldfoperations.NewMemoryReporter()),
},
input: UpdateEnvMetadataChangesetInput{
EnvMetadata: envMetadataUpdated,
},
want: cldf.ChangesetOutput{
DataStore: testDataStoreWithEnvMetadata(t, envMetadataUpdated),
Reports: []cldfoperations.Report[any, any]{{
Def: cldfoperations.Definition{
ID: "catalog-update-env-metadata",
Version: semver.MustParse("1.0.0"),
Description: "Update env metadata entries in the Catalog service",
},
Input: operations.UpdateEnvMetadataInput{
EnvMetadata: envMetadataUpdated,
},
Output: operations.UpdateEnvMetadataOutput{
DataStore: testDataStoreWithEnvMetadata(t, envMetadataUpdated),
},
}},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

got, err := UpdateEnvMetadataChangeset{}.Apply(tt.env, tt.input)

if tt.wantErr == "" {
require.NoError(t, err)
require.Empty(t,
cmp.Diff(tt.want, got,
cmpopts.IgnoreFields(cldfoperations.Report[any, any]{}, "ID", "Timestamp"),
cmpopts.IgnoreUnexported(cldfdatastore.MemoryAddressRefStore{}, cldfdatastore.MemoryChainMetadataStore{},
cldfdatastore.MemoryContractMetadataStore{}, cldfdatastore.MemoryEnvMetadataStore{})))
} else {
require.ErrorContains(t, err, tt.wantErr)
}
})
}
}

// ----- helpers -----

func testDataStoreWithEnvMetadata(
t *testing.T, metadata cldfdatastore.EnvMetadata,
) cldfdatastore.MutableDataStore {
t.Helper()

ds := cldfdatastore.NewMemoryDataStore()
err := ds.EnvMetadata().Set(metadata)
require.NoError(t, err)

return ds
}
49 changes: 49 additions & 0 deletions catalog/operations/update_env_metadata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package operations

import (
"fmt"

"github.com/Masterminds/semver/v3"

cldfdatastore "github.com/smartcontractkit/chainlink-deployments-framework/datastore"
cldfops "github.com/smartcontractkit/chainlink-deployments-framework/operations"
)

// UpdateEnvMetadataDeps holds non-serializable dependencies for the
// UpdateEnvMetadataOp operation.
type UpdateEnvMetadataDeps struct {
DataStore cldfdatastore.DataStore
}

// UpdateEnvMetadataInput is the serializable input of an UpdateEnvMetadataOp invocation.
type UpdateEnvMetadataInput struct {
EnvMetadata cldfdatastore.EnvMetadata
}

// UpdateEnvMetadataOutput is the serializable output of an UpdateEnvMetadataOp invocation.
type UpdateEnvMetadataOutput struct {
DataStore cldfdatastore.MutableDataStore
}

// UpdateEnvMetadataOp updates existing env metadata entries in the Catalog service.
var UpdateEnvMetadataOp = cldfops.NewOperation(
"catalog-update-env-metadata",
semver.MustParse("1.0.0"),
"Update env metadata entries in the Catalog service",
func(b cldfops.Bundle, deps UpdateEnvMetadataDeps, input UpdateEnvMetadataInput) (UpdateEnvMetadataOutput, error) {
dataStore := cldfdatastore.NewMemoryDataStore()
err := dataStore.Merge(deps.DataStore)
if err != nil {
return UpdateEnvMetadataOutput{}, fmt.Errorf("failed to create memory data store: %w", err)
}

err = dataStore.EnvMetadata().Set(input.EnvMetadata)
if err != nil {
return UpdateEnvMetadataOutput{}, fmt.Errorf("failed to update env metadata in catalog store: %w", err)
}

b.Logger.Infow("Catalog EnvMetadata updated successfully")

return UpdateEnvMetadataOutput{DataStore: dataStore}, nil
},
)
Loading