Skip to content

Commit 041d69e

Browse files
author
Mateusz Kuziemko
authored
Validate TypeInstance input (#629)
1 parent 8c7864c commit 041d69e

35 files changed

+549
-51
lines changed

.mlc.config.json

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
},
1515
{
1616
"pattern": "^http://capact-hub-local.capact-system/graphql$"
17+
},
18+
{
19+
"pattern": "^http://capact-hub-public.capact-system/graphql$"
1720
}
1821
],
1922
"timeout": "20s",

cmd/argo-actions/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ The following environment variables can be set:
3535
|--------------------------|----------|-------------------------------------------------|--------------------------------------------------------|
3636
| APP_ACTION | yes | | Defines action to perform |
3737
| APP_LOCAL_HUB_ENDPOINT | no | http://capact-hub-local.capact-system/graphql | Defines local Hub Endpoint |
38+
| APP_PUBLIC_HUB_ENDPOINT | no | http://capact-hub-public.capact-system/graphql | Defines public Hub Endpoint |
3839
| APP_DOWNLOAD_CONFIG | no | | For download action defines Type Instances to download |
3940
| APP_LOGGER_DEV_MODE | no | `false` | Enable additional log messages |
4041

cmd/argo-actions/main.go

+17-10
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,23 @@ import (
88

99
"capact.io/capact/internal/logger"
1010
argoactions "capact.io/capact/pkg/argo-actions"
11+
hubclient "capact.io/capact/pkg/hub/client"
1112
"capact.io/capact/pkg/hub/client/local"
13+
"capact.io/capact/pkg/hub/client/public"
1214

1315
"github.com/vrischmann/envconfig"
1416
"go.uber.org/zap"
1517
)
1618

1719
// Config for the argo-actions command.
1820
type Config struct {
19-
Action string
20-
DownloadConfig []argoactions.DownloadConfig `envconfig:"optional"`
21-
UploadConfig argoactions.UploadConfig `envconfig:"optional"`
22-
UpdateConfig argoactions.UpdateConfig `envconfig:"optional"`
23-
LocalHubEndpoint string `envconfig:"default=http://capact-hub-local.capact-system/graphql"`
24-
Logger logger.Config
21+
Action string
22+
DownloadConfig []argoactions.DownloadConfig `envconfig:"optional"`
23+
UploadConfig argoactions.UploadConfig `envconfig:"optional"`
24+
UpdateConfig argoactions.UpdateConfig `envconfig:"optional"`
25+
LocalHubEndpoint string `envconfig:"default=http://capact-hub-local.capact-system/graphql"`
26+
PublicHubEndpoint string `envconfig:"default=http://capact-hub-public.capact-system/graphql"`
27+
Logger logger.Config
2528
}
2629

2730
func main() {
@@ -37,20 +40,24 @@ func main() {
3740
logger, err := logger.New(cfg.Logger)
3841
exitOnError(err, "while creating zap logger")
3942

40-
client := local.NewDefaultClient(cfg.LocalHubEndpoint)
43+
// TODO: Consider using connection `hubclient.New` and route requests through Gateway
44+
client := hubclient.Client{
45+
Local: local.NewDefaultClient(cfg.LocalHubEndpoint),
46+
Public: public.NewDefaultClient(cfg.PublicHubEndpoint),
47+
}
4148

4249
switch cfg.Action {
4350
case argoactions.DownloadAction:
4451
log := logger.With(zap.String("Action", argoactions.DownloadAction))
45-
action = argoactions.NewDownloadAction(log, client, cfg.DownloadConfig)
52+
action = argoactions.NewDownloadAction(log, &client, cfg.DownloadConfig)
4653

4754
case argoactions.UploadAction:
4855
log := logger.With(zap.String("Action", argoactions.UploadAction))
49-
action = argoactions.NewUploadAction(log, client, cfg.UploadConfig)
56+
action = argoactions.NewUploadAction(log, &client, cfg.UploadConfig)
5057

5158
case argoactions.UpdateAction:
5259
log := logger.With(zap.String("Action", argoactions.UpdateAction))
53-
action = argoactions.NewUpdateAction(log, client, cfg.UpdateConfig)
60+
action = argoactions.NewUpdateAction(log, &client, cfg.UpdateConfig)
5461

5562
default:
5663
err := fmt.Errorf("Invalid action: %s", cfg.Action)

cmd/cli/cmd/typeinstance/create.go

+16-7
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"capact.io/capact/internal/cli/heredoc"
1414
"capact.io/capact/internal/cli/printer"
1515
gqllocalapi "capact.io/capact/pkg/hub/api/graphql/local"
16+
"capact.io/capact/pkg/sdk/validation"
1617

1718
"github.com/pkg/errors"
1819
"github.com/spf13/cobra"
@@ -85,6 +86,12 @@ func NewCreate() *cobra.Command {
8586
func createTI(ctx context.Context, opts createOptions, resourcePrinter *printer.ResourcePrinter) error {
8687
typeInstanceToCreate := &gqllocalapi.CreateTypeInstancesInput{}
8788

89+
server := config.GetDefaultContext()
90+
hubCli, err := client.NewHub(server)
91+
if err != nil {
92+
return err
93+
}
94+
8895
for _, path := range opts.TypeInstancesFiles {
8996
out, err := loadCreateTypeInstanceFromFile(path)
9097
if err != nil {
@@ -94,18 +101,20 @@ func createTI(ctx context.Context, opts createOptions, resourcePrinter *printer.
94101
typeInstanceToCreate = mergeCreateTypeInstances(typeInstanceToCreate, out)
95102
}
96103

104+
r := validation.ResultAggregator{}
105+
err = r.Report(validation.ValidateTypeInstancesToCreate(ctx, hubCli, typeInstanceToCreate))
106+
if err != nil {
107+
return errors.Wrap(err, "while validating TypeInstances")
108+
}
109+
if r.ErrorOrNil() != nil {
110+
return r.ErrorOrNil()
111+
}
112+
97113
// HACK: UsesRelations are required on GQL side so at least empty array needs to be send
98114
if typeInstanceToCreate.UsesRelations == nil {
99115
typeInstanceToCreate.UsesRelations = []*gqllocalapi.TypeInstanceUsesRelationInput{}
100116
}
101117

102-
server := config.GetDefaultContext()
103-
104-
hubCli, err := client.NewHub(server)
105-
if err != nil {
106-
return err
107-
}
108-
109118
createdTI, err := hubCli.CreateTypeInstances(ctx, typeInstanceToCreate)
110119
if err != nil {
111120
return err

cmd/cli/cmd/typeinstance/edit.go

+11
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ import (
99
"capact.io/capact/internal/cli/client"
1010
"capact.io/capact/internal/cli/config"
1111
gqllocalapi "capact.io/capact/pkg/hub/api/graphql/local"
12+
"capact.io/capact/pkg/sdk/validation"
1213

1314
"github.com/AlecAivazis/survey/v2"
1415
"github.com/MakeNowJust/heredoc"
1516
"github.com/fatih/color"
17+
"github.com/pkg/errors"
1618
"github.com/spf13/cobra"
1719
"sigs.k8s.io/yaml"
1820
)
@@ -58,6 +60,15 @@ func editTI(ctx context.Context, opts editOptions, w io.Writer) error {
5860
return err
5961
}
6062

63+
r := validation.ResultAggregator{}
64+
err = r.Report(validation.ValidateTypeInstanceToUpdate(ctx, hubCli, typeInstanceToUpdate))
65+
if err != nil {
66+
return errors.Wrap(err, "while validating TypeInstance")
67+
}
68+
if r.ErrorOrNil() != nil {
69+
return r.ErrorOrNil()
70+
}
71+
6172
_, err = hubCli.UpdateTypeInstances(ctx, typeInstanceToUpdate)
6273
if err != nil {
6374
return err

cmd/k8s-engine/main.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ type Config struct {
6464

6565
Logger logger.Config
6666

67+
LocalHubEndpoint string `envconfig:"default=http://capact-hub-local.capact-system/graphql"`
68+
PublicHubEndpoint string `envconfig:"default=http://capact-hub-public.capact-system/graphql"`
69+
6770
GraphQLGateway struct {
6871
Endpoint string `envconfig:"default=http://capact-gateway/graphql"`
6972
Username string
@@ -108,7 +111,7 @@ func main() {
108111
exitOnError(err, "while creating manager")
109112

110113
hubClient := getHubClient(&cfg)
111-
typeInstanceHandler := argo.NewTypeInstanceHandler(cfg.HubActionsImage)
114+
typeInstanceHandler := argo.NewTypeInstanceHandler(cfg.HubActionsImage, cfg.LocalHubEndpoint, cfg.PublicHubEndpoint)
112115
interfaceIOValidator := actionvalidation.NewValidator(hubClient)
113116
policyIOValidator := policyvalidation.NewValidator(hubClient)
114117
wfValidator := renderer.NewWorkflowInputValidator(interfaceIOValidator, policyIOValidator)

deploy/kubernetes/charts/capact/charts/engine/templates/deployment.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ spec:
4848
value: "{{ .Values.global.gateway.auth.username }}"
4949
- name: APP_GRAPHQLGATEWAY_PASSWORD
5050
value: "{{ .Values.global.gateway.auth.password }}"
51+
- name: APP_LOCAL_HUB_ENDPOINT
52+
value: "http://capact-hub-local.{{.Release.Namespace}}.svc.cluster.local/graphql"
53+
- name: APP_PUBLIC_HUB_ENDPOINT
54+
value: "http://capact-hub-public.{{.Release.Namespace}}.svc.cluster.local/graphql"
5155
- name: APP_BUILTIN_RUNNER_IMAGE
5256
value: "{{ .Values.global.containerRegistry.path }}/{{ .Values.builtInRunner.image.name }}:{{ .Values.global.containerRegistry.overrideTag | default .Chart.AppVersion }}"
5357
- name: APP_BUILTIN_RUNNER_TIMEOUT

pkg/argo-actions/download_type_instances.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import (
44
"context"
55
"fmt"
66

7-
"capact.io/capact/pkg/hub/client/local"
7+
hubclient "capact.io/capact/pkg/hub/client"
88
"capact.io/capact/pkg/runner"
99
"github.com/pkg/errors"
1010
"go.uber.org/zap"
@@ -25,11 +25,11 @@ type DownloadConfig struct {
2525
type Download struct {
2626
log *zap.Logger
2727
cfg []DownloadConfig
28-
client *local.Client
28+
client *hubclient.Client
2929
}
3030

3131
// NewDownloadAction returns a new Download instance.
32-
func NewDownloadAction(log *zap.Logger, client *local.Client, cfg []DownloadConfig) Action {
32+
func NewDownloadAction(log *zap.Logger, client *hubclient.Client, cfg []DownloadConfig) Action {
3333
return &Download{
3434
log: log,
3535
cfg: cfg,

pkg/argo-actions/update_type_instances.go

+16-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import (
77
"path/filepath"
88

99
graphqllocal "capact.io/capact/pkg/hub/api/graphql/local"
10-
"capact.io/capact/pkg/hub/client/local"
10+
hubclient "capact.io/capact/pkg/hub/client"
11+
"capact.io/capact/pkg/sdk/validation"
1112
"github.com/pkg/errors"
1213
"go.uber.org/zap"
1314
"sigs.k8s.io/yaml"
@@ -26,12 +27,12 @@ type UpdateConfig struct {
2627
// It is used to update existing TypeInstances in the Local Hub.
2728
type Update struct {
2829
log *zap.Logger
29-
client *local.Client
30+
client *hubclient.Client
3031
cfg UpdateConfig
3132
}
3233

3334
// NewUpdateAction returns a new Update instance.
34-
func NewUpdateAction(log *zap.Logger, client *local.Client, cfg UpdateConfig) Action {
35+
func NewUpdateAction(log *zap.Logger, client *hubclient.Client, cfg UpdateConfig) Action {
3536
return &Update{
3637
log: log,
3738
client: client,
@@ -83,6 +84,17 @@ func (u *Update) Do(ctx context.Context) error {
8384
return errors.Wrap(err, "while rendering UpdateTypeInstancesInput")
8485
}
8586

87+
u.log.Info("Validating TypeInstances")
88+
89+
r := validation.ResultAggregator{}
90+
err = r.Report(validation.ValidateTypeInstanceToUpdate(ctx, u.client, payload))
91+
if err != nil {
92+
return errors.Wrap(err, "while validating TypeInstance")
93+
}
94+
if r.ErrorOrNil() != nil {
95+
return r.ErrorOrNil()
96+
}
97+
8698
u.log.Info("Updating TypeInstances in Hub...", zap.Int("TypeInstance count", len(payload)))
8799

88100
uploadOutput, err := u.updateTypeInstances(ctx, payload)
@@ -110,5 +122,5 @@ func (u *Update) render(payload []graphqllocal.UpdateTypeInstancesInput, values
110122
}
111123

112124
func (u *Update) updateTypeInstances(ctx context.Context, in []graphqllocal.UpdateTypeInstancesInput) ([]graphqllocal.TypeInstance, error) {
113-
return u.client.UpdateTypeInstances(ctx, in)
125+
return u.client.Local.UpdateTypeInstances(ctx, in)
114126
}

pkg/argo-actions/upload_type_instances.go

+17-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import (
77
"path/filepath"
88

99
graphqllocal "capact.io/capact/pkg/hub/api/graphql/local"
10-
"capact.io/capact/pkg/hub/client/local"
10+
hubclient "capact.io/capact/pkg/hub/client"
11+
"capact.io/capact/pkg/sdk/validation"
12+
1113
"github.com/pkg/errors"
1214
"go.uber.org/zap"
1315
"sigs.k8s.io/yaml"
@@ -26,12 +28,12 @@ type UploadConfig struct {
2628
// It is used to upload TypeInstances to the Local Hub.
2729
type Upload struct {
2830
log *zap.Logger
29-
client *local.Client
31+
client *hubclient.Client
3032
cfg UploadConfig
3133
}
3234

3335
// NewUploadAction returns a new Upload instance.
34-
func NewUploadAction(log *zap.Logger, client *local.Client, cfg UploadConfig) Action {
36+
func NewUploadAction(log *zap.Logger, client *hubclient.Client, cfg UploadConfig) Action {
3537
return &Upload{
3638
log: log,
3739
client: client,
@@ -83,6 +85,17 @@ func (u *Upload) Do(ctx context.Context) error {
8385
return errors.Wrap(err, "while rendering CreateTypeInstancesInput")
8486
}
8587

88+
u.log.Info("Validating TypeInstances")
89+
90+
r := validation.ResultAggregator{}
91+
err = r.Report(validation.ValidateTypeInstancesToCreate(ctx, u.client, payload))
92+
if err != nil {
93+
return errors.Wrap(err, "while validating TypeInstances")
94+
}
95+
if r.ErrorOrNil() != nil {
96+
return r.ErrorOrNil()
97+
}
98+
8699
u.log.Info("Uploading TypeInstances to Hub...", zap.Int("TypeInstance count", len(payload.TypeInstances)))
87100

88101
uploadOutput, err := u.uploadTypeInstances(ctx, payload)
@@ -112,5 +125,5 @@ func (u *Upload) render(payload *graphqllocal.CreateTypeInstancesInput, values m
112125
}
113126

114127
func (u *Upload) uploadTypeInstances(ctx context.Context, in *graphqllocal.CreateTypeInstancesInput) ([]graphqllocal.CreateTypeInstanceOutput, error) {
115-
return u.client.CreateTypeInstances(ctx, in)
128+
return u.client.Local.CreateTypeInstances(ctx, in)
116129
}

pkg/hub/client/public/client.go

+10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"regexp"
77
"strings"
88

9+
"capact.io/capact/pkg/httputil"
910
gqlpublicapi "capact.io/capact/pkg/hub/api/graphql/public"
1011
"github.com/avast/retry-go"
1112

@@ -25,6 +26,15 @@ func NewClient(cli *graphql.Client) *Client {
2526
return &Client{client: cli}
2627
}
2728

29+
// NewDefaultClient creates ready to use client with default values.
30+
func NewDefaultClient(endpoint string, opts ...httputil.ClientOption) *Client {
31+
httpClient := httputil.NewClient(opts...)
32+
clientOpt := graphql.WithHTTPClient(httpClient)
33+
client := graphql.NewClient(endpoint, clientOpt)
34+
35+
return NewClient(client)
36+
}
37+
2838
// FindInterfaceRevision returns the InterfaceRevision for the given InterfaceReference.
2939
// It will return nil, if the InterfaceRevision is not found.
3040
func (c *Client) FindInterfaceRevision(ctx context.Context, ref gqlpublicapi.InterfaceReference, opts ...InterfaceRevisionOption) (*gqlpublicapi.InterfaceRevision, error) {

pkg/sdk/apis/0.0.1/types/types.extend.go

+4
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ type ManifestRef struct {
3131
Revision string `json:"revision"` // Version of the manifest content in the SemVer format.
3232
}
3333

34+
func (in *ManifestRef) String() string {
35+
return fmt.Sprintf("%s:%s", in.Path, in.Revision)
36+
}
37+
3438
// ManifestRefWithOptRevision specifies type by path and optional revision.
3539
// +kubebuilder:object:generate=true
3640
type ManifestRefWithOptRevision struct {

pkg/sdk/renderer/argo/dedicated_renderer_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func createFakeDedicatedRendererObject(t *testing.T) *dedicatedRenderer {
1616
require.NoError(t, err)
1717

1818
genUUID := func() string { return "uuid" }
19-
typeInstanceHandler := NewTypeInstanceHandler("alpine:3.7")
19+
typeInstanceHandler := NewTypeInstanceHandler("alpine:3.7", "", "")
2020
typeInstanceHandler.SetGenUUID(genUUID)
2121

2222
policyIOValidator := policyvalidation.NewValidator(fakeCli)

0 commit comments

Comments
 (0)