Skip to content

Commit

Permalink
Support workflow specs added via UI (#12091)
Browse files Browse the repository at this point in the history
Uploads were failing due to missing validations
Specs are still empty for the time being.
  • Loading branch information
bolekk authored Feb 20, 2024
1 parent 05a05c6 commit 84783a8
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 0 deletions.
3 changes: 3 additions & 0 deletions core/services/job/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ var (
Stream: true,
VRF: true,
Webhook: true,
Workflow: false,
}
supportsAsync = map[Type]bool{
BlockHeaderFeeder: false,
Expand All @@ -104,6 +105,7 @@ var (
Stream: true,
VRF: true,
Webhook: true,
Workflow: false,
}
schemaVersions = map[Type]uint32{
BlockHeaderFeeder: 1,
Expand All @@ -121,6 +123,7 @@ var (
Stream: 1,
VRF: 1,
Webhook: 1,
Workflow: 1,
}
)

Expand Down
25 changes: 25 additions & 0 deletions core/services/workflows/delegate.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package workflows

import (
"fmt"

"github.com/google/uuid"
"github.com/pelletier/go-toml"

"github.com/smartcontractkit/chainlink-common/pkg/types"
"github.com/smartcontractkit/chainlink/v2/core/capabilities/targets"
"github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm"
Expand Down Expand Up @@ -43,3 +48,23 @@ func NewDelegate(logger logger.Logger, registry types.CapabilitiesRegistry, lega

return &Delegate{logger: logger, registry: registry}
}

func ValidatedWorkflowSpec(tomlString string) (job.Job, error) {
var jb = job.Job{ExternalJobID: uuid.New()}

tree, err := toml.Load(tomlString)
if err != nil {
return jb, fmt.Errorf("toml error on load: %w", err)
}

err = tree.Unmarshal(&jb)
if err != nil {
return jb, fmt.Errorf("toml unmarshal error on spec: %w", err)
}

if jb.Type != job.Workflow {
return jb, fmt.Errorf("unsupported type %s", jb.Type)
}

return jb, nil
}
54 changes: 54 additions & 0 deletions core/services/workflows/delegate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package workflows_test

import (
"testing"

"github.com/stretchr/testify/require"

"github.com/smartcontractkit/chainlink/v2/core/services/workflows"
)

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

var tt = []struct {
name string
toml string
valid bool
}{
{
"valid spec",
`
type = "workflow"
schemaVersion = 1
`,
true,
},
{
"parse error",
`
invalid syntax{{{{
`,
false,
},
{
"invalid job type",
`
type = "work flows"
schemaVersion = 1
`,
false,
},
}
for _, tc := range tt {
tc := tc
t.Run(tc.name, func(t *testing.T) {
_, err := workflows.ValidatedWorkflowSpec(tc.toml)
if tc.valid {
require.NoError(t, err)
} else {
require.Error(t, err)
}
})
}
}
42 changes: 42 additions & 0 deletions core/store/migrate/migrations/0223_workflow_spec_validation.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
-- +goose Up
ALTER TABLE
jobs
DROP
CONSTRAINT chk_specs,
ADD
CONSTRAINT chk_specs CHECK (
num_nonnulls(
ocr_oracle_spec_id, ocr2_oracle_spec_id,
direct_request_spec_id, flux_monitor_spec_id,
keeper_spec_id, cron_spec_id, webhook_spec_id,
vrf_spec_id, blockhash_store_spec_id,
block_header_feeder_spec_id, bootstrap_spec_id,
gateway_spec_id,
legacy_gas_station_server_spec_id,
legacy_gas_station_sidecar_spec_id,
eal_spec_id,
CASE "type" WHEN 'stream' THEN 1 ELSE NULL END, -- 'stream' type lacks a spec but should not cause validation to fail
CASE "type" WHEN 'workflow' THEN 1 ELSE NULL END -- 'workflow' type currently lacks a spec but should not cause validation to fail
) = 1
);

-- +goose Down
ALTER TABLE
jobs
DROP
CONSTRAINT chk_specs,
ADD
CONSTRAINT chk_specs CHECK (
num_nonnulls(
ocr_oracle_spec_id, ocr2_oracle_spec_id,
direct_request_spec_id, flux_monitor_spec_id,
keeper_spec_id, cron_spec_id, webhook_spec_id,
vrf_spec_id, blockhash_store_spec_id,
block_header_feeder_spec_id, bootstrap_spec_id,
gateway_spec_id,
legacy_gas_station_server_spec_id,
legacy_gas_station_sidecar_spec_id,
eal_spec_id,
CASE "type" WHEN 'stream' THEN 1 ELSE NULL END -- 'stream' type lacks a spec but should not cause validation to fail
) = 1
);
3 changes: 3 additions & 0 deletions core/web/jobs_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/streams"
"github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon"
"github.com/smartcontractkit/chainlink/v2/core/services/webhook"
"github.com/smartcontractkit/chainlink/v2/core/services/workflows"
"github.com/smartcontractkit/chainlink/v2/core/web/presenters"
)

Expand Down Expand Up @@ -253,6 +254,8 @@ func (jc *JobsController) validateJobSpec(tomlString string) (jb job.Job, status
jb, err = gateway.ValidatedGatewaySpec(tomlString)
case job.Stream:
jb, err = streams.ValidatedStreamSpec(tomlString)
case job.Workflow:
jb, err = workflows.ValidatedWorkflowSpec(tomlString)
default:
return jb, http.StatusUnprocessableEntity, errors.Errorf("unknown job type: %s", jobType)
}
Expand Down
3 changes: 3 additions & 0 deletions core/web/resolver/mutation.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap"
"github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon"
"github.com/smartcontractkit/chainlink/v2/core/services/webhook"
"github.com/smartcontractkit/chainlink/v2/core/services/workflows"
"github.com/smartcontractkit/chainlink/v2/core/store/models"
"github.com/smartcontractkit/chainlink/v2/core/utils"
"github.com/smartcontractkit/chainlink/v2/core/utils/crypto"
Expand Down Expand Up @@ -1047,6 +1048,8 @@ func (r *Resolver) CreateJob(ctx context.Context, args struct {
jb, err = ocrbootstrap.ValidatedBootstrapSpecToml(args.Input.TOML)
case job.Gateway:
jb, err = gateway.ValidatedGatewaySpec(args.Input.TOML)
case job.Workflow:
jb, err = workflows.ValidatedWorkflowSpec(args.Input.TOML)
default:
return NewCreateJobPayload(r.App, nil, map[string]string{
"Job Type": fmt.Sprintf("unknown job type: %s", jbt),
Expand Down

0 comments on commit 84783a8

Please sign in to comment.