From eaeda9e485d0484961f2573205926716a346fc37 Mon Sep 17 00:00:00 2001 From: Mateusz Kuziemko Date: Tue, 22 Feb 2022 23:15:28 +0100 Subject: [PATCH 1/9] Add Default Interface Policy --- .../graphql/domain/policy/converter.go | 26 +- pkg/engine/api/graphql/config.yaml | 2 + pkg/engine/api/graphql/examples.graphql | 18 ++ pkg/engine/api/graphql/models_gen.go | 23 +- pkg/engine/api/graphql/policy.go | 6 + pkg/engine/api/graphql/schema.graphql | 18 ++ pkg/engine/api/graphql/schema_gen.go | 274 +++++++++++++++++- pkg/engine/client/fields.go | 8 + pkg/engine/k8s/policy/types.go | 11 +- 9 files changed, 378 insertions(+), 8 deletions(-) diff --git a/internal/k8s-engine/graphql/domain/policy/converter.go b/internal/k8s-engine/graphql/domain/policy/converter.go index 3bc3c4566..13bc7d19b 100644 --- a/internal/k8s-engine/graphql/domain/policy/converter.go +++ b/internal/k8s-engine/graphql/domain/policy/converter.go @@ -49,7 +49,20 @@ func (c *Converter) interfaceFromGraphQLInput(in *graphql.InterfacePolicyInput) }) } - return policy.InterfacePolicy{Rules: rules}, nil + if in.Default == nil || in.Default.Inject == nil || in.Default.Inject.RequiredTypeInstances == nil || len(in.Default.Inject.RequiredTypeInstances) == 0 { + return policy.InterfacePolicy{ + Rules: rules, + }, nil + } + + return policy.InterfacePolicy{ + Default: &policy.DefaultInterfaceData{ + Inject: &policy.DefaultInjectInterfaceData{ + RequiredTypeInstances: c.requiredTypeInstancesToInjectFromGraphQLInput(in.Default.Inject.RequiredTypeInstances), + }, + }, + Rules: rules, + }, nil } func (c *Converter) typeInstanceFromGraphQLInput(in *graphql.TypeInstancePolicyInput) policy.TypeInstancePolicy { @@ -117,7 +130,18 @@ func (c *Converter) interfaceToGraphQL(in policy.InterfacePolicy) *graphql.Inter }) } + if in.Default == nil || in.Default.Inject == nil || len(in.Default.Inject.RequiredTypeInstances) == 0 { + return &graphql.InterfacePolicy{ + Rules: gqlRules, + } + } + return &graphql.InterfacePolicy{ + Default: &graphql.DefaultInterfaceData{ + Inject: &graphql.DefaultInjectData{ + RequiredTypeInstances: c.requiredTypeInstancesToInjectToGraphQL(in.Default.Inject.RequiredTypeInstances), + }, + }, Rules: gqlRules, } } diff --git a/pkg/engine/api/graphql/config.yaml b/pkg/engine/api/graphql/config.yaml index de2675ea0..3c4cd5211 100644 --- a/pkg/engine/api/graphql/config.yaml +++ b/pkg/engine/api/graphql/config.yaml @@ -32,4 +32,6 @@ models: model: "capact.io/capact/pkg/engine/api/graphql.RequiredTypeInstanceReference" AdditionalTypeInstanceReference: model: "capact.io/capact/pkg/engine/api/graphql.AdditionalTypeInstanceReference" + InterfacePolicy: + model: "capact.io/capact/pkg/engine/api/graphql.InterfacePolicy" diff --git a/pkg/engine/api/graphql/examples.graphql b/pkg/engine/api/graphql/examples.graphql index e693924f3..8ca4a4a78 100644 --- a/pkg/engine/api/graphql/examples.graphql +++ b/pkg/engine/api/graphql/examples.graphql @@ -166,6 +166,16 @@ mutation UpdatePolicy { updatePolicy( in: { interface: { + default: { + inject: { + requiredTypeInstances: [ + { + id: "edf854df-86cf-4855-9d38-8d88545fb9c9" + description: "My TypeInstance" + } + ] + } + } rules: [ { interface: { @@ -294,6 +304,14 @@ fragment ActionFields on Action { fragment PolicyFields on Policy { interface { + default { + inject { + requiredTypeInstances { + id + description + } + } + } rules { interface { path diff --git a/pkg/engine/api/graphql/models_gen.go b/pkg/engine/api/graphql/models_gen.go index b4457fe95..7b80f09c2 100644 --- a/pkg/engine/api/graphql/models_gen.go +++ b/pkg/engine/api/graphql/models_gen.go @@ -119,6 +119,22 @@ type AdvancedModeContinueRenderingInput struct { TypeInstances []*InputTypeInstanceData `json:"typeInstances"` } +type DefaultInjectData struct { + RequiredTypeInstances []*RequiredTypeInstanceReference `json:"requiredTypeInstances"` +} + +type DefaultInjectInputData struct { + RequiredTypeInstances []*RequiredTypeInstanceReferenceInput `json:"requiredTypeInstances"` +} + +type DefaultInterfaceData struct { + Inject *DefaultInjectData `json:"inject"` +} + +type DefaultInterfaceInputData struct { + Inject *DefaultInjectInputData `json:"inject"` +} + // Client input for Input TypeInstance type InputTypeInstanceData struct { Name string `json:"name"` @@ -137,12 +153,9 @@ type InputTypeInstanceToProvide struct { TypeRef *ManifestReference `json:"typeRef"` } -type InterfacePolicy struct { - Rules []*RulesForInterface `json:"rules"` -} - type InterfacePolicyInput struct { - Rules []*RulesForInterfaceInput `json:"rules"` + Default *DefaultInterfaceInputData `json:"default"` + Rules []*RulesForInterfaceInput `json:"rules"` } type ManifestReference struct { diff --git a/pkg/engine/api/graphql/policy.go b/pkg/engine/api/graphql/policy.go index 4b4ac2461..ef5085408 100644 --- a/pkg/engine/api/graphql/policy.go +++ b/pkg/engine/api/graphql/policy.go @@ -2,6 +2,12 @@ package graphql // The types had to be moved out from generated models to add `omitempty` tags. +//InterfacePolicy represents Interface Policy. +type InterfacePolicy struct { + Default *DefaultInterfaceData `json:"default,omitempty"` + Rules []*RulesForInterface `json:"rules"` +} + // PolicyRule represents a single policy rule. type PolicyRule struct { ImplementationConstraints *PolicyRuleImplementationConstraints `json:"implementationConstraints,omitempty"` diff --git a/pkg/engine/api/graphql/schema.graphql b/pkg/engine/api/graphql/schema.graphql index d8c9c0330..9c0799896 100644 --- a/pkg/engine/api/graphql/schema.graphql +++ b/pkg/engine/api/graphql/schema.graphql @@ -330,9 +330,18 @@ input TypeInstanceBackendRuleInput { # Interface Policy Input input InterfacePolicyInput { + default: DefaultInterfaceInputData rules: [RulesForInterfaceInput!]! } +input DefaultInterfaceInputData { + inject: DefaultInjectInputData +} + +input DefaultInjectInputData{ + requiredTypeInstances: [RequiredTypeInstanceReferenceInput!] +} + input RulesForInterfaceInput { interface: ManifestReferenceInput! oneOf: [PolicyRuleInput!]! @@ -393,9 +402,18 @@ type TypeInstanceBackendRule { # Interface Policy type InterfacePolicy { + default: DefaultInterfaceData rules: [RulesForInterface!]! } +type DefaultInterfaceData { + inject: DefaultInjectData +} + +type DefaultInjectData { + requiredTypeInstances: [RequiredTypeInstanceReference!] +} + type RulesForInterface { interface: ManifestReferenceWithOptionalRevision! oneOf: [PolicyRule!]! diff --git a/pkg/engine/api/graphql/schema_gen.go b/pkg/engine/api/graphql/schema_gen.go index 9b46e58ac..63ba45e0b 100644 --- a/pkg/engine/api/graphql/schema_gen.go +++ b/pkg/engine/api/graphql/schema_gen.go @@ -92,6 +92,14 @@ type ComplexityRoot struct { Name func(childComplexity int) int } + DefaultInjectData struct { + RequiredTypeInstances func(childComplexity int) int + } + + DefaultInterfaceData struct { + Inject func(childComplexity int) int + } + InputTypeInstanceDetails struct { ID func(childComplexity int) int Name func(childComplexity int) int @@ -103,7 +111,8 @@ type ComplexityRoot struct { } InterfacePolicy struct { - Rules func(childComplexity int) int + Default func(childComplexity int) int + Rules func(childComplexity int) int } ManifestReference struct { @@ -433,6 +442,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.AdditionalTypeInstanceReference.Name(childComplexity), true + case "DefaultInjectData.requiredTypeInstances": + if e.complexity.DefaultInjectData.RequiredTypeInstances == nil { + break + } + + return e.complexity.DefaultInjectData.RequiredTypeInstances(childComplexity), true + + case "DefaultInterfaceData.inject": + if e.complexity.DefaultInterfaceData.Inject == nil { + break + } + + return e.complexity.DefaultInterfaceData.Inject(childComplexity), true + case "InputTypeInstanceDetails.id": if e.complexity.InputTypeInstanceDetails.ID == nil { break @@ -461,6 +484,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.InputTypeInstanceToProvide.TypeRef(childComplexity), true + case "InterfacePolicy.default": + if e.complexity.InterfacePolicy.Default == nil { + break + } + + return e.complexity.InterfacePolicy.Default(childComplexity), true + case "InterfacePolicy.rules": if e.complexity.InterfacePolicy.Rules == nil { break @@ -1203,9 +1233,18 @@ input TypeInstanceBackendRuleInput { # Interface Policy Input input InterfacePolicyInput { + default: DefaultInterfaceInputData rules: [RulesForInterfaceInput!]! } +input DefaultInterfaceInputData { + inject: DefaultInjectInputData +} + +input DefaultInjectInputData{ + requiredTypeInstances: [RequiredTypeInstanceReferenceInput!] +} + input RulesForInterfaceInput { interface: ManifestReferenceInput! oneOf: [PolicyRuleInput!]! @@ -1266,9 +1305,18 @@ type TypeInstanceBackendRule { # Interface Policy type InterfacePolicy { + default: DefaultInterfaceData rules: [RulesForInterface!]! } +type DefaultInterfaceData { + inject: DefaultInjectData +} + +type DefaultInjectData { + requiredTypeInstances: [RequiredTypeInstanceReference!] +} + type RulesForInterface { interface: ManifestReferenceWithOptionalRevision! oneOf: [PolicyRule!]! @@ -2526,6 +2574,70 @@ func (ec *executionContext) _AdditionalTypeInstanceReference_id(ctx context.Cont return ec.marshalNID2string(ctx, field.Selections, res) } +func (ec *executionContext) _DefaultInjectData_requiredTypeInstances(ctx context.Context, field graphql.CollectedField, obj *DefaultInjectData) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "DefaultInjectData", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.RequiredTypeInstances, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*RequiredTypeInstanceReference) + fc.Result = res + return ec.marshalORequiredTypeInstanceReference2ᚕᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐRequiredTypeInstanceReferenceᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) _DefaultInterfaceData_inject(ctx context.Context, field graphql.CollectedField, obj *DefaultInterfaceData) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "DefaultInterfaceData", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Inject, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*DefaultInjectData) + fc.Result = res + return ec.marshalODefaultInjectData2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInjectData(ctx, field.Selections, res) +} + func (ec *executionContext) _InputTypeInstanceDetails_id(ctx context.Context, field graphql.CollectedField, obj *InputTypeInstanceDetails) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -2666,6 +2778,38 @@ func (ec *executionContext) _InputTypeInstanceToProvide_typeRef(ctx context.Cont return ec.marshalNManifestReference2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐManifestReference(ctx, field.Selections, res) } +func (ec *executionContext) _InterfacePolicy_default(ctx context.Context, field graphql.CollectedField, obj *InterfacePolicy) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "InterfacePolicy", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Default, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*DefaultInterfaceData) + fc.Result = res + return ec.marshalODefaultInterfaceData2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInterfaceData(ctx, field.Selections, res) +} + func (ec *executionContext) _InterfacePolicy_rules(ctx context.Context, field graphql.CollectedField, obj *InterfacePolicy) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -5552,6 +5696,46 @@ func (ec *executionContext) unmarshalInputAdvancedModeContinueRenderingInput(ctx return it, nil } +func (ec *executionContext) unmarshalInputDefaultInjectInputData(ctx context.Context, obj interface{}) (DefaultInjectInputData, error) { + var it DefaultInjectInputData + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "requiredTypeInstances": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("requiredTypeInstances")) + it.RequiredTypeInstances, err = ec.unmarshalORequiredTypeInstanceReferenceInput2ᚕᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐRequiredTypeInstanceReferenceInputᚄ(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputDefaultInterfaceInputData(ctx context.Context, obj interface{}) (DefaultInterfaceInputData, error) { + var it DefaultInterfaceInputData + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "inject": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("inject")) + it.Inject, err = ec.unmarshalODefaultInjectInputData2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInjectInputData(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputInputTypeInstanceData(ctx context.Context, obj interface{}) (InputTypeInstanceData, error) { var it InputTypeInstanceData var asMap = obj.(map[string]interface{}) @@ -5586,6 +5770,14 @@ func (ec *executionContext) unmarshalInputInterfacePolicyInput(ctx context.Conte for k, v := range asMap { switch k { + case "default": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("default")) + it.Default, err = ec.unmarshalODefaultInterfaceInputData2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInterfaceInputData(ctx, v) + if err != nil { + return it, err + } case "rules": var err error @@ -6156,6 +6348,54 @@ func (ec *executionContext) _AdditionalTypeInstanceReference(ctx context.Context return out } +var defaultInjectDataImplementors = []string{"DefaultInjectData"} + +func (ec *executionContext) _DefaultInjectData(ctx context.Context, sel ast.SelectionSet, obj *DefaultInjectData) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, defaultInjectDataImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("DefaultInjectData") + case "requiredTypeInstances": + out.Values[i] = ec._DefaultInjectData_requiredTypeInstances(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var defaultInterfaceDataImplementors = []string{"DefaultInterfaceData"} + +func (ec *executionContext) _DefaultInterfaceData(ctx context.Context, sel ast.SelectionSet, obj *DefaultInterfaceData) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, defaultInterfaceDataImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("DefaultInterfaceData") + case "inject": + out.Values[i] = ec._DefaultInterfaceData_inject(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + var inputTypeInstanceDetailsImplementors = []string{"InputTypeInstanceDetails"} func (ec *executionContext) _InputTypeInstanceDetails(ctx context.Context, sel ast.SelectionSet, obj *InputTypeInstanceDetails) graphql.Marshaler { @@ -6231,6 +6471,8 @@ func (ec *executionContext) _InterfacePolicy(ctx context.Context, sel ast.Select switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("InterfacePolicy") + case "default": + out.Values[i] = ec._InterfacePolicy_default(ctx, field, obj) case "rules": out.Values[i] = ec._InterfacePolicy_rules(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -8224,6 +8466,36 @@ func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast return graphql.MarshalBoolean(*v) } +func (ec *executionContext) marshalODefaultInjectData2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInjectData(ctx context.Context, sel ast.SelectionSet, v *DefaultInjectData) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._DefaultInjectData(ctx, sel, v) +} + +func (ec *executionContext) unmarshalODefaultInjectInputData2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInjectInputData(ctx context.Context, v interface{}) (*DefaultInjectInputData, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputDefaultInjectInputData(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalODefaultInterfaceData2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInterfaceData(ctx context.Context, sel ast.SelectionSet, v *DefaultInterfaceData) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._DefaultInterfaceData(ctx, sel, v) +} + +func (ec *executionContext) unmarshalODefaultInterfaceInputData2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInterfaceInputData(ctx context.Context, v interface{}) (*DefaultInterfaceInputData, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputDefaultInterfaceInputData(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalOInputTypeInstanceData2ᚕᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐInputTypeInstanceDataᚄ(ctx context.Context, v interface{}) ([]*InputTypeInstanceData, error) { if v == nil { return nil, nil diff --git a/pkg/engine/client/fields.go b/pkg/engine/client/fields.go index d5523cde4..b72c33478 100644 --- a/pkg/engine/client/fields.go +++ b/pkg/engine/client/fields.go @@ -74,6 +74,14 @@ var actionFields = fmt.Sprintf(` const policyFields = ` interface { + default { + inject { + requiredTypeInstances { + id + description + } + } + } rules { interface { path diff --git a/pkg/engine/k8s/policy/types.go b/pkg/engine/k8s/policy/types.go index 327059670..ba8bcf4a1 100644 --- a/pkg/engine/k8s/policy/types.go +++ b/pkg/engine/k8s/policy/types.go @@ -36,7 +36,16 @@ type Policy struct { // InterfacePolicy holds the Policy for Interfaces. type InterfacePolicy struct { - Rules InterfaceRulesList `json:"rules"` + Default *DefaultInterfaceData `json:"default,omitempty"` + Rules InterfaceRulesList `json:"rules"` +} + +type DefaultInterfaceData struct { + Inject *DefaultInjectInterfaceData `json:"inject,omitempty"` +} + +type DefaultInjectInterfaceData struct { + RequiredTypeInstances []RequiredTypeInstanceToInject `json:"requiredTypeInstances,omitempty"` } // ActionPolicy holds the Policy injected during Action creation properties. From 8ee40031a62eaa68c74a5b270f1df6fc61add08f Mon Sep 17 00:00:00 2001 From: Mateusz Kuziemko Date: Wed, 23 Feb 2022 21:32:02 +0100 Subject: [PATCH 2/9] Add injection of TI into metadata and hub client --- pkg/engine/k8s/policy/metadata/metadata.go | 17 +++++++++ .../k8s/policy/metadata/metadata_resolver.go | 35 +++++++++++++++++++ pkg/hub/client/policy_enforced_client.go | 28 +++++++++++++++ pkg/hub/client/policy_merger.go | 7 ++++ 4 files changed, 87 insertions(+) diff --git a/pkg/engine/k8s/policy/metadata/metadata.go b/pkg/engine/k8s/policy/metadata/metadata.go index be9185317..fd6d6c235 100644 --- a/pkg/engine/k8s/policy/metadata/metadata.go +++ b/pkg/engine/k8s/policy/metadata/metadata.go @@ -12,6 +12,7 @@ type typeInstanceKind string const ( requiredTypeInstance typeInstanceKind = "RequiredTypeInstance" additionalTypeInstance typeInstanceKind = "AdditionalTypeInstance" + defaultTypeInstance typeInstanceKind = "DefaultTypeInstance" backendTypeInstance typeInstanceKind = "BackendTypeInstance" ) @@ -56,6 +57,22 @@ func TypeInstanceIDsWithUnresolvedMetadataForPolicy(in policy.Policy) []TypeInst } } + // Interface Defaults + fmt.Println("TypeInstanceIDsWithUnresolvedMetadataForPolicy") + if in.Interface.Default != nil && in.Interface.Default.Inject != nil { + for _, defaultTI := range in.Interface.Default.Inject.RequiredTypeInstances { + fmt.Println("Adding ID", defaultTI.ID) + if defaultTI.TypeRef != nil && defaultTI.TypeRef.Path != "" && defaultTI.TypeRef.Revision != "" { + continue + } + tis = append(tis, TypeInstanceMetadata{ + ID: defaultTI.ID, + Description: defaultTI.Description, + Kind: defaultTypeInstance, + }) + } + } + // TypeInstances backends for _, rule := range in.TypeInstance.Rules { if rule.Backend.TypeRef != nil && rule.Backend.TypeRef.Path != "" && rule.Backend.TypeRef.Revision != "" { diff --git a/pkg/engine/k8s/policy/metadata/metadata_resolver.go b/pkg/engine/k8s/policy/metadata/metadata_resolver.go index 9f41f5021..1d4e3bbb9 100644 --- a/pkg/engine/k8s/policy/metadata/metadata_resolver.go +++ b/pkg/engine/k8s/policy/metadata/metadata_resolver.go @@ -11,6 +11,7 @@ import ( hubpublicgraphql "capact.io/capact/pkg/hub/api/graphql/public" "capact.io/capact/pkg/hub/client/public" "capact.io/capact/pkg/sdk/apis/0.0.1/types" + "github.com/davecgh/go-spew/spew" multierr "github.com/hashicorp/go-multierror" "github.com/pkg/errors" @@ -53,18 +54,31 @@ func (r *Resolver) ResolveTypeInstanceMetadata(ctx context.Context, policy *poli return nil } + fmt.Println("idsToQuery") + spew.Dump(idsToQuery) + resolvedTypeRefs, err := r.hubCli.FindTypeInstancesTypeRef(ctx, idsToQuery) if err != nil { return errors.Wrap(err, "while finding TypeRef for TypeInstances") } + fmt.Println("resolvedTypeRefs") + spew.Dump(resolvedTypeRefs) + // verify if all TypeInstances are resolved multiErr := multierror.New() for _, ti := range unresolvedTIs { + fmt.Println("Checking ti", ti.ID) + if typeRef, exists := resolvedTypeRefs[ti.ID]; exists && typeRef.Path != "" && typeRef.Revision != "" { + fmt.Println("OK!!!!", typeRef.Path, typeRef.Revision) continue } + fmt.Println("ERRORRRR!!!") + fmt.Println("resolvedTypeRefs!!!") + spew.Dump(resolvedTypeRefs) + multiErr = multierr.Append(multiErr, fmt.Errorf("missing Type reference for %s", ti.String(true))) } if multiErr.ErrorOrNil() != nil { @@ -76,6 +90,7 @@ func (r *Resolver) ResolveTypeInstanceMetadata(ctx context.Context, policy *poli return errors.Wrap(err, "while resolving parent nodes for TypeRefs") } + r.setTypeRefsForDefaultTypeInstances(policy, typeRefWithParentNodes) r.setTypeRefsForAdditionalTypeInstances(policy, typeRefWithParentNodes) r.setTypeRefsForRequiredTypeInstances(policy, typeRefWithParentNodes) r.setTypeRefsForBackendTypeInstances(policy, typeRefWithParentNodes) @@ -115,6 +130,26 @@ func (r *Resolver) mapToTypeRefs(in map[string]hublocalgraphql.TypeInstanceTypeR return out } +func (r *Resolver) setTypeRefsForDefaultTypeInstances(policy *policy.Policy, typeRefs map[string]TypeRefWithAdditionalRefs) { + fmt.Println("setTypeRefsForDefaultTypeInstances") + if policy.Interface.Default == nil || policy.Interface.Default.Inject == nil || len(policy.Interface.Default.Inject.RequiredTypeInstances) == 0 { + fmt.Println("empty policy.Interface.Default in setTypeRefsForDefaultTypeInstances") + return + } + for reqTIIdx, reqTI := range policy.Interface.Default.Inject.RequiredTypeInstances { + typeRef, exists := typeRefs[reqTI.ID] + if !exists { + continue + } + + fmt.Println("Addding TypeRef for", policy.Interface.Default.Inject.RequiredTypeInstances[reqTIIdx]) + policy.Interface.Default.Inject.RequiredTypeInstances[reqTIIdx].TypeRef = &types.TypeRef{ + Path: typeRef.Path, + Revision: typeRef.Revision, + } + } +} + func (r *Resolver) setTypeRefsForRequiredTypeInstances(policy *policy.Policy, typeRefs map[string]TypeRefWithAdditionalRefs) { for ruleIdx, rule := range policy.Interface.Rules { for ruleItemIdx, ruleItem := range rule.OneOf { diff --git a/pkg/hub/client/policy_enforced_client.go b/pkg/hub/client/policy_enforced_client.go index ea5fe79e3..2e28d948c 100644 --- a/pkg/hub/client/policy_enforced_client.go +++ b/pkg/hub/client/policy_enforced_client.go @@ -13,6 +13,7 @@ import ( "capact.io/capact/pkg/sdk/apis/0.0.1/types" "capact.io/capact/pkg/sdk/validation" + "github.com/davecgh/go-spew/spew" "github.com/pkg/errors" "sigs.k8s.io/yaml" ) @@ -101,6 +102,10 @@ func (e *PolicyEnforcedClient) ListImplementationRevisionForInterface(ctx contex return nil, policy.Rule{}, err } + fmt.Println("ListImplementationRevisionForInterface") + fmt.Println("found implementations", implementations) + spew.Dump(implementations) + return implementations, rule, nil } @@ -154,6 +159,13 @@ type requiredTypeInstanceToInject map[string]policy.RequiredTypeInstanceToInject func (e *PolicyEnforcedClient) listRequiredTypeInstancesToInjectBasedOnPolicy(policyRule policy.Rule, implRev hubpublicgraphql.ImplementationRevision) (requiredTypeInstanceToInject, error) { requiredTIs := policyRule.RequiredTypeInstancesToInject() + + // inject Default RequiredTypeInstances + if e.mergedPolicy.Interface.Default != nil && e.mergedPolicy.Interface.Default.Inject != nil { + fmt.Println("inject Default RequiredTypeInstances") + requiredTIs = append(requiredTIs, e.mergedPolicy.Interface.Default.Inject.RequiredTypeInstances...) + } + if len(requiredTIs) == 0 { return nil, nil } @@ -445,6 +457,22 @@ func (e *PolicyEnforcedClient) hubFilterForPolicyRule(rule policy.Rule, allTypeI filter.RequiredTypeInstancesInjectionSatisfiedBy = injectedRequiredTypeInstances } + fmt.Println("Default Injection in hubFilterForPolicyRule") + + // Default Injection + if e.mergedPolicy.Interface.Default != nil && e.mergedPolicy.Interface.Default.Inject != nil { + for _, ti := range e.mergedPolicy.Interface.Default.Inject.RequiredTypeInstances { + fmt.Println("Add a new TI in Default Injection in hubFilterForPolicyRule...") + filter.RequiredTypeInstancesInjectionSatisfiedBy = append(filter.RequiredTypeInstancesInjectionSatisfiedBy, &hubpublicgraphql.TypeInstanceValue{ + TypeRef: &hubpublicgraphql.TypeReferenceInput{ + Path: ti.TypeRef.Path, + Revision: ti.TypeRef.Revision, + }, + Value: nil, // not supported right now + }) + } + } + return filter } diff --git a/pkg/hub/client/policy_merger.go b/pkg/hub/client/policy_merger.go index 986a1737b..e5734705d 100644 --- a/pkg/hub/client/policy_merger.go +++ b/pkg/hub/client/policy_merger.go @@ -52,6 +52,13 @@ func applyInterfacePolicy(currentPolicy *policy.InterfacePolicy, newPolicy polic mergeRules(&ruleForInterface.OneOf[ruleIndex], newRule) } } + if newPolicy.Default != nil && newPolicy.Default.Inject != nil { + if currentPolicy.Default == nil || currentPolicy.Default.Inject == nil { + currentPolicy.Default = newPolicy.Default + } else { + currentPolicy.Default.Inject.RequiredTypeInstances = append(currentPolicy.Default.Inject.RequiredTypeInstances, newPolicy.Default.Inject.RequiredTypeInstances...) + } + } } func mergeRules(rule *policy.Rule, newRule policy.Rule) { From b8f49fb4933a6cb60afcb82c97da982dd654b1d1 Mon Sep 17 00:00:00 2001 From: Mateusz Kuziemko Date: Thu, 24 Feb 2022 11:51:14 +0100 Subject: [PATCH 3/9] Fixes --- .../graphql/domain/policy/converter.go | 4 +-- .../graphql/domain/policy/fixtures_test.go | 32 +++++++++++++++++++ .../k8s/policy/metadata/metadata_resolver.go | 20 +----------- pkg/engine/k8s/policy/types.go | 8 +++++ pkg/hub/client/policy_enforced_client.go | 15 ++------- 5 files changed, 46 insertions(+), 33 deletions(-) diff --git a/internal/k8s-engine/graphql/domain/policy/converter.go b/internal/k8s-engine/graphql/domain/policy/converter.go index 13bc7d19b..40cddb9f0 100644 --- a/internal/k8s-engine/graphql/domain/policy/converter.go +++ b/internal/k8s-engine/graphql/domain/policy/converter.go @@ -49,7 +49,7 @@ func (c *Converter) interfaceFromGraphQLInput(in *graphql.InterfacePolicyInput) }) } - if in.Default == nil || in.Default.Inject == nil || in.Default.Inject.RequiredTypeInstances == nil || len(in.Default.Inject.RequiredTypeInstances) == 0 { + if in.Default == nil || in.Default.Inject == nil { return policy.InterfacePolicy{ Rules: rules, }, nil @@ -130,7 +130,7 @@ func (c *Converter) interfaceToGraphQL(in policy.InterfacePolicy) *graphql.Inter }) } - if in.Default == nil || in.Default.Inject == nil || len(in.Default.Inject.RequiredTypeInstances) == 0 { + if in.DefaultRequiredTypeInstancesToInject() == nil { return &graphql.InterfacePolicy{ Rules: gqlRules, } diff --git a/internal/k8s-engine/graphql/domain/policy/fixtures_test.go b/internal/k8s-engine/graphql/domain/policy/fixtures_test.go index 86de2dbb3..7c50a3826 100644 --- a/internal/k8s-engine/graphql/domain/policy/fixtures_test.go +++ b/internal/k8s-engine/graphql/domain/policy/fixtures_test.go @@ -10,6 +10,16 @@ import ( func fixGQLInput() graphql.PolicyInput { return graphql.PolicyInput{ Interface: &graphql.InterfacePolicyInput{ + Default: &graphql.DefaultInterfaceInputData{ + Inject: &graphql.DefaultInjectInputData{ + RequiredTypeInstances: []*graphql.RequiredTypeInstanceReferenceInput{ + { + ID: "28806e5a-3b13-4d58-915b-8357a51c3e95", + Description: ptr.String("Sample description"), + }, + }, + }, + }, Rules: []*graphql.RulesForInterfaceInput{ { Interface: &graphql.ManifestReferenceInput{ @@ -110,6 +120,16 @@ func fixGQLInput() graphql.PolicyInput { func fixGQL() graphql.Policy { return graphql.Policy{ Interface: &graphql.InterfacePolicy{ + Default: &graphql.DefaultInterfaceData{ + Inject: &graphql.DefaultInjectData{ + RequiredTypeInstances: []*graphql.RequiredTypeInstanceReference{ + { + ID: "28806e5a-3b13-4d58-915b-8357a51c3e95", + Description: ptr.String("Sample description"), + }, + }, + }, + }, Rules: []*graphql.RulesForInterface{ { Interface: &graphql.ManifestReferenceWithOptionalRevision{ @@ -210,6 +230,18 @@ func fixGQL() graphql.Policy { func fixModel() policy.Policy { return policy.Policy{ Interface: policy.InterfacePolicy{ + Default: &policy.DefaultInterfaceData{ + Inject: &policy.DefaultInjectInterfaceData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "28806e5a-3b13-4d58-915b-8357a51c3e95", + Description: ptr.String("Sample description"), + }, + }, + }, + }, + }, Rules: policy.InterfaceRulesList{ { Interface: types.ManifestRefWithOptRevision{ diff --git a/pkg/engine/k8s/policy/metadata/metadata_resolver.go b/pkg/engine/k8s/policy/metadata/metadata_resolver.go index 1d4e3bbb9..47184677f 100644 --- a/pkg/engine/k8s/policy/metadata/metadata_resolver.go +++ b/pkg/engine/k8s/policy/metadata/metadata_resolver.go @@ -11,7 +11,6 @@ import ( hubpublicgraphql "capact.io/capact/pkg/hub/api/graphql/public" "capact.io/capact/pkg/hub/client/public" "capact.io/capact/pkg/sdk/apis/0.0.1/types" - "github.com/davecgh/go-spew/spew" multierr "github.com/hashicorp/go-multierror" "github.com/pkg/errors" @@ -54,31 +53,17 @@ func (r *Resolver) ResolveTypeInstanceMetadata(ctx context.Context, policy *poli return nil } - fmt.Println("idsToQuery") - spew.Dump(idsToQuery) - resolvedTypeRefs, err := r.hubCli.FindTypeInstancesTypeRef(ctx, idsToQuery) if err != nil { return errors.Wrap(err, "while finding TypeRef for TypeInstances") } - fmt.Println("resolvedTypeRefs") - spew.Dump(resolvedTypeRefs) - // verify if all TypeInstances are resolved multiErr := multierror.New() for _, ti := range unresolvedTIs { - fmt.Println("Checking ti", ti.ID) - if typeRef, exists := resolvedTypeRefs[ti.ID]; exists && typeRef.Path != "" && typeRef.Revision != "" { - fmt.Println("OK!!!!", typeRef.Path, typeRef.Revision) continue } - - fmt.Println("ERRORRRR!!!") - fmt.Println("resolvedTypeRefs!!!") - spew.Dump(resolvedTypeRefs) - multiErr = multierr.Append(multiErr, fmt.Errorf("missing Type reference for %s", ti.String(true))) } if multiErr.ErrorOrNil() != nil { @@ -131,9 +116,7 @@ func (r *Resolver) mapToTypeRefs(in map[string]hublocalgraphql.TypeInstanceTypeR } func (r *Resolver) setTypeRefsForDefaultTypeInstances(policy *policy.Policy, typeRefs map[string]TypeRefWithAdditionalRefs) { - fmt.Println("setTypeRefsForDefaultTypeInstances") - if policy.Interface.Default == nil || policy.Interface.Default.Inject == nil || len(policy.Interface.Default.Inject.RequiredTypeInstances) == 0 { - fmt.Println("empty policy.Interface.Default in setTypeRefsForDefaultTypeInstances") + if policy.Interface.Default == nil || policy.Interface.Default.Inject == nil { return } for reqTIIdx, reqTI := range policy.Interface.Default.Inject.RequiredTypeInstances { @@ -142,7 +125,6 @@ func (r *Resolver) setTypeRefsForDefaultTypeInstances(policy *policy.Policy, typ continue } - fmt.Println("Addding TypeRef for", policy.Interface.Default.Inject.RequiredTypeInstances[reqTIIdx]) policy.Interface.Default.Inject.RequiredTypeInstances[reqTIIdx].TypeRef = &types.TypeRef{ Path: typeRef.Path, Revision: typeRef.Revision, diff --git a/pkg/engine/k8s/policy/types.go b/pkg/engine/k8s/policy/types.go index ba8bcf4a1..d035fc11c 100644 --- a/pkg/engine/k8s/policy/types.go +++ b/pkg/engine/k8s/policy/types.go @@ -40,6 +40,14 @@ type InterfacePolicy struct { Rules InterfaceRulesList `json:"rules"` } +// DefaultRequiredTypeInstancesToInject returns default required TypeInstances to inject for a given interface. +func (in *InterfacePolicy) DefaultRequiredTypeInstancesToInject() []RequiredTypeInstanceToInject { + if in.Default == nil || in.Default.Inject == nil { + return nil + } + return in.Default.Inject.RequiredTypeInstances +} + type DefaultInterfaceData struct { Inject *DefaultInjectInterfaceData `json:"inject,omitempty"` } diff --git a/pkg/hub/client/policy_enforced_client.go b/pkg/hub/client/policy_enforced_client.go index 2e28d948c..306a91bc9 100644 --- a/pkg/hub/client/policy_enforced_client.go +++ b/pkg/hub/client/policy_enforced_client.go @@ -13,7 +13,6 @@ import ( "capact.io/capact/pkg/sdk/apis/0.0.1/types" "capact.io/capact/pkg/sdk/validation" - "github.com/davecgh/go-spew/spew" "github.com/pkg/errors" "sigs.k8s.io/yaml" ) @@ -102,10 +101,6 @@ func (e *PolicyEnforcedClient) ListImplementationRevisionForInterface(ctx contex return nil, policy.Rule{}, err } - fmt.Println("ListImplementationRevisionForInterface") - fmt.Println("found implementations", implementations) - spew.Dump(implementations) - return implementations, rule, nil } @@ -158,13 +153,9 @@ func (e *PolicyEnforcedClient) ListRequiredTypeInstancesToInjectBasedOnPolicy(po type requiredTypeInstanceToInject map[string]policy.RequiredTypeInstanceToInject func (e *PolicyEnforcedClient) listRequiredTypeInstancesToInjectBasedOnPolicy(policyRule policy.Rule, implRev hubpublicgraphql.ImplementationRevision) (requiredTypeInstanceToInject, error) { - requiredTIs := policyRule.RequiredTypeInstancesToInject() - - // inject Default RequiredTypeInstances - if e.mergedPolicy.Interface.Default != nil && e.mergedPolicy.Interface.Default.Inject != nil { - fmt.Println("inject Default RequiredTypeInstances") - requiredTIs = append(requiredTIs, e.mergedPolicy.Interface.Default.Inject.RequiredTypeInstances...) - } + var requiredTIs []policy.RequiredTypeInstanceToInject + requiredTIs = append(requiredTIs, policyRule.RequiredTypeInstancesToInject()...) + requiredTIs = append(requiredTIs, e.mergedPolicy.Interface.DefaultRequiredTypeInstancesToInject()...) if len(requiredTIs) == 0 { return nil, nil From 2e9f0cfe0d848f2cd8f31073e176935189fad21e Mon Sep 17 00:00:00 2001 From: Mateusz Kuziemko Date: Thu, 24 Feb 2022 13:16:36 +0100 Subject: [PATCH 4/9] refactor --- .../graphql/domain/action/fixtures_test.go | 2 +- .../graphql/domain/policy/converter.go | 8 +- .../graphql/domain/policy/fixtures_test.go | 12 +- pkg/engine/api/graphql/examples.graphql | 2 +- pkg/engine/api/graphql/models_gen.go | 20 +-- pkg/engine/api/graphql/policy.go | 4 +- pkg/engine/api/graphql/schema.graphql | 16 +-- pkg/engine/api/graphql/schema_gen.go | 122 ++++++++--------- .../k8s/policy/metadata/fixtures_test.go | 26 ++++ pkg/engine/k8s/policy/metadata/metadata.go | 40 +++--- .../k8s/policy/metadata/metadata_resolver.go | 2 +- .../policy/metadata/metadata_resolver_test.go | 4 +- pkg/engine/k8s/policy/types.go | 12 +- pkg/hub/client/policy_enforced_client.go | 32 ++--- pkg/hub/client/policy_merger.go | 22 ++-- pkg/hub/client/policy_merger_test.go | 124 +++++++++++++++++- test/e2e/action_test.go | 96 +++++++++++++- 17 files changed, 395 insertions(+), 149 deletions(-) diff --git a/internal/k8s-engine/graphql/domain/action/fixtures_test.go b/internal/k8s-engine/graphql/domain/action/fixtures_test.go index 818eab78c..01192c3f3 100644 --- a/internal/k8s-engine/graphql/domain/action/fixtures_test.go +++ b/internal/k8s-engine/graphql/domain/action/fixtures_test.go @@ -480,7 +480,7 @@ func fixModelInputSecret(name string, paramsEnabled, policyEnabled bool) *corev1 sec.StringData["parameter-input-parameters"] = `{"param":"one"}` } if policyEnabled { - sec.StringData["action-policy.json"] = `{"interface":{"rules":[{"interface":{"path":"cap.interface.dummy","revision":null},"oneOf":[{"implementationConstraints":{"requires":null,"attributes":null,"path":"cap.implementation.dummy"},"inject":{"requiredTypeInstances":[{"id":"policy-ti-id","description":"Sample description"}],"additionalParameters":[{"name":"additional-parameters","value":{"snapshot":true}}],"additionalTypeInstances":[{"name":"additional-ti","id":"additional-ti-id"}]}}]}]},"typeInstance":{"rules":[{"typeRef":{"path":"cap.type.aws.auth.credentials","revision":"0.1.0"},"backend":{"id":"00fd161c-01bd-47a6-9872-47490e11f996","description":"Vault TI"}},{"typeRef":{"path":"cap.type.aws.*","revision":null},"backend":{"id":"31bb8355-10d7-49ce-a739-4554d8a40b63","description":null}},{"typeRef":{"path":"cap.*","revision":null},"backend":{"id":"a36ed738-dfe7-45ec-acd1-8e44e8db893b","description":"Default Capact PostgreSQL backend"}}]}}` + sec.StringData["action-policy.json"] = `{"interface":{"default":null,"rules":[{"interface":{"path":"cap.interface.dummy","revision":null},"oneOf":[{"implementationConstraints":{"requires":null,"attributes":null,"path":"cap.implementation.dummy"},"inject":{"requiredTypeInstances":[{"id":"policy-ti-id","description":"Sample description"}],"additionalParameters":[{"name":"additional-parameters","value":{"snapshot":true}}],"additionalTypeInstances":[{"name":"additional-ti","id":"additional-ti-id"}]}}]}]},"typeInstance":{"rules":[{"typeRef":{"path":"cap.type.aws.auth.credentials","revision":"0.1.0"},"backend":{"id":"00fd161c-01bd-47a6-9872-47490e11f996","description":"Vault TI"}},{"typeRef":{"path":"cap.type.aws.*","revision":null},"backend":{"id":"31bb8355-10d7-49ce-a739-4554d8a40b63","description":null}},{"typeRef":{"path":"cap.*","revision":null},"backend":{"id":"a36ed738-dfe7-45ec-acd1-8e44e8db893b","description":"Default Capact PostgreSQL backend"}}]}}` } return sec diff --git a/internal/k8s-engine/graphql/domain/policy/converter.go b/internal/k8s-engine/graphql/domain/policy/converter.go index 40cddb9f0..8c5fe22f3 100644 --- a/internal/k8s-engine/graphql/domain/policy/converter.go +++ b/internal/k8s-engine/graphql/domain/policy/converter.go @@ -56,8 +56,8 @@ func (c *Converter) interfaceFromGraphQLInput(in *graphql.InterfacePolicyInput) } return policy.InterfacePolicy{ - Default: &policy.DefaultInterfaceData{ - Inject: &policy.DefaultInjectInterfaceData{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ RequiredTypeInstances: c.requiredTypeInstancesToInjectFromGraphQLInput(in.Default.Inject.RequiredTypeInstances), }, }, @@ -137,8 +137,8 @@ func (c *Converter) interfaceToGraphQL(in policy.InterfacePolicy) *graphql.Inter } return &graphql.InterfacePolicy{ - Default: &graphql.DefaultInterfaceData{ - Inject: &graphql.DefaultInjectData{ + Default: &graphql.DefaultForInterface{ + Inject: &graphql.DefaultInjectForInterface{ RequiredTypeInstances: c.requiredTypeInstancesToInjectToGraphQL(in.Default.Inject.RequiredTypeInstances), }, }, diff --git a/internal/k8s-engine/graphql/domain/policy/fixtures_test.go b/internal/k8s-engine/graphql/domain/policy/fixtures_test.go index 7c50a3826..71d57e0eb 100644 --- a/internal/k8s-engine/graphql/domain/policy/fixtures_test.go +++ b/internal/k8s-engine/graphql/domain/policy/fixtures_test.go @@ -10,8 +10,8 @@ import ( func fixGQLInput() graphql.PolicyInput { return graphql.PolicyInput{ Interface: &graphql.InterfacePolicyInput{ - Default: &graphql.DefaultInterfaceInputData{ - Inject: &graphql.DefaultInjectInputData{ + Default: &graphql.DefaultForInterfaceInput{ + Inject: &graphql.DefaultInjectForInterfaceInput{ RequiredTypeInstances: []*graphql.RequiredTypeInstanceReferenceInput{ { ID: "28806e5a-3b13-4d58-915b-8357a51c3e95", @@ -120,8 +120,8 @@ func fixGQLInput() graphql.PolicyInput { func fixGQL() graphql.Policy { return graphql.Policy{ Interface: &graphql.InterfacePolicy{ - Default: &graphql.DefaultInterfaceData{ - Inject: &graphql.DefaultInjectData{ + Default: &graphql.DefaultForInterface{ + Inject: &graphql.DefaultInjectForInterface{ RequiredTypeInstances: []*graphql.RequiredTypeInstanceReference{ { ID: "28806e5a-3b13-4d58-915b-8357a51c3e95", @@ -230,8 +230,8 @@ func fixGQL() graphql.Policy { func fixModel() policy.Policy { return policy.Policy{ Interface: policy.InterfacePolicy{ - Default: &policy.DefaultInterfaceData{ - Inject: &policy.DefaultInjectInterfaceData{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ { TypeInstanceReference: policy.TypeInstanceReference{ diff --git a/pkg/engine/api/graphql/examples.graphql b/pkg/engine/api/graphql/examples.graphql index 8ca4a4a78..868c985f1 100644 --- a/pkg/engine/api/graphql/examples.graphql +++ b/pkg/engine/api/graphql/examples.graphql @@ -170,7 +170,7 @@ mutation UpdatePolicy { inject: { requiredTypeInstances: [ { - id: "edf854df-86cf-4855-9d38-8d88545fb9c9" + id: "28806e5a-3b13-4d58-915b-8357a51c3e95" description: "My TypeInstance" } ] diff --git a/pkg/engine/api/graphql/models_gen.go b/pkg/engine/api/graphql/models_gen.go index 7b80f09c2..79cc93a8d 100644 --- a/pkg/engine/api/graphql/models_gen.go +++ b/pkg/engine/api/graphql/models_gen.go @@ -119,20 +119,20 @@ type AdvancedModeContinueRenderingInput struct { TypeInstances []*InputTypeInstanceData `json:"typeInstances"` } -type DefaultInjectData struct { - RequiredTypeInstances []*RequiredTypeInstanceReference `json:"requiredTypeInstances"` +type DefaultForInterface struct { + Inject *DefaultInjectForInterface `json:"inject"` } -type DefaultInjectInputData struct { - RequiredTypeInstances []*RequiredTypeInstanceReferenceInput `json:"requiredTypeInstances"` +type DefaultForInterfaceInput struct { + Inject *DefaultInjectForInterfaceInput `json:"inject"` } -type DefaultInterfaceData struct { - Inject *DefaultInjectData `json:"inject"` +type DefaultInjectForInterface struct { + RequiredTypeInstances []*RequiredTypeInstanceReference `json:"requiredTypeInstances"` } -type DefaultInterfaceInputData struct { - Inject *DefaultInjectInputData `json:"inject"` +type DefaultInjectForInterfaceInput struct { + RequiredTypeInstances []*RequiredTypeInstanceReferenceInput `json:"requiredTypeInstances"` } // Client input for Input TypeInstance @@ -154,8 +154,8 @@ type InputTypeInstanceToProvide struct { } type InterfacePolicyInput struct { - Default *DefaultInterfaceInputData `json:"default"` - Rules []*RulesForInterfaceInput `json:"rules"` + Default *DefaultForInterfaceInput `json:"default"` + Rules []*RulesForInterfaceInput `json:"rules"` } type ManifestReference struct { diff --git a/pkg/engine/api/graphql/policy.go b/pkg/engine/api/graphql/policy.go index ef5085408..45a58d3d1 100644 --- a/pkg/engine/api/graphql/policy.go +++ b/pkg/engine/api/graphql/policy.go @@ -4,8 +4,8 @@ package graphql //InterfacePolicy represents Interface Policy. type InterfacePolicy struct { - Default *DefaultInterfaceData `json:"default,omitempty"` - Rules []*RulesForInterface `json:"rules"` + Default *DefaultForInterface `json:"default,omitempty"` + Rules []*RulesForInterface `json:"rules"` } // PolicyRule represents a single policy rule. diff --git a/pkg/engine/api/graphql/schema.graphql b/pkg/engine/api/graphql/schema.graphql index 9c0799896..8175ef999 100644 --- a/pkg/engine/api/graphql/schema.graphql +++ b/pkg/engine/api/graphql/schema.graphql @@ -330,15 +330,15 @@ input TypeInstanceBackendRuleInput { # Interface Policy Input input InterfacePolicyInput { - default: DefaultInterfaceInputData + default: DefaultForInterfaceInput rules: [RulesForInterfaceInput!]! } -input DefaultInterfaceInputData { - inject: DefaultInjectInputData +input DefaultForInterfaceInput { + inject: DefaultInjectForInterfaceInput } -input DefaultInjectInputData{ +input DefaultInjectForInterfaceInput{ requiredTypeInstances: [RequiredTypeInstanceReferenceInput!] } @@ -402,15 +402,15 @@ type TypeInstanceBackendRule { # Interface Policy type InterfacePolicy { - default: DefaultInterfaceData + default: DefaultForInterface rules: [RulesForInterface!]! } -type DefaultInterfaceData { - inject: DefaultInjectData +type DefaultForInterface { + inject: DefaultInjectForInterface } -type DefaultInjectData { +type DefaultInjectForInterface { requiredTypeInstances: [RequiredTypeInstanceReference!] } diff --git a/pkg/engine/api/graphql/schema_gen.go b/pkg/engine/api/graphql/schema_gen.go index 63ba45e0b..f8615077d 100644 --- a/pkg/engine/api/graphql/schema_gen.go +++ b/pkg/engine/api/graphql/schema_gen.go @@ -92,12 +92,12 @@ type ComplexityRoot struct { Name func(childComplexity int) int } - DefaultInjectData struct { - RequiredTypeInstances func(childComplexity int) int + DefaultForInterface struct { + Inject func(childComplexity int) int } - DefaultInterfaceData struct { - Inject func(childComplexity int) int + DefaultInjectForInterface struct { + RequiredTypeInstances func(childComplexity int) int } InputTypeInstanceDetails struct { @@ -442,19 +442,19 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.AdditionalTypeInstanceReference.Name(childComplexity), true - case "DefaultInjectData.requiredTypeInstances": - if e.complexity.DefaultInjectData.RequiredTypeInstances == nil { + case "DefaultForInterface.inject": + if e.complexity.DefaultForInterface.Inject == nil { break } - return e.complexity.DefaultInjectData.RequiredTypeInstances(childComplexity), true + return e.complexity.DefaultForInterface.Inject(childComplexity), true - case "DefaultInterfaceData.inject": - if e.complexity.DefaultInterfaceData.Inject == nil { + case "DefaultInjectForInterface.requiredTypeInstances": + if e.complexity.DefaultInjectForInterface.RequiredTypeInstances == nil { break } - return e.complexity.DefaultInterfaceData.Inject(childComplexity), true + return e.complexity.DefaultInjectForInterface.RequiredTypeInstances(childComplexity), true case "InputTypeInstanceDetails.id": if e.complexity.InputTypeInstanceDetails.ID == nil { @@ -1233,15 +1233,15 @@ input TypeInstanceBackendRuleInput { # Interface Policy Input input InterfacePolicyInput { - default: DefaultInterfaceInputData + default: DefaultForInterfaceInput rules: [RulesForInterfaceInput!]! } -input DefaultInterfaceInputData { - inject: DefaultInjectInputData +input DefaultForInterfaceInput { + inject: DefaultInjectForInterfaceInput } -input DefaultInjectInputData{ +input DefaultInjectForInterfaceInput{ requiredTypeInstances: [RequiredTypeInstanceReferenceInput!] } @@ -1305,15 +1305,15 @@ type TypeInstanceBackendRule { # Interface Policy type InterfacePolicy { - default: DefaultInterfaceData + default: DefaultForInterface rules: [RulesForInterface!]! } -type DefaultInterfaceData { - inject: DefaultInjectData +type DefaultForInterface { + inject: DefaultInjectForInterface } -type DefaultInjectData { +type DefaultInjectForInterface { requiredTypeInstances: [RequiredTypeInstanceReference!] } @@ -2574,7 +2574,7 @@ func (ec *executionContext) _AdditionalTypeInstanceReference_id(ctx context.Cont return ec.marshalNID2string(ctx, field.Selections, res) } -func (ec *executionContext) _DefaultInjectData_requiredTypeInstances(ctx context.Context, field graphql.CollectedField, obj *DefaultInjectData) (ret graphql.Marshaler) { +func (ec *executionContext) _DefaultForInterface_inject(ctx context.Context, field graphql.CollectedField, obj *DefaultForInterface) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2582,7 +2582,7 @@ func (ec *executionContext) _DefaultInjectData_requiredTypeInstances(ctx context } }() fc := &graphql.FieldContext{ - Object: "DefaultInjectData", + Object: "DefaultForInterface", Field: field, Args: nil, IsMethod: false, @@ -2592,7 +2592,7 @@ func (ec *executionContext) _DefaultInjectData_requiredTypeInstances(ctx context ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.RequiredTypeInstances, nil + return obj.Inject, nil }) if err != nil { ec.Error(ctx, err) @@ -2601,12 +2601,12 @@ func (ec *executionContext) _DefaultInjectData_requiredTypeInstances(ctx context if resTmp == nil { return graphql.Null } - res := resTmp.([]*RequiredTypeInstanceReference) + res := resTmp.(*DefaultInjectForInterface) fc.Result = res - return ec.marshalORequiredTypeInstanceReference2ᚕᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐRequiredTypeInstanceReferenceᚄ(ctx, field.Selections, res) + return ec.marshalODefaultInjectForInterface2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInjectForInterface(ctx, field.Selections, res) } -func (ec *executionContext) _DefaultInterfaceData_inject(ctx context.Context, field graphql.CollectedField, obj *DefaultInterfaceData) (ret graphql.Marshaler) { +func (ec *executionContext) _DefaultInjectForInterface_requiredTypeInstances(ctx context.Context, field graphql.CollectedField, obj *DefaultInjectForInterface) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2614,7 +2614,7 @@ func (ec *executionContext) _DefaultInterfaceData_inject(ctx context.Context, fi } }() fc := &graphql.FieldContext{ - Object: "DefaultInterfaceData", + Object: "DefaultInjectForInterface", Field: field, Args: nil, IsMethod: false, @@ -2624,7 +2624,7 @@ func (ec *executionContext) _DefaultInterfaceData_inject(ctx context.Context, fi ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Inject, nil + return obj.RequiredTypeInstances, nil }) if err != nil { ec.Error(ctx, err) @@ -2633,9 +2633,9 @@ func (ec *executionContext) _DefaultInterfaceData_inject(ctx context.Context, fi if resTmp == nil { return graphql.Null } - res := resTmp.(*DefaultInjectData) + res := resTmp.([]*RequiredTypeInstanceReference) fc.Result = res - return ec.marshalODefaultInjectData2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInjectData(ctx, field.Selections, res) + return ec.marshalORequiredTypeInstanceReference2ᚕᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐRequiredTypeInstanceReferenceᚄ(ctx, field.Selections, res) } func (ec *executionContext) _InputTypeInstanceDetails_id(ctx context.Context, field graphql.CollectedField, obj *InputTypeInstanceDetails) (ret graphql.Marshaler) { @@ -2805,9 +2805,9 @@ func (ec *executionContext) _InterfacePolicy_default(ctx context.Context, field if resTmp == nil { return graphql.Null } - res := resTmp.(*DefaultInterfaceData) + res := resTmp.(*DefaultForInterface) fc.Result = res - return ec.marshalODefaultInterfaceData2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInterfaceData(ctx, field.Selections, res) + return ec.marshalODefaultForInterface2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultForInterface(ctx, field.Selections, res) } func (ec *executionContext) _InterfacePolicy_rules(ctx context.Context, field graphql.CollectedField, obj *InterfacePolicy) (ret graphql.Marshaler) { @@ -5696,17 +5696,17 @@ func (ec *executionContext) unmarshalInputAdvancedModeContinueRenderingInput(ctx return it, nil } -func (ec *executionContext) unmarshalInputDefaultInjectInputData(ctx context.Context, obj interface{}) (DefaultInjectInputData, error) { - var it DefaultInjectInputData +func (ec *executionContext) unmarshalInputDefaultForInterfaceInput(ctx context.Context, obj interface{}) (DefaultForInterfaceInput, error) { + var it DefaultForInterfaceInput var asMap = obj.(map[string]interface{}) for k, v := range asMap { switch k { - case "requiredTypeInstances": + case "inject": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("requiredTypeInstances")) - it.RequiredTypeInstances, err = ec.unmarshalORequiredTypeInstanceReferenceInput2ᚕᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐRequiredTypeInstanceReferenceInputᚄ(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("inject")) + it.Inject, err = ec.unmarshalODefaultInjectForInterfaceInput2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInjectForInterfaceInput(ctx, v) if err != nil { return it, err } @@ -5716,17 +5716,17 @@ func (ec *executionContext) unmarshalInputDefaultInjectInputData(ctx context.Con return it, nil } -func (ec *executionContext) unmarshalInputDefaultInterfaceInputData(ctx context.Context, obj interface{}) (DefaultInterfaceInputData, error) { - var it DefaultInterfaceInputData +func (ec *executionContext) unmarshalInputDefaultInjectForInterfaceInput(ctx context.Context, obj interface{}) (DefaultInjectForInterfaceInput, error) { + var it DefaultInjectForInterfaceInput var asMap = obj.(map[string]interface{}) for k, v := range asMap { switch k { - case "inject": + case "requiredTypeInstances": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("inject")) - it.Inject, err = ec.unmarshalODefaultInjectInputData2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInjectInputData(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("requiredTypeInstances")) + it.RequiredTypeInstances, err = ec.unmarshalORequiredTypeInstanceReferenceInput2ᚕᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐRequiredTypeInstanceReferenceInputᚄ(ctx, v) if err != nil { return it, err } @@ -5774,7 +5774,7 @@ func (ec *executionContext) unmarshalInputInterfacePolicyInput(ctx context.Conte var err error ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("default")) - it.Default, err = ec.unmarshalODefaultInterfaceInputData2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInterfaceInputData(ctx, v) + it.Default, err = ec.unmarshalODefaultForInterfaceInput2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultForInterfaceInput(ctx, v) if err != nil { return it, err } @@ -6348,19 +6348,19 @@ func (ec *executionContext) _AdditionalTypeInstanceReference(ctx context.Context return out } -var defaultInjectDataImplementors = []string{"DefaultInjectData"} +var defaultForInterfaceImplementors = []string{"DefaultForInterface"} -func (ec *executionContext) _DefaultInjectData(ctx context.Context, sel ast.SelectionSet, obj *DefaultInjectData) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, defaultInjectDataImplementors) +func (ec *executionContext) _DefaultForInterface(ctx context.Context, sel ast.SelectionSet, obj *DefaultForInterface) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, defaultForInterfaceImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("DefaultInjectData") - case "requiredTypeInstances": - out.Values[i] = ec._DefaultInjectData_requiredTypeInstances(ctx, field, obj) + out.Values[i] = graphql.MarshalString("DefaultForInterface") + case "inject": + out.Values[i] = ec._DefaultForInterface_inject(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -6372,19 +6372,19 @@ func (ec *executionContext) _DefaultInjectData(ctx context.Context, sel ast.Sele return out } -var defaultInterfaceDataImplementors = []string{"DefaultInterfaceData"} +var defaultInjectForInterfaceImplementors = []string{"DefaultInjectForInterface"} -func (ec *executionContext) _DefaultInterfaceData(ctx context.Context, sel ast.SelectionSet, obj *DefaultInterfaceData) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, defaultInterfaceDataImplementors) +func (ec *executionContext) _DefaultInjectForInterface(ctx context.Context, sel ast.SelectionSet, obj *DefaultInjectForInterface) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, defaultInjectForInterfaceImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("DefaultInterfaceData") - case "inject": - out.Values[i] = ec._DefaultInterfaceData_inject(ctx, field, obj) + out.Values[i] = graphql.MarshalString("DefaultInjectForInterface") + case "requiredTypeInstances": + out.Values[i] = ec._DefaultInjectForInterface_requiredTypeInstances(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -8466,33 +8466,33 @@ func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast return graphql.MarshalBoolean(*v) } -func (ec *executionContext) marshalODefaultInjectData2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInjectData(ctx context.Context, sel ast.SelectionSet, v *DefaultInjectData) graphql.Marshaler { +func (ec *executionContext) marshalODefaultForInterface2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultForInterface(ctx context.Context, sel ast.SelectionSet, v *DefaultForInterface) graphql.Marshaler { if v == nil { return graphql.Null } - return ec._DefaultInjectData(ctx, sel, v) + return ec._DefaultForInterface(ctx, sel, v) } -func (ec *executionContext) unmarshalODefaultInjectInputData2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInjectInputData(ctx context.Context, v interface{}) (*DefaultInjectInputData, error) { +func (ec *executionContext) unmarshalODefaultForInterfaceInput2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultForInterfaceInput(ctx context.Context, v interface{}) (*DefaultForInterfaceInput, error) { if v == nil { return nil, nil } - res, err := ec.unmarshalInputDefaultInjectInputData(ctx, v) + res, err := ec.unmarshalInputDefaultForInterfaceInput(ctx, v) return &res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalODefaultInterfaceData2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInterfaceData(ctx context.Context, sel ast.SelectionSet, v *DefaultInterfaceData) graphql.Marshaler { +func (ec *executionContext) marshalODefaultInjectForInterface2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInjectForInterface(ctx context.Context, sel ast.SelectionSet, v *DefaultInjectForInterface) graphql.Marshaler { if v == nil { return graphql.Null } - return ec._DefaultInterfaceData(ctx, sel, v) + return ec._DefaultInjectForInterface(ctx, sel, v) } -func (ec *executionContext) unmarshalODefaultInterfaceInputData2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInterfaceInputData(ctx context.Context, v interface{}) (*DefaultInterfaceInputData, error) { +func (ec *executionContext) unmarshalODefaultInjectForInterfaceInput2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐDefaultInjectForInterfaceInput(ctx context.Context, v interface{}) (*DefaultInjectForInterfaceInput, error) { if v == nil { return nil, nil } - res, err := ec.unmarshalInputDefaultInterfaceInputData(ctx, v) + res, err := ec.unmarshalInputDefaultInjectForInterfaceInput(ctx, v) return &res, graphql.ErrorOnPath(ctx, err) } diff --git a/pkg/engine/k8s/policy/metadata/fixtures_test.go b/pkg/engine/k8s/policy/metadata/fixtures_test.go index da34d40a7..d47f87e38 100644 --- a/pkg/engine/k8s/policy/metadata/fixtures_test.go +++ b/pkg/engine/k8s/policy/metadata/fixtures_test.go @@ -19,6 +19,17 @@ import ( func fixComplexPolicyWithoutTypeRef() *policy.Policy { return &policy.Policy{ Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "id12", + }, + }, + }, + }, + }, Rules: policy.InterfaceRulesList{ { Interface: types.ManifestRefWithOptRevision{ @@ -157,6 +168,21 @@ func fixComplexPolicyWithoutTypeRef() *policy.Policy { func fixComplexPolicyWithTypeRef() *policy.Policy { return &policy.Policy{ Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "id12", + TypeRef: &types.TypeRef{ + Path: "cap.type.type12", + Revision: "0.12.0", + }, + }, + }, + }, + }, + }, Rules: policy.InterfaceRulesList{ { Interface: types.ManifestRefWithOptRevision{ diff --git a/pkg/engine/k8s/policy/metadata/metadata.go b/pkg/engine/k8s/policy/metadata/metadata.go index fd6d6c235..cf39fa048 100644 --- a/pkg/engine/k8s/policy/metadata/metadata.go +++ b/pkg/engine/k8s/policy/metadata/metadata.go @@ -50,28 +50,15 @@ func (m TypeInstanceMetadata) String(withKind bool) string { func TypeInstanceIDsWithUnresolvedMetadataForPolicy(in policy.Policy) []TypeInstanceMetadata { var tis []TypeInstanceMetadata - // Interface + // Interface rules for _, rule := range in.Interface.Rules { for _, ruleItem := range rule.OneOf { tis = append(tis, TypeInstanceIDsWithUnresolvedMetadataForRule(ruleItem)...) } } - // Interface Defaults - fmt.Println("TypeInstanceIDsWithUnresolvedMetadataForPolicy") - if in.Interface.Default != nil && in.Interface.Default.Inject != nil { - for _, defaultTI := range in.Interface.Default.Inject.RequiredTypeInstances { - fmt.Println("Adding ID", defaultTI.ID) - if defaultTI.TypeRef != nil && defaultTI.TypeRef.Path != "" && defaultTI.TypeRef.Revision != "" { - continue - } - tis = append(tis, TypeInstanceMetadata{ - ID: defaultTI.ID, - Description: defaultTI.Description, - Kind: defaultTypeInstance, - }) - } - } + // Interface default + tis = append(tis, TypeInstanceIDsWithUnresolvedMetadataForDefault(in.Interface.Default)...) // TypeInstances backends for _, rule := range in.TypeInstance.Rules { @@ -89,6 +76,27 @@ func TypeInstanceIDsWithUnresolvedMetadataForPolicy(in policy.Policy) []TypeInst return tis } +// TypeInstanceIDsWithUnresolvedMetadataForDefault filters TypeInstances that have unresolved metadata for a given Interface default. +func TypeInstanceIDsWithUnresolvedMetadataForDefault(in *policy.InterfaceDefault) []TypeInstanceMetadata { + if in == nil || in.Inject == nil { + return nil + } + + var tis []TypeInstanceMetadata + for _, defaultTI := range in.Inject.RequiredTypeInstances { + if defaultTI.TypeRef != nil && defaultTI.TypeRef.Path != "" && defaultTI.TypeRef.Revision != "" { + continue + } + tis = append(tis, TypeInstanceMetadata{ + ID: defaultTI.ID, + Description: defaultTI.Description, + Kind: defaultTypeInstance, + }) + } + + return tis +} + // TypeInstanceIDsWithUnresolvedMetadataForRule filters TypeInstances that have unresolved metadata for a given rule. func TypeInstanceIDsWithUnresolvedMetadataForRule(in policy.Rule) []TypeInstanceMetadata { if in.Inject == nil { diff --git a/pkg/engine/k8s/policy/metadata/metadata_resolver.go b/pkg/engine/k8s/policy/metadata/metadata_resolver.go index 47184677f..9f7ca39bf 100644 --- a/pkg/engine/k8s/policy/metadata/metadata_resolver.go +++ b/pkg/engine/k8s/policy/metadata/metadata_resolver.go @@ -75,9 +75,9 @@ func (r *Resolver) ResolveTypeInstanceMetadata(ctx context.Context, policy *poli return errors.Wrap(err, "while resolving parent nodes for TypeRefs") } - r.setTypeRefsForDefaultTypeInstances(policy, typeRefWithParentNodes) r.setTypeRefsForAdditionalTypeInstances(policy, typeRefWithParentNodes) r.setTypeRefsForRequiredTypeInstances(policy, typeRefWithParentNodes) + r.setTypeRefsForDefaultTypeInstances(policy, typeRefWithParentNodes) r.setTypeRefsForBackendTypeInstances(policy, typeRefWithParentNodes) return nil diff --git a/pkg/engine/k8s/policy/metadata/metadata_resolver_test.go b/pkg/engine/k8s/policy/metadata/metadata_resolver_test.go index 9d012bf5d..4650bfc2e 100644 --- a/pkg/engine/k8s/policy/metadata/metadata_resolver_test.go +++ b/pkg/engine/k8s/policy/metadata/metadata_resolver_test.go @@ -37,13 +37,13 @@ func TestResolveTypeInstanceMetadata(t *testing.T) { { Name: "Unresolved TypeRefs", Input: fixComplexPolicyWithoutTypeRef(), - HubCli: &fakeHub{ShouldRun: true, ExpectedIDLen: 12}, + HubCli: &fakeHub{ShouldRun: true, ExpectedIDLen: 13}, Expected: fixComplexPolicyWithTypeRef(), }, { Name: "Partial result", Input: fixComplexPolicyWithoutTypeRef(), - HubCli: &fakeHub{ShouldRun: true, ExpectedIDLen: 12, IgnoreIDs: map[string]struct{}{ + HubCli: &fakeHub{ShouldRun: true, ExpectedIDLen: 13, IgnoreIDs: map[string]struct{}{ "id2": {}, "id4": {}, // required "id8": {}, // additional "id9": {}, "id11": {}, // backend diff --git a/pkg/engine/k8s/policy/types.go b/pkg/engine/k8s/policy/types.go index d035fc11c..e2fd6961a 100644 --- a/pkg/engine/k8s/policy/types.go +++ b/pkg/engine/k8s/policy/types.go @@ -36,8 +36,8 @@ type Policy struct { // InterfacePolicy holds the Policy for Interfaces. type InterfacePolicy struct { - Default *DefaultInterfaceData `json:"default,omitempty"` - Rules InterfaceRulesList `json:"rules"` + Default *InterfaceDefault `json:"default,omitempty"` + Rules InterfaceRulesList `json:"rules"` } // DefaultRequiredTypeInstancesToInject returns default required TypeInstances to inject for a given interface. @@ -48,11 +48,13 @@ func (in *InterfacePolicy) DefaultRequiredTypeInstancesToInject() []RequiredType return in.Default.Inject.RequiredTypeInstances } -type DefaultInterfaceData struct { - Inject *DefaultInjectInterfaceData `json:"inject,omitempty"` +// InterfaceDefault holds a defaults for the Interface Policy. +type InterfaceDefault struct { + Inject *DefaultInject `json:"inject,omitempty"` } -type DefaultInjectInterfaceData struct { +//DefaultInject holds default injection for the Interface Policy. +type DefaultInject struct { RequiredTypeInstances []RequiredTypeInstanceToInject `json:"requiredTypeInstances,omitempty"` } diff --git a/pkg/hub/client/policy_enforced_client.go b/pkg/hub/client/policy_enforced_client.go index 306a91bc9..319feb51d 100644 --- a/pkg/hub/client/policy_enforced_client.go +++ b/pkg/hub/client/policy_enforced_client.go @@ -113,11 +113,7 @@ func (e *PolicyEnforcedClient) ListTypeInstancesBackendsBasedOnPolicy(_ context. out.SetByTypeRef(rule.TypeRef, rule.Backend) } - // TODO(https://github.com/capactio/capact/issues/635): - // 2. Global defaults based on required TypeInstance injection - // e.mergedPolicy.Interface.Defaults - - //3. Override defaults with specific Interface Policy rule + //2. Override defaults with specific Interface Policy rule inject, err := e.listRequiredTypeInstancesToInjectBasedOnPolicy(rule, implRev) if err != nil { return policy.TypeInstanceBackendCollection{}, err @@ -448,21 +444,19 @@ func (e *PolicyEnforcedClient) hubFilterForPolicyRule(rule policy.Rule, allTypeI filter.RequiredTypeInstancesInjectionSatisfiedBy = injectedRequiredTypeInstances } - fmt.Println("Default Injection in hubFilterForPolicyRule") - - // Default Injection - if e.mergedPolicy.Interface.Default != nil && e.mergedPolicy.Interface.Default.Inject != nil { - for _, ti := range e.mergedPolicy.Interface.Default.Inject.RequiredTypeInstances { - fmt.Println("Add a new TI in Default Injection in hubFilterForPolicyRule...") - filter.RequiredTypeInstancesInjectionSatisfiedBy = append(filter.RequiredTypeInstancesInjectionSatisfiedBy, &hubpublicgraphql.TypeInstanceValue{ - TypeRef: &hubpublicgraphql.TypeReferenceInput{ - Path: ti.TypeRef.Path, - Revision: ti.TypeRef.Revision, - }, - Value: nil, // not supported right now - }) - } + // Append TypeInstance from Interface Default + defaultTI := e.mergedPolicy.Interface.DefaultRequiredTypeInstancesToInject() + var injectedDefaultRequiredTypeInstances []*hubpublicgraphql.TypeInstanceValue + for _, ti := range defaultTI { + injectedDefaultRequiredTypeInstances = append(injectedDefaultRequiredTypeInstances, &hubpublicgraphql.TypeInstanceValue{ + TypeRef: &hubpublicgraphql.TypeReferenceInput{ + Path: ti.TypeRef.Path, + Revision: ti.TypeRef.Revision, + }, + Value: nil, // not supported right now + }) } + filter.RequiredTypeInstancesInjectionSatisfiedBy = append(filter.RequiredTypeInstancesInjectionSatisfiedBy, injectedDefaultRequiredTypeInstances...) return filter } diff --git a/pkg/hub/client/policy_merger.go b/pkg/hub/client/policy_merger.go index e5734705d..e157c35c9 100644 --- a/pkg/hub/client/policy_merger.go +++ b/pkg/hub/client/policy_merger.go @@ -30,10 +30,19 @@ func (e *PolicyEnforcedClient) mergePolicies() { e.mergedPolicy = currentPolicy } -// from new policy we are checking if there are the same rules. If yes we fill missing data, -// if not we add a rule to the end -// current policy is a higher priority policy func applyInterfacePolicy(currentPolicy *policy.InterfacePolicy, newPolicy policy.InterfacePolicy) { + // Default + if newPolicy.Default != nil && newPolicy.Default.Inject != nil { + if currentPolicy.Default == nil || currentPolicy.Default.Inject == nil { + currentPolicy.Default = newPolicy.Default + } else { + currentPolicy.Default.Inject.RequiredTypeInstances = mergeRequiredTypeInstances(currentPolicy.Default.Inject.RequiredTypeInstances, newPolicy.Default.Inject.RequiredTypeInstances) + } + } + + // from new policy we are checking if there are the same rules. If yes we fill missing data, + // if not we add a rule to the end + // current policy is a higher priority policy for _, newRuleForInterface := range newPolicy.Rules { policyRuleIndex := getIndexOfInterfacePolicyRule(currentPolicy, newRuleForInterface) if policyRuleIndex == -1 { @@ -52,13 +61,6 @@ func applyInterfacePolicy(currentPolicy *policy.InterfacePolicy, newPolicy polic mergeRules(&ruleForInterface.OneOf[ruleIndex], newRule) } } - if newPolicy.Default != nil && newPolicy.Default.Inject != nil { - if currentPolicy.Default == nil || currentPolicy.Default.Inject == nil { - currentPolicy.Default = newPolicy.Default - } else { - currentPolicy.Default.Inject.RequiredTypeInstances = append(currentPolicy.Default.Inject.RequiredTypeInstances, newPolicy.Default.Inject.RequiredTypeInstances...) - } - } } func mergeRules(rule *policy.Rule, newRule policy.Rule) { diff --git a/pkg/hub/client/policy_merger_test.go b/pkg/hub/client/policy_merger_test.go index 51d0b7def..eba76faad 100644 --- a/pkg/hub/client/policy_merger_test.go +++ b/pkg/hub/client/policy_merger_test.go @@ -28,6 +28,22 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { name: "only global policy", global: policy.Policy{ Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1234-123-123", + Description: ptr.String("Sample TI"), + TypeRef: &types.TypeRef{ + Path: "cap.type.aws.auth.credentials", + Revision: "0.1.0", + }, + }, + }, + }, + }, + }, Rules: policy.InterfaceRulesList{ policy.RulesForInterface{ Interface: types.ManifestRefWithOptRevision{ @@ -83,6 +99,22 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { action: policy.ActionPolicy{}, expected: policy.Policy{ Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1234-123-123", + Description: ptr.String("Sample TI"), + TypeRef: &types.TypeRef{ + Path: "cap.type.aws.auth.credentials", + Revision: "0.1.0", + }, + }, + }, + }, + }, + }, Rules: policy.InterfaceRulesList{ policy.RulesForInterface{ Interface: types.ManifestRefWithOptRevision{ @@ -141,6 +173,22 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { name: "only action policy", action: policy.ActionPolicy{ Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1234-123-123", + Description: ptr.String("Sample TI"), + TypeRef: &types.TypeRef{ + Path: "cap.type.aws.auth.credentials", + Revision: "0.1.0", + }, + }, + }, + }, + }, + }, Rules: policy.InterfaceRulesList{ policy.RulesForInterface{ Interface: types.ManifestRefWithOptRevision{ @@ -195,6 +243,22 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { global: policy.Policy{}, expected: policy.Policy{ Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1234-123-123", + Description: ptr.String("Sample TI"), + TypeRef: &types.TypeRef{ + Path: "cap.type.aws.auth.credentials", + Revision: "0.1.0", + }, + }, + }, + }, + }, + }, Rules: policy.InterfaceRulesList{ policy.RulesForInterface{ Interface: types.ManifestRefWithOptRevision{ @@ -496,9 +560,25 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { order: policy.MergeOrder{policy.Action, policy.Global}, }, { - name: "merge type instances and additional input", + name: "merge type instances and additional input for default and rule", action: policy.ActionPolicy{ Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1234-123-123", + Description: ptr.String("Sample TI"), + TypeRef: &types.TypeRef{ + Path: "cap.type.a", + Revision: "0.1.0", + }, + }, + }, + }, + }, + }, Rules: policy.InterfaceRulesList{ policy.RulesForInterface{ Interface: types.ManifestRefWithOptRevision{ @@ -552,6 +632,22 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { }, global: policy.Policy{ Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1111-2222-3333", + Description: ptr.String("Sample TI"), + TypeRef: &types.TypeRef{ + Path: "cap.type.b", + Revision: "0.1.0", + }, + }, + }, + }, + }, + }, Rules: policy.InterfaceRulesList{ policy.RulesForInterface{ Interface: types.ManifestRefWithOptRevision{ @@ -595,6 +691,32 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { }, expected: policy.Policy{ Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1234-123-123", + Description: ptr.String("Sample TI"), + TypeRef: &types.TypeRef{ + Path: "cap.type.a", + Revision: "0.1.0", + }, + }, + }, + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1111-2222-3333", + Description: ptr.String("Sample TI"), + TypeRef: &types.TypeRef{ + Path: "cap.type.b", + Revision: "0.1.0", + }, + }, + }, + }, + }, + }, Rules: policy.InterfaceRulesList{ policy.RulesForInterface{ Interface: types.ManifestRefWithOptRevision{ diff --git a/test/e2e/action_test.go b/test/e2e/action_test.go index 619204689..981d36e3c 100644 --- a/test/e2e/action_test.go +++ b/test/e2e/action_test.go @@ -141,7 +141,7 @@ var _ = Describe("Action", func() { assertOutputTypeInstancesInActionStatus(ctx, engineClient, action.Name, And(ContainElements(expUpdatedTIOutput, uploadedTIOutput), HaveLen(2))) }) - It("should pick Implementation B", func() { + It("should pick Implementation B based on Policy rule", func() { implIndicatorValue := "Implementation B" // TODO: This can be extracted after switching to ginkgo v2 @@ -174,7 +174,7 @@ var _ = Describe("Action", func() { }, } - By("2. Modifying Policy to pick Implementation B...") + By("2. Modifying rule Policy to pick Implementation B...") globalPolicyRequiredTypeInstances := []*enginegraphql.RequiredTypeInstanceReferenceInput{ { ID: injectTypeInstance.ID, @@ -203,6 +203,68 @@ var _ = Describe("Action", func() { assertOutputTypeInstancesInActionStatus(ctx, engineClient, action.Name, And(ContainElements(uploadedTIOutput), HaveLen(1))) }) + It("should pick Implementation B based on Interface default", func() { + implIndicatorValue := "Implementation B" + + // TODO: This can be extracted after switching to ginkgo v2 + // see: https://github.com/onsi/ginkgo/issues/70#issuecomment-924250145 + By("1. Preparing input Type Instances") + By("1.1 Creating TypeInstance which will be downloaded") + download := getTypeInstanceInputForDownload(implIndicatorValue) + downloadTI, downloadTICleanup := createTypeInstance(ctx, hubClient, download) + defer downloadTICleanup() + + By("1.2 Creating TypeInstance which will be downloaded and updated") + update := getTypeInstanceInputForUpdate() + updateTI, updateTICleanup := createTypeInstance(ctx, hubClient, update) + defer updateTICleanup() + + By("1.3 Creating TypeInstance that describes Helm storage") + helmStorage := fixHelmStorageTypeInstanceCreateInput() + helmStorageTI, helmStorageTICleanup := createTypeInstance(ctx, hubClient, helmStorage) + defer helmStorageTICleanup() + + By("1.4 Create TypeInstance which is required for Implementation B to be picked based on Policy") + typeInstanceValue := getTypeInstanceInputForPolicy() + injectTypeInstance, tiCleanupFn := createTypeInstance(ctx, hubClient, typeInstanceValue) + defer tiCleanupFn() + + inputData := &enginegraphql.ActionInputData{ + TypeInstances: []*enginegraphql.InputTypeInstanceData{ + {Name: "testInput", ID: downloadTI.ID}, + {Name: "testUpdate", ID: updateTI.ID}, + }, + } + + By("2. Modifying rule Policy to pick Implementation B...") + globalPolicyRequiredTypeInstances := []*enginegraphql.RequiredTypeInstanceReferenceInput{ + { + ID: injectTypeInstance.ID, + Description: ptr.String("Test TypeInstance"), + }, + { + ID: helmStorageTI.ID, + Description: ptr.String("Helm backend TypeInstance"), + }, + } + setGlobalTestPolicy(ctx, engineClient, addInterfacePolicyDefaultInjectionForPassingActionInterface(globalPolicyRequiredTypeInstances)) + + By("3. Expecting Implementation B is picked and injected Helm storage is used...") + action := createActionAndWaitForReadyToRunPhase(ctx, engineClient, actionName, actionPassingInterfacePath, inputData) + assertActionRenderedWorkflowContains(action, "echo '%s'", implIndicatorValue) + runActionAndWaitForSucceeded(ctx, engineClient, actionName) + + By("4.1 Check uploaded TypeInstances") + expUploadTIBackend := &hublocalgraphql.TypeInstanceBackendReference{ID: helmStorageTI.ID, Abstract: false} + uploadedTI, cleanupUploaded := getUploadedTypeInstanceByValue(ctx, hubClient, implIndicatorValue) + defer cleanupUploaded() // We need to clean it up as it's not deleted when Action is deleted. + Expect(uploadedTI.Backend).Should(Equal(expUploadTIBackend)) + + By("4.2 Check Action output TypeInstances") + uploadedTIOutput := mapToOutputTypeInstanceDetails(uploadedTI, expUploadTIBackend) + assertOutputTypeInstancesInActionStatus(ctx, engineClient, action.Name, And(ContainElements(uploadedTIOutput), HaveLen(1))) + }) + It("should have failed status after a failed workflow", func() { _, err := engineClient.CreateAction(ctx, &enginegraphql.ActionDetailsInput{ Name: failingActionName, @@ -547,6 +609,36 @@ func prependInjectRuleForPassingActionInterface(reqInput []*enginegraphql.Requir } } +func addInterfacePolicyDefaultInjectionForPassingActionInterface(reqInput []*enginegraphql.RequiredTypeInstanceReferenceInput) policyOption { + manifestRef := func(path string) []*enginegraphql.ManifestReferenceInput { + return []*enginegraphql.ManifestReferenceInput{ + { + Path: path, + }, + } + } + return func(policy *enginegraphql.PolicyInput) { + for idx, rule := range policy.Interface.Rules { + if rule.Interface.Path != actionPassingInterfacePath { + continue + } + policy.Interface.Rules[idx].OneOf = append([]*enginegraphql.PolicyRuleInput{ + { + ImplementationConstraints: &enginegraphql.PolicyRuleImplementationConstraintsInput{ + Requires: manifestRef(singleKeyTypePath), + Attributes: manifestRef("cap.attribute.capactio.capact.validation.policy.most-preferred"), + }, + }, + }, policy.Interface.Rules[idx].OneOf...) + } + policy.Interface.Default = &enginegraphql.DefaultForInterfaceInput{ + Inject: &enginegraphql.DefaultInjectForInterfaceInput{ + RequiredTypeInstances: reqInput, + }, + } + } +} + func setGlobalTestPolicy(ctx context.Context, client *engine.Client, opts ...policyOption) { p := fixGQLTestPolicyInput() From b8cf0bcfee558ec846b82e2e04b5624e0bda307a Mon Sep 17 00:00:00 2001 From: Mateusz Kuziemko Date: Tue, 1 Mar 2022 22:09:22 +0100 Subject: [PATCH 5/9] Small fix for integration test --- pkg/engine/k8s/policy/metadata/metadata_resolver.go | 1 + test/e2e/action_test.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/engine/k8s/policy/metadata/metadata_resolver.go b/pkg/engine/k8s/policy/metadata/metadata_resolver.go index 9f7ca39bf..020d524eb 100644 --- a/pkg/engine/k8s/policy/metadata/metadata_resolver.go +++ b/pkg/engine/k8s/policy/metadata/metadata_resolver.go @@ -129,6 +129,7 @@ func (r *Resolver) setTypeRefsForDefaultTypeInstances(policy *policy.Policy, typ Path: typeRef.Path, Revision: typeRef.Revision, } + policy.Interface.Default.Inject.RequiredTypeInstances[reqTIIdx].ExtendsHubStorage = r.isExtendingHubStorage(typeRef) } } diff --git a/test/e2e/action_test.go b/test/e2e/action_test.go index 981d36e3c..419586283 100644 --- a/test/e2e/action_test.go +++ b/test/e2e/action_test.go @@ -236,7 +236,7 @@ var _ = Describe("Action", func() { }, } - By("2. Modifying rule Policy to pick Implementation B...") + By("2. Modifying default Policy to pick Implementation B...") globalPolicyRequiredTypeInstances := []*enginegraphql.RequiredTypeInstanceReferenceInput{ { ID: injectTypeInstance.ID, From 07f929eb85289fceef6567413c26dc0eb9afce5d Mon Sep 17 00:00:00 2001 From: Mateusz Kuziemko Date: Wed, 2 Mar 2022 13:22:18 +0100 Subject: [PATCH 6/9] Add more tests and fixes for merger --- .../graphql/domain/policy/converter.go | 19 +-- pkg/hub/client/policy_enforced_client.go | 4 +- pkg/hub/client/policy_merger.go | 17 +- pkg/hub/client/policy_merger_test.go | 160 ++++++++++++++++++ 4 files changed, 183 insertions(+), 17 deletions(-) diff --git a/internal/k8s-engine/graphql/domain/policy/converter.go b/internal/k8s-engine/graphql/domain/policy/converter.go index 8c5fe22f3..3aae49b88 100644 --- a/internal/k8s-engine/graphql/domain/policy/converter.go +++ b/internal/k8s-engine/graphql/domain/policy/converter.go @@ -49,19 +49,18 @@ func (c *Converter) interfaceFromGraphQLInput(in *graphql.InterfacePolicyInput) }) } - if in.Default == nil || in.Default.Inject == nil { - return policy.InterfacePolicy{ - Rules: rules, - }, nil - } - - return policy.InterfacePolicy{ - Default: &policy.InterfaceDefault{ + var interfaceDefaults *policy.InterfaceDefault + if in.Default != nil && in.Default.Inject != nil { + interfaceDefaults = &policy.InterfaceDefault{ Inject: &policy.DefaultInject{ RequiredTypeInstances: c.requiredTypeInstancesToInjectFromGraphQLInput(in.Default.Inject.RequiredTypeInstances), }, - }, - Rules: rules, + } + } + + return policy.InterfacePolicy{ + Default: interfaceDefaults, + Rules: rules, }, nil } diff --git a/pkg/hub/client/policy_enforced_client.go b/pkg/hub/client/policy_enforced_client.go index 319feb51d..6c8a793ee 100644 --- a/pkg/hub/client/policy_enforced_client.go +++ b/pkg/hub/client/policy_enforced_client.go @@ -149,9 +149,7 @@ func (e *PolicyEnforcedClient) ListRequiredTypeInstancesToInjectBasedOnPolicy(po type requiredTypeInstanceToInject map[string]policy.RequiredTypeInstanceToInject func (e *PolicyEnforcedClient) listRequiredTypeInstancesToInjectBasedOnPolicy(policyRule policy.Rule, implRev hubpublicgraphql.ImplementationRevision) (requiredTypeInstanceToInject, error) { - var requiredTIs []policy.RequiredTypeInstanceToInject - requiredTIs = append(requiredTIs, policyRule.RequiredTypeInstancesToInject()...) - requiredTIs = append(requiredTIs, e.mergedPolicy.Interface.DefaultRequiredTypeInstancesToInject()...) + requiredTIs := e.MergeRequiredTypeInstances(policyRule) if len(requiredTIs) == 0 { return nil, nil diff --git a/pkg/hub/client/policy_merger.go b/pkg/hub/client/policy_merger.go index e157c35c9..723f92866 100644 --- a/pkg/hub/client/policy_merger.go +++ b/pkg/hub/client/policy_merger.go @@ -30,14 +30,23 @@ func (e *PolicyEnforcedClient) mergePolicies() { e.mergedPolicy = currentPolicy } +// MergeRequiredTypeInstances returns the merged list of TypeInstances from Rule and Defaults +func (e *PolicyEnforcedClient) MergeRequiredTypeInstances(policyRule policy.Rule) []policy.RequiredTypeInstanceToInject { + // prefer policy Rule over Default + return mergeRequiredTypeInstances(e.mergedPolicy.Interface.DefaultRequiredTypeInstancesToInject(), policyRule.RequiredTypeInstancesToInject()) +} + func applyInterfacePolicy(currentPolicy *policy.InterfacePolicy, newPolicy policy.InterfacePolicy) { // Default - if newPolicy.Default != nil && newPolicy.Default.Inject != nil { + if len(newPolicy.DefaultRequiredTypeInstancesToInject()) > 0 { if currentPolicy.Default == nil || currentPolicy.Default.Inject == nil { - currentPolicy.Default = newPolicy.Default - } else { - currentPolicy.Default.Inject.RequiredTypeInstances = mergeRequiredTypeInstances(currentPolicy.Default.Inject.RequiredTypeInstances, newPolicy.Default.Inject.RequiredTypeInstances) + currentPolicy.Default = &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{}, + }, + } } + currentPolicy.Default.Inject.RequiredTypeInstances = mergeRequiredTypeInstances(currentPolicy.Default.Inject.RequiredTypeInstances, newPolicy.Default.Inject.RequiredTypeInstances) } // from new policy we are checking if there are the same rules. If yes we fill missing data, diff --git a/pkg/hub/client/policy_merger_test.go b/pkg/hub/client/policy_merger_test.go index eba76faad..1860e9d61 100644 --- a/pkg/hub/client/policy_merger_test.go +++ b/pkg/hub/client/policy_merger_test.go @@ -1183,6 +1183,166 @@ func TestPolicyEnforcedClient_mergeTypeInstancePolicies(t *testing.T) { } } +func TestPolicyEnforcedClient_mergeTypeInstancePoliciesForDefault(t *testing.T) { + tests := []struct { + name string + global policy.Policy + action policy.ActionPolicy + expected policy.Policy + order policy.MergeOrder + }{ + { + name: "TypeInstance with the same Typeref for Global and Action Policy", + global: policy.Policy{ + Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1234-123-123", + Description: ptr.String("A"), + TypeRef: &types.TypeRef{ + Path: "cap.type.aws.auth.credentials", + Revision: "0.1.0", + }, + }, + }, + }, + }, + }, + }, + }, + action: policy.ActionPolicy{ + Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1111-2222-3333", + Description: ptr.String("B"), + TypeRef: &types.TypeRef{ + Path: "cap.type.aws.auth.credentials", + Revision: "0.1.0", + }, + }, + }, + }, + }, + }, + }, + }, + expected: policy.Policy{ + Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1111-2222-3333", + Description: ptr.String("B"), + TypeRef: &types.TypeRef{ + Path: "cap.type.aws.auth.credentials", + Revision: "0.1.0", + }, + }, + }, + }, + }, + }, + }, + }, + order: policy.MergeOrder{policy.Global, policy.Action}, + }, + } + for _, test := range tests { + tt := test + t.Run(tt.name, func(t *testing.T) { + // given + cli := client.NewPolicyEnforcedClient(nil, nil) + cli.SetPolicyOrder(tt.order) + cli.SetGlobalPolicy(tt.global) + cli.SetActionPolicy(tt.action) + + // expect + assert.Equal(t, tt.expected, cli.Policy()) + }) + } +} + +func TestMergeRequiredTypeInstances(t *testing.T) { + tests := []struct { + name string + rule policy.Rule + global policy.Policy + expected []policy.RequiredTypeInstanceToInject + }{ + { + name: "Rule TypeInstance injection is preferred over Default", + rule: policy.Rule{ + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1111-2222-3333", + Description: ptr.String("Sample TI"), + TypeRef: &types.TypeRef{ + Path: "cap.type.gcp.auth.service-account", + Revision: "0.1.0", + }, + }, + }, + }, + }, + }, + global: policy.Policy{ + Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1314-142-123", + Description: ptr.String("Sample TI"), + TypeRef: &types.TypeRef{ + Path: "cap.type.gcp.auth.service-account", + Revision: "0.1.0", + }, + }, + }, + }, + }, + }, + }, + }, + expected: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1111-2222-3333", + Description: ptr.String("Sample TI"), + TypeRef: &types.TypeRef{ + Path: "cap.type.gcp.auth.service-account", + Revision: "0.1.0", + }, + }, + }, + }, + }, + } + for _, test := range tests { + tt := test + t.Run(tt.name, func(t *testing.T) { + // given + cli := client.NewPolicyEnforcedClient(nil, nil) + cli.SetGlobalPolicy(tt.global) + + // expect + assert.Equal(t, tt.expected, cli.MergeRequiredTypeInstances(tt.rule)) + }) + } +} + func TestNestedWorkflowPolicy(t *testing.T) { w1 := workflowPolicyWithAdditionalInput(map[string]interface{}{"a": 1}) w2 := workflowPolicyWithAdditionalInput(map[string]interface{}{"a": 2, "b": 3}) From 971f410de9b66583a874ad88f1a9c52b6851bb77 Mon Sep 17 00:00:00 2001 From: Mateusz Kuziemko Date: Wed, 2 Mar 2022 16:01:33 +0100 Subject: [PATCH 7/9] Refactoring --- .../graphql/domain/policy/converter.go | 17 +++--- pkg/hub/client/policy_enforced_client.go | 22 ++------ pkg/hub/client/policy_merger.go | 4 +- pkg/hub/client/policy_merger_test.go | 55 ++++++++++++++++++- 4 files changed, 67 insertions(+), 31 deletions(-) diff --git a/internal/k8s-engine/graphql/domain/policy/converter.go b/internal/k8s-engine/graphql/domain/policy/converter.go index 3aae49b88..1b1548e01 100644 --- a/internal/k8s-engine/graphql/domain/policy/converter.go +++ b/internal/k8s-engine/graphql/domain/policy/converter.go @@ -129,19 +129,18 @@ func (c *Converter) interfaceToGraphQL(in policy.InterfacePolicy) *graphql.Inter }) } - if in.DefaultRequiredTypeInstancesToInject() == nil { - return &graphql.InterfacePolicy{ - Rules: gqlRules, + var defaultForInterface *graphql.DefaultForInterface + if in.DefaultRequiredTypeInstancesToInject() != nil { + defaultForInterface = &graphql.DefaultForInterface{ + Inject: &graphql.DefaultInjectForInterface{ + RequiredTypeInstances: c.requiredTypeInstancesToInjectToGraphQL(in.Default.Inject.RequiredTypeInstances), + }, } } return &graphql.InterfacePolicy{ - Default: &graphql.DefaultForInterface{ - Inject: &graphql.DefaultInjectForInterface{ - RequiredTypeInstances: c.requiredTypeInstancesToInjectToGraphQL(in.Default.Inject.RequiredTypeInstances), - }, - }, - Rules: gqlRules, + Default: defaultForInterface, + Rules: gqlRules, } } diff --git a/pkg/hub/client/policy_enforced_client.go b/pkg/hub/client/policy_enforced_client.go index 6c8a793ee..9ea007ea4 100644 --- a/pkg/hub/client/policy_enforced_client.go +++ b/pkg/hub/client/policy_enforced_client.go @@ -149,7 +149,7 @@ func (e *PolicyEnforcedClient) ListRequiredTypeInstancesToInjectBasedOnPolicy(po type requiredTypeInstanceToInject map[string]policy.RequiredTypeInstanceToInject func (e *PolicyEnforcedClient) listRequiredTypeInstancesToInjectBasedOnPolicy(policyRule policy.Rule, implRev hubpublicgraphql.ImplementationRevision) (requiredTypeInstanceToInject, error) { - requiredTIs := e.MergeRequiredTypeInstances(policyRule) + requiredTIs := e.RequiredTypeInstancesForRule(policyRule) if len(requiredTIs) == 0 { return nil, nil @@ -428,9 +428,10 @@ func (e *PolicyEnforcedClient) hubFilterForPolicyRule(rule policy.Rule, allTypeI filter.RequirementsSatisfiedBy = allTypeInstances // Requirements Injection - if rule.Inject != nil { + tisToInject := e.RequiredTypeInstancesForRule(rule) + if len(tisToInject) > 0 { var injectedRequiredTypeInstances []*hubpublicgraphql.TypeInstanceValue - for _, ti := range rule.Inject.RequiredTypeInstances { + for _, ti := range tisToInject { injectedRequiredTypeInstances = append(injectedRequiredTypeInstances, &hubpublicgraphql.TypeInstanceValue{ TypeRef: &hubpublicgraphql.TypeReferenceInput{ Path: ti.TypeRef.Path, @@ -441,21 +442,6 @@ func (e *PolicyEnforcedClient) hubFilterForPolicyRule(rule policy.Rule, allTypeI } filter.RequiredTypeInstancesInjectionSatisfiedBy = injectedRequiredTypeInstances } - - // Append TypeInstance from Interface Default - defaultTI := e.mergedPolicy.Interface.DefaultRequiredTypeInstancesToInject() - var injectedDefaultRequiredTypeInstances []*hubpublicgraphql.TypeInstanceValue - for _, ti := range defaultTI { - injectedDefaultRequiredTypeInstances = append(injectedDefaultRequiredTypeInstances, &hubpublicgraphql.TypeInstanceValue{ - TypeRef: &hubpublicgraphql.TypeReferenceInput{ - Path: ti.TypeRef.Path, - Revision: ti.TypeRef.Revision, - }, - Value: nil, // not supported right now - }) - } - filter.RequiredTypeInstancesInjectionSatisfiedBy = append(filter.RequiredTypeInstancesInjectionSatisfiedBy, injectedDefaultRequiredTypeInstances...) - return filter } diff --git a/pkg/hub/client/policy_merger.go b/pkg/hub/client/policy_merger.go index 723f92866..710ef9435 100644 --- a/pkg/hub/client/policy_merger.go +++ b/pkg/hub/client/policy_merger.go @@ -30,8 +30,8 @@ func (e *PolicyEnforcedClient) mergePolicies() { e.mergedPolicy = currentPolicy } -// MergeRequiredTypeInstances returns the merged list of TypeInstances from Rule and Defaults -func (e *PolicyEnforcedClient) MergeRequiredTypeInstances(policyRule policy.Rule) []policy.RequiredTypeInstanceToInject { +// RequiredTypeInstancesForRule returns the merged list of TypeInstances from Rule and Defaults. +func (e *PolicyEnforcedClient) RequiredTypeInstancesForRule(policyRule policy.Rule) []policy.RequiredTypeInstanceToInject { // prefer policy Rule over Default return mergeRequiredTypeInstances(e.mergedPolicy.Interface.DefaultRequiredTypeInstancesToInject(), policyRule.RequiredTypeInstancesToInject()) } diff --git a/pkg/hub/client/policy_merger_test.go b/pkg/hub/client/policy_merger_test.go index 1860e9d61..bd260c4dc 100644 --- a/pkg/hub/client/policy_merger_test.go +++ b/pkg/hub/client/policy_merger_test.go @@ -1271,7 +1271,7 @@ func TestPolicyEnforcedClient_mergeTypeInstancePoliciesForDefault(t *testing.T) } } -func TestMergeRequiredTypeInstances(t *testing.T) { +func TestRequiredTypeInstancesForRule(t *testing.T) { tests := []struct { name string rule policy.Rule @@ -1329,6 +1329,57 @@ func TestMergeRequiredTypeInstances(t *testing.T) { }, }, }, + { + name: "TypeInstaces should not contain duplicates", + rule: policy.Rule{ + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1111-2222-3333", + Description: ptr.String("Sample TI"), + TypeRef: &types.TypeRef{ + Path: "cap.type.gcp.auth.service-account", + Revision: "0.1.0", + }, + }, + }, + }, + }, + }, + global: policy.Policy{ + Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1111-2222-3333", + Description: ptr.String("Sample TI"), + TypeRef: &types.TypeRef{ + Path: "cap.type.gcp.auth.service-account", + Revision: "0.1.0", + }, + }, + }, + }, + }, + }, + }, + }, + expected: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1111-2222-3333", + Description: ptr.String("Sample TI"), + TypeRef: &types.TypeRef{ + Path: "cap.type.gcp.auth.service-account", + Revision: "0.1.0", + }, + }, + }, + }, + }, } for _, test := range tests { tt := test @@ -1338,7 +1389,7 @@ func TestMergeRequiredTypeInstances(t *testing.T) { cli.SetGlobalPolicy(tt.global) // expect - assert.Equal(t, tt.expected, cli.MergeRequiredTypeInstances(tt.rule)) + assert.Equal(t, tt.expected, cli.RequiredTypeInstancesForRule(tt.rule)) }) } } From 599982b3db6834e8013454d6075cdb6cf5fdbe35 Mon Sep 17 00:00:00 2001 From: Mateusz Kuziemko Date: Fri, 4 Mar 2022 17:32:13 +0100 Subject: [PATCH 8/9] Fixes after review --- pkg/hub/client/policy_enforced_client.go | 37 ++-- pkg/hub/client/policy_merger.go | 3 +- pkg/hub/client/policy_merger_test.go | 220 +++++++++++++++++++++++ 3 files changed, 245 insertions(+), 15 deletions(-) diff --git a/pkg/hub/client/policy_enforced_client.go b/pkg/hub/client/policy_enforced_client.go index 9ea007ea4..ae1f747fe 100644 --- a/pkg/hub/client/policy_enforced_client.go +++ b/pkg/hub/client/policy_enforced_client.go @@ -107,9 +107,8 @@ func (e *PolicyEnforcedClient) ListImplementationRevisionForInterface(ctx contex // ListTypeInstancesBackendsBasedOnPolicy returns default backends defined in Policy and those specified explicitly in a given policy rule. func (e *PolicyEnforcedClient) ListTypeInstancesBackendsBasedOnPolicy(_ context.Context, rule policy.Rule, implRev hubpublicgraphql.ImplementationRevision) (policy.TypeInstanceBackendCollection, error) { out := policy.TypeInstanceBackendCollection{} - // 1. Global Defaults based on TypeRefs - for _, rule := range e.mergedPolicy.TypeInstance.Rules { + for _, rule := range e.Policy().TypeInstance.Rules { out.SetByTypeRef(rule.TypeRef, rule.Backend) } @@ -252,7 +251,6 @@ func (e *PolicyEnforcedClient) FindInterfaceRevision(ctx context.Context, ref hu func (e *PolicyEnforcedClient) SetPolicyOrder(order policy.MergeOrder) { e.mu.Lock() e.policyOrder = order - e.mergePolicies() e.mu.Unlock() } @@ -260,7 +258,6 @@ func (e *PolicyEnforcedClient) SetPolicyOrder(order policy.MergeOrder) { func (e *PolicyEnforcedClient) SetGlobalPolicy(p policy.Policy) { e.mu.Lock() e.globalPolicy = p - e.mergePolicies() e.mu.Unlock() } @@ -268,7 +265,6 @@ func (e *PolicyEnforcedClient) SetGlobalPolicy(p policy.Policy) { func (e *PolicyEnforcedClient) SetActionPolicy(p policy.ActionPolicy) { e.mu.Lock() e.actionPolicy = policy.Policy(p) - e.mergePolicies() e.mu.Unlock() } @@ -280,7 +276,6 @@ func (e *PolicyEnforcedClient) PushWorkflowStepPolicy(workflowPolicy policy.Work return errors.Wrap(err, "while getting Policy from WorkflowPolicy") } e.workflowStepPolicies = append(e.workflowStepPolicies, p) - e.mergePolicies() e.mu.Unlock() return nil } @@ -298,6 +293,7 @@ func (e *PolicyEnforcedClient) PopWorkflowStepPolicy() { // Policy gets policy which the Client uses. This getter is thread safe. func (e *PolicyEnforcedClient) Policy() policy.Policy { e.mu.Lock() + e.mergePolicies() defer e.mu.Unlock() return e.mergedPolicy } @@ -324,17 +320,30 @@ func (e *PolicyEnforcedClient) findRulesForInterface(interfaceRef hubpublicgraph } func (e *PolicyEnforcedClient) resolvePolicyTIMetadataIfShould(ctx context.Context) error { - if e.validator.AreTypeInstancesMetadataResolved(e.mergedPolicy) { - return nil - } + validatePolicyFunc := func(ctx context.Context, policyToResolve policy.Policy) error { + if e.validator.AreTypeInstancesMetadataResolved(policyToResolve) { + return nil + } - err := e.policyMetadataResolver.ResolveTypeInstanceMetadata(ctx, &e.mergedPolicy) - if err != nil { - return errors.Wrap(err, "while resolving TypeInstance metadata for Policy") + err := e.policyMetadataResolver.ResolveTypeInstanceMetadata(ctx, &policyToResolve) + if err != nil { + return errors.Wrap(err, "while resolving TypeInstance metadata for Policy") + } + + if res := e.validator.ValidateTypeInstancesMetadata(policyToResolve); res.ErrorOrNil() != nil { + return e.wrapValidationResultError(res.ErrorOrNil(), "while TypeInstance metadata validation after resolving TypeRefs") + } + + return nil } - if res := e.validator.ValidateTypeInstancesMetadata(e.mergedPolicy); res.ErrorOrNil() != nil { - return e.wrapValidationResultError(res.ErrorOrNil(), "while TypeInstance metadata validation after resolving TypeRefs") + availablePolicies := []policy.Policy{e.globalPolicy, e.actionPolicy} + availablePolicies = append(availablePolicies, e.workflowStepPolicies...) + for _, availablePolicy := range availablePolicies { + err := validatePolicyFunc(ctx, availablePolicy) + if err != nil { + return errors.Wrap(err, "while resolving policy TypeInstances") + } } return nil diff --git a/pkg/hub/client/policy_merger.go b/pkg/hub/client/policy_merger.go index 710ef9435..f57ef5b89 100644 --- a/pkg/hub/client/policy_merger.go +++ b/pkg/hub/client/policy_merger.go @@ -32,8 +32,9 @@ func (e *PolicyEnforcedClient) mergePolicies() { // RequiredTypeInstancesForRule returns the merged list of TypeInstances from Rule and Defaults. func (e *PolicyEnforcedClient) RequiredTypeInstancesForRule(policyRule policy.Rule) []policy.RequiredTypeInstanceToInject { + mergedPolicy := e.Policy() // prefer policy Rule over Default - return mergeRequiredTypeInstances(e.mergedPolicy.Interface.DefaultRequiredTypeInstancesToInject(), policyRule.RequiredTypeInstancesToInject()) + return mergeRequiredTypeInstances(mergedPolicy.Interface.DefaultRequiredTypeInstancesToInject(), policyRule.RequiredTypeInstancesToInject()) } func applyInterfacePolicy(currentPolicy *policy.InterfacePolicy, newPolicy policy.InterfacePolicy) { diff --git a/pkg/hub/client/policy_merger_test.go b/pkg/hub/client/policy_merger_test.go index bd260c4dc..374da80c5 100644 --- a/pkg/hub/client/policy_merger_test.go +++ b/pkg/hub/client/policy_merger_test.go @@ -1191,6 +1191,100 @@ func TestPolicyEnforcedClient_mergeTypeInstancePoliciesForDefault(t *testing.T) expected policy.Policy order policy.MergeOrder }{ + { + name: "TypeInstance with different Typeref for Global and Action Policy", + global: policy.Policy{ + Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1234-123-123", + Description: ptr.String("A"), + TypeRef: &types.TypeRef{ + Path: "cap.type.aws.auth.credentials", + Revision: "0.1.0", + }, + }, + }, + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "3333-3333-3333", + Description: ptr.String("C"), + TypeRef: &types.TypeRef{ + Path: "cap.type.gcp.auth.credentials", + Revision: "0.1.0", + }, + }, + }, + }, + }, + }, + }, + }, + action: policy.ActionPolicy{ + Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1111-2222-3333", + Description: ptr.String("B"), + TypeRef: &types.TypeRef{ + Path: "cap.type.aws.auth.credentials", + Revision: "0.2.0", + }, + }, + }, + }, + }, + }, + }, + }, + expected: policy.Policy{ + Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1234-123-123", + Description: ptr.String("A"), + TypeRef: &types.TypeRef{ + Path: "cap.type.aws.auth.credentials", + Revision: "0.1.0", + }, + }, + }, + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "3333-3333-3333", + Description: ptr.String("C"), + TypeRef: &types.TypeRef{ + Path: "cap.type.gcp.auth.credentials", + Revision: "0.1.0", + }, + }, + }, + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1111-2222-3333", + Description: ptr.String("B"), + TypeRef: &types.TypeRef{ + Path: "cap.type.aws.auth.credentials", + Revision: "0.2.0", + }, + }, + }, + }, + }, + }, + }, + }, + order: policy.MergeOrder{policy.Global, policy.Action}, + }, { name: "TypeInstance with the same Typeref for Global and Action Policy", global: policy.Policy{ @@ -1255,6 +1349,70 @@ func TestPolicyEnforcedClient_mergeTypeInstancePoliciesForDefault(t *testing.T) }, order: policy.MergeOrder{policy.Global, policy.Action}, }, + { + name: "TypeInstance with the same Typeref for Global and Action Policy but Action has higher priority", + global: policy.Policy{ + Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1234-123-123", + Description: ptr.String("A"), + TypeRef: &types.TypeRef{ + Path: "cap.type.aws.auth.credentials", + Revision: "0.1.0", + }, + }, + }, + }, + }, + }, + }, + }, + action: policy.ActionPolicy{ + Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1111-2222-3333", + Description: ptr.String("B"), + TypeRef: &types.TypeRef{ + Path: "cap.type.aws.auth.credentials", + Revision: "0.1.0", + }, + }, + }, + }, + }, + }, + }, + }, + expected: policy.Policy{ + Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1234-123-123", + Description: ptr.String("A"), + TypeRef: &types.TypeRef{ + Path: "cap.type.aws.auth.credentials", + Revision: "0.1.0", + }, + }, + }, + }, + }, + }, + }, + }, + order: policy.MergeOrder{policy.Action, policy.Global}, + }, } for _, test := range tests { tt := test @@ -1380,7 +1538,69 @@ func TestRequiredTypeInstancesForRule(t *testing.T) { }, }, }, + { + name: "TypeInstaces are correctly distinguished based on Typeref", + rule: policy.Rule{ + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1111-1111-1111", + Description: ptr.String("Sample TI"), + TypeRef: &types.TypeRef{ + Path: "cap.type.gcp.auth.service-account", + Revision: "0.1.0", + }, + }, + }, + }, + }, + }, + global: policy.Policy{ + Interface: policy.InterfacePolicy{ + Default: &policy.InterfaceDefault{ + Inject: &policy.DefaultInject{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "2222-2222-2222", + Description: ptr.String("Sample TI"), + TypeRef: &types.TypeRef{ + Path: "cap.type.gcp.auth.service-account", + Revision: "0.2.0", + }, + }, + }, + }, + }, + }, + }, + }, + expected: []policy.RequiredTypeInstanceToInject{ + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "2222-2222-2222", + Description: ptr.String("Sample TI"), + TypeRef: &types.TypeRef{ + Path: "cap.type.gcp.auth.service-account", + Revision: "0.2.0", + }, + }, + }, + { + TypeInstanceReference: policy.TypeInstanceReference{ + ID: "1111-1111-1111", + Description: ptr.String("Sample TI"), + TypeRef: &types.TypeRef{ + Path: "cap.type.gcp.auth.service-account", + Revision: "0.1.0", + }, + }, + }, + }, + }, } + for _, test := range tests { tt := test t.Run(tt.name, func(t *testing.T) { From efcf17c31ec013e463851d5a2f01a7a39d76453a Mon Sep 17 00:00:00 2001 From: Mateusz Kuziemko Date: Mon, 7 Mar 2022 22:37:59 +0100 Subject: [PATCH 9/9] Cleanup of mergedPolicy --- pkg/hub/client/policy_enforced_client.go | 42 +++++++++++++----------- pkg/hub/client/policy_merger.go | 10 +++--- pkg/hub/client/policy_merger_test.go | 14 ++++---- 3 files changed, 34 insertions(+), 32 deletions(-) diff --git a/pkg/hub/client/policy_enforced_client.go b/pkg/hub/client/policy_enforced_client.go index ae1f747fe..e49d80291 100644 --- a/pkg/hub/client/policy_enforced_client.go +++ b/pkg/hub/client/policy_enforced_client.go @@ -49,7 +49,6 @@ type PolicyEnforcedClient struct { hubCli HubClient globalPolicy policy.Policy actionPolicy policy.Policy - mergedPolicy policy.Policy policyOrder policy.MergeOrder workflowStepPolicies []policy.Policy validator PolicyIOValidator @@ -108,7 +107,8 @@ func (e *PolicyEnforcedClient) ListImplementationRevisionForInterface(ctx contex func (e *PolicyEnforcedClient) ListTypeInstancesBackendsBasedOnPolicy(_ context.Context, rule policy.Rule, implRev hubpublicgraphql.ImplementationRevision) (policy.TypeInstanceBackendCollection, error) { out := policy.TypeInstanceBackendCollection{} // 1. Global Defaults based on TypeRefs - for _, rule := range e.Policy().TypeInstance.Rules { + mergedPolicy := e.MergedPolicy() + for _, rule := range mergedPolicy.TypeInstance.Rules { out.SetByTypeRef(rule.TypeRef, rule.Backend) } @@ -148,7 +148,7 @@ func (e *PolicyEnforcedClient) ListRequiredTypeInstancesToInjectBasedOnPolicy(po type requiredTypeInstanceToInject map[string]policy.RequiredTypeInstanceToInject func (e *PolicyEnforcedClient) listRequiredTypeInstancesToInjectBasedOnPolicy(policyRule policy.Rule, implRev hubpublicgraphql.ImplementationRevision) (requiredTypeInstanceToInject, error) { - requiredTIs := e.RequiredTypeInstancesForRule(policyRule) + requiredTIs := e.MergeRequiredTypeInstancesForRule(policyRule) if len(requiredTIs) == 0 { return nil, nil @@ -286,20 +286,18 @@ func (e *PolicyEnforcedClient) PopWorkflowStepPolicy() { if len(e.workflowStepPolicies) > 0 { e.workflowStepPolicies = e.workflowStepPolicies[:len(e.workflowStepPolicies)-1] } - e.mergePolicies() e.mu.Unlock() } -// Policy gets policy which the Client uses. This getter is thread safe. -func (e *PolicyEnforcedClient) Policy() policy.Policy { - e.mu.Lock() - e.mergePolicies() - defer e.mu.Unlock() - return e.mergedPolicy +// MergedPolicy gets policy which the Client uses. This getter is thread safe. +func (e *PolicyEnforcedClient) MergedPolicy() policy.Policy { + e.mu.RLock() + defer e.mu.RUnlock() + return e.mergePolicies() } func (e *PolicyEnforcedClient) findRulesForInterface(interfaceRef hubpublicgraphql.InterfaceReference) policy.RulesForInterface { - rulesMap := e.interfaceRulesMapForPolicy(e.Policy()) + rulesMap := e.interfaceRulesMapForPolicy(e.MergedPolicy()) ruleKeysToCheck := []string{ fmt.Sprintf("%s:%s", interfaceRef.Path, interfaceRef.Revision), @@ -320,27 +318,31 @@ func (e *PolicyEnforcedClient) findRulesForInterface(interfaceRef hubpublicgraph } func (e *PolicyEnforcedClient) resolvePolicyTIMetadataIfShould(ctx context.Context) error { - validatePolicyFunc := func(ctx context.Context, policyToResolve policy.Policy) error { - if e.validator.AreTypeInstancesMetadataResolved(policyToResolve) { + resolvePolicyIfShouldFn := func(ctx context.Context, policyToResolve *policy.Policy) error { + if policyToResolve == nil { + return errors.New("policy cannot be nil") + } + + if e.validator.AreTypeInstancesMetadataResolved(*policyToResolve) { return nil } - err := e.policyMetadataResolver.ResolveTypeInstanceMetadata(ctx, &policyToResolve) + err := e.policyMetadataResolver.ResolveTypeInstanceMetadata(ctx, policyToResolve) if err != nil { return errors.Wrap(err, "while resolving TypeInstance metadata for Policy") } - if res := e.validator.ValidateTypeInstancesMetadata(policyToResolve); res.ErrorOrNil() != nil { + if res := e.validator.ValidateTypeInstancesMetadata(*policyToResolve); res.ErrorOrNil() != nil { return e.wrapValidationResultError(res.ErrorOrNil(), "while TypeInstance metadata validation after resolving TypeRefs") } return nil } - availablePolicies := []policy.Policy{e.globalPolicy, e.actionPolicy} - availablePolicies = append(availablePolicies, e.workflowStepPolicies...) - for _, availablePolicy := range availablePolicies { - err := validatePolicyFunc(ctx, availablePolicy) + // Ignore workflow policies as there's no TypeRefs to resolve anyway + policiesToResolve := []policy.Policy{e.globalPolicy, e.actionPolicy} + for i := range policiesToResolve { + err := resolvePolicyIfShouldFn(ctx, &policiesToResolve[i]) if err != nil { return errors.Wrap(err, "while resolving policy TypeInstances") } @@ -437,7 +439,7 @@ func (e *PolicyEnforcedClient) hubFilterForPolicyRule(rule policy.Rule, allTypeI filter.RequirementsSatisfiedBy = allTypeInstances // Requirements Injection - tisToInject := e.RequiredTypeInstancesForRule(rule) + tisToInject := e.MergeRequiredTypeInstancesForRule(rule) if len(tisToInject) > 0 { var injectedRequiredTypeInstances []*hubpublicgraphql.TypeInstanceValue for _, ti := range tisToInject { diff --git a/pkg/hub/client/policy_merger.go b/pkg/hub/client/policy_merger.go index f57ef5b89..55229f31a 100644 --- a/pkg/hub/client/policy_merger.go +++ b/pkg/hub/client/policy_merger.go @@ -8,7 +8,7 @@ import ( "capact.io/capact/pkg/engine/k8s/policy" ) -func (e *PolicyEnforcedClient) mergePolicies() { +func (e *PolicyEnforcedClient) mergePolicies() policy.Policy { currentPolicy := policy.Policy{} for _, p := range e.policyOrder { @@ -27,12 +27,12 @@ func (e *PolicyEnforcedClient) mergePolicies() { } } } - e.mergedPolicy = currentPolicy + return currentPolicy } -// RequiredTypeInstancesForRule returns the merged list of TypeInstances from Rule and Defaults. -func (e *PolicyEnforcedClient) RequiredTypeInstancesForRule(policyRule policy.Rule) []policy.RequiredTypeInstanceToInject { - mergedPolicy := e.Policy() +// MergeRequiredTypeInstancesForRule returns the merged list of TypeInstances from Rule and Defaults. +func (e *PolicyEnforcedClient) MergeRequiredTypeInstancesForRule(policyRule policy.Rule) []policy.RequiredTypeInstanceToInject { + mergedPolicy := e.MergedPolicy() // prefer policy Rule over Default return mergeRequiredTypeInstances(mergedPolicy.Interface.DefaultRequiredTypeInstancesToInject(), policyRule.RequiredTypeInstancesToInject()) } diff --git a/pkg/hub/client/policy_merger_test.go b/pkg/hub/client/policy_merger_test.go index 374da80c5..af5700a29 100644 --- a/pkg/hub/client/policy_merger_test.go +++ b/pkg/hub/client/policy_merger_test.go @@ -800,7 +800,7 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { cli.SetActionPolicy(tt.action) // expect - assert.Equal(t, tt.expected, cli.Policy()) + assert.Equal(t, tt.expected, cli.MergedPolicy()) }) } } @@ -1178,7 +1178,7 @@ func TestPolicyEnforcedClient_mergeTypeInstancePolicies(t *testing.T) { cli.SetActionPolicy(tt.action) // expect - assert.Equal(t, tt.expected, cli.Policy()) + assert.Equal(t, tt.expected, cli.MergedPolicy()) }) } } @@ -1424,7 +1424,7 @@ func TestPolicyEnforcedClient_mergeTypeInstancePoliciesForDefault(t *testing.T) cli.SetActionPolicy(tt.action) // expect - assert.Equal(t, tt.expected, cli.Policy()) + assert.Equal(t, tt.expected, cli.MergedPolicy()) }) } } @@ -1609,7 +1609,7 @@ func TestRequiredTypeInstancesForRule(t *testing.T) { cli.SetGlobalPolicy(tt.global) // expect - assert.Equal(t, tt.expected, cli.RequiredTypeInstancesForRule(tt.rule)) + assert.Equal(t, tt.expected, cli.MergeRequiredTypeInstancesForRule(tt.rule)) }) } } @@ -1628,14 +1628,14 @@ func TestNestedWorkflowPolicy(t *testing.T) { err = cli.PushWorkflowStepPolicy(w1) assert.NoError(t, err) - assert.Equal(t, expected1, cli.Policy()) + assert.Equal(t, expected1, cli.MergedPolicy()) err = cli.PushWorkflowStepPolicy(w2) assert.NoError(t, err) - assert.Equal(t, expected2, cli.Policy()) + assert.Equal(t, expected2, cli.MergedPolicy()) cli.PopWorkflowStepPolicy() - assert.Equal(t, expected1, cli.Policy()) + assert.Equal(t, expected1, cli.MergedPolicy()) } func workflowPolicyWithAdditionalInput(input map[string]interface{}) policy.WorkflowPolicy {