diff --git a/.editorconfig b/.editorconfig index f1ad1260c..c461e151f 100755 --- a/.editorconfig +++ b/.editorconfig @@ -4,6 +4,10 @@ insert_final_newline = true [{*.yml, *.yaml}] indent_size = 2 +[*.graphql] +indent_size = 4 +indent_style = space + [Makefile] indent_style = tab indent_size = 4 diff --git a/deploy/kubernetes/charts/capact/charts/engine/templates/clusterpolicy-configmap.yaml b/deploy/kubernetes/charts/capact/charts/engine/templates/clusterpolicy-configmap.yaml index dbf820795..433a716ec 100644 --- a/deploy/kubernetes/charts/capact/charts/engine/templates/clusterpolicy-configmap.yaml +++ b/deploy/kubernetes/charts/capact/charts/engine/templates/clusterpolicy-configmap.yaml @@ -6,10 +6,4 @@ metadata: {{- include "engine.labels" . | nindent 4 }} data: cluster-policy.yaml: | - apiVersion: 0.2.0 - - rules: - {{- if .Values.testSetup.enabled }} - {{- toYaml .Values.testSetup.globalPolicyRules | nindent 8 }} - {{- end }} - {{- toYaml .Values.globalPolicyRules | nindent 8 }} + {{- toYaml .Values.globalPolicy | nindent 4 }} diff --git a/deploy/kubernetes/charts/capact/charts/engine/values.yaml b/deploy/kubernetes/charts/capact/charts/engine/values.yaml index 91053606b..441aec783 100644 --- a/deploy/kubernetes/charts/capact/charts/engine/values.yaml +++ b/deploy/kubernetes/charts/capact/charts/engine/values.yaml @@ -60,67 +60,57 @@ affinity: {} # order from highest priority to the lowest policyOrder: "ACTION,GLOBAL,WORKFLOW" -globalPolicyRules: +globalPolicy: # Insert Interface paths with Implementations. For example: -# -# - interface: -# # Rules for exact path and revision (looked up in first place) -# path: "cap.interface.database.postgresql.install" -# revision: "0.1.0" -# oneOf: -# - implementationConstraints: -# requires: -# - path: "cap.type.gcp.auth.service-account" -# # any revision -# attributes: -# - path: "cap.attribute.cloud.provider.gcp" -# # any revision -# inject: -# typeInstances: -# - id: "{uuid}" -# typeRef: -# path: "cap.type.gcp.auth.service-account" -# revision: "0.1.0" -# - implementationConstraints: -# attributes: -# - path: cap.attribute.cloud.provider.aws -# # any revision -# - implementationConstraints: -# path: cap.implementation.bitnami.postgresql.install -# - interface: -# # Rules for exact path in any revision (looked up in second place) -# path: "cap.interface.database.postgresql.install" -# oneOf: -# - implementationConstraints: -# requires: -# - path: "cap.type.gcp.auth.service-account" -# # any revision -# attributes: -# - path: "cap.attribute.cloud.provider.gcp" -# # any revision - - - interface: - # any other Interface (looked up in third place, if there is no rule for `path` and `revision` or `path`) - path: "cap.*" - oneOf: - - implementationConstraints: # prefer Implementation for Kubernetes - requires: - - path: "cap.core.type.platform.kubernetes" - # any revision - - implementationConstraints: {} # fallback to any Implementation - -testSetup: - enabled: false - globalPolicyRules: - - interface: - path: "cap.interface.capactio.capact.validation.action.passing" - oneOf: - - implementationConstraints: - requires: - - path: "cap.type.capactio.capact.validation.single-key" - attributes: - - path: "cap.attribute.capactio.capact.validation.policy.most-preferred" - inject: - requiredTypeInstances: [] # DO NOT MODIFY this line, as it is found and replaced during integration tests - - implementationConstraints: - path: cap.implementation.capactio.capact.validation.action.passing-a +# interface: +# rules: +# - interface: +# # Rules for exact path and revision (looked up in first place) +# path: "cap.interface.database.postgresql.install" +# revision: "0.1.0" +# oneOf: +# - implementationConstraints: +# requires: +# - path: "cap.type.gcp.auth.service-account" +# # any revision +# attributes: +# - path: "cap.attribute.cloud.provider.gcp" +# # any revision +# inject: +# typeInstances: +# - id: "{uuid}" +# typeRef: +# path: "cap.type.gcp.auth.service-account" +# revision: "0.1.0" +# - implementationConstraints: +# attributes: +# - path: cap.attribute.cloud.provider.aws +# # any revision +# - implementationConstraints: +# path: cap.implementation.bitnami.postgresql.install +# - interface: +# # Rules for exact path in any revision (looked up in second place) +# path: "cap.interface.database.postgresql.install" +# oneOf: +# - implementationConstraints: +# requires: +# - path: "cap.type.gcp.auth.service-account" +# # any revision +# attributes: +# - path: "cap.attribute.cloud.provider.gcp" +# # any revision + interface: + rules: + - interface: + # any other Interface (looked up in third place, if there is no rule for `path` and `revision` or `path`) + path: "cap.*" + oneOf: + - implementationConstraints: # prefer Implementation for Kubernetes + requires: + - path: "cap.core.type.platform.kubernetes" + # any revision + - implementationConstraints: {} # fallback to any Implementation + +## Currently, not used but setting this filed is supported by all scripts and CLI. +#testSetup: +# enabled: false diff --git a/deploy/kubernetes/charts/capact/templates/tests/test-e2e.yaml b/deploy/kubernetes/charts/capact/templates/tests/test-e2e.yaml index 9fb56bc8e..49750ffcd 100644 --- a/deploy/kubernetes/charts/capact/templates/tests/test-e2e.yaml +++ b/deploy/kubernetes/charts/capact/templates/tests/test-e2e.yaml @@ -22,9 +22,5 @@ spec: value: "{{ .Values.global.gateway.auth.username }}" - name: GATEWAY_PASSWORD value: "{{ .Values.global.gateway.auth.password }}" - - name: APP_CLUSTER_POLICY_NAME - value: {{ include "capact.fullname" . }}-engine-cluster-policy - - name: APP_CLUSTER_POLICY_NAMESPACE - value: {{.Release.Namespace}} imagePullPolicy: {{ .Values.integrationTest.image.pullPolicy }} restartPolicy: Never diff --git a/hub-js/graphql/public/examples.graphql b/hub-js/graphql/public/examples.graphql index 26d6af96c..d59e24593 100644 --- a/hub-js/graphql/public/examples.graphql +++ b/hub-js/graphql/public/examples.graphql @@ -4,305 +4,305 @@ # To use all queries without specifying your own variables, use the JSON from `examples.variables.json` file. query RepoMetadata { - repoMetadata { - path - name - prefix - revision(revision: "0.1.0") { - ...RepoMetadataRevision - } - latestRevision { - ...RepoMetadataRevision - } - revisions { - ...RepoMetadataRevision + repoMetadata { + path + name + prefix + revision(revision: "0.1.0") { + ...RepoMetadataRevision + } + latestRevision { + ...RepoMetadataRevision + } + revisions { + ...RepoMetadataRevision + } } - } } # Example variables: {"interfaceGroupPath": "cap.interface.productivity.mattermost"} query InterfaceGroup($interfaceGroupPath: NodePath!) { - interfaceGroup(path: $interfaceGroupPath) { - ...InterfaceGroup - } + interfaceGroup(path: $interfaceGroupPath) { + ...InterfaceGroup + } } query InterfaceGroups { - interfaceGroups { - ...InterfaceGroup - } + interfaceGroups { + ...InterfaceGroup + } } # Example variables: {"interfaceGroupPathPattern": "cap.interface.*"} query InterfaceGroupsWithPrefixFilter( - $interfaceGroupPathPattern: NodePathPattern! + $interfaceGroupPathPattern: NodePathPattern! ) { - interfaceGroups(filter: { pathPattern: $interfaceGroupPathPattern }) { - ...InterfaceGroup - } + interfaceGroups(filter: { pathPattern: $interfaceGroupPathPattern }) { + ...InterfaceGroup + } } query InterfaceGroupsWithInterfacesAndImplementations { - interfaceGroups { - ...InterfaceGroup - interfaces { - name - prefix - path - revision(revision: "0.1.0") { - ...InterfaceRevision - } - latestRevision { - ...InterfaceRevision - } - revisions { - ...InterfaceRevision - ...ImplementationsForInterface - } - } - } + interfaceGroups { + ...InterfaceGroup + interfaces { + name + prefix + path + revision(revision: "0.1.0") { + ...InterfaceRevision + } + latestRevision { + ...InterfaceRevision + } + revisions { + ...InterfaceRevision + ...ImplementationsForInterface + } + } + } } # Example variables: {"interfacePath": "cap.interface.productivity.mattermost.install"} query Interface($interfacePath: NodePath!) { - interface(path: $interfacePath) { - name - prefix - path - revision(revision: "0.1.0") { - ...InterfaceRevision - } - latestRevision { - ...InterfaceRevision - } - revisions { - ...InterfaceRevision + interface(path: $interfacePath) { + name + prefix + path + revision(revision: "0.1.0") { + ...InterfaceRevision + } + latestRevision { + ...InterfaceRevision + } + revisions { + ...InterfaceRevision + } } - } } query Interfaces { - interfaces { - name - prefix - path - revision(revision: "0.1.0") { - ...InterfaceRevision - } - latestRevision { - ...InterfaceRevision - } - revisions { - ...InterfaceRevision + interfaces { + name + prefix + path + revision(revision: "0.1.0") { + ...InterfaceRevision + } + latestRevision { + ...InterfaceRevision + } + revisions { + ...InterfaceRevision + } } - } } query InterfacesWithImplementations { - interfaces { - path - revisions { - ...InterfaceRevision - ...ImplementationsForInterface + interfaces { + path + revisions { + ...InterfaceRevision + ...ImplementationsForInterface + } } - } } # Example variables: {"interfacesPathPattern": "cap.interface.*"} query InterfacesWithPrefixFilter($interfacesPathPattern: NodePathPattern!) { - interfaces(filter: { pathPattern: $interfacesPathPattern }) { - name - prefix - path - revision(revision: "0.1.0") { - ...InterfaceRevision - } - latestRevision { - ...InterfaceRevision - } - revisions { - ...InterfaceRevision + interfaces(filter: { pathPattern: $interfacesPathPattern }) { + name + prefix + path + revision(revision: "0.1.0") { + ...InterfaceRevision + } + latestRevision { + ...InterfaceRevision + } + revisions { + ...InterfaceRevision + } } - } } # Example variables: {"implementationPath": "cap.implementation.database.postgresql.create-db"} query Implementation($implementationPath: NodePath!) { - implementation(path: $implementationPath) { - name - prefix - path - revision(revision: "0.1.0") { - ...ImplementationRevision - } - latestRevision { - ...ImplementationRevision - } - revisions { - ...ImplementationRevision + implementation(path: $implementationPath) { + name + prefix + path + revision(revision: "0.1.0") { + ...ImplementationRevision + } + latestRevision { + ...ImplementationRevision + } + revisions { + ...ImplementationRevision + } } - } } query Implementations { - implementations { - name - prefix - path - revision(revision: "0.1.0") { - ...ImplementationRevision - } - latestRevision { - ...ImplementationRevision - } - revisions { - ...ImplementationRevision + implementations { + name + prefix + path + revision(revision: "0.1.0") { + ...ImplementationRevision + } + latestRevision { + ...ImplementationRevision + } + revisions { + ...ImplementationRevision + } } - } } # Example variables: {"implementationsPathPattern": "cap.implementation.gcp.*"} query ImplementationsWithPrefixFilter( - $implementationsPathPattern: NodePathPattern! + $implementationsPathPattern: NodePathPattern! ) { - implementations(filter: { pathPattern: $implementationsPathPattern }) { - name - prefix - path - revision(revision: "0.1.0") { - ...ImplementationRevision - } - latestRevision { - ...ImplementationRevision - } - revisions { - ...ImplementationRevision + implementations(filter: { pathPattern: $implementationsPathPattern }) { + name + prefix + path + revision(revision: "0.1.0") { + ...ImplementationRevision + } + latestRevision { + ...ImplementationRevision + } + revisions { + ...ImplementationRevision + } } - } } # Example variables: {"typePath": "cap.core.type.networking.hostname"} query Type($typePath: NodePath!) { - type(path: $typePath) { - name - prefix - path - revision(revision: "0.1.0") { - ...TypeRevision - } - latestRevision { - ...TypeRevision - } - revisions { - ...TypeRevision + type(path: $typePath) { + name + prefix + path + revision(revision: "0.1.0") { + ...TypeRevision + } + latestRevision { + ...TypeRevision + } + revisions { + ...TypeRevision + } } - } } query Types { - types { - name - prefix - path - revision(revision: "0.1.0") { - ...TypeRevision - } - latestRevision { - ...TypeRevision - } - revisions { - ...TypeRevision + types { + name + prefix + path + revision(revision: "0.1.0") { + ...TypeRevision + } + latestRevision { + ...TypeRevision + } + revisions { + ...TypeRevision + } } - } } # Example variables: {"typesPathPattern": "cap.core.type.*"} query TypesWithPrefixFilter($typesPathPattern: NodePathPattern!) { - types(filter: { pathPattern: $typesPathPattern }) { - name - prefix - path - revision(revision: "0.1.0") { - ...TypeRevision - } - latestRevision { - ...TypeRevision - } - revisions { - ...TypeRevision + types(filter: { pathPattern: $typesPathPattern }) { + name + prefix + path + revision(revision: "0.1.0") { + ...TypeRevision + } + latestRevision { + ...TypeRevision + } + revisions { + ...TypeRevision + } } - } } query TypesWithORPrefixFilter { - types( - filter: { - pathPattern: "(cap.core.type.generic.value|cap.type.platform.cloud-foundry)" - } - ) { - prefix - path - revisions { - revision - spec { - additionalRefs - } + types( + filter: { + pathPattern: "(cap.core.type.generic.value|cap.type.platform.nomad)" + } + ) { + prefix + path + revisions { + revision + spec { + additionalRefs + } + } } - } } # Example variables: {"attributePath": "cap.core.attribute.workload.stateless"} query Attribute($attributePath: NodePath!) { - attribute(path: $attributePath) { - name - prefix - path - revision(revision: "0.1.0") { - ...AttributeRevision - } - latestRevision { - ...AttributeRevision - } - revisions { - ...AttributeRevision + attribute(path: $attributePath) { + name + prefix + path + revision(revision: "0.1.0") { + ...AttributeRevision + } + latestRevision { + ...AttributeRevision + } + revisions { + ...AttributeRevision + } } - } } query Attributes { - attributes { - name - prefix - path - revision(revision: "0.1.0") { - ...AttributeRevision - } - latestRevision { - ...AttributeRevision - } - revisions { - ...AttributeRevision + attributes { + name + prefix + path + revision(revision: "0.1.0") { + ...AttributeRevision + } + latestRevision { + ...AttributeRevision + } + revisions { + ...AttributeRevision + } } - } } # Lists all Attributes with a given prefix. # Example variables: {"attributesPathPattern": "cap.core.attribute.workload.*"} query AttributesWithPrefixFilter($attributesPathPattern: NodePathPattern!) { - attributes(filter: { pathPattern: $attributesPathPattern }) { - name - prefix - path - revision(revision: "0.1.0") { - ...AttributeRevision - } - latestRevision { - ...AttributeRevision - } - revisions { - ...AttributeRevision + attributes(filter: { pathPattern: $attributesPathPattern }) { + name + prefix + path + revision(revision: "0.1.0") { + ...AttributeRevision + } + latestRevision { + ...AttributeRevision + } + revisions { + ...AttributeRevision + } } - } } # @@ -310,218 +310,218 @@ query AttributesWithPrefixFilter($attributesPathPattern: NodePathPattern!) { # fragment InterfaceGroup on InterfaceGroup { - metadata { - ...GenericMetadata - } - interfaces { - name - prefix - path - revision(revision: "0.1.0") { - ...InterfaceRevision - } - latestRevision { - ...InterfaceRevision + metadata { + ...GenericMetadata } - revisions { - ...InterfaceRevision + interfaces { + name + prefix + path + revision(revision: "0.1.0") { + ...InterfaceRevision + } + latestRevision { + ...InterfaceRevision + } + revisions { + ...InterfaceRevision + } } - } } fragment GenericMetadata on MetadataBaseFields { - prefix - path - name - displayName - description - maintainers { - name - email - } - iconURL - documentationURL - supportURL - iconURL -} - -fragment InterfaceRevision on InterfaceRevision { - metadata { prefix path name displayName description maintainers { - name - email + name + email } iconURL - } - revision - spec { - input { - parameters { - name - jsonSchema - } - typeInstances { + documentationURL + supportURL + iconURL +} + +fragment InterfaceRevision on InterfaceRevision { + metadata { + prefix + path name - typeRef { - path - revision + displayName + description + maintainers { + name + email } - verbs - } - } - output { - typeInstances { - name - typeRef { - path - revision + iconURL + } + revision + spec { + input { + parameters { + name + jsonSchema + } + typeInstances { + name + typeRef { + path + revision + } + verbs + } + } + output { + typeInstances { + name + typeRef { + path + revision + } + } } - } } - } } fragment ImplementationRevision on ImplementationRevision { - metadata { - ...GenericMetadata - attributes { - ...AttributeRevision - } - } - revision - spec { - appVersion - implements { - path - revision - } - requires { - prefix - oneOf { - alias - typeRef { - path - revision - } - valueConstraints - } - anyOf { - alias - typeRef { - path - revision - } - valueConstraints - } - allOf { - alias - typeRef { - path - revision - } - valueConstraints - } - } - imports { - interfaceGroupPath - alias - appVersion - methods { - name - revision - } + metadata { + ...GenericMetadata + attributes { + ...AttributeRevision + } } - additionalInput { - typeInstances { - name - typeRef { - path - revision + revision + spec { + appVersion + implements { + path + revision } - verbs - } - parameters { - typeRef { - path - revision + requires { + prefix + oneOf { + alias + typeRef { + path + revision + } + valueConstraints + } + anyOf { + alias + typeRef { + path + revision + } + valueConstraints + } + allOf { + alias + typeRef { + path + revision + } + valueConstraints + } } - } - } - additionalOutput { - typeInstances { - name - typeRef { - path - revision + imports { + interfaceGroupPath + alias + appVersion + methods { + name + revision + } + } + additionalInput { + typeInstances { + name + typeRef { + path + revision + } + verbs + } + parameters { + typeRef { + path + revision + } + } + } + additionalOutput { + typeInstances { + name + typeRef { + path + revision + } + } + } + outputTypeInstanceRelations { + typeInstanceName + uses + } + action { + runnerInterface + args } - } - } - outputTypeInstanceRelations { - typeInstanceName - uses - } - action { - runnerInterface - args } - } } fragment AttributeRevision on AttributeRevision { - metadata { - ...GenericMetadata - } - revision - spec { - additionalRefs - } + metadata { + ...GenericMetadata + } + revision + spec { + additionalRefs + } } fragment TypeRevision on TypeRevision { - revision - metadata { - ...GenericMetadata - attributes { - ...AttributeRevision + revision + metadata { + ...GenericMetadata + attributes { + ...AttributeRevision + } + } + spec { + additionalRefs + jsonSchema } - } - spec { - additionalRefs - jsonSchema - } } fragment RepoMetadataRevision on RepoMetadataRevision { - revision - metadata { - ...GenericMetadata - } - spec { - hubVersion - ocfVersion { - supported - default - } - implementation { - appVersion { - semVerTaggingStrategy { - latest { - pointsTo - } - } - } - } - } + revision + metadata { + ...GenericMetadata + } + spec { + hubVersion + ocfVersion { + supported + default + } + implementation { + appVersion { + semVerTaggingStrategy { + latest { + pointsTo + } + } + } + } + } } # Additional resolvers for Interface fragment ImplementationsForInterface on InterfaceRevision { - implementationRevisions { - ...ImplementationRevision - } + implementationRevisions { + ...ImplementationRevision + } } diff --git a/internal/cli/action/create_opts.go b/internal/cli/action/create_opts.go index 09bf9b9d9..3c77c85f5 100644 --- a/internal/cli/action/create_opts.go +++ b/internal/cli/action/create_opts.go @@ -304,12 +304,13 @@ func askForActionPolicy(ifacePath string) (*gqlengine.PolicyInput, error) { prompt := &survey.Editor{ Message: "Please type one-time Action policy in YAML format", Default: heredoc.Doc(fmt.Sprintf(` - rules: - - interface: - path: "%s" - oneOf: - - implementationConstraints: - path: "" + interface: + rules: + - interface: + path: "%s" + oneOf: + - implementationConstraints: + path: "" `, ifacePath)), AppendDefault: true, HideDefault: true, diff --git a/internal/cli/policy/edit.go b/internal/cli/policy/edit.go index 3e3c0c735..68d558dde 100644 --- a/internal/cli/policy/edit.go +++ b/internal/cli/policy/edit.go @@ -9,7 +9,6 @@ import ( "capact.io/capact/internal/cli/config" "capact.io/capact/pkg/engine/api/graphql" "github.com/AlecAivazis/survey/v2" - "github.com/MakeNowJust/heredoc" "github.com/fatih/color" "sigs.k8s.io/yaml" ) @@ -56,7 +55,7 @@ func askForPolicyInput(existingPolicy *graphql.Policy) (*graphql.PolicyInput, er editor := "" prompt := &survey.Editor{ Message: "Edit current Policy using YAML syntax", - Default: heredoc.Doc(policyStr), + Default: policyStr, AppendDefault: true, HideDefault: true, } diff --git a/internal/k8s-engine/graphql/domain/action/fixtures_test.go b/internal/k8s-engine/graphql/domain/action/fixtures_test.go index ebefbf5c8..0003a199a 100644 --- a/internal/k8s-engine/graphql/domain/action/fixtures_test.go +++ b/internal/k8s-engine/graphql/domain/action/fixtures_test.go @@ -302,33 +302,35 @@ func fixGQLInputActionPolicy() *graphql.PolicyInput { } return &graphql.PolicyInput{ - Rules: []*graphql.RulesForInterfaceInput{ - { - Interface: &graphql.ManifestReferenceInput{ - Path: "cap.interface.dummy", - }, - OneOf: []*graphql.PolicyRuleInput{ - { - ImplementationConstraints: &graphql.PolicyRuleImplementationConstraintsInput{ - Path: ptr.String("cap.implementation.dummy"), - }, - Inject: &graphql.PolicyRuleInjectDataInput{ - RequiredTypeInstances: []*graphql.RequiredTypeInstanceReferenceInput{ - { - ID: "policy-ti-id", - Description: ptr.String("Sample description"), - }, + Interface: &graphql.InterfacePolicyInput{ + Rules: []*graphql.RulesForInterfaceInput{ + { + Interface: &graphql.ManifestReferenceInput{ + Path: "cap.interface.dummy", + }, + OneOf: []*graphql.PolicyRuleInput{ + { + ImplementationConstraints: &graphql.PolicyRuleImplementationConstraintsInput{ + Path: ptr.String("cap.implementation.dummy"), }, - AdditionalParameters: []*graphql.AdditionalParameterInput{ - { - Name: "additional-parameters", - Value: additionalInput, + Inject: &graphql.PolicyRuleInjectDataInput{ + RequiredTypeInstances: []*graphql.RequiredTypeInstanceReferenceInput{ + { + ID: "policy-ti-id", + Description: ptr.String("Sample description"), + }, }, - }, - AdditionalTypeInstances: []*graphql.AdditionalTypeInstanceReferenceInput{ - { - Name: "additional-ti", - ID: "additional-ti-id", + AdditionalParameters: []*graphql.AdditionalParameterInput{ + { + Name: "additional-parameters", + Value: additionalInput, + }, + }, + AdditionalTypeInstances: []*graphql.AdditionalTypeInstanceReferenceInput{ + { + Name: "additional-ti", + ID: "additional-ti-id", + }, }, }, }, @@ -430,7 +432,7 @@ func fixModelInputSecret(name string, paramsEnabled, policyEnabled bool) *corev1 sec.StringData["parameter-input-parameters"] = `{"param":"one"}` } if policyEnabled { - sec.StringData["action-policy.json"] = `{"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"}]}}]}]}` + 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"}]}}]}]}}` } return sec diff --git a/internal/k8s-engine/graphql/domain/policy/converter.go b/internal/k8s-engine/graphql/domain/policy/converter.go index 746793c66..21980bd4b 100644 --- a/internal/k8s-engine/graphql/domain/policy/converter.go +++ b/internal/k8s-engine/graphql/domain/policy/converter.go @@ -17,27 +17,46 @@ func NewConverter() *Converter { // FromGraphQLInput coverts Graphql Policy data to model. func (c *Converter) FromGraphQLInput(in graphql.PolicyInput) (policy.Policy, error) { + ifaceRules, err := c.interfaceFromGraphQLInput(in.Interface) + if err != nil { + return policy.Policy{}, err + } + + return policy.Policy{ + Interface: ifaceRules, + }, nil +} + +func (c *Converter) interfaceFromGraphQLInput(in *graphql.InterfacePolicyInput) (policy.InterfacePolicy, error) { + if in == nil { + return policy.InterfacePolicy{}, nil + } var rules policy.RulesList for _, gqlRule := range in.Rules { + iface := c.manifestRefFromGraphQLInput(gqlRule.Interface) policyRules, err := c.policyRulesFromGraphQLInput(gqlRule.OneOf) if err != nil { - return policy.Policy{}, errors.Wrap(err, "while getting Policy rules") + return policy.InterfacePolicy{}, errors.Wrapf(err, "while converting 'OneOf' rules for %q", iface.String()) } rules = append(rules, policy.RulesForInterface{ - Interface: c.manifestRefFromGraphQLInput(gqlRule.Interface), + Interface: iface, OneOf: policyRules, }) } - return policy.Policy{ - Rules: rules, - }, nil + return policy.InterfacePolicy{Rules: rules}, nil } // ToGraphQL converts Policy model representation to GraphQL DTO. func (c *Converter) ToGraphQL(in policy.Policy) graphql.Policy { + return graphql.Policy{ + Interface: c.interfaceToGraphQL(in.Interface), + } +} + +func (c *Converter) interfaceToGraphQL(in policy.InterfacePolicy) *graphql.InterfacePolicy { var gqlRules []*graphql.RulesForInterface for _, rule := range in.Rules { @@ -47,7 +66,7 @@ func (c *Converter) ToGraphQL(in policy.Policy) graphql.Policy { }) } - return graphql.Policy{ + return &graphql.InterfacePolicy{ Rules: gqlRules, } } diff --git a/internal/k8s-engine/graphql/domain/policy/converter_test.go b/internal/k8s-engine/graphql/domain/policy/converter_test.go index 7249f307a..f4dadf7d4 100644 --- a/internal/k8s-engine/graphql/domain/policy/converter_test.go +++ b/internal/k8s-engine/graphql/domain/policy/converter_test.go @@ -23,6 +23,23 @@ func TestConverter_FromGraphQLInput_HappyPath(t *testing.T) { assert.Equal(t, expectedModel, actualModel) } +func TestConverter_FromGraphQLInput_Failure(t *testing.T) { + // given + gqlInput := fixGQLInput() + + // simulate wrong additional params format + gqlInput.Interface.Rules[0].OneOf[0].Inject.AdditionalParameters[0].Value = "string" + + expErrMsg := `while converting 'OneOf' rules for "cap.interface.database.postgresql.install:0.1.0": while getting Policy inject data: while converting additional parameters: additional input cannot be converted to map[string]interface{}` + c := policy.NewConverter() + + // when + _, err := c.FromGraphQLInput(gqlInput) + + // then + assert.EqualError(t, err, expErrMsg) +} + func TestConverter_ToGraphQL_HappyPath(t *testing.T) { // given input := fixModel() diff --git a/internal/k8s-engine/graphql/domain/policy/fixtures_test.go b/internal/k8s-engine/graphql/domain/policy/fixtures_test.go index 84e2030a3..1d1cf4a70 100644 --- a/internal/k8s-engine/graphql/domain/policy/fixtures_test.go +++ b/internal/k8s-engine/graphql/domain/policy/fixtures_test.go @@ -9,64 +9,66 @@ import ( func fixGQLInput() graphql.PolicyInput { return graphql.PolicyInput{ - Rules: []*graphql.RulesForInterfaceInput{ - { - Interface: &graphql.ManifestReferenceInput{ - Path: "cap.interface.database.postgresql.install", - Revision: ptr.String("0.1.0"), - }, - OneOf: []*graphql.PolicyRuleInput{ - { - ImplementationConstraints: &graphql.PolicyRuleImplementationConstraintsInput{ - Requires: []*graphql.ManifestReferenceInput{ - { - Path: "cap.type.gcp.auth.service-account", - Revision: ptr.String("0.1.0"), + Interface: &graphql.InterfacePolicyInput{ + Rules: []*graphql.RulesForInterfaceInput{ + { + Interface: &graphql.ManifestReferenceInput{ + Path: "cap.interface.database.postgresql.install", + Revision: ptr.String("0.1.0"), + }, + OneOf: []*graphql.PolicyRuleInput{ + { + ImplementationConstraints: &graphql.PolicyRuleImplementationConstraintsInput{ + Requires: []*graphql.ManifestReferenceInput{ + { + Path: "cap.type.gcp.auth.service-account", + Revision: ptr.String("0.1.0"), + }, }, - }, - Attributes: []*graphql.ManifestReferenceInput{ - { - Path: "cap.attribute.cloud.provider.gcp", + Attributes: []*graphql.ManifestReferenceInput{ + { + Path: "cap.attribute.cloud.provider.gcp", + }, }, }, - }, - Inject: &graphql.PolicyRuleInjectDataInput{ - RequiredTypeInstances: []*graphql.RequiredTypeInstanceReferenceInput{ - { - ID: "c268d3f5-8834-434b-bea2-b677793611c5", - Description: ptr.String("Sample description"), + Inject: &graphql.PolicyRuleInjectDataInput{ + RequiredTypeInstances: []*graphql.RequiredTypeInstanceReferenceInput{ + { + ID: "c268d3f5-8834-434b-bea2-b677793611c5", + Description: ptr.String("Sample description"), + }, }, - }, - AdditionalParameters: []*graphql.AdditionalParameterInput{ - { - Name: "additional-parameters", - Value: map[string]interface{}{ - "key1": "boom", + AdditionalParameters: []*graphql.AdditionalParameterInput{ + { + Name: "additional-parameters", + Value: map[string]interface{}{ + "key1": "boom", + }, }, }, - }, - AdditionalTypeInstances: []*graphql.AdditionalTypeInstanceReferenceInput{ - { - Name: "sample", - ID: "0b6dba9a-d111-419d-b236-357cf0e8603a", + AdditionalTypeInstances: []*graphql.AdditionalTypeInstanceReferenceInput{ + { + Name: "sample", + ID: "0b6dba9a-d111-419d-b236-357cf0e8603a", + }, }, }, }, - }, - { - ImplementationConstraints: &graphql.PolicyRuleImplementationConstraintsInput{ - Path: ptr.String("cap.implementation.bitnami.postgresql.install"), + { + ImplementationConstraints: &graphql.PolicyRuleImplementationConstraintsInput{ + Path: ptr.String("cap.implementation.bitnami.postgresql.install"), + }, }, }, }, - }, - { - Interface: &graphql.ManifestReferenceInput{ - Path: "cap.*", - }, - OneOf: []*graphql.PolicyRuleInput{ - { - ImplementationConstraints: &graphql.PolicyRuleImplementationConstraintsInput{}, + { + Interface: &graphql.ManifestReferenceInput{ + Path: "cap.*", + }, + OneOf: []*graphql.PolicyRuleInput{ + { + ImplementationConstraints: &graphql.PolicyRuleImplementationConstraintsInput{}, + }, }, }, }, @@ -76,64 +78,66 @@ func fixGQLInput() graphql.PolicyInput { func fixGQL() graphql.Policy { return graphql.Policy{ - Rules: []*graphql.RulesForInterface{ - { - Interface: &graphql.ManifestReferenceWithOptionalRevision{ - Path: "cap.interface.database.postgresql.install", - Revision: ptr.String("0.1.0"), - }, - OneOf: []*graphql.PolicyRule{ - { - ImplementationConstraints: &graphql.PolicyRuleImplementationConstraints{ - Requires: []*graphql.ManifestReferenceWithOptionalRevision{ - { - Path: "cap.type.gcp.auth.service-account", - Revision: ptr.String("0.1.0"), + Interface: &graphql.InterfacePolicy{ + Rules: []*graphql.RulesForInterface{ + { + Interface: &graphql.ManifestReferenceWithOptionalRevision{ + Path: "cap.interface.database.postgresql.install", + Revision: ptr.String("0.1.0"), + }, + OneOf: []*graphql.PolicyRule{ + { + ImplementationConstraints: &graphql.PolicyRuleImplementationConstraints{ + Requires: []*graphql.ManifestReferenceWithOptionalRevision{ + { + Path: "cap.type.gcp.auth.service-account", + Revision: ptr.String("0.1.0"), + }, }, - }, - Attributes: []*graphql.ManifestReferenceWithOptionalRevision{ - { - Path: "cap.attribute.cloud.provider.gcp", + Attributes: []*graphql.ManifestReferenceWithOptionalRevision{ + { + Path: "cap.attribute.cloud.provider.gcp", + }, }, }, - }, - Inject: &graphql.PolicyRuleInjectData{ - RequiredTypeInstances: []*graphql.RequiredTypeInstanceReference{ - { - ID: "c268d3f5-8834-434b-bea2-b677793611c5", - Description: ptr.String("Sample description"), + Inject: &graphql.PolicyRuleInjectData{ + RequiredTypeInstances: []*graphql.RequiredTypeInstanceReference{ + { + ID: "c268d3f5-8834-434b-bea2-b677793611c5", + Description: ptr.String("Sample description"), + }, }, - }, - AdditionalParameters: []*graphql.AdditionalParameter{ - { - Name: "additional-parameters", - Value: map[string]interface{}{ - "key1": "boom", + AdditionalParameters: []*graphql.AdditionalParameter{ + { + Name: "additional-parameters", + Value: map[string]interface{}{ + "key1": "boom", + }, }, }, - }, - AdditionalTypeInstances: []*graphql.AdditionalTypeInstanceReference{ - { - Name: "sample", - ID: "0b6dba9a-d111-419d-b236-357cf0e8603a", + AdditionalTypeInstances: []*graphql.AdditionalTypeInstanceReference{ + { + Name: "sample", + ID: "0b6dba9a-d111-419d-b236-357cf0e8603a", + }, }, }, }, - }, - { - ImplementationConstraints: &graphql.PolicyRuleImplementationConstraints{ - Path: ptr.String("cap.implementation.bitnami.postgresql.install"), + { + ImplementationConstraints: &graphql.PolicyRuleImplementationConstraints{ + Path: ptr.String("cap.implementation.bitnami.postgresql.install"), + }, }, }, }, - }, - { - Interface: &graphql.ManifestReferenceWithOptionalRevision{ - Path: "cap.*", - }, - OneOf: []*graphql.PolicyRule{ - { - ImplementationConstraints: &graphql.PolicyRuleImplementationConstraints{}, + { + Interface: &graphql.ManifestReferenceWithOptionalRevision{ + Path: "cap.*", + }, + OneOf: []*graphql.PolicyRule{ + { + ImplementationConstraints: &graphql.PolicyRuleImplementationConstraints{}, + }, }, }, }, @@ -143,68 +147,70 @@ func fixGQL() graphql.Policy { func fixModel() policy.Policy { return policy.Policy{ - Rules: policy.RulesList{ - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.interface.database.postgresql.install", - Revision: ptr.String("0.1.0"), - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Requires: &[]types.ManifestRefWithOptRevision{ - { - Path: "cap.type.gcp.auth.service-account", - Revision: ptr.String("0.1.0"), + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.interface.database.postgresql.install", + Revision: ptr.String("0.1.0"), + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Requires: &[]types.ManifestRefWithOptRevision{ + { + Path: "cap.type.gcp.auth.service-account", + Revision: ptr.String("0.1.0"), + }, }, - }, - Attributes: &[]types.ManifestRefWithOptRevision{ - { - Path: "cap.attribute.cloud.provider.gcp", + Attributes: &[]types.ManifestRefWithOptRevision{ + { + Path: "cap.attribute.cloud.provider.gcp", + }, }, }, - }, - Inject: &policy.InjectData{ - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "c268d3f5-8834-434b-bea2-b677793611c5", - Description: ptr.String("Sample description"), + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "c268d3f5-8834-434b-bea2-b677793611c5", + Description: ptr.String("Sample description"), + }, }, }, - }, - AdditionalParameters: []policy.AdditionalParametersToInject{ - { - Name: "additional-parameters", - Value: map[string]interface{}{ - "key1": "boom", + AdditionalParameters: []policy.AdditionalParametersToInject{ + { + Name: "additional-parameters", + Value: map[string]interface{}{ + "key1": "boom", + }, }, }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - Name: "sample", - ID: "0b6dba9a-d111-419d-b236-357cf0e8603a", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + Name: "sample", + ID: "0b6dba9a-d111-419d-b236-357cf0e8603a", + }, }, }, }, }, - }, - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: ptr.String("cap.implementation.bitnami.postgresql.install"), + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: ptr.String("cap.implementation.bitnami.postgresql.install"), + }, }, }, }, - }, - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.*", - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{}, + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.*", + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{}, + }, }, }, }, diff --git a/internal/k8s-engine/policy/fixtures_test.go b/internal/k8s-engine/policy/fixtures_test.go index 6f8f1c59b..9e1f8064a 100644 --- a/internal/k8s-engine/policy/fixtures_test.go +++ b/internal/k8s-engine/policy/fixtures_test.go @@ -32,52 +32,54 @@ func fixCfgMap(t *testing.T, in policy.Policy) *v1.ConfigMap { func fixModel() policy.Policy { return policy.Policy{ - Rules: policy.RulesList{ - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.interface.database.postgresql.install", - Revision: ptr.String("0.1.0"), - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Requires: &[]types.ManifestRefWithOptRevision{ - { - Path: "cap.type.gcp.auth.service-account", - Revision: ptr.String("0.1.0"), + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.interface.database.postgresql.install", + Revision: ptr.String("0.1.0"), + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Requires: &[]types.ManifestRefWithOptRevision{ + { + Path: "cap.type.gcp.auth.service-account", + Revision: ptr.String("0.1.0"), + }, }, - }, - Attributes: &[]types.ManifestRefWithOptRevision{ - { - Path: "cap.attribute.cloud.provider.gcp", + Attributes: &[]types.ManifestRefWithOptRevision{ + { + Path: "cap.attribute.cloud.provider.gcp", + }, }, }, - }, - Inject: &policy.InjectData{ - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "c268d3f5-8834-434b-bea2-b677793611c5", - Description: ptr.String("Sample description"), + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "c268d3f5-8834-434b-bea2-b677793611c5", + Description: ptr.String("Sample description"), + }, }, }, }, }, - }, - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: ptr.String("cap.implementation.bitnami.postgresql.install"), + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: ptr.String("cap.implementation.bitnami.postgresql.install"), + }, }, }, }, - }, - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.*", - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{}, + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.*", + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{}, + }, }, }, }, diff --git a/internal/k8s-engine/policy/service_test.go b/internal/k8s-engine/policy/service_test.go index 25e20ddc9..f4ca49e45 100644 --- a/internal/k8s-engine/policy/service_test.go +++ b/internal/k8s-engine/policy/service_test.go @@ -32,8 +32,8 @@ func TestService_Update(t *testing.T) { svc, k8sCli := newServiceWithFakeClient(t, cfgMap) // change few properties in model - model.Rules[0].Interface.Path = "cap.interface.updated.path" - model.Rules[1].OneOf = []policy.Rule{ + model.Interface.Rules[0].Interface.Path = "cap.interface.updated.path" + model.Interface.Rules[1].OneOf = []policy.Rule{ { ImplementationConstraints: policy.ImplementationConstraints{ Requires: &[]types.ManifestRefWithOptRevision{ diff --git a/ocf-spec/0.0.1/examples/implementation.yaml b/ocf-spec/0.0.1/examples/implementation.yaml index 98f9381bc..9e3c98f80 100644 --- a/ocf-spec/0.0.1/examples/implementation.yaml +++ b/ocf-spec/0.0.1/examples/implementation.yaml @@ -61,7 +61,7 @@ spec: alias: k8s valueConstraints: version: "1.14.x, 1.15.x" - - name: cap.type.platform.cloudFoundry + - name: cap.type.platform.nomad revision: 0.0.1 valueConstraints: version: "2.33.0, 2.34.x" diff --git a/pkg/engine/api/graphql/examples.graphql b/pkg/engine/api/graphql/examples.graphql index 6eab59be0..e693924f3 100644 --- a/pkg/engine/api/graphql/examples.graphql +++ b/pkg/engine/api/graphql/examples.graphql @@ -165,58 +165,63 @@ query Policy { mutation UpdatePolicy { updatePolicy( in: { - rules: [ - { - interface: { - path: "cap.interface.capactio.capact.validation.hub.install" - } - oneOf: [ - { - implementationConstraints: { - path: "cap.implementation.capactio.capact.validation.io.install" - } - inject: { - requiredTypeInstances: [{ - id: "edf854df-86cf-4855-9d38-8d88545fb9c9" - description: "My TypeInstance" - }] - additionalParameters: [ - { - name: "mattermost-parameters" - value: { revisionHistoryLimit: 123 } - } - { - name: "rocketchat-parameters" - value: { replicaCount: 3 } - } - ] - } + interface: { + rules: [ + { + interface: { + path: "cap.interface.capactio.capact.validation.hub.install" } - { - implementationConstraints: { - requires: { path: "cap.core.type.platform.kubernetes" } + oneOf: [ + { + implementationConstraints: { + path: "cap.implementation.capactio.capact.validation.io.install" + } + inject: { + requiredTypeInstances: [ + { + id: "edf854df-86cf-4855-9d38-8d88545fb9c9" + description: "My TypeInstance" + } + ] + additionalParameters: [ + { + name: "mattermost-parameters" + value: { revisionHistoryLimit: 123 } + } + { + name: "rocketchat-parameters" + value: { replicaCount: 3 } + } + ] + } } - } - ] - } - { - interface: { path: "cap.*" } - oneOf: [ - { - implementationConstraints: { - requires: { path: "cap.core.type.platform.kubernetes" } + { + implementationConstraints: { + requires: { path: "cap.core.type.platform.kubernetes" } + } } - } - {} - ] - } - ] + ] + } + { + interface: { path: "cap.*" } + oneOf: [ + { + implementationConstraints: { + requires: { path: "cap.core.type.platform.kubernetes" } + } + } + {} + ] + } + ] + } } ) { ...PolicyFields } } + # # Fragments with all possible fields for Engine entities # @@ -288,35 +293,37 @@ fragment ActionFields on Action { } fragment PolicyFields on Policy { - rules { - interface { - path - revision - } - oneOf { - implementationConstraints { - requires { - path - revision - } - attributes { - path - revision - } + interface { + rules { + interface { path + revision } - inject { - requiredTypeInstances { - id - description - } - additionalParameters { - name - value + oneOf { + implementationConstraints { + requires { + path + revision + } + attributes { + path + revision + } + path } - additionalTypeInstances { - name - id + inject { + requiredTypeInstances { + id + description + } + additionalParameters { + name + value + } + additionalTypeInstances { + name + id + } } } } diff --git a/pkg/engine/api/graphql/models_gen.go b/pkg/engine/api/graphql/models_gen.go index abfb00d9e..9e507c82d 100644 --- a/pkg/engine/api/graphql/models_gen.go +++ b/pkg/engine/api/graphql/models_gen.go @@ -137,6 +137,14 @@ type InputTypeInstanceToProvide struct { TypeRef *ManifestReference `json:"typeRef"` } +type InterfacePolicy struct { + Rules []*RulesForInterface `json:"rules"` +} + +type InterfacePolicyInput struct { + Rules []*RulesForInterfaceInput `json:"rules"` +} + type ManifestReference struct { Path string `json:"path"` Revision string `json:"revision"` @@ -156,11 +164,11 @@ type OutputTypeInstanceDetails struct { } type Policy struct { - Rules []*RulesForInterface `json:"rules"` + Interface *InterfacePolicy `json:"interface"` } type PolicyInput struct { - Rules []*RulesForInterfaceInput `json:"rules"` + Interface *InterfacePolicyInput `json:"interface"` } type PolicyRuleImplementationConstraintsInput struct { diff --git a/pkg/engine/api/graphql/schema.graphql b/pkg/engine/api/graphql/schema.graphql index 2ed150350..ca7d4c5b9 100644 --- a/pkg/engine/api/graphql/schema.graphql +++ b/pkg/engine/api/graphql/schema.graphql @@ -303,7 +303,11 @@ enum ActionStatusPhase { } input PolicyInput { - rules: [RulesForInterfaceInput!]! + interface: InterfacePolicyInput +} + +input InterfacePolicyInput { + rules: [RulesForInterfaceInput!]! } input RulesForInterfaceInput { @@ -345,7 +349,11 @@ input PolicyRuleImplementationConstraintsInput { } type Policy { - rules: [RulesForInterface!]! + interface: InterfacePolicy +} + +type InterfacePolicy { + rules: [RulesForInterface!]! } type RulesForInterface { diff --git a/pkg/engine/api/graphql/schema_gen.go b/pkg/engine/api/graphql/schema_gen.go index 06a7dee02..f3134b4ce 100644 --- a/pkg/engine/api/graphql/schema_gen.go +++ b/pkg/engine/api/graphql/schema_gen.go @@ -102,6 +102,10 @@ type ComplexityRoot struct { TypeRef func(childComplexity int) int } + InterfacePolicy struct { + Rules func(childComplexity int) int + } + ManifestReference struct { Path func(childComplexity int) int Revision func(childComplexity int) int @@ -128,7 +132,7 @@ type ComplexityRoot struct { } Policy struct { - Rules func(childComplexity int) int + Interface func(childComplexity int) int } PolicyRule struct { @@ -436,6 +440,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.InputTypeInstanceToProvide.TypeRef(childComplexity), true + case "InterfacePolicy.rules": + if e.complexity.InterfacePolicy.Rules == nil { + break + } + + return e.complexity.InterfacePolicy.Rules(childComplexity), true + case "ManifestReference.path": if e.complexity.ManifestReference.Path == nil { break @@ -562,12 +573,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.OutputTypeInstanceDetails.TypeRef(childComplexity), true - case "Policy.rules": - if e.complexity.Policy.Rules == nil { + case "Policy.interface": + if e.complexity.Policy.Interface == nil { break } - return e.complexity.Policy.Rules(childComplexity), true + return e.complexity.Policy.Interface(childComplexity), true case "PolicyRule.implementationConstraints": if e.complexity.PolicyRule.ImplementationConstraints == nil { @@ -1081,7 +1092,11 @@ enum ActionStatusPhase { } input PolicyInput { - rules: [RulesForInterfaceInput!]! + interface: InterfacePolicyInput +} + +input InterfacePolicyInput { + rules: [RulesForInterfaceInput!]! } input RulesForInterfaceInput { @@ -1123,7 +1138,11 @@ input PolicyRuleImplementationConstraintsInput { } type Policy { - rules: [RulesForInterface!]! + interface: InterfacePolicy +} + +type InterfacePolicy { + rules: [RulesForInterface!]! } type RulesForInterface { @@ -2523,6 +2542,41 @@ 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_rules(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.Rules, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*RulesForInterface) + fc.Result = res + return ec.marshalNRulesForInterface2ᚕᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐRulesForInterfaceᚄ(ctx, field.Selections, res) +} + func (ec *executionContext) _ManifestReference_path(ctx context.Context, field graphql.CollectedField, obj *ManifestReference) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -3024,7 +3078,7 @@ func (ec *executionContext) _OutputTypeInstanceDetails_typeRef(ctx context.Conte return ec.marshalNManifestReference2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐManifestReference(ctx, field.Selections, res) } -func (ec *executionContext) _Policy_rules(ctx context.Context, field graphql.CollectedField, obj *Policy) (ret graphql.Marshaler) { +func (ec *executionContext) _Policy_interface(ctx context.Context, field graphql.CollectedField, obj *Policy) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -3042,21 +3096,18 @@ func (ec *executionContext) _Policy_rules(ctx context.Context, field graphql.Col 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.Rules, nil + return obj.Interface, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } return graphql.Null } - res := resTmp.([]*RulesForInterface) + res := resTmp.(*InterfacePolicy) fc.Result = res - return ec.marshalNRulesForInterface2ᚕᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐRulesForInterfaceᚄ(ctx, field.Selections, res) + return ec.marshalOInterfacePolicy2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐInterfacePolicy(ctx, field.Selections, res) } func (ec *executionContext) _PolicyRule_implementationConstraints(ctx context.Context, field graphql.CollectedField, obj *PolicyRule) (ret graphql.Marshaler) { @@ -5096,6 +5147,26 @@ func (ec *executionContext) unmarshalInputInputTypeInstanceData(ctx context.Cont return it, nil } +func (ec *executionContext) unmarshalInputInterfacePolicyInput(ctx context.Context, obj interface{}) (InterfacePolicyInput, error) { + var it InterfacePolicyInput + var asMap = obj.(map[string]interface{}) + + for k, v := range asMap { + switch k { + case "rules": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("rules")) + it.Rules, err = ec.unmarshalNRulesForInterfaceInput2ᚕᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐRulesForInterfaceInputᚄ(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputManifestReferenceInput(ctx context.Context, obj interface{}) (ManifestReferenceInput, error) { var it ManifestReferenceInput var asMap = obj.(map[string]interface{}) @@ -5130,11 +5201,11 @@ func (ec *executionContext) unmarshalInputPolicyInput(ctx context.Context, obj i for k, v := range asMap { switch k { - case "rules": + case "interface": var err error - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("rules")) - it.Rules, err = ec.unmarshalNRulesForInterfaceInput2ᚕᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐRulesForInterfaceInputᚄ(ctx, v) + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("interface")) + it.Interface, err = ec.unmarshalOInterfacePolicyInput2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐInterfacePolicyInput(ctx, v) if err != nil { return it, err } @@ -5632,6 +5703,33 @@ func (ec *executionContext) _InputTypeInstanceToProvide(ctx context.Context, sel return out } +var interfacePolicyImplementors = []string{"InterfacePolicy"} + +func (ec *executionContext) _InterfacePolicy(ctx context.Context, sel ast.SelectionSet, obj *InterfacePolicy) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, interfacePolicyImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("InterfacePolicy") + case "rules": + out.Values[i] = ec._InterfacePolicy_rules(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + var manifestReferenceImplementors = []string{"ManifestReference"} func (ec *executionContext) _ManifestReference(ctx context.Context, sel ast.SelectionSet, obj *ManifestReference) graphql.Marshaler { @@ -5797,11 +5895,8 @@ func (ec *executionContext) _Policy(ctx context.Context, sel ast.SelectionSet, o switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Policy") - case "rules": - out.Values[i] = ec._Policy_rules(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ - } + case "interface": + out.Values[i] = ec._Policy_interface(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -7411,6 +7506,21 @@ func (ec *executionContext) unmarshalOInputTypeInstanceData2ᚕᚖcapactᚗioᚋ return res, nil } +func (ec *executionContext) marshalOInterfacePolicy2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐInterfacePolicy(ctx context.Context, sel ast.SelectionSet, v *InterfacePolicy) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._InterfacePolicy(ctx, sel, v) +} + +func (ec *executionContext) unmarshalOInterfacePolicyInput2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐInterfacePolicyInput(ctx context.Context, v interface{}) (*InterfacePolicyInput, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputInterfacePolicyInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalOJSON2ᚖcapactᚗioᚋcapactᚋpkgᚋengineᚋapiᚋgraphqlᚐJSON(ctx context.Context, v interface{}) (*JSON, error) { if v == nil { return nil, nil diff --git a/pkg/engine/client/fields.go b/pkg/engine/client/fields.go index 77a431d5f..8653d349d 100644 --- a/pkg/engine/client/fields.go +++ b/pkg/engine/client/fields.go @@ -69,35 +69,37 @@ var actionFields = fmt.Sprintf(` `, policyFields) const policyFields = ` - rules { - interface { - path - revision - } - oneOf { - implementationConstraints { - requires { - path - revision - } - attributes { - path - revision - } + interface { + rules { + interface { path + revision } - inject { - requiredTypeInstances { - id - description - } - additionalParameters { - name - value + oneOf { + implementationConstraints { + requires { + path + revision + } + attributes { + path + revision + } + path } - additionalTypeInstances { - name - id + inject { + requiredTypeInstances { + id + description + } + additionalParameters { + name + value + } + additionalTypeInstances { + name + id + } } } } diff --git a/pkg/engine/k8s/policy/fixtures_test.go b/pkg/engine/k8s/policy/fixtures_test.go index 20964332d..f94c9a0e1 100644 --- a/pkg/engine/k8s/policy/fixtures_test.go +++ b/pkg/engine/k8s/policy/fixtures_test.go @@ -8,45 +8,47 @@ import ( func fixPolicyWithTypeRef() policy.Policy { return policy.Policy{ - Rules: policy.RulesList{ - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.*", - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{}, - Inject: &policy.InjectData{ - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "id", - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.sample", - Revision: "0.1.0", - }, - }, - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "id2", - Description: ptr.String("ID 2"), + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.*", + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{}, + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "id", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.sample", + Revision: "0.1.0", + }, }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.sample2", - Revision: "0.2.0", + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "id2", + Description: ptr.String("ID 2"), + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.sample2", + Revision: "0.2.0", + }, }, }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "id3", - Name: "name", - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.sample3", - Revision: "0.3.0", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "id3", + Name: "name", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.sample3", + Revision: "0.3.0", + }, }, }, }, diff --git a/pkg/engine/k8s/policy/from_yaml_test.go b/pkg/engine/k8s/policy/from_yaml_test.go index 49a05ed9d..38b4c96df 100644 --- a/pkg/engine/k8s/policy/from_yaml_test.go +++ b/pkg/engine/k8s/policy/from_yaml_test.go @@ -47,85 +47,87 @@ func loadInput(t *testing.T, path string) string { func fixValidPolicy() policy.Policy { return policy.Policy{ - Rules: policy.RulesList{ - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.interface.database.postgresql.install", - Revision: ptr.String("0.1.0"), - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Requires: &[]types.ManifestRefWithOptRevision{ - { - Path: "cap.type.gcp.auth.service-account", - Revision: ptr.String("0.1.0"), - }, - }, - Attributes: &[]types.ManifestRefWithOptRevision{ - { - Path: "cap.attribute.cloud.provider.gcp", - Revision: ptr.String("0.1.1"), + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.interface.database.postgresql.install", + Revision: ptr.String("0.1.0"), + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Requires: &[]types.ManifestRefWithOptRevision{ + { + Path: "cap.type.gcp.auth.service-account", + Revision: ptr.String("0.1.0"), + }, }, - { - Path: "cap.core.attribute.workload.stateful", - Revision: ptr.String("0.1.0"), + Attributes: &[]types.ManifestRefWithOptRevision{ + { + Path: "cap.attribute.cloud.provider.gcp", + Revision: ptr.String("0.1.1"), + }, + { + Path: "cap.core.attribute.workload.stateful", + Revision: ptr.String("0.1.0"), + }, }, }, - }, - Inject: &policy.InjectData{ - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "sample-uuid", - Description: ptr.String("Google Cloud Platform Service Account"), + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "sample-uuid", + Description: ptr.String("Google Cloud Platform Service Account"), + }, }, }, - }, - AdditionalParameters: []policy.AdditionalParametersToInject{ - { - Name: "additional-parameters", - Value: map[string]interface{}{ - "snapshot": true, + AdditionalParameters: []policy.AdditionalParametersToInject{ + { + Name: "additional-parameters", + Value: map[string]interface{}{ + "snapshot": true, + }, }, }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "sample-uuid", - Name: "sample-name", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "sample-uuid", + Name: "sample-name", + }, }, }, }, }, - }, - { - ImplementationConstraints: policy.ImplementationConstraints{ - Attributes: &[]types.ManifestRefWithOptRevision{ - { - Path: "cap.attribute.cloud.provider.aws", + { + ImplementationConstraints: policy.ImplementationConstraints{ + Attributes: &[]types.ManifestRefWithOptRevision{ + { + Path: "cap.attribute.cloud.provider.aws", + }, }, }, }, - }, - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: ptr.String("cap.implementation.bitnami.postgresql.install"), + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: ptr.String("cap.implementation.bitnami.postgresql.install"), + }, }, }, }, - }, - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.*", - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Requires: &[]types.ManifestRefWithOptRevision{ - { - Path: "cap.core.type.platform.kubernetes", + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.*", + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Requires: &[]types.ManifestRefWithOptRevision{ + { + Path: "cap.core.type.platform.kubernetes", + }, }, }, }, diff --git a/pkg/engine/k8s/policy/metadata/fixtures_test.go b/pkg/engine/k8s/policy/metadata/fixtures_test.go index cf93037c4..3ff0a27b8 100644 --- a/pkg/engine/k8s/policy/metadata/fixtures_test.go +++ b/pkg/engine/k8s/policy/metadata/fixtures_test.go @@ -14,92 +14,94 @@ import ( func fixComplexPolicyWithoutTypeRef() *policy.Policy { return &policy.Policy{ - Rules: policy.RulesList{ - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.*", - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{}, - Inject: &policy.InjectData{ - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "id1", + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.*", + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{}, + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "id1", + }, }, - }, - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "id2", - Description: ptr.String("ID 2"), + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "id2", + Description: ptr.String("ID 2"), + }, }, }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "id1", - Name: "ID1", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "id1", + Name: "ID1", + }, }, - }, - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "id3", - Name: "ID3", + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "id3", + Name: "ID3", + }, }, }, }, }, - }, - { - ImplementationConstraints: policy.ImplementationConstraints{}, - Inject: &policy.InjectData{ - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "id4", + { + ImplementationConstraints: policy.ImplementationConstraints{}, + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "id4", + }, }, }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "id5", - Name: "ID5", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "id5", + Name: "ID5", + }, }, - }, - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "id6", - Name: "ID6", + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "id6", + Name: "ID6", + }, }, }, }, }, }, }, - }, - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.interface.productivity.mattermost.install", - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{}, - Inject: &policy.InjectData{ - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "id7", + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.interface.productivity.mattermost.install", + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{}, + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "id7", + }, }, }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "id8", - Name: "ID8", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "id8", + Name: "ID8", + }, }, }, }, @@ -113,128 +115,130 @@ func fixComplexPolicyWithoutTypeRef() *policy.Policy { func fixComplexPolicyWithTypeRef() *policy.Policy { return &policy.Policy{ - Rules: policy.RulesList{ - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.*", - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{}, - Inject: &policy.InjectData{ - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "id1", - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.type1", - Revision: "0.1.0", - }, - }, - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "id2", - Description: ptr.String("ID 2"), - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.type2", - Revision: "0.2.0", - }, - }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "id1", - Name: "ID1", + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.*", + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{}, + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "id1", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.type1", + Revision: "0.1.0", + }, }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.type1", - Revision: "0.1.0", + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "id2", + Description: ptr.String("ID 2"), + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.type2", + Revision: "0.2.0", + }, }, }, - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "id3", - Name: "ID3", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "id1", + Name: "ID1", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.type1", + Revision: "0.1.0", + }, }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.type3", - Revision: "0.3.0", + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "id3", + Name: "ID3", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.type3", + Revision: "0.3.0", + }, }, }, }, }, - }, - { - ImplementationConstraints: policy.ImplementationConstraints{}, - Inject: &policy.InjectData{ - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "id4", - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.type4", - Revision: "0.4.0", - }, - }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "id5", - Name: "ID5", - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.type5", - Revision: "0.5.0", + { + ImplementationConstraints: policy.ImplementationConstraints{}, + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "id4", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.type4", + Revision: "0.4.0", + }, }, }, - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "id6", - Name: "ID6", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "id5", + Name: "ID5", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.type5", + Revision: "0.5.0", + }, }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.type6", - Revision: "0.6.0", + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "id6", + Name: "ID6", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.type6", + Revision: "0.6.0", + }, }, }, }, }, }, }, - }, - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.interface.productivity.mattermost.install", - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{}, - Inject: &policy.InjectData{ - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "id7", - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.type7", - Revision: "0.7.0", + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.interface.productivity.mattermost.install", + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{}, + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "id7", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.type7", + Revision: "0.7.0", + }, }, }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "id8", - Name: "ID8", - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.type8", - Revision: "0.8.0", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "id8", + Name: "ID8", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.type8", + Revision: "0.8.0", + }, }, }, }, diff --git a/pkg/engine/k8s/policy/metadata/metadata.go b/pkg/engine/k8s/policy/metadata/metadata.go index a869ec994..6485394e5 100644 --- a/pkg/engine/k8s/policy/metadata/metadata.go +++ b/pkg/engine/k8s/policy/metadata/metadata.go @@ -47,7 +47,9 @@ func (m TypeInstanceMetadata) String(withKind bool) string { // TypeInstanceIDsWithUnresolvedMetadataForPolicy filters TypeInstances that have unresolved metadata. func TypeInstanceIDsWithUnresolvedMetadataForPolicy(in policy.Policy) []TypeInstanceMetadata { var tis []TypeInstanceMetadata - for _, rule := range in.Rules { + + // Interface + for _, rule := range in.Interface.Rules { for _, ruleItem := range rule.OneOf { tis = append(tis, TypeInstanceIDsWithUnresolvedMetadataForRule(ruleItem)...) } diff --git a/pkg/engine/k8s/policy/metadata/metadata_resolver.go b/pkg/engine/k8s/policy/metadata/metadata_resolver.go index c8bec79fb..ea94ace28 100644 --- a/pkg/engine/k8s/policy/metadata/metadata_resolver.go +++ b/pkg/engine/k8s/policy/metadata/metadata_resolver.go @@ -67,14 +67,14 @@ func (r *Resolver) ResolveTypeInstanceMetadata(ctx context.Context, policy *poli return multiErr } - r.resolveTypeRefsForRequiredTypeInstances(policy, res) - r.resolveTypeRefsForAdditionalTypeInstances(policy, res) + r.setTypeRefsForRequiredTypeInstances(policy, res) + r.setTypeRefsForAdditionalTypeInstances(policy, res) return nil } -func (r *Resolver) resolveTypeRefsForRequiredTypeInstances(policy *policy.Policy, typeRefs map[string]hublocalgraphql.TypeInstanceTypeReference) { - for ruleIdx, rule := range policy.Rules { +func (r *Resolver) setTypeRefsForRequiredTypeInstances(policy *policy.Policy, typeRefs map[string]hublocalgraphql.TypeInstanceTypeReference) { + for ruleIdx, rule := range policy.Interface.Rules { for ruleItemIdx, ruleItem := range rule.OneOf { if ruleItem.Inject == nil { continue @@ -85,7 +85,7 @@ func (r *Resolver) resolveTypeRefsForRequiredTypeInstances(policy *policy.Policy continue } - policy.Rules[ruleIdx].OneOf[ruleItemIdx].Inject.RequiredTypeInstances[reqTIIdx].TypeRef = &types.ManifestRef{ + policy.Interface.Rules[ruleIdx].OneOf[ruleItemIdx].Inject.RequiredTypeInstances[reqTIIdx].TypeRef = &types.ManifestRef{ Path: typeRef.Path, Revision: typeRef.Revision, } @@ -94,8 +94,8 @@ func (r *Resolver) resolveTypeRefsForRequiredTypeInstances(policy *policy.Policy } } -func (r *Resolver) resolveTypeRefsForAdditionalTypeInstances(policy *policy.Policy, typeRefs map[string]hublocalgraphql.TypeInstanceTypeReference) { - for ruleIdx, rule := range policy.Rules { +func (r *Resolver) setTypeRefsForAdditionalTypeInstances(policy *policy.Policy, typeRefs map[string]hublocalgraphql.TypeInstanceTypeReference) { + for ruleIdx, rule := range policy.Interface.Rules { for ruleItemIdx, ruleItem := range rule.OneOf { if ruleItem.Inject == nil { continue @@ -106,7 +106,7 @@ func (r *Resolver) resolveTypeRefsForAdditionalTypeInstances(policy *policy.Poli continue } - policy.Rules[ruleIdx].OneOf[ruleItemIdx].Inject.AdditionalTypeInstances[reqTIIdx].TypeRef = &types.ManifestRef{ + policy.Interface.Rules[ruleIdx].OneOf[ruleItemIdx].Inject.AdditionalTypeInstances[reqTIIdx].TypeRef = &types.ManifestRef{ Path: typeRef.Path, Revision: typeRef.Revision, } diff --git a/pkg/engine/k8s/policy/predefined.go b/pkg/engine/k8s/policy/predefined.go index 4ef173ad4..8b6949420 100644 --- a/pkg/engine/k8s/policy/predefined.go +++ b/pkg/engine/k8s/policy/predefined.go @@ -5,21 +5,25 @@ import "capact.io/capact/pkg/sdk/apis/0.0.1/types" // NewDenyAll returns a policy, which denies all Implementations. func NewDenyAll() Policy { return Policy{ - Rules: nil, + Interface: InterfacePolicy{ + Rules: nil, + }, } } // NewAllowAll returns a policy, which allows all Implementations. func NewAllowAll() Policy { return Policy{ - Rules: RulesList{ - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.*", - }, - OneOf: []Rule{ - { - ImplementationConstraints: ImplementationConstraints{}, + Interface: InterfacePolicy{ + Rules: RulesList{ + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.*", + }, + OneOf: []Rule{ + { + ImplementationConstraints: ImplementationConstraints{}, + }, }, }, }, diff --git a/pkg/engine/k8s/policy/testdata/valid.yaml b/pkg/engine/k8s/policy/testdata/valid.yaml index c523bca8e..ca7b38548 100644 --- a/pkg/engine/k8s/policy/testdata/valid.yaml +++ b/pkg/engine/k8s/policy/testdata/valid.yaml @@ -1,41 +1,42 @@ -rules: - - interface: - path: cap.interface.database.postgresql.install - revision: 0.1.0 - oneOf: - - implementationConstraints: - requires: - - path: "cap.type.gcp.auth.service-account" - revision: "0.1.0" - attributes: - - path: "cap.attribute.cloud.provider.gcp" - revision: "0.1.1" - - path: "cap.core.attribute.workload.stateful" - revision: "0.1.0" - inject: - requiredTypeInstances: - - id: sample-uuid - description: Google Cloud Platform Service Account - typeRef: # this should be ignored during loading YAML - path: "cap.type.gcp.auth.service-account" +interface: + rules: + - interface: + path: cap.interface.database.postgresql.install + revision: 0.1.0 + oneOf: + - implementationConstraints: + requires: + - path: "cap.type.gcp.auth.service-account" revision: "0.1.0" - additionalParameters: # Injects additional parameters for the Implementation - - name: additional-parameters # Name must match one of the parameter defined under `additionalInput.parameters` in the Implementation - value: - snapshot: true - additionalTypeInstances: - - name: sample-name - id: sample-uuid - - implementationConstraints: - attributes: - - path: cap.attribute.cloud.provider.aws - - implementationConstraints: - path: cap.implementation.bitnami.postgresql.install + attributes: + - path: "cap.attribute.cloud.provider.gcp" + revision: "0.1.1" + - path: "cap.core.attribute.workload.stateful" + revision: "0.1.0" + inject: + requiredTypeInstances: + - id: sample-uuid + description: Google Cloud Platform Service Account + typeRef: # this should be ignored during loading YAML + path: "cap.type.gcp.auth.service-account" + revision: "0.1.0" + additionalParameters: # Injects additional parameters for the Implementation + - name: additional-parameters # Name must match one of the parameter defined under `additionalInput.parameters` in the Implementation + value: + snapshot: true + additionalTypeInstances: + - name: sample-name + id: sample-uuid + - implementationConstraints: + attributes: + - path: cap.attribute.cloud.provider.aws + - implementationConstraints: + path: cap.implementation.bitnami.postgresql.install - - interface: - path: cap.* # any other Interface - oneOf: - - implementationConstraints: - requires: - - path: "cap.core.type.platform.kubernetes" - # any revision + - interface: + path: cap.* # any other Interface + oneOf: + - implementationConstraints: + requires: + - path: "cap.core.type.platform.kubernetes" + # any revision diff --git a/pkg/engine/k8s/policy/types.go b/pkg/engine/k8s/policy/types.go index c511da15e..8f0915e24 100644 --- a/pkg/engine/k8s/policy/types.go +++ b/pkg/engine/k8s/policy/types.go @@ -30,10 +30,15 @@ const ( // Policy holds the policy properties. type Policy struct { + Interface InterfacePolicy `json:"interface"` +} + +// InterfacePolicy holds the Policy for Interfaces. +type InterfacePolicy struct { Rules RulesList `json:"rules"` } -// ActionPolicy holds the Action policy properties. +// ActionPolicy holds the Policy injected during Action creation properties. type ActionPolicy Policy // RulesList holds the list of the rules in the policy. diff --git a/pkg/engine/k8s/policy/types_test.go b/pkg/engine/k8s/policy/types_test.go index 456917e7c..045c280f8 100644 --- a/pkg/engine/k8s/policy/types_test.go +++ b/pkg/engine/k8s/policy/types_test.go @@ -23,7 +23,7 @@ func TestRule_RequiredTypeInstancesToInject(t *testing.T) { }, { Name: "Inject with RequiredTypeInstances", - Input: fixPolicyWithTypeRef().Rules[0].OneOf[0], + Input: fixPolicyWithTypeRef().Interface.Rules[0].OneOf[0], Expected: []policy.RequiredTypeInstanceToInject{ { RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ diff --git a/pkg/engine/k8s/policy/workflow.go b/pkg/engine/k8s/policy/workflow.go index ad18e8752..9712f7b84 100644 --- a/pkg/engine/k8s/policy/workflow.go +++ b/pkg/engine/k8s/policy/workflow.go @@ -13,13 +13,18 @@ import ( // WorkflowPolicy represents a Workflow step policy. type WorkflowPolicy struct { + Interface WorkflowInterfacePolicy `json:"interface"` +} + +// WorkflowInterfacePolicy represent an Interface policy. +type WorkflowInterfacePolicy struct { Rules WorkflowRulesList `json:"rules"` } // WorkflowRulesList holds the list of the rules in the policy. type WorkflowRulesList []WorkflowRulesForInterface -// WorkflowInterfaceRef represents an reference to an Interface +// WorkflowInterfaceRef represents a reference to an Interface // in the workflow step policy. // The Interface can be provided either using the full path and revision // or using an alias from the imported Interfaces in the Implementation. @@ -54,7 +59,7 @@ type WorkflowInjectData struct { // ResolveImports is used to resolve the Manifest Reference for the rules, // if the Interface reference is provided using an alias. func (p *WorkflowPolicy) ResolveImports(imports []*hubpublicapi.ImplementationImport) error { - for i, r := range p.Rules { + for i, r := range p.Interface.Rules { if r.Interface.Alias == nil || *r.Interface.Alias == "" { continue } @@ -62,8 +67,8 @@ func (p *WorkflowPolicy) ResolveImports(imports []*hubpublicapi.ImplementationIm if err != nil { return errors.Wrap(err, "while resolving Action path") } - p.Rules[i].Interface.ManifestRef.Path = actionRef.Path - p.Rules[i].Interface.ManifestRef.Revision = &actionRef.Revision + p.Interface.Rules[i].Interface.ManifestRef.Path = actionRef.Path + p.Interface.Rules[i].Interface.ManifestRef.Revision = &actionRef.Revision } return nil } diff --git a/pkg/engine/k8s/policy/workflow_test.go b/pkg/engine/k8s/policy/workflow_test.go index 23af904ca..f07d47776 100644 --- a/pkg/engine/k8s/policy/workflow_test.go +++ b/pkg/engine/k8s/policy/workflow_test.go @@ -21,23 +21,25 @@ func TestToPolicy(t *testing.T) { func workflowPolicyWithAdditionalInput(input map[string]interface{}) WorkflowPolicy { implementation := "cap.implementation.bitnami.postgresql.install" return WorkflowPolicy{ - Rules: WorkflowRulesList{ - WorkflowRulesForInterface{ - Interface: WorkflowInterfaceRef{ - ManifestRef: &types.ManifestRefWithOptRevision{ - Path: "cap.interface.database.postgresql.install", - }, - }, - OneOf: []WorkflowRule{ - { - ImplementationConstraints: ImplementationConstraints{ - Path: &implementation, + Interface: WorkflowInterfacePolicy{ + Rules: WorkflowRulesList{ + WorkflowRulesForInterface{ + Interface: WorkflowInterfaceRef{ + ManifestRef: &types.ManifestRefWithOptRevision{ + Path: "cap.interface.database.postgresql.install", }, - Inject: &WorkflowInjectData{ - AdditionalParameters: []AdditionalParametersToInject{ - { - Name: "additional-parameters", - Value: input, + }, + OneOf: []WorkflowRule{ + { + ImplementationConstraints: ImplementationConstraints{ + Path: &implementation, + }, + Inject: &WorkflowInjectData{ + AdditionalParameters: []AdditionalParametersToInject{ + { + Name: "additional-parameters", + Value: input, + }, }, }, }, @@ -51,21 +53,23 @@ func workflowPolicyWithAdditionalInput(input map[string]interface{}) WorkflowPol func policyWithAdditionalInput(input map[string]interface{}) Policy { implementation := "cap.implementation.bitnami.postgresql.install" return Policy{ - Rules: RulesList{ - RulesForInterface{ - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.interface.database.postgresql.install", - }, - OneOf: []Rule{ - { - ImplementationConstraints: ImplementationConstraints{ - Path: &implementation, - }, - Inject: &InjectData{ - AdditionalParameters: []AdditionalParametersToInject{ - { - Name: "additional-parameters", - Value: input, + Interface: InterfacePolicy{ + Rules: RulesList{ + RulesForInterface{ + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.interface.database.postgresql.install", + }, + OneOf: []Rule{ + { + ImplementationConstraints: ImplementationConstraints{ + Path: &implementation, + }, + Inject: &InjectData{ + AdditionalParameters: []AdditionalParametersToInject{ + { + Name: "additional-parameters", + Value: input, + }, }, }, }, diff --git a/pkg/hub/client/policy_enforced_client.go b/pkg/hub/client/policy_enforced_client.go index 02452ba4b..ee9df9de7 100644 --- a/pkg/hub/client/policy_enforced_client.go +++ b/pkg/hub/client/policy_enforced_client.go @@ -262,7 +262,7 @@ func (e *PolicyEnforcedClient) Policy() policy.Policy { } func (e *PolicyEnforcedClient) findRulesForInterface(interfaceRef hubpublicgraphql.InterfaceReference) policy.RulesForInterface { - rulesMap := e.rulesMapForPolicy(e.Policy()) + rulesMap := e.interfaceRulesMapForPolicy(e.Policy()) ruleKeysToCheck := []string{ fmt.Sprintf("%s:%s", interfaceRef.Path, interfaceRef.Revision), @@ -443,9 +443,9 @@ func (e *PolicyEnforcedClient) constantTypeInstanceValues() []*hubpublicgraphql. } } -func (e *PolicyEnforcedClient) rulesMapForPolicy(p policy.Policy) map[string]policy.RulesForInterface { +func (e *PolicyEnforcedClient) interfaceRulesMapForPolicy(p policy.Policy) map[string]policy.RulesForInterface { rulesMap := map[string]policy.RulesForInterface{} - for _, rule := range p.Rules { + for _, rule := range p.Interface.Rules { key := rule.Interface.Path if rule.Interface.Revision != nil { key = fmt.Sprintf("%s:%s", key, *rule.Interface.Revision) diff --git a/pkg/hub/client/policy_merger.go b/pkg/hub/client/policy_merger.go index 1fc517b1d..88e944754 100644 --- a/pkg/hub/client/policy_merger.go +++ b/pkg/hub/client/policy_merger.go @@ -14,12 +14,12 @@ func (e *PolicyEnforcedClient) mergePolicies() { for _, p := range e.policyOrder { switch p { case policy.Global: - applyPolicy(¤tPolicy, e.globalPolicy) + applyInterfacePolicy(¤tPolicy.Interface, e.globalPolicy.Interface) case policy.Action: - applyPolicy(¤tPolicy, e.actionPolicy) + applyInterfacePolicy(¤tPolicy.Interface, e.actionPolicy.Interface) case policy.Workflow: for _, wp := range e.workflowStepPolicies { - applyPolicy(¤tPolicy, wp) + applyInterfacePolicy(¤tPolicy.Interface, wp.Interface) } } } @@ -29,7 +29,7 @@ func (e *PolicyEnforcedClient) mergePolicies() { // 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 applyPolicy(currentPolicy *policy.Policy, newPolicy policy.Policy) { +func applyInterfacePolicy(currentPolicy *policy.InterfacePolicy, newPolicy policy.InterfacePolicy) { for _, newRuleForInterface := range newPolicy.Rules { policyRuleIndex := getIndexOfPolicyRule(currentPolicy, newRuleForInterface) if policyRuleIndex == -1 { @@ -71,7 +71,7 @@ func mergeRules(rule *policy.Rule, newRule policy.Rule) { } } -func getIndexOfPolicyRule(p *policy.Policy, rule policy.RulesForInterface) int { +func getIndexOfPolicyRule(p *policy.InterfacePolicy, rule policy.RulesForInterface) int { for i, ruleForInterface := range p.Rules { if isForSameInterface(ruleForInterface, rule) { return i diff --git a/pkg/hub/client/policy_merger_test.go b/pkg/hub/client/policy_merger_test.go index 449a0da38..fdb592c72 100644 --- a/pkg/hub/client/policy_merger_test.go +++ b/pkg/hub/client/policy_merger_test.go @@ -27,48 +27,50 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { { name: "only global policy", global: policy.Policy{ - Rules: policy.RulesList{ - policy.RulesForInterface{ - Interface: types.ManifestRefWithOptRevision{ - Path: interfacePath, - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: &implementationPath, - }, - Inject: &policy.InjectData{ - AdditionalParameters: []policy.AdditionalParametersToInject{ - { - Name: "additional-parameters", - Value: map[string]interface{}{ - "host": map[string]interface{}{ - "name": "capact", + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + policy.RulesForInterface{ + Interface: types.ManifestRefWithOptRevision{ + Path: interfacePath, + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: &implementationPath, + }, + Inject: &policy.InjectData{ + AdditionalParameters: []policy.AdditionalParametersToInject{ + { + Name: "additional-parameters", + Value: map[string]interface{}{ + "host": map[string]interface{}{ + "name": "capact", + }, }, }, }, - }, - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "1314-142-123", - Description: ptr.String("Sample TI"), - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.gcp.auth.service-account", - Revision: "0.1.0", + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "1314-142-123", + Description: ptr.String("Sample TI"), + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.gcp.auth.service-account", + Revision: "0.1.0", + }, }, }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "additional1", - Name: "additional", - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.sample", - Revision: "0.1.0", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "additional1", + Name: "additional", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.sample", + Revision: "0.1.0", + }, }, }, }, @@ -80,48 +82,50 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { }, action: policy.ActionPolicy{}, expected: policy.Policy{ - Rules: policy.RulesList{ - policy.RulesForInterface{ - Interface: types.ManifestRefWithOptRevision{ - Path: interfacePath, - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: &implementationPath, - }, - Inject: &policy.InjectData{ - AdditionalParameters: []policy.AdditionalParametersToInject{ - { - Name: "additional-parameters", - Value: map[string]interface{}{ - "host": map[string]interface{}{ - "name": "capact", + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + policy.RulesForInterface{ + Interface: types.ManifestRefWithOptRevision{ + Path: interfacePath, + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: &implementationPath, + }, + Inject: &policy.InjectData{ + AdditionalParameters: []policy.AdditionalParametersToInject{ + { + Name: "additional-parameters", + Value: map[string]interface{}{ + "host": map[string]interface{}{ + "name": "capact", + }, }, }, }, - }, - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "1314-142-123", - Description: ptr.String("Sample TI"), - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.gcp.auth.service-account", - Revision: "0.1.0", + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "1314-142-123", + Description: ptr.String("Sample TI"), + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.gcp.auth.service-account", + Revision: "0.1.0", + }, }, }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "additional1", - Name: "additional", - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.sample", - Revision: "0.1.0", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "additional1", + Name: "additional", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.sample", + Revision: "0.1.0", + }, }, }, }, @@ -136,47 +140,49 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { { name: "only action policy", action: policy.ActionPolicy{ - Rules: policy.RulesList{ - policy.RulesForInterface{ - Interface: types.ManifestRefWithOptRevision{ - Path: interfacePath, - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: &implementationPath, - }, - Inject: &policy.InjectData{ - AdditionalParameters: []policy.AdditionalParametersToInject{ - { - Name: "additional-parameters", - Value: map[string]interface{}{ - "host": map[string]interface{}{ - "address": "1.2.3.4", + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + policy.RulesForInterface{ + Interface: types.ManifestRefWithOptRevision{ + Path: interfacePath, + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: &implementationPath, + }, + Inject: &policy.InjectData{ + AdditionalParameters: []policy.AdditionalParametersToInject{ + { + Name: "additional-parameters", + Value: map[string]interface{}{ + "host": map[string]interface{}{ + "address": "1.2.3.4", + }, }, }, }, - }, - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "1314-142-123", - Description: ptr.String("Sample TI"), - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.gcp.auth.service-account", + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "1314-142-123", + Description: ptr.String("Sample TI"), + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.gcp.auth.service-account", + }, }, }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "additional1", - Name: "additional", - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.sample", - Revision: "0.1.0", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "additional1", + Name: "additional", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.sample", + Revision: "0.1.0", + }, }, }, }, @@ -188,47 +194,49 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { }, global: policy.Policy{}, expected: policy.Policy{ - Rules: policy.RulesList{ - policy.RulesForInterface{ - Interface: types.ManifestRefWithOptRevision{ - Path: interfacePath, - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: &implementationPath, - }, - Inject: &policy.InjectData{ - AdditionalParameters: []policy.AdditionalParametersToInject{ - { - Name: "additional-parameters", - Value: map[string]interface{}{ - "host": map[string]interface{}{ - "address": "1.2.3.4", + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + policy.RulesForInterface{ + Interface: types.ManifestRefWithOptRevision{ + Path: interfacePath, + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: &implementationPath, + }, + Inject: &policy.InjectData{ + AdditionalParameters: []policy.AdditionalParametersToInject{ + { + Name: "additional-parameters", + Value: map[string]interface{}{ + "host": map[string]interface{}{ + "address": "1.2.3.4", + }, }, }, }, - }, - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "1314-142-123", - Description: ptr.String("Sample TI"), - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.gcp.auth.service-account", + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "1314-142-123", + Description: ptr.String("Sample TI"), + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.gcp.auth.service-account", + }, }, }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "additional1", - Name: "additional", - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.sample", - Revision: "0.1.0", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "additional1", + Name: "additional", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.sample", + Revision: "0.1.0", + }, }, }, }, @@ -243,48 +251,50 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { { name: "action first then global for the same interface", action: policy.ActionPolicy{ - Rules: policy.RulesList{ - policy.RulesForInterface{ - Interface: types.ManifestRefWithOptRevision{ - Path: interfacePath, - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: &implementationPath, - }, - Inject: &policy.InjectData{ - AdditionalParameters: []policy.AdditionalParametersToInject{ - { - Name: "additional-parameters", - Value: map[string]interface{}{ - "host": map[string]interface{}{ - "address": "1.2.3.4", - "alias": "karpatka", + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + policy.RulesForInterface{ + Interface: types.ManifestRefWithOptRevision{ + Path: interfacePath, + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: &implementationPath, + }, + Inject: &policy.InjectData{ + AdditionalParameters: []policy.AdditionalParametersToInject{ + { + Name: "additional-parameters", + Value: map[string]interface{}{ + "host": map[string]interface{}{ + "address": "1.2.3.4", + "alias": "karpatka", + }, }, }, }, - }, - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "1314-142-123-111", - Description: ptr.String("Sample TI"), - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.gcp.auth.service-account", + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "1314-142-123-111", + Description: ptr.String("Sample TI"), + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.gcp.auth.service-account", + }, }, }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "additional1", - Name: "additional", - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.sample", - Revision: "0.1.0", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "additional1", + Name: "additional", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.sample", + Revision: "0.1.0", + }, }, }, }, @@ -295,56 +305,58 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { }, }, global: policy.Policy{ - Rules: policy.RulesList{ - policy.RulesForInterface{ - Interface: types.ManifestRefWithOptRevision{ - Path: interfacePath, - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: &implementationPath, - }, - Inject: &policy.InjectData{ - AdditionalParameters: []policy.AdditionalParametersToInject{ - { - Name: "additional-parameters", - Value: map[string]interface{}{ - "host": map[string]interface{}{ - "name": "capact", - "alias": "capactio", + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + policy.RulesForInterface{ + Interface: types.ManifestRefWithOptRevision{ + Path: interfacePath, + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: &implementationPath, + }, + Inject: &policy.InjectData{ + AdditionalParameters: []policy.AdditionalParametersToInject{ + { + Name: "additional-parameters", + Value: map[string]interface{}{ + "host": map[string]interface{}{ + "name": "capact", + "alias": "capactio", + }, }, }, }, - }, - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "1314-142-123-222", - Description: ptr.String("Sample TI"), - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.gcp.auth.service-account", + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "1314-142-123-222", + Description: ptr.String("Sample TI"), + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.gcp.auth.service-account", + }, }, }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "additional-global", - Name: "additional-global", - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.sample", - Revision: "0.1.0", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "additional-global", + Name: "additional-global", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.sample", + Revision: "0.1.0", + }, }, }, }, }, - }, - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: &secondImplementationPath, + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: &secondImplementationPath, + }, }, }, }, @@ -352,57 +364,59 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { }, }, expected: policy.Policy{ - Rules: policy.RulesList{ - policy.RulesForInterface{ - Interface: types.ManifestRefWithOptRevision{ - Path: interfacePath, - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: &implementationPath, - }, - Inject: &policy.InjectData{ - AdditionalParameters: []policy.AdditionalParametersToInject{ - { - Name: "additional-parameters", - Value: map[string]interface{}{ - "host": map[string]interface{}{ - "name": "capact", - "address": "1.2.3.4", - "alias": "karpatka", + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + policy.RulesForInterface{ + Interface: types.ManifestRefWithOptRevision{ + Path: interfacePath, + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: &implementationPath, + }, + Inject: &policy.InjectData{ + AdditionalParameters: []policy.AdditionalParametersToInject{ + { + Name: "additional-parameters", + Value: map[string]interface{}{ + "host": map[string]interface{}{ + "name": "capact", + "address": "1.2.3.4", + "alias": "karpatka", + }, }, }, }, - }, - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "1314-142-123-111", - Description: ptr.String("Sample TI"), - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.gcp.auth.service-account", + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "1314-142-123-111", + Description: ptr.String("Sample TI"), + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.gcp.auth.service-account", + }, }, }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "additional1", - Name: "additional", - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.sample", - Revision: "0.1.0", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "additional1", + Name: "additional", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.sample", + Revision: "0.1.0", + }, }, }, }, }, - }, - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: &secondImplementationPath, + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: &secondImplementationPath, + }, }, }, }, @@ -414,15 +428,17 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { { name: "action first then global for different interfaces - only rules", action: policy.ActionPolicy{ - Rules: policy.RulesList{ - policy.RulesForInterface{ - Interface: types.ManifestRefWithOptRevision{ - Path: interfacePath, - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: &implementationPath, + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + policy.RulesForInterface{ + Interface: types.ManifestRefWithOptRevision{ + Path: interfacePath, + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: &implementationPath, + }, }, }, }, @@ -430,15 +446,17 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { }, }, global: policy.Policy{ - Rules: policy.RulesList{ - policy.RulesForInterface{ - Interface: types.ManifestRefWithOptRevision{ - Path: secondInterfacePath, - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: &secondImplementationPath, + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + policy.RulesForInterface{ + Interface: types.ManifestRefWithOptRevision{ + Path: secondInterfacePath, + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: &secondImplementationPath, + }, }, }, }, @@ -446,27 +464,29 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { }, }, expected: policy.Policy{ - Rules: policy.RulesList{ - policy.RulesForInterface{ - Interface: types.ManifestRefWithOptRevision{ - Path: interfacePath, - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: &implementationPath, + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + policy.RulesForInterface{ + Interface: types.ManifestRefWithOptRevision{ + Path: interfacePath, + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: &implementationPath, + }, }, }, }, - }, - policy.RulesForInterface{ - Interface: types.ManifestRefWithOptRevision{ - Path: secondInterfacePath, - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: &secondImplementationPath, + policy.RulesForInterface{ + Interface: types.ManifestRefWithOptRevision{ + Path: secondInterfacePath, + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: &secondImplementationPath, + }, }, }, }, @@ -478,47 +498,49 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { { name: "merge type instances and additional input", action: policy.ActionPolicy{ - Rules: policy.RulesList{ - policy.RulesForInterface{ - Interface: types.ManifestRefWithOptRevision{ - Path: interfacePath, - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: &implementationPath, - }, - Inject: &policy.InjectData{ - AdditionalParameters: []policy.AdditionalParametersToInject{ - { - Name: "additional-parameters", - Value: map[string]interface{}{ - "additional-input": map[string]interface{}{ - "a": 1, + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + policy.RulesForInterface{ + Interface: types.ManifestRefWithOptRevision{ + Path: interfacePath, + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: &implementationPath, + }, + Inject: &policy.InjectData{ + AdditionalParameters: []policy.AdditionalParametersToInject{ + { + Name: "additional-parameters", + Value: map[string]interface{}{ + "additional-input": map[string]interface{}{ + "a": 1, + }, }, }, }, - }, - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "1314-142-123-111", - Description: ptr.String("Sample TI"), - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.gcp.auth.service-account", + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "1314-142-123-111", + Description: ptr.String("Sample TI"), + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.gcp.auth.service-account", + }, }, }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "additional1", - Name: "additional", - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.sample", - Revision: "0.1.0", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "additional1", + Name: "additional", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.sample", + Revision: "0.1.0", + }, }, }, }, @@ -529,37 +551,39 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { }, }, global: policy.Policy{ - Rules: policy.RulesList{ - policy.RulesForInterface{ - Interface: types.ManifestRefWithOptRevision{ - Path: interfacePath, - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: &implementationPath, - }, - Inject: &policy.InjectData{ - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "123-321-123", - Description: ptr.String("Sample TI"), - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.x", - }, - }, + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + policy.RulesForInterface{ + Interface: types.ManifestRefWithOptRevision{ + Path: interfacePath, + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: &implementationPath, }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "additional-global", - Name: "additional-global", + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "123-321-123", + Description: ptr.String("Sample TI"), + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.x", + }, }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.sample-global", - Revision: "0.1.0", + }, + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "additional-global", + Name: "additional-global", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.sample-global", + Revision: "0.1.0", + }, }, }, }, @@ -570,66 +594,68 @@ func TestPolicyEnforcedClient_mergePolicies(t *testing.T) { }, }, expected: policy.Policy{ - Rules: policy.RulesList{ - policy.RulesForInterface{ - Interface: types.ManifestRefWithOptRevision{ - Path: interfacePath, - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: &implementationPath, - }, - Inject: &policy.InjectData{ - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "123-321-123", - Description: ptr.String("Sample TI"), - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.x", - }, - }, - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "1314-142-123-111", - Description: ptr.String("Sample TI"), - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.gcp.auth.service-account", - }, - }, + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + policy.RulesForInterface{ + Interface: types.ManifestRefWithOptRevision{ + Path: interfacePath, + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: &implementationPath, }, - AdditionalParameters: []policy.AdditionalParametersToInject{ - { - Name: "additional-parameters", - Value: map[string]interface{}{ - "additional-input": map[string]interface{}{ - "a": 1, + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "123-321-123", + Description: ptr.String("Sample TI"), + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.x", }, }, - }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "additional-global", - Name: "additional-global", + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "1314-142-123-111", + Description: ptr.String("Sample TI"), + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.gcp.auth.service-account", + }, }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.sample-global", - Revision: "0.1.0", + }, + AdditionalParameters: []policy.AdditionalParametersToInject{ + { + Name: "additional-parameters", + Value: map[string]interface{}{ + "additional-input": map[string]interface{}{ + "a": 1, + }, + }, }, }, - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "additional1", - Name: "additional", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "additional-global", + Name: "additional-global", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.sample-global", + Revision: "0.1.0", + }, }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.sample", - Revision: "0.1.0", + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "additional1", + Name: "additional", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.sample", + Revision: "0.1.0", + }, }, }, }, @@ -684,23 +710,25 @@ func TestNestedWorkflowPolicy(t *testing.T) { func workflowPolicyWithAdditionalInput(input map[string]interface{}) policy.WorkflowPolicy { implementation := "cap.implementation.bitnami.postgresql.install" return policy.WorkflowPolicy{ - Rules: policy.WorkflowRulesList{ - policy.WorkflowRulesForInterface{ - Interface: policy.WorkflowInterfaceRef{ - ManifestRef: &types.ManifestRefWithOptRevision{ - Path: "cap.interface.database.postgresql.install", - }, - }, - OneOf: []policy.WorkflowRule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: &implementation, + Interface: policy.WorkflowInterfacePolicy{ + Rules: policy.WorkflowRulesList{ + policy.WorkflowRulesForInterface{ + Interface: policy.WorkflowInterfaceRef{ + ManifestRef: &types.ManifestRefWithOptRevision{ + Path: "cap.interface.database.postgresql.install", }, - Inject: &policy.WorkflowInjectData{ - AdditionalParameters: []policy.AdditionalParametersToInject{ - { - Name: "additional-parameters", - Value: input, + }, + OneOf: []policy.WorkflowRule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: &implementation, + }, + Inject: &policy.WorkflowInjectData{ + AdditionalParameters: []policy.AdditionalParametersToInject{ + { + Name: "additional-parameters", + Value: input, + }, }, }, }, diff --git a/pkg/sdk/apis/0.0.1/types/types.extend.go b/pkg/sdk/apis/0.0.1/types/types.extend.go index cabcabc5d..0947f85b9 100644 --- a/pkg/sdk/apis/0.0.1/types/types.extend.go +++ b/pkg/sdk/apis/0.0.1/types/types.extend.go @@ -1,6 +1,8 @@ // Package types holds manually added types. package types +import "fmt" + // OCFPathPrefix defines path prefix that all OCF manifest must have. const OCFPathPrefix = "cap." @@ -29,6 +31,18 @@ type ManifestRefWithOptRevision struct { Revision *string `json:"revision"` } +func (in *ManifestRefWithOptRevision) String() string { + if in == nil { + return "" + } + out := in.Path + if in.Revision != nil && *in.Revision != "" { + out = fmt.Sprintf("%s:%s", out, *in.Revision) + } + + return out +} + // InputTypeInstanceRef holds input TypeInstance reference. type InputTypeInstanceRef struct { // Name refers to input TypeInstance name used in rendered Action. diff --git a/pkg/sdk/renderer/argo/fixtures_test.go b/pkg/sdk/renderer/argo/fixtures_test.go index 2c6739ffb..2fe1f1261 100644 --- a/pkg/sdk/renderer/argo/fixtures_test.go +++ b/pkg/sdk/renderer/argo/fixtures_test.go @@ -8,52 +8,54 @@ import ( func fixGCPGlobalPolicy() policy.Policy { return policy.Policy{ - Rules: policy.RulesList{ - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.interface.database.postgresql.install", - Revision: ptr.String("0.1.0"), - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Requires: &[]types.ManifestRefWithOptRevision{ - { - Path: "cap.type.gcp.auth.service-account", - Revision: ptr.String("0.1.0"), + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.interface.database.postgresql.install", + Revision: ptr.String("0.1.0"), + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Requires: &[]types.ManifestRefWithOptRevision{ + { + Path: "cap.type.gcp.auth.service-account", + Revision: ptr.String("0.1.0"), + }, }, - }, - Attributes: &[]types.ManifestRefWithOptRevision{ - { - Path: "cap.attribute.cloud.provider.gcp", + Attributes: &[]types.ManifestRefWithOptRevision{ + { + Path: "cap.attribute.cloud.provider.gcp", + }, }, }, - }, - Inject: &policy.InjectData{ - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "c268d3f5-8834-434b-bea2-b677793611c5", - Description: ptr.String("GCP SA"), + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "c268d3f5-8834-434b-bea2-b677793611c5", + Description: ptr.String("GCP SA"), + }, }, }, }, }, - }, - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: ptr.String("cap.implementation.bitnami.postgresql.install"), + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: ptr.String("cap.implementation.bitnami.postgresql.install"), + }, }, }, }, - }, - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.*", - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{}, + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.*", + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{}, + }, }, }, }, @@ -63,48 +65,50 @@ func fixGCPGlobalPolicy() policy.Policy { func fixAWSGlobalPolicy(additionalParameters ...policy.AdditionalParametersToInject) policy.Policy { return policy.Policy{ - Rules: policy.RulesList{ - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.interface.database.postgresql.install", - Revision: ptr.String("0.1.0"), - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Requires: &[]types.ManifestRefWithOptRevision{ - { - Path: "cap.type.aws.auth.credentials", - Revision: ptr.String("0.1.0"), + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.interface.database.postgresql.install", + Revision: ptr.String("0.1.0"), + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Requires: &[]types.ManifestRefWithOptRevision{ + { + Path: "cap.type.aws.auth.credentials", + Revision: ptr.String("0.1.0"), + }, }, - }, - Attributes: &[]types.ManifestRefWithOptRevision{ - { - Path: "cap.attribute.cloud.provider.aws", + Attributes: &[]types.ManifestRefWithOptRevision{ + { + Path: "cap.attribute.cloud.provider.aws", + }, }, }, - }, - Inject: &policy.InjectData{ - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "517cf827-233c-4bf1-8fc9-48534424dd58", - Description: ptr.String("AWS Credentials"), + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "517cf827-233c-4bf1-8fc9-48534424dd58", + Description: ptr.String("AWS Credentials"), + }, }, }, + AdditionalParameters: additionalParameters, }, - AdditionalParameters: additionalParameters, }, }, }, - }, - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.*", - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{}, + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.*", + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{}, + }, }, }, }, @@ -114,63 +118,65 @@ func fixAWSGlobalPolicy(additionalParameters ...policy.AdditionalParametersToInj func fixGlobalPolicyForFallback() policy.Policy { return policy.Policy{ - Rules: policy.RulesList{ - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.interface.database.postgresql.install", - Revision: ptr.String("0.1.0"), - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Attributes: &[]types.ManifestRefWithOptRevision{ - { - Path: "cap.attribute.not-existing", - Revision: ptr.String("0.1.0"), + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.interface.database.postgresql.install", + Revision: ptr.String("0.1.0"), + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Attributes: &[]types.ManifestRefWithOptRevision{ + { + Path: "cap.attribute.not-existing", + Revision: ptr.String("0.1.0"), + }, }, }, - }, - Inject: &policy.InjectData{ - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "517cf827-233c-4bf1-8fc9-48534424dd58", - Description: ptr.String("AWS Credentials"), + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "517cf827-233c-4bf1-8fc9-48534424dd58", + Description: ptr.String("AWS Credentials"), + }, }, }, }, }, - }, - { - ImplementationConstraints: policy.ImplementationConstraints{ - Requires: &[]types.ManifestRefWithOptRevision{ - { - Path: "cap.type.aws.auth.credentials", - Revision: ptr.String("0.1.0"), + { + ImplementationConstraints: policy.ImplementationConstraints{ + Requires: &[]types.ManifestRefWithOptRevision{ + { + Path: "cap.type.aws.auth.credentials", + Revision: ptr.String("0.1.0"), + }, }, - }, - Attributes: &[]types.ManifestRefWithOptRevision{ - { - Path: "cap.attribute.cloud.provider.aws", + Attributes: &[]types.ManifestRefWithOptRevision{ + { + Path: "cap.attribute.cloud.provider.aws", + }, }, }, + // No injects, even if the requirements are satisfied this Implementation should be ignored }, - // No injects, even if the requirements are satisfied this Implementation should be ignored - }, - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: ptr.String("cap.implementation.bitnami.postgresql.install"), + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: ptr.String("cap.implementation.bitnami.postgresql.install"), + }, }, }, }, - }, - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.*", - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{}, + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.*", + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{}, + }, }, }, }, @@ -180,37 +186,39 @@ func fixGlobalPolicyForFallback() policy.Policy { func fixTerraformPolicy() policy.Policy { return policy.Policy{ - Rules: policy.RulesList{ - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.interface.database.postgresql.install", - Revision: ptr.String("0.1.0"), - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: ptr.String("cap.implementation.terraform.gcp.cloudsql.postgresql.install"), - }, - Inject: &policy.InjectData{ - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "c268d3f5-8834-434b-bea2-b677793611c5", - Description: ptr.String("GCP SA"), + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.interface.database.postgresql.install", + Revision: ptr.String("0.1.0"), + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: ptr.String("cap.implementation.terraform.gcp.cloudsql.postgresql.install"), + }, + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "c268d3f5-8834-434b-bea2-b677793611c5", + Description: ptr.String("GCP SA"), + }, }, }, }, }, }, }, - }, - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.*", - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{}, + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.*", + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{}, + }, }, }, }, @@ -220,45 +228,47 @@ func fixTerraformPolicy() policy.Policy { func fixAWSRDSPolicy() policy.Policy { return policy.Policy{ - Rules: policy.RulesList{ - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.interface.database.postgresql.install", - Revision: ptr.String("0.1.0"), - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{ - Path: ptr.String("cap.implementation.aws.rds.postgresql.install"), - }, - Inject: &policy.InjectData{ - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "517cf827-233c-4bf1-8fc9-48534424dd58", - Description: ptr.String("AWS SA"), + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.interface.database.postgresql.install", + Revision: ptr.String("0.1.0"), + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{ + Path: ptr.String("cap.implementation.aws.rds.postgresql.install"), + }, + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "517cf827-233c-4bf1-8fc9-48534424dd58", + Description: ptr.String("AWS SA"), + }, }, }, - }, - AdditionalParameters: []policy.AdditionalParametersToInject{ - { - Name: "additional-parameters", - Value: map[string]interface{}{ - "region": "eu-central-1", + AdditionalParameters: []policy.AdditionalParametersToInject{ + { + Name: "additional-parameters", + Value: map[string]interface{}{ + "region": "eu-central-1", + }, }, }, }, }, }, }, - }, - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.*", - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{}, + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.*", + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{}, + }, }, }, }, @@ -268,35 +278,37 @@ func fixAWSRDSPolicy() policy.Policy { func fixExistingDBPolicy() policy.Policy { return policy.Policy{ - Rules: policy.RulesList{ - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.interface.productivity.mattermost.install", - Revision: ptr.String("0.1.0"), - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{}, - Inject: &policy.InjectData{ - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - Name: "postgresql", - ID: "f2421415-b8a4-464b-be12-b617794411c5", + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.interface.productivity.mattermost.install", + Revision: ptr.String("0.1.0"), + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{}, + Inject: &policy.InjectData{ + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + Name: "postgresql", + ID: "f2421415-b8a4-464b-be12-b617794411c5", + }, }, }, }, }, }, }, - }, - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.*", - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{}, + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.*", + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{}, + }, }, }, }, diff --git a/pkg/sdk/renderer/argo/testdata/hub/implementation/app-stack/app1/install.yaml b/pkg/sdk/renderer/argo/testdata/hub/implementation/app-stack/app1/install.yaml index aa76ff0ff..afa2bd491 100644 --- a/pkg/sdk/renderer/argo/testdata/hub/implementation/app-stack/app1/install.yaml +++ b/pkg/sdk/renderer/argo/testdata/hub/implementation/app-stack/app1/install.yaml @@ -86,22 +86,23 @@ spec: name: install-db capact-when: postgresql == nil capact-policy: - rules: - - interface: - path: cap.interface.database.postgresql.install - revision: 0.1.0 - oneOf: - - implementationConstraints: - attributes: - - path: cap.attribute.cloud.provider.aws - requires: - - path: cap.type.aws.auth.credentials - revision: 0.1.0 - inject: - additionalParameters: # Injects additional parameters for the Implementation - - name: additional-parameters # Name must match one of the parameter defined under `additionalInput.parameters` in the Implementation - value: - region: eu-west-2 + interface: + rules: + - interface: + path: cap.interface.database.postgresql.install + revision: 0.1.0 + oneOf: + - implementationConstraints: + attributes: + - path: cap.attribute.cloud.provider.aws + requires: + - path: cap.type.aws.auth.credentials + revision: 0.1.0 + inject: + additionalParameters: # Injects additional parameters for the Implementation + - name: additional-parameters # Name must match one of the parameter defined under `additionalInput.parameters` in the Implementation + value: + region: eu-west-2 capact-outputTypeInstances: - name: postgresql from: postgresql diff --git a/pkg/sdk/renderer/argo/testdata/hub/implementation/app-stack/app2/install.yaml b/pkg/sdk/renderer/argo/testdata/hub/implementation/app-stack/app2/install.yaml index d87fef922..0e30f74d8 100644 --- a/pkg/sdk/renderer/argo/testdata/hub/implementation/app-stack/app2/install.yaml +++ b/pkg/sdk/renderer/argo/testdata/hub/implementation/app-stack/app2/install.yaml @@ -100,20 +100,21 @@ spec: - - name: install-db capact-action: postgresql.install capact-policy: - rules: - - interface: postgresql.install - oneOf: - - implementationConstraints: - attributes: - - path: cap.attribute.cloud.provider.aws - requires: - - path: cap.type.aws.auth.credentials - revision: 0.1.0 - inject: - additionalParameters: # Injects additional parameters for the Implementation - - name: additional-parameters # Name must match one of the parameter defined under `additionalInput.parameters` in the Implementation - value: - region: eu-west-2 + interface: + rules: + - interface: postgresql.install + oneOf: + - implementationConstraints: + attributes: + - path: cap.attribute.cloud.provider.aws + requires: + - path: cap.type.aws.auth.credentials + revision: 0.1.0 + inject: + additionalParameters: # Injects additional parameters for the Implementation + - name: additional-parameters # Name must match one of the parameter defined under `additionalInput.parameters` in the Implementation + value: + region: eu-west-2 capact-outputTypeInstances: - name: postgresql from: postgresql diff --git a/pkg/sdk/validation/manifest/json_remote_implementation.go b/pkg/sdk/validation/manifest/json_remote_implementation.go index 5d5a62357..998d7bdb9 100644 --- a/pkg/sdk/validation/manifest/json_remote_implementation.go +++ b/pkg/sdk/validation/manifest/json_remote_implementation.go @@ -264,7 +264,7 @@ func (v *RemoteImplementationValidator) resolveRequiresPath(parentPrefix string, // requires: // cap.core.type.platform: // oneOf: - // - name: cap.type.platform.cloud-foundry # this MUST be attached to `cap.core.type.platform` + // - name: cap.type.platform.nomad # this MUST be attached to `cap.core.type.platform` // revision: 0.1.0 if strings.HasPrefix(requiresSubItem.Name, types.OCFPathPrefix) { ref.Path = requiresSubItem.Name diff --git a/pkg/sdk/validation/policy/fixtures_test.go b/pkg/sdk/validation/policy/fixtures_test.go index f1234237d..f34f2de7c 100644 --- a/pkg/sdk/validation/policy/fixtures_test.go +++ b/pkg/sdk/validation/policy/fixtures_test.go @@ -8,33 +8,35 @@ import ( func fixPolicyWithoutTypeRef() policy.Policy { return policy.Policy{ - Rules: policy.RulesList{ - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.*", - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{}, - Inject: &policy.InjectData{ - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "id", + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.*", + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{}, + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "id", + }, }, - }, - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "id2", - Description: ptr.String("ID 2"), + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "id2", + Description: ptr.String("ID 2"), + }, }, }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "id3", - Name: "id-3", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "id3", + Name: "id-3", + }, }, }, }, @@ -48,45 +50,47 @@ func fixPolicyWithoutTypeRef() policy.Policy { func fixPolicyWithTypeRef() policy.Policy { return policy.Policy{ - Rules: policy.RulesList{ - { - Interface: types.ManifestRefWithOptRevision{ - Path: "cap.*", - }, - OneOf: []policy.Rule{ - { - ImplementationConstraints: policy.ImplementationConstraints{}, - Inject: &policy.InjectData{ - RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "id", - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.sample", - Revision: "0.1.0", - }, - }, - { - RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ - ID: "id2", - Description: ptr.String("ID 2"), + Interface: policy.InterfacePolicy{ + Rules: policy.RulesList{ + { + Interface: types.ManifestRefWithOptRevision{ + Path: "cap.*", + }, + OneOf: []policy.Rule{ + { + ImplementationConstraints: policy.ImplementationConstraints{}, + Inject: &policy.InjectData{ + RequiredTypeInstances: []policy.RequiredTypeInstanceToInject{ + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "id", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.sample", + Revision: "0.1.0", + }, }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.sample2", - Revision: "0.2.0", + { + RequiredTypeInstanceReference: policy.RequiredTypeInstanceReference{ + ID: "id2", + Description: ptr.String("ID 2"), + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.sample2", + Revision: "0.2.0", + }, }, }, - }, - AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ - { - AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ - ID: "id3", - Name: "name", - }, - TypeRef: &types.ManifestRef{ - Path: "cap.type.sample3", - Revision: "0.3.0", + AdditionalTypeInstances: []policy.AdditionalTypeInstanceToInject{ + { + AdditionalTypeInstanceReference: policy.AdditionalTypeInstanceReference{ + ID: "id3", + Name: "name", + }, + TypeRef: &types.ManifestRef{ + Path: "cap.type.sample3", + Revision: "0.3.0", + }, }, }, }, diff --git a/pkg/sdk/validation/policy/policy_test.go b/pkg/sdk/validation/policy/policy_test.go index 1d97936e7..d63917524 100644 --- a/pkg/sdk/validation/policy/policy_test.go +++ b/pkg/sdk/validation/policy/policy_test.go @@ -187,11 +187,11 @@ func TestValidator_ValidateTypeInstanceMetadata(t *testing.T) { }, { Name: "Valid", - Input: fixPolicyWithTypeRef().Rules[0].OneOf[0], + Input: fixPolicyWithTypeRef().Interface.Rules[0].OneOf[0], }, { Name: "Invalid", - Input: fixPolicyWithoutTypeRef().Rules[0].OneOf[0], + Input: fixPolicyWithoutTypeRef().Interface.Rules[0].OneOf[0], ExpectedErrMessage: ptr.String( heredoc.Doc(` - Metadata for "AdditionalTypeInstance": diff --git a/test/e2e/action_test.go b/test/e2e/action_test.go index 0ad88d8d9..c3f403528 100644 --- a/test/e2e/action_test.go +++ b/test/e2e/action_test.go @@ -1,3 +1,4 @@ +//go:build integration // +build integration package e2e @@ -12,24 +13,21 @@ import ( "time" "capact.io/capact/internal/ptr" + enginegraphql "capact.io/capact/pkg/engine/api/graphql" + engine "capact.io/capact/pkg/engine/client" hublocalgraphql "capact.io/capact/pkg/hub/api/graphql/local" hubclient "capact.io/capact/pkg/hub/client" + . "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" "github.com/onsi/gomega/types" "github.com/pkg/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" - "sigs.k8s.io/controller-runtime/pkg/client/config" - - enginegraphql "capact.io/capact/pkg/engine/api/graphql" - engine "capact.io/capact/pkg/engine/client" ) -const globalPolicyConfigMapKey = "cluster-policy.yaml" -const globalPolicyTokenToReplace = "requiredTypeInstances: []" -const globalPolicyRequiredTypeInstancesFmt = `requiredTypeInstances: [{ "id": "%s", "description": "Test TypeInstance" }]` +const ( + actionPassingPath = "cap.interface.capactio.capact.validation.action.passing" +) func getActionName() string { return fmt.Sprintf("e2e-test-%d-%s", GinkgoParallelNode(), strconv.Itoa(rand.Intn(10000))) @@ -47,6 +45,9 @@ var _ = Describe("Action", func() { engineClient = getEngineGraphQLClient() hubClient = getHubGraphQLClient() actionName = getActionName() + + // Ensure Test Policy + updateGlobalPolicy(ctx, engineClient, nil) }) AfterEach(func() { @@ -123,9 +124,11 @@ var _ = Describe("Action", func() { waitForActionDeleted(ctx, engineClient, actionName) By("4. Modifying Policy to make Implementation B picked for next run...") - globalPolicyRequiredTypeInstances := fmt.Sprintf(globalPolicyRequiredTypeInstancesFmt, injectedTypeInstanceID) - cfgMapCleanupFn := updateGlobalPolicyConfigMap(ctx, globalPolicyTokenToReplace, globalPolicyRequiredTypeInstances) - defer cfgMapCleanupFn() + globalPolicyRequiredTypeInstances := enginegraphql.RequiredTypeInstanceReferenceInput{ + ID: injectedTypeInstanceID, + Description: ptr.String("Test TypeInstance"), + } + updateGlobalPolicy(ctx, engineClient, &globalPolicyRequiredTypeInstances) By("5. Expecting Implementation B is picked based on test policy...") action = createActionAndWaitForReadyToRunPhase(ctx, engineClient, actionName, actionPath, inputData) @@ -386,18 +389,15 @@ func createTypeInstance(ctx context.Context, hubClient *hubclient.Client, in *hu return createdTypeInstance, cleanupFn } -func updateGlobalPolicyConfigMap(ctx context.Context, stringToFind, stringToReplace string) func() { - err := replaceInGlobalPolicyConfigMap(ctx, stringToFind, stringToReplace) - Expect(err).ToNot(HaveOccurred()) - - cleanupFn := func() { - err := replaceInGlobalPolicyConfigMap(ctx, stringToReplace, stringToFind) - if err != nil { - log(errors.Wrap(err, "while cleaning up ConfigMap with cluster policy").Error()) - } +func updateGlobalPolicy(ctx context.Context, client *engine.Client, reqTypeInstance *enginegraphql.RequiredTypeInstanceReferenceInput) { + var reqInput []*enginegraphql.RequiredTypeInstanceReferenceInput + // nils element are not handled by GraphQL + if reqTypeInstance != nil { + reqInput = append(reqInput, reqTypeInstance) } - - return cleanupFn + p := PolicyInputTestFixture(reqInput) + _, err := client.UpdatePolicy(ctx, p) + Expect(err).ToNot(HaveOccurred()) } func assertUploadedTypeInstance(ctx context.Context, hubClient *hubclient.Client, testValue string) { @@ -434,36 +434,6 @@ func assertOutputTypeInstancesInActionStatus(ctx context.Context, engineClient * }, 10*time.Second).Should(match) } -func replaceInGlobalPolicyConfigMap(ctx context.Context, stringToFind, stringToReplace string) error { - k8sCfg, err := config.GetConfig() - if err != nil { - return err - } - - clientset, err := kubernetes.NewForConfig(k8sCfg) - if err != nil { - return err - } - - cfgMapCli := clientset.CoreV1().ConfigMaps(cfg.ClusterPolicy.Namespace) - - globalPolicyCfgMap, err := cfgMapCli.Get(ctx, cfg.ClusterPolicy.Name, metav1.GetOptions{}) - if err != nil { - return err - } - - oldContent := globalPolicyCfgMap.Data[globalPolicyConfigMapKey] - newContent := strings.ReplaceAll(oldContent, stringToFind, stringToReplace) - globalPolicyCfgMap.Data[globalPolicyConfigMapKey] = newContent - - _, err = cfgMapCli.Update(ctx, globalPolicyCfgMap, metav1.UpdateOptions{}) - if err != nil { - return err - } - - return nil -} - func getTypeInstanceWithValue(typeInstances []hublocalgraphql.TypeInstance, testValue string) (*hublocalgraphql.TypeInstance, error) { for _, ti := range typeInstances { values, ok := ti.LatestResourceVersion.Spec.Value.(map[string]interface{}) @@ -490,3 +460,48 @@ func mapToInputParameters(params map[string]interface{}) (*enginegraphql.JSON, e res := enginegraphql.JSON(marshaled) return &res, nil } + +func PolicyInputTestFixture(reqInput []*enginegraphql.RequiredTypeInstanceReferenceInput) *enginegraphql.PolicyInput { + manifestRef := func(path string) []*enginegraphql.ManifestReferenceInput { + return []*enginegraphql.ManifestReferenceInput{ + { + Path: path, + }, + } + } + + return &enginegraphql.PolicyInput{ + Interface: &enginegraphql.InterfacePolicyInput{ + Rules: []*enginegraphql.RulesForInterfaceInput{ + { + Interface: manifestRef(actionPassingPath)[0], + OneOf: []*enginegraphql.PolicyRuleInput{ + { + ImplementationConstraints: &enginegraphql.PolicyRuleImplementationConstraintsInput{ + Requires: manifestRef("cap.type.capactio.capact.validation.single-key"), + Attributes: manifestRef("cap.attribute.capactio.capact.validation.policy.most-preferred"), + }, + Inject: &enginegraphql.PolicyRuleInjectDataInput{ + RequiredTypeInstances: reqInput, + }, + }, + { + ImplementationConstraints: &enginegraphql.PolicyRuleImplementationConstraintsInput{ + Path: ptr.String("cap.implementation.capactio.capact.validation.action.passing-a"), + }, + }, + }, + }, + // allow all others + { + Interface: manifestRef("cap.*")[0], + OneOf: []*enginegraphql.PolicyRuleInput{ + { + ImplementationConstraints: &enginegraphql.PolicyRuleImplementationConstraintsInput{}, + }, + }, + }, + }, + }, + } +} diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go index aa3688ea1..5c78d3036 100644 --- a/test/e2e/e2e_suite_test.go +++ b/test/e2e/e2e_suite_test.go @@ -10,14 +10,17 @@ import ( "testing" "time" + enginegraphql "capact.io/capact/pkg/engine/api/graphql" engineclient "capact.io/capact/pkg/engine/client" "capact.io/capact/pkg/httputil" hubclient "capact.io/capact/pkg/hub/client" "capact.io/capact/pkg/iosafety" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/pkg/errors" "github.com/vrischmann/envconfig" + "sigs.k8s.io/yaml" ) type GatewayConfig struct { @@ -26,32 +29,46 @@ type GatewayConfig struct { Password string } -type GlobalPolicyConfig struct { - Name string `envconfig:"default=capact-engine-cluster-policy"` - Namespace string `envconfig:"default=capact-system"` -} - type Config struct { StatusEndpoints []string IgnoredPodsNames []string `envconfig:"optional"` PollingInterval time.Duration `envconfig:"default=2s"` PollingTimeout time.Duration `envconfig:"default=5m"` Gateway GatewayConfig - ClusterPolicy GlobalPolicyConfig HubLocalDeployNamespace string `envconfig:"default=capact-system"` HubLocalDeployName string `envconfig:"default=capact-hub-local"` } -var cfg Config +var ( + cfg Config + originalGlobalPolicy enginegraphql.PolicyInput +) var _ = BeforeSuite(func() { err := envconfig.Init(&cfg) Expect(err).ToNot(HaveOccurred()) + cli := getEngineGraphQLClient() + originalPolicy, err := cli.GetPolicy(context.Background()) + + rawPolicy, err := yaml.Marshal(originalPolicy) + Expect(err).ToNot(HaveOccurred()) + + input := enginegraphql.PolicyInput{} + err = yaml.Unmarshal(rawPolicy, &input) + Expect(err).ToNot(HaveOccurred()) + originalGlobalPolicy = input + waitTillServiceEndpointsAreReady() waitTillDataIsPopulated() }) +var _ = AfterSuite(func() { + cli := getEngineGraphQLClient() + _, err := cli.UpdatePolicy(context.Background(), &originalGlobalPolicy) + Expect(err).ToNot(HaveOccurred()) +}) + func TestE2E(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "E2E Suite") diff --git a/test/e2e/hub_test.go b/test/e2e/hub_test.go index e2061ca6e..2dc439de8 100644 --- a/test/e2e/hub_test.go +++ b/test/e2e/hub_test.go @@ -47,7 +47,7 @@ var _ = Describe("GraphQL API", func() { It("based on a prefix of the parent node", func() { const parentNode = "cap.core.type.platform.*" - expAssociatedPaths := []string{"cap.core.type.platform.kubernetes", "cap.type.platform.cloud-foundry"} + expAssociatedPaths := []string{"cap.core.type.platform.kubernetes", "cap.type.platform.nomad"} gotTypes, err := cli.ListTypes(ctx, public.WithTypeFilter(gqlpublicapi.TypeFilter{ PathPattern: ptr.String(parentNode), @@ -58,7 +58,7 @@ var _ = Describe("GraphQL API", func() { HasOnlyExpectTypePaths(gotTypes, expAssociatedPaths) }) It("only child node if full path name specified", func() { - const fullTypePath = "cap.type.platform.cloud-foundry" + const fullTypePath = "cap.type.platform.nomad" gotTypes, err := cli.ListTypes(ctx, public.WithTypeFilter(gqlpublicapi.TypeFilter{ PathPattern: ptr.String(fullTypePath), @@ -69,8 +69,8 @@ var _ = Describe("GraphQL API", func() { Expect(gotTypes).To(HaveLen(1)) Expect(gotTypes[0].Path).To(Equal(fullTypePath)) }) - It("entries matching or regex (cap.core.type.generic.value|cap.type.platform.cloud-foundry)", func() { - expTypePaths := []string{"cap.core.type.generic.value", "cap.type.platform.cloud-foundry"} + It("entries matching or regex (cap.core.type.generic.value|cap.type.platform.nomad)", func() { + expTypePaths := []string{"cap.core.type.generic.value", "cap.type.platform.nomad"} typePathORFilter := regexutil.OrStringSlice(expTypePaths) gotTypes, err := cli.ListTypes(ctx, public.WithTypeFilter(gqlpublicapi.TypeFilter{