From 964f35ce35a1b32fb8a4788d3b88dad370e4e82d Mon Sep 17 00:00:00 2001 From: Shyam Radhakrishnan Date: Thu, 7 Jul 2022 10:59:26 +0530 Subject: [PATCH] Fix merge strategy for NSG/Subnet and remove usage of ID for NSG seclist reconciliation --- api/v1beta1/types.go | 10 +- cloud/scope/nsg_reconciler.go | 171 ++++++------------ cloud/scope/nsg_reconciler_test.go | 48 ++--- ...tructure.cluster.x-k8s.io_ociclusters.yaml | 17 +- ....cluster.x-k8s.io_ociclustertemplates.yaml | 19 +- docs/src/networking/custom-networking.md | 9 + .../cluster.yaml | 8 +- 7 files changed, 124 insertions(+), 158 deletions(-) diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go index 73f5a7f3..3eb61fe6 100644 --- a/api/v1beta1/types.go +++ b/api/v1beta1/types.go @@ -147,14 +147,16 @@ type IngressSecurityRule struct { type IngressSecurityRuleForNSG struct { //IngressSecurityRule ID for NSG. // +optional + // Deprecated: this field is not populated and used during reconciliation ID *string `json:"id,omitempty"` IngressSecurityRule `json:"ingressRule,omitempty"` } // EgressSecurityRuleForNSG is EgressSecurityRule for NSG. type EgressSecurityRuleForNSG struct { - //EgressSecurityRule ID for NSG. + // EgressSecurityRule ID for NSG. // +optional + // Deprecated: this field is not populated and used during reconciliation ID *string `json:"id,omitempty"` EgressSecurityRule `json:"egressRule,omitempty"` } @@ -251,7 +253,6 @@ type Subnet struct { // +optional ID *string `json:"id,omitempty"` // Subnet Name. - // +optional Name string `json:"name"` // Subnet CIDR. // +optional @@ -271,7 +272,6 @@ type NSG struct { // +optional ID *string `json:"id,omitempty"` // NSG Name. - // +optional Name string `json:"name"` // Role defines the NSG role (eg. control-plane, control-plane-endpoint, service-lb, worker). Role Role `json:"role,omitempty"` @@ -318,10 +318,14 @@ type VCN struct { // Subnets is the configuration for subnets required in the VCN. // +optional + // +listType=map + // +listMapKey=name Subnets []*Subnet `json:"subnets,omitempty"` // NetworkSecurityGroups is the configuration for the Network Security Groups required in the VCN. // +optional + // +listType=map + // +listMapKey=name NetworkSecurityGroups []*NSG `json:"networkSecurityGroups,omitempty"` } diff --git a/cloud/scope/nsg_reconciler.go b/cloud/scope/nsg_reconciler.go index b3abb577..8e7382a9 100644 --- a/cloud/scope/nsg_reconciler.go +++ b/cloud/scope/nsg_reconciler.go @@ -49,12 +49,10 @@ func (s *ClusterScope) ReconcileNSG(ctx context.Context) error { } s.Logger.Info("Successfully updated network security list", "nsg", nsgOCID) } - ingressRules, egressRules, isNSGUpdated, err := s.UpdateNSGSecurityRulesIfNeeded(ctx, *desiredNSG, nsg) + isNSGUpdated, err := s.UpdateNSGSecurityRulesIfNeeded(ctx, *desiredNSG, nsg) if err != nil { return err } - desiredNSG.IngressRules = ingressRules - desiredNSG.EgressRules = egressRules if !isNSGUpdated { s.Logger.Info("No Reconciliation Required for Network Security Group", "nsg", *desiredNSG.ID) } @@ -67,12 +65,10 @@ func (s *ClusterScope) ReconcileNSG(ctx context.Context) error { } s.Logger.Info("Created the nsg", "nsg", nsgID) desiredNSG.ID = nsgID - ingressRules, egressRules, err := s.AddNSGSecurityRules(ctx, desiredNSG.ID, desiredNSG.IngressRules, desiredNSG.EgressRules) + err = s.AddNSGSecurityRules(ctx, desiredNSG.ID, desiredNSG.IngressRules, desiredNSG.EgressRules) if err != nil { return err } - desiredNSG.IngressRules = ingressRules - desiredNSG.EgressRules = egressRules } return nil } @@ -184,6 +180,7 @@ func (s *ClusterScope) IsNSGExitsByRole(role infrastructurev1beta1.Role) bool { return false } +// IsNSGEqual compares the actual and desired NSG using name/freeform tags and defined tags. func (s *ClusterScope) IsNSGEqual(actual *core.NetworkSecurityGroup, desired infrastructurev1beta1.NSG) bool { if *actual.DisplayName != desired.Name { return false @@ -191,10 +188,11 @@ func (s *ClusterScope) IsNSGEqual(actual *core.NetworkSecurityGroup, desired inf return s.IsTagsEqual(actual.FreeformTags, actual.DefinedTags) } +// UpdateNSGSecurityRulesIfNeeded updates NSG rules if required by comparing actual and desired. func (s *ClusterScope) UpdateNSGSecurityRulesIfNeeded(ctx context.Context, desired infrastructurev1beta1.NSG, - actual *core.NetworkSecurityGroup) ([]infrastructurev1beta1.IngressSecurityRuleForNSG, []infrastructurev1beta1.EgressSecurityRuleForNSG, bool, error) { - var ingressRulesToAdd, ingressRulesToUpdate, finalIngressRules []infrastructurev1beta1.IngressSecurityRuleForNSG - var egressRulesToAdd, egressRulesToUpdate, finalEgressRules []infrastructurev1beta1.EgressSecurityRuleForNSG + actual *core.NetworkSecurityGroup) (bool, error) { + var ingressRulesToAdd []infrastructurev1beta1.IngressSecurityRuleForNSG + var egressRulesToAdd []infrastructurev1beta1.EgressSecurityRuleForNSG var securityRulesToRemove []string var isNSGUpdated bool listSecurityRulesResponse, err := s.VCNClient.ListNetworkSecurityGroupSecurityRules(ctx, core.ListNetworkSecurityGroupSecurityRulesRequest{ @@ -202,84 +200,81 @@ func (s *ClusterScope) UpdateNSGSecurityRulesIfNeeded(ctx context.Context, desir }) if err != nil { s.Logger.Error(err, "failed to reconcile the network security group, failed to list security rules") - return nil, nil, isNSGUpdated, errors.Wrap(err, "failed to reconcile the network security group, failed to list security rules") + return isNSGUpdated, errors.Wrap(err, "failed to reconcile the network security group, failed to list security rules") } ingressRules, egressRules := generateSpecFromSecurityRules(listSecurityRulesResponse.Items) for i, ingressRule := range desired.IngressRules { - if ingressRule.ID == nil { - ingressRulesToAdd = append(ingressRulesToAdd, ingressRule) - } if ingressRule.IsStateless == nil { desired.IngressRules[i].IsStateless = common.Bool(false) } } for i, egressRule := range desired.EgressRules { - if egressRule.ID == nil { - egressRulesToAdd = append(egressRulesToAdd, egressRule) - } if egressRule.IsStateless == nil { desired.EgressRules[i].IsStateless = common.Bool(false) } } - for _, actualRule := range ingressRules { + for _, desiredRule := range desired.IngressRules { + found := false + for _, actualRule := range ingressRules { + if reflect.DeepEqual(desiredRule, actualRule) { + found = true + break + } + } + if !found { + ingressRulesToAdd = append(ingressRulesToAdd, desiredRule) + } + } + + for id, actualRule := range ingressRules { found := false for _, desiredRule := range desired.IngressRules { - if (desiredRule.ID != nil) && (*actualRule.ID == *desiredRule.ID) { + if reflect.DeepEqual(desiredRule, actualRule) { found = true - if !reflect.DeepEqual(desiredRule, actualRule) { - ingressRulesToUpdate = append(ingressRulesToUpdate, desiredRule) - } - finalIngressRules = append(finalIngressRules, desiredRule) break } } if !found { - securityRulesToRemove = append(securityRulesToRemove, *actualRule.ID) + securityRulesToRemove = append(securityRulesToRemove, id) } } - for _, actualRule := range egressRules { + + for _, desiredRule := range desired.EgressRules { + found := false + for _, actualRule := range egressRules { + if reflect.DeepEqual(desiredRule, actualRule) { + found = true + break + } + } + if !found { + egressRulesToAdd = append(egressRulesToAdd, desiredRule) + } + } + + for id, actualRule := range egressRules { found := false for _, desiredRule := range desired.EgressRules { - if (desiredRule.ID != nil) && (*actualRule.ID == *desiredRule.ID) { + if reflect.DeepEqual(desiredRule, actualRule) { found = true - if !reflect.DeepEqual(desiredRule, actualRule) { - egressRulesToUpdate = append(egressRulesToUpdate, desiredRule) - } - finalEgressRules = append(finalEgressRules, desiredRule) break } } if !found { - securityRulesToRemove = append(securityRulesToRemove, *actualRule.ID) + securityRulesToRemove = append(securityRulesToRemove, id) } } + if len(ingressRulesToAdd) > 0 || len(egressRulesToAdd) > 0 { isNSGUpdated = true - ingress, egress, err := s.AddNSGSecurityRules(ctx, desired.ID, ingressRulesToAdd, egressRulesToAdd) + err := s.AddNSGSecurityRules(ctx, desired.ID, ingressRulesToAdd, egressRulesToAdd) if err != nil { s.Logger.Error(err, "failed to reconcile the network security group, failed to add security rules") - return nil, nil, isNSGUpdated, err + return isNSGUpdated, err } s.Logger.Info("Successfully added missing rules in NSG", "nsg", *actual.Id) - finalEgressRules = append(finalEgressRules, egress...) - finalIngressRules = append(finalIngressRules, ingress...) - } - if len(ingressRulesToUpdate) > 0 || len(egressRulesToUpdate) > 0 { - isNSGUpdated = true - securityRules := generateUpdateSecurityRuleFromSpec(ingressRulesToUpdate, egressRulesToUpdate) - _, err := s.VCNClient.UpdateNetworkSecurityGroupSecurityRules(ctx, core.UpdateNetworkSecurityGroupSecurityRulesRequest{ - NetworkSecurityGroupId: desired.ID, - UpdateNetworkSecurityGroupSecurityRulesDetails: core.UpdateNetworkSecurityGroupSecurityRulesDetails{ - SecurityRules: securityRules, - }, - }) - if err != nil { - s.Logger.Error(err, "failed to reconcile the network security group, failed to update security rules") - return nil, nil, isNSGUpdated, err - } - s.Logger.Info("Successfully updated rules in NSG", "nsg", *actual.Id) } if len(securityRulesToRemove) > 0 { isNSGUpdated = true @@ -291,12 +286,11 @@ func (s *ClusterScope) UpdateNSGSecurityRulesIfNeeded(ctx context.Context, desir }) if err != nil { s.Logger.Error(err, "failed to reconcile the network security group, failed to remove security rules") - return nil, nil, isNSGUpdated, err + return isNSGUpdated, err } s.Logger.Info("Successfully deleted rules in NSG", "nsg", *actual.Id) } - s.Logger.Info("No Reconciliation Required for Network Security List rules", "nsg", desired.ID) - return finalIngressRules, finalEgressRules, isNSGUpdated, nil + return isNSGUpdated, nil } func (s *ClusterScope) UpdateNSG(ctx context.Context, nsgSpec infrastructurev1beta1.NSG) error { @@ -365,58 +359,9 @@ func generateAddSecurityRuleFromSpec(ingressRules []infrastructurev1beta1.Ingres return securityRules } -func generateUpdateSecurityRuleFromSpec(ingressRules []infrastructurev1beta1.IngressSecurityRuleForNSG, - egressRules []infrastructurev1beta1.EgressSecurityRuleForNSG) []core.UpdateSecurityRuleDetails { - var securityRules []core.UpdateSecurityRuleDetails - var icmpOptions *core.IcmpOptions - var tcpOptions *core.TcpOptions - var udpOptions *core.UdpOptions - var stateless *bool - for _, ingressRule := range ingressRules { - icmpOptions, tcpOptions, udpOptions = getProtocolOptions(ingressRule.IcmpOptions, ingressRule.TcpOptions, ingressRule.UdpOptions) - // while comparing values, the boolean value has to be always set - stateless = ingressRule.IsStateless - if stateless == nil { - stateless = common.Bool(false) - } - securityRules = append(securityRules, core.UpdateSecurityRuleDetails{ - Direction: core.UpdateSecurityRuleDetailsDirectionIngress, - Id: ingressRule.ID, - Protocol: ingressRule.Protocol, - Description: ingressRule.Description, - IcmpOptions: icmpOptions, - IsStateless: stateless, - Source: ingressRule.Source, - SourceType: core.UpdateSecurityRuleDetailsSourceTypeEnum(ingressRule.SourceType), - TcpOptions: tcpOptions, - UdpOptions: udpOptions, - }) - } - for _, egressRule := range egressRules { - icmpOptions, tcpOptions, udpOptions = getProtocolOptions(egressRule.IcmpOptions, egressRule.TcpOptions, egressRule.UdpOptions) - stateless = egressRule.IsStateless - if stateless == nil { - stateless = common.Bool(false) - } - securityRules = append(securityRules, core.UpdateSecurityRuleDetails{ - Direction: core.UpdateSecurityRuleDetailsDirectionEgress, - Protocol: egressRule.Protocol, - Description: egressRule.Description, - IcmpOptions: icmpOptions, - IsStateless: stateless, - Destination: egressRule.Destination, - DestinationType: core.UpdateSecurityRuleDetailsDestinationTypeEnum(egressRule.DestinationType), - TcpOptions: tcpOptions, - UdpOptions: udpOptions, - Id: egressRule.ID, - }) - } - return securityRules -} - -func generateSpecFromSecurityRules(rules []core.SecurityRule) ([]infrastructurev1beta1.IngressSecurityRuleForNSG, []infrastructurev1beta1.EgressSecurityRuleForNSG) { - var ingressRules []infrastructurev1beta1.IngressSecurityRuleForNSG - var egressRules []infrastructurev1beta1.EgressSecurityRuleForNSG +func generateSpecFromSecurityRules(rules []core.SecurityRule) (map[string]infrastructurev1beta1.IngressSecurityRuleForNSG, map[string]infrastructurev1beta1.EgressSecurityRuleForNSG) { + var ingressRules = make(map[string]infrastructurev1beta1.IngressSecurityRuleForNSG) + var egressRules = make(map[string]infrastructurev1beta1.EgressSecurityRuleForNSG) var stateless *bool for _, rule := range rules { @@ -428,7 +373,6 @@ func generateSpecFromSecurityRules(rules []core.SecurityRule) ([]infrastructurev switch rule.Direction { case core.SecurityRuleDirectionIngress: ingressRule := infrastructurev1beta1.IngressSecurityRuleForNSG{ - ID: rule.Id, IngressSecurityRule: infrastructurev1beta1.IngressSecurityRule{ Protocol: rule.Protocol, Source: rule.Source, @@ -440,10 +384,9 @@ func generateSpecFromSecurityRules(rules []core.SecurityRule) ([]infrastructurev Description: rule.Description, }, } - ingressRules = append(ingressRules, ingressRule) + ingressRules[*rule.Id] = ingressRule case core.SecurityRuleDirectionEgress: egressRule := infrastructurev1beta1.EgressSecurityRuleForNSG{ - ID: rule.Id, EgressSecurityRule: infrastructurev1beta1.EgressSecurityRule{ Destination: rule.Destination, Protocol: rule.Protocol, @@ -455,7 +398,7 @@ func generateSpecFromSecurityRules(rules []core.SecurityRule) ([]infrastructurev Description: rule.Description, }, } - egressRules = append(egressRules, egressRule) + egressRules[*rule.Id] = egressRule } } return ingressRules, egressRules @@ -463,10 +406,10 @@ func generateSpecFromSecurityRules(rules []core.SecurityRule) ([]infrastructurev } func (s *ClusterScope) AddNSGSecurityRules(ctx context.Context, nsgID *string, ingress []infrastructurev1beta1.IngressSecurityRuleForNSG, - egress []infrastructurev1beta1.EgressSecurityRuleForNSG) ([]infrastructurev1beta1.IngressSecurityRuleForNSG, []infrastructurev1beta1.EgressSecurityRuleForNSG, error) { + egress []infrastructurev1beta1.EgressSecurityRuleForNSG) error { securityRules := generateAddSecurityRuleFromSpec(ingress, egress) - addNetworkSecurityGroupSecurityRulesResponse, err := s.VCNClient.AddNetworkSecurityGroupSecurityRules(ctx, core.AddNetworkSecurityGroupSecurityRulesRequest{ + _, err := s.VCNClient.AddNetworkSecurityGroupSecurityRules(ctx, core.AddNetworkSecurityGroupSecurityRulesRequest{ NetworkSecurityGroupId: nsgID, AddNetworkSecurityGroupSecurityRulesDetails: core.AddNetworkSecurityGroupSecurityRulesDetails{ SecurityRules: securityRules, @@ -474,11 +417,9 @@ func (s *ClusterScope) AddNSGSecurityRules(ctx context.Context, nsgID *string, i }) if err != nil { s.Logger.Error(err, "failed add nsg security rules") - return nil, nil, errors.Wrap(err, "failed add nsg security rules") + return errors.Wrap(err, "failed add nsg security rules") } - ingressRules, egressRules := generateSpecFromSecurityRules(addNetworkSecurityGroupSecurityRulesResponse.SecurityRules) - s.Logger.Info("successfully added nsg rules", "nsg", *nsgID) - return ingressRules, egressRules, nil + return nil } func (s *ClusterScope) CreateNSG(ctx context.Context, nsg infrastructurev1beta1.NSG) (*string, error) { @@ -925,7 +866,7 @@ func getProtocolOptionsForSpec(icmp *core.IcmpOptions, tcp *core.TcpOptions, udp if icmp != nil { icmpOptions = &infrastructurev1beta1.IcmpOptions{ Type: icmp.Type, - Code: icmp.Type, + Code: icmp.Code, } } if tcp != nil { diff --git a/cloud/scope/nsg_reconciler_test.go b/cloud/scope/nsg_reconciler_test.go index 659c1ccd..bf1583d5 100644 --- a/cloud/scope/nsg_reconciler_test.go +++ b/cloud/scope/nsg_reconciler_test.go @@ -1326,6 +1326,20 @@ func TestClusterScope_ReconcileNSG(t *testing.T) { vcnClient.EXPECT().AddNetworkSecurityGroupSecurityRules(gomock.Any(), gomock.Eq(core.AddNetworkSecurityGroupSecurityRulesRequest{ NetworkSecurityGroupId: common.String("update-rules-id"), AddNetworkSecurityGroupSecurityRulesDetails: core.AddNetworkSecurityGroupSecurityRulesDetails{SecurityRules: []core.AddSecurityRuleDetails{ + { + Direction: core.AddSecurityRuleDetailsDirectionIngress, + Protocol: common.String("6"), + Description: common.String("External access to Kubernetes API endpoint"), + Source: common.String("0.0.0.0/0"), + SourceType: core.AddSecurityRuleDetailsSourceTypeCidrBlock, + IsStateless: common.Bool(false), + TcpOptions: &core.TcpOptions{ + DestinationPortRange: &core.PortRange{ + Max: common.Int(6443), + Min: common.Int(6443), + }, + }, + }, { Direction: core.AddSecurityRuleDetailsDirectionEgress, Protocol: common.String("6"), @@ -1352,51 +1366,19 @@ func TestClusterScope_ReconcileNSG(t *testing.T) { }, }, }, nil) - vcnClient.EXPECT().UpdateNetworkSecurityGroupSecurityRules(gomock.Any(), gomock.Eq(core.UpdateNetworkSecurityGroupSecurityRulesRequest{ - NetworkSecurityGroupId: common.String("update-rules-id"), - UpdateNetworkSecurityGroupSecurityRulesDetails: core.UpdateNetworkSecurityGroupSecurityRulesDetails{ - SecurityRules: []core.UpdateSecurityRuleDetails{ - { - Direction: core.UpdateSecurityRuleDetailsDirectionIngress, - Protocol: common.String("6"), - Description: common.String("External access to Kubernetes API endpoint"), - Id: common.String("ingress-id"), - Source: common.String("0.0.0.0/0"), - SourceType: core.UpdateSecurityRuleDetailsSourceTypeCidrBlock, - IsStateless: common.Bool(false), - TcpOptions: &core.TcpOptions{ - DestinationPortRange: &core.PortRange{ - Max: common.Int(6443), - Min: common.Int(6443), - }, - }, - }, - }, - }, - })).Return(core.UpdateNetworkSecurityGroupSecurityRulesResponse{ - UpdatedNetworkSecurityGroupSecurityRules: core.UpdatedNetworkSecurityGroupSecurityRules{ - SecurityRules: []core.SecurityRule{ - { - Id: common.String("ingress-id"), - }, - }, - }, - }, nil) vcnClient.EXPECT().RemoveNetworkSecurityGroupSecurityRules(gomock.Any(), gomock.Eq(core.RemoveNetworkSecurityGroupSecurityRulesRequest{ NetworkSecurityGroupId: common.String("update-rules-id"), RemoveNetworkSecurityGroupSecurityRulesDetails: core.RemoveNetworkSecurityGroupSecurityRulesDetails{ - SecurityRuleIds: []string{"egress-id-changed"}, + SecurityRuleIds: []string{"ingress-id", "egress-id-changed"}, }, })).Return(core.RemoveNetworkSecurityGroupSecurityRulesResponse{}, nil) customNSGEgressWithId := make([]infrastructurev1beta1.EgressSecurityRuleForNSG, len(customNSGEgress)) copy(customNSGEgressWithId, customNSGEgress) - customNSGEgressWithId[0].ID = common.String("egress-id") customNSGIngressWithId := make([]infrastructurev1beta1.IngressSecurityRuleForNSG, len(customNSGIngress)) copy(customNSGIngressWithId, customNSGIngress) - customNSGIngressWithId[0].ID = common.String("ingress-id") tests := []struct { name string diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_ociclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_ociclusters.yaml index 3393af5f..45703384 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_ociclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_ociclusters.yaml @@ -282,7 +282,9 @@ spec: type: object type: object id: - description: EgressSecurityRule ID for NSG. + description: 'EgressSecurityRule ID for NSG. Deprecated: + this field is not populated and used during + reconciliation' type: string type: object type: array @@ -296,7 +298,9 @@ spec: for NSG properties: id: - description: IngressSecurityRule ID for NSG. + description: 'IngressSecurityRule ID for NSG. + Deprecated: this field is not populated and + used during reconciliation' type: string ingressRule: description: IngressSecurityRule A rule for allowing @@ -469,8 +473,13 @@ spec: description: Role defines the NSG role (eg. control-plane, control-plane-endpoint, service-lb, worker). type: string + required: + - name type: object type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map privateRouteTableId: description: ID of Private Route Table. type: string @@ -846,9 +855,13 @@ spec: private). type: string required: + - name - role type: object type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map type: object vcnPeering: description: VCNPeering configuration. diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_ociclustertemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_ociclustertemplates.yaml index e9fbf945..8f08579b 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_ociclustertemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_ociclustertemplates.yaml @@ -320,8 +320,9 @@ spec: type: object type: object id: - description: EgressSecurityRule ID for - NSG. + description: 'EgressSecurityRule ID for + NSG. Deprecated: this field is not populated + and used during reconciliation' type: string type: object type: array @@ -335,8 +336,9 @@ spec: IngressSecurityRule for NSG properties: id: - description: IngressSecurityRule ID for - NSG. + description: 'IngressSecurityRule ID for + NSG. Deprecated: this field is not populated + and used during reconciliation' type: string ingressRule: description: IngressSecurityRule A rule @@ -536,8 +538,13 @@ spec: control-plane, control-plane-endpoint, service-lb, worker). type: string + required: + - name type: object type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map privateRouteTableId: description: ID of Private Route Table. type: string @@ -966,9 +973,13 @@ spec: public, private). type: string required: + - name - role type: object type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map type: object vcnPeering: description: VCNPeering configuration. diff --git a/docs/src/networking/custom-networking.md b/docs/src/networking/custom-networking.md index c3a3f651..00d75c00 100644 --- a/docs/src/networking/custom-networking.md +++ b/docs/src/networking/custom-networking.md @@ -294,17 +294,26 @@ spec: networkSecurityGroups: - id: role: control-plane-endpoint + name: control-plane-endpoint - id: role: worker + name: worker - id: role: control-plane + name: control-plane subnets: - id: role: control-plane-endpoint + name: control-plane-endpoint - id: role: worker + name: worker - id: role: control-plane + name: control-plane ``` +In the above spec, note that name has to be mentioned for Subnet/NSG. This is so that Kubernetes +can merge the list properly when there is an update. + [sl-vs-nsg]: https://docs.oracle.com/en-us/iaas/Content/Network/Concepts/securityrules.htm#comparison diff --git a/test/e2e/data/infrastructure-oci/v1beta1/cluster-template-externally-managed-vcn/cluster.yaml b/test/e2e/data/infrastructure-oci/v1beta1/cluster-template-externally-managed-vcn/cluster.yaml index 7289f101..aa2e3842 100644 --- a/test/e2e/data/infrastructure-oci/v1beta1/cluster-template-externally-managed-vcn/cluster.yaml +++ b/test/e2e/data/infrastructure-oci/v1beta1/cluster-template-externally-managed-vcn/cluster.yaml @@ -11,14 +11,20 @@ spec: networkSecurityGroups: - id: "${EXTERNAL_VCN_CPE_NSG}" role: control-plane-endpoint + name: control-plane-endpoint - id: "${EXTERNAL_VCN_WORKER_NSG}" role: worker + name: worker - id: "${EXTERNAL_VCN_CP_NSG}" role: control-plane + name: control-plane subnets: - id: "${EXTERNAL_VCN_CPE_SUBNET}" role: control-plane-endpoint + name: control-plane-endpoint - id: "${EXTERNAL_VCN_WORKER_SUBNET}" role: worker + name: worker - id: "${EXTERNAL_VCN_CP_SUBNET}" - role: control-plane \ No newline at end of file + role: control-plane + name: control-plane \ No newline at end of file