Skip to content

Conversation

@Miciah
Copy link
Contributor

@Miciah Miciah commented Feb 15, 2023

Add gatewayapi controller

Introduce a new "gatewayapi" controller, which creates the Gateway API CRDs when the "GatewayAPI" feature gate is enabled.

  • assets/gateway-api/gateway.networking.k8s.io_gatewayclasses.yaml:
  • assets/gateway-api/gateway.networking.k8s.io_gateways.yaml:
  • assets/gateway-api/gateway.networking.k8s.io_httproutes.yaml:
  • assets/gateway-api/gateway.networking.k8s.io_referencegrants.yaml: New files.
  • manifests/00-cluster-role.yaml: Allow the operator to manage the Gateway API CRDs.
  • pkg/manifests/bindata.go: Regenerate.
  • pkg/manifests/manifests.go (GatewayClassCRDAsset, GatewayCRDAsset, HTTPRouteCRDAsset, ReferenceGrantCRDAsset): New consts.
    (GatewayClassCRD, GatewayCRD, HTTPRouteCRD, ReferenceGrantCRD, NewCustomResourceDefinition): New functions.
  • pkg/manifests/manifests_test.go (TestManifests): Test GatewayClassCRD, GatewayCRD, HTTPRouteCRD, and ReferenceGrantCRD.
  • pkg/operator/controller/gatewayapi/controller.go: New file.
    (controllerName, featureGateName): New consts.
    (log): New variable. Define a logger for the controller.
    (New): New function. Create an instance of the controller.
    (reconciler): New type. Store the state of a gatewayapi controller.
    (Reconcile): New method. Handle reconciliation requests for featuregates by checking for the "GatewayAPI" feature and ensuring the Gateway API CRDs exist if the feature is enabled.
    (featureIsEnabled): New function. Helper for Reconcile.
  • pkg/operator/controller/gatewayapi/controller_test.go: New file.
    (Test_Reconcile): New test. Verify that Reconcile behaves as expected.
    (fakeCache, fakeClientRecorder): New types, used in Test_Reconcile.
    (Get, List, Scheme, RESTMapper, Create, Delete, DeleteAllOf, Update, Patch, Status): New methods for fakeClientRecorder to implement the controller-runtime client.Client interface.
  • pkg/operator/controller/gatewayapi/crds.go: New file.
    (managedCRDs): New variable. Define the CRDs that this controller manages.
    (ensureCRD): New method. Ensure the specified CRD is present, using currentCRD, createCRD, and updateCRD.
    (ensureGatewayAPICRDs): Ensure the CRDs in managedCRDs are present, using ensureCRD.
    (currentCRD, createCRD, updateCRD): New methods.
    (crdChanged): New function, used by updateCRD.
  • pkg/operator/operator.go (New): Initialize the new gatewayapi controller.
  • go.mod:
  • vendor/*: Regenerate.

Add gatewayclass controller

Introduce a new "gatewayclass" controller, which watches gatewayclasses and installs the Service Mesh operator when a GatewayClass owned by OpenShift is first observed.

A GatewayClass is considered owned by OpenShift if its spec.controllerName field specifies "openshift.io/gateway-controller".

  • manifests/00-cluster-role.yaml: Allow the operator to manage the Gateway API CRs, the servicemeshoperator subscription, and servicemeshcontrolplanes.
  • go.mod: Add github.com/maistra/istio-operator, github.com/operator-framework/api, and sigs.k8s.io/gateway-api.
  • go.sum:
  • pkg/manifests/bindata.go:
  • vendor/*: Regenerate.
  • pkg/operator/client/client.go (init): Add apiextensionsv1, gatewayapiv1beta1, operatorsv1alpha1, maistrav1, and maistrav2 to the client scheme.
  • pkg/operator/controller/gatewayapi/controller.go (New): Add a config parameter.
    (Config): New type. Define configuration for the gatewayapi controller. For now, the only configuration is a list of dependent controllers, which for now includes only the gatewayclass controller.
    (reconciler): Add a config field with the controller configuration. Add a startControllers sync.Once field to ensure the gatewayapi controller only starts all dependent controllers once.
    (Reconcile): Start dependent controllers (i.e. the gatewayclass controller) after installing the Gateway API CRDs.
  • pkg/operator/controller/gatewayapi/controller_test.go (Test_Reconcile): Configure the reconciler with a fake gatewayclass controller.
    (TestReconcileOnlyStartsControllerOnce): New test. Verify that Reconcile only starts the gatewayclass controller once even if the gatewayapi controller gets multiple reconcile requests for the featuregate.
    (fakeController): New type, used in TestReconcileOnlyStartsControllerOnce.
    (Reconcile, Watch, Start, GetLogger): New methods for fakeController to implement the controller-runtime controller.Controller interface.
  • pkg/operator/controller/gatewayclass/controller.go: New file.
    (controllerName, OpenShiftGatewayClassControllerName, OpenShiftDefaultGatewayClassName): New consts.
    (NewUnmanaged): New function. Create a new gatewayclass controller that is not started automatically by the manager.
    (Config): New type. Store the configuration for a gatewayclass controller.
    (reconciler): New type. Store the state of a gatewayclass controller.
    (Reconcile): New method. Reconcile a gatewayclass by deploying OpenShift Service Mesh, using ensureServiceMeshOperatorSubscription and ensureServiceMeshControlPlane.
  • pkg/operator/controller/gatewayclass/servicemeshcontrolplane.go (ensureServiceMeshControlPlane): New method. Ensure a servicemeshcontrolplanes is present, using currentServiceMeshControlPlane, desiredServiceMeshControlPlane, createServiceMeshControlPlane, and updateServiceMeshControlPlane.
    (desiredServiceMeshControlPlane): New function.
    (currentServiceMeshControlPlane, createServiceMeshControlPlane, updateServiceMeshControlPlane): New methods.
    (serviceMeshControlPlaneChanged): New function, used by updateServiceMeshControlPlane.
  • pkg/operator/controller/gatewayclass/subscription.go (ensureServiceMeshOperatorSubscription): New method. Ensure a subscription for servicemeshoperator exists, using desiredSubscription, currentSubscription, createSubscription, and updateSubscription.
    (desiredSubscription): New function.
    (currentSubscription, createSubscription, updateSubscription): New methods.
    (subscriptionChanged): New function, used by updateSubscription.
  • pkg/operator/controller/names.go (ServiceMeshControlPlaneName): New function. Return the namespaced name for a ServiceMeshControlPlane CR that is associated with a GatewayClass CR.
    (ServiceMeshSubscriptionName): New function. Return the namespaced name for a Subscription CR for installing OSSM.
  • pkg/operator/operator.go (New): Create the gatewayclass controller and pass it to the constructor for the gatewayapi controller so that the latter controller can start the former one when Gateway API is enabled.

ensureWildcardDNSRecord: Delete ic parameter

Replace the operatorv1.IngressController parameter of ensureWildcardDNSRecord with parameters for the DNSRecord name, labels, owner reference, domain, and endpoint publishing strategy, and similarly for currentWildcardDNSRecord, desiredWildcardDNSRecord, and deleteWildcardDNSRecord.

  • pkg/operator/controller/ingress/controller.go (ensureIngressDeleted): Update call to deleteWildcardDNSRecord with the appropriate arguments.
    (ensureIngressController): Update to call ensureWildcardDNSRecord with the appropriate arguments.
  • pkg/operator/controller/ingress/dns.go (ensureWildcardDNSRecord): Replace the ic parameter with name, dnsRecordLabels, ownerRef, domain, and endpointPublishingStrategy parameters. Update calls to desiredWildcardDNSRecord and currentWildcardDNSRecord with the appropriate arguments.
    (desiredWildcardDNSRecord): Replace the ic parameter with name, dnsRecordLabels, ownerRef, dnsRecordDomain, and endpointPublishingStrategy parameters.
    (currentWildcardDNSRecord, deleteWildcardDNSRecord): Replace the ic parameter with a name parameter.
  • pkg/operator/controller/ingress/dns_test.go (TestDesiredWildcardDNSRecord): Update call to desiredWildcardDNSRecord.

ensureWildcardDNSRecord: Delete receiver

Replace the reconciler receiver of ensureWildcardDNSRecord and deleteWildcardDNSRecord with a client parameter.

  • pkg/operator/controller/ingress/controller.go (ensureIngressDeleted): Update call to deleteWildcardDNSRecord.
    (ensureIngressController): Update to call ensureWildcardDNSRecord.
  • pkg/operator/controller/ingress/dns.go (ensureWildcardDNSRecord, currentWildcardDNSRecord, deleteWildcardDNSRecord, updateDNSRecord): Replace receiver with client parameter.

Rename toYaml to ToYaml and move it to pkg/util

  • pkg/operator/controller/ingress/dns_test.go (toYaml): Move from here...
  • pkg/util/yaml.go (ToYaml): ...to here. New file.
  • pkg/operator/controller/ingress/controller_test.go:
  • pkg/operator/controller/ingress/status_test.go: Import and call ToYaml using its new location.

dnsrecord: New package for managing DNSRecords

  • pkg/operator/controller/ingress/controller.go: Import the new dnsrecord package and update calls to manageDNSForDomain, deleteWildcardDNSRecord, currentWildcardDNSRecord, and ensureWildcardDNSRecord to use ManageDNSForDomain, DeleteWildcardDNSRecord, CurrentWildcardDNSRecord, and EnsureWildcardDNSRecord, respectively, from the new location.
  • pkg/operator/controller/ingress/dns.go: Move file...
  • pkg/resources/dnsrecord/dns.go: ...here.
    (log): New variable. Define a logger for the new package.
    (ensureWildcardDNSRecord): Rename function...
    (EnsureWildcardDNSRecord): ...to this.
    (currentWildcardDNSRecord): Rename function...
    (CurrentWildcardDNSRecord): ...to this.
    (deleteWildcardDNSRecord): Rename function...
    (DeleteWildcardDNSRecord): ...to this
    (manageDNSForDomain): Rename function...
    (ManageDNSForDomain): ...to this.
  • pkg/operator/controller/ingress/dns_test.go: Move file...
  • pkg/resources/dnsrecord/dns_test.go: ...here.
    (TestManageDNSForDomain): Update to call ManageDNSForDomain using its new name.

dns: Don't require an owning ingresscontroller

Reconcile even a dnsrecord that has no associated ingresscontroller.

  • pkg/operator/controller/dns/controller.go (Reconcile): Delete check for owning ingresscontroller.

dns: Reconcile dnsrecords in the operand namespace

Reconcile not only dnsrecords in the operator namespace but also dnsrecords in the operand namespace.

  • pkg/operator/controller/dns/controller.go (Config): Rename the Namespace field to CredentialsRequestNamespace. Add a DNSRecordNamespaces field.
    (ToDNSRecords): Check for dnsrecords in all namespaces listed in r.config.DNSRecordNamespaces.
  • pkg/operator/operator.go (New): Specify CredentialsRequestNamespace with the operator namespace and DNSRecordNamespaces with the operator and operand namespaces.

Add service-dns controller

Introduce a new "service-api" controller, which watches services, dnsrecords, and gateways and creates DNSRecord CRs for services that are associated with gateways that OpenShift manages.

  • pkg/operator/controller/names.go (GatewayDNSRecordName): New function. Return the namespaced name for a DNSRecord CR associated with a Gateway.
  • pkg/operator/controller/service-dns/controller.go: New file.
    (controllerName, gatewayNameLabelKey, managedByIstioLabelKey): New consts.
    (log): New variable. Define a logger for the service-dns controller.
    (NewUnmanaged): New function. Create a new service-dns controller that is not started automatically by the manager.
    (gatewayListenersHostnamesChanged): New function, used in NewUnmanaged.
    (Config): New type. Store configuration for the controller.
    (reconciler): New type. Store the state of a service-dns controller.
    (Reconcile): New method. Handle reconciliation requests for services by checking whether they are associated with OpenShift-managed gateways and creating or deleting DNSRecord CRs as appropriate, using the new getGatewayHostnames function and ensureDNSRecordsForGateway and deleteStaleDNSRecordsForGateway methods.
    (getGatewayHostnames): New function. Return the domains for a gateway listener.
    (ensureDNSRecordsForGateway): New method. Ensure DNSRecord CRs exist for the given domains, associated with the given gateway and service.
    (deleteStaleDNSRecordsForGateway): New method. Delete any DNSRecord CRs that are associated with the given gateway but have DNS names that are not in the given set of domains.
  • pkg/operator/controller/service-dns/controller_test.go: New file.
    (Test_Reconcile): New test. Verify that Reconcile behaves as expected.
    (fakeCache, fakeClientRecorder): New types, used in Test_Reconcile.
    (Get, List, Scheme, RESTMapper, Create, Delete, DeleteAllOf, Update, Patch, Status): New methods for fakeClientRecorder to implement the controller-runtime client.Client interface.
    (Test_gatewayListenersHostnamesChanged): New test. Verify that gatewayListenersHostnamesChanged behaves as expected.
  • pkg/operator/operator.go (New): Instantiate the new service-dns controller and pass it to the constructor for the gatewayapi controller so that the latter controller can start the former when Gateway API is enabled.
  • pkg/resources/dnsrecord/dns.go (EnsureWildcardDNSRecord): Update calls to CurrentWildcardDNSRecord to use CurrentDNSRecord instead.
    (EnsureDNSRecord): New function. Create a DNS record with the specified domain without prepending a wildcard prefix, using the new desiredDNSRecord function.
    (desiredWildcardDNSRecord): Factor general logic out of this function...
    (desiredDNSRecord): ...into this.
    (CurrentWildcardDNSRecord): Rename from this...
    (CurrentDNSRecord): ...to this.
    (DeleteWildcardDNSRecord): Rename from this...
    (DeleteDNSRecordand): ...to this.
  • pkg/operator/controller/ingress/controller.go (ensureIngressDeleted): Update calls to DeleteWildcardDNSRecord and CurrentWildcardDNSRecord to use DeleteDNSRecordand and CurrentDNSRecord, respectively, instead.
  • vendor/*: Regenerate.

dns/aws: Store target hosted zone id in annotation

When upserting a DNS record in Route 53, store the target hosted zone id of the ELB on the associated DNSRecord CR. If a subsequent lookup of this id fails for whatever reason, fall back to using the annotation value.

This change is necessary for Gateway API because Istio sometimes deletes the ELB before the ingress operator deletes the DNS record, and so the ELB no longer exists when the DNS record deletion logic needs to look up the target hosted zone id of the ELB.

  • pkg/dns/aws/dns.go (targetHostedZoneIdAnnotationKey): New const.
    (Config): Add Client field.
    (change): Use config.Client and targetHostedZoneIdAnnotationKey to annotate the DNSRecord CR with the target hosted zone id of the ELB on upsert and look up the id on deletion.
  • pkg/operator/controller/dns/controller.go (Reconcile): Get the DNSRecord CR before updating its status in case it has changed since the previous get.
    (createDNSProvider): Provide the client to the AWS DNS provider implementation.

@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Feb 15, 2023
@candita
Copy link
Contributor

candita commented Feb 15, 2023

/assign @gcs278
/assign


// Only process records associated with ingresscontrollers, because this isn't
// intended to be a general purpose DNS management system.
ingressName, ok := record.Labels[manifests.OwningIngressControllerLabel]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if instead of removing this entirely, we could add a label for gateway DNS records that we need. Then, we are only managing 2 known kinds of records instead of becoming a general purpose DNS management system.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could, but if people wanted to abuse this controller, they could just as easily create a dnsrecord CR with whatever label we wrote the controller to check for. Checking labels seems like unnecessary complexity with little benefit.

log.Info("reconciling", "request", request)

var fg configv1.FeatureGate
if err := r.cache.Get(ctx, request.NamespacedName, &fg); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will we allow the feature gate to be enabled and disabled? If not, we should be able to check only once, store the value, and refer to that variable from lots of places.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current logic doesn't undo anything when the feature gate is turned off. Where would it be useful to be able to refer to a stored value?

func (r *reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
log.Info("reconciling", "request", request)

var fg configv1.FeatureGate
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The feature gate should be named "cluster", you could look it up by name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I'll add a predicate on the watch so that we don't get reconcile requests bogus featuregates.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in https://github.com/openshift/cluster-ingress-operator/compare/9742e1ad86e7114b21eb78fde9be83caccc596b3..d4ac3988e55abd6c35f865e03366a20245ad4256 (I did a rebase at the same time—sorry about that!—I'll try to remember to do the rebase and other changes in separate pushes in the future).

return false
}

if fs, ok := configv1.FeatureSets[fg.Spec.FeatureSet]; ok {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just extra, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is in case a feature set (such as "TechPreviewNoUpgrade") includes the "GatewayAPI" feature. It isn't needed at this time because there is no feature set that includes the "GatewayAPI" feature; it's just here for correctness and future-proofing.

},
},
},
// TODO Update expectCreate and expectStartCtrl when
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not any more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say "not yet"; eventually this feature will be tech preview, and then "GatewayAPI" may be added to the "TechPreviewNoUpgrade" feature set.

}
}

func TestReconcileOnlyStartsControllerOnce(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func TestReconcileOnlyStartsControllerOnce(t *testing.T) {
func Test_ReconcileOnlyStartsControllerOnce(t *testing.T) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no "ReconcileOnlyStartsControllerOnce" function or method.

return r.currentCRD(ctx, name)
}
}
return have, current, nil
Copy link
Contributor

@candita candita Feb 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like dead code?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We reach this line if have is true and no update was needed.

// currentCRD returns a Boolean indicating whether an CRD
// exists for the IngressController with the given name, as well as the
// CRD if it does exist and an error value.
func (r *reconciler) currentCRD(ctx context.Context, name types.NamespacedName) (bool, *apiextensionsv1.CustomResourceDefinition, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should be storing and checking versions on CRDs? And in the feature gate name. When we move from v1beta1 to v1, will there be a chicken and egg upgrade problem?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'll add a to-do for updating CRDs. I'm not sure what you mean about the feature gate name. Keep in mind that we don't support upgrades in dev preview.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the to-do comment; see #890 (comment).

class := o.(*gatewayapiv1beta1.GatewayClass)
return class.Spec.ControllerName == OpenShiftGatewayClassControllerName
})
if err := c.Watch(&source.Kind{Type: &gatewayapiv1beta1.GatewayClass{}}, &handler.EnqueueRequestForObject{}, isOurGatewayClass); err != nil {
Copy link
Contributor

@candita candita Feb 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have we definitely decided that no other "custom" GatewayClasses can be created? Or does it not matter, because this watch is only for creating the other CRDs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what you mean. We only care about gatewayclasses that specify our controller name. The cluster admin absolutely can create gatewayclasses that specify other controller names, but then any such named controllers (not ours) are responsible for managing those gatewayclasses.

}
f := false
t := true
smcp := maistrav2.ServiceMeshControlPlane{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems risky to hard code the SMCP values before we have attained release alignment. Things could change on OSSM between OpenShift releases. Is there any way to do this without hard-coding it ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you have in mind? Do you envision that the ingress operator could download the SMCP configuration from some out-of-payload source? That seems like it might be fragile and a potential attack vector, so I'd want us to design any such mechanism very carefully. For now, I'd rather not deviate to far from the design in the EP. If something changes in the SMCP definition, we can address it as a bug fix.

Security: &maistrav2.SecurityConfig{
ManageNetworkPolicy: &f,
},
TechPreview: maistrav1.NewHelmValues(map[string]interface{}{
Copy link
Contributor

@candita candita Feb 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the controlPlaneMode going to move out of the TechPreview map before FF?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly with OSSM 2.4.

Package: "servicemeshoperator",
CatalogSource: "redhat-operators",
CatalogSourceNamespace: "openshift-marketplace",
},
Copy link
Contributor

@candita candita Feb 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't look like like anything in this Subscription would ever change even if the version changed. I wonder if there needs to be another field set here, e.g. StartingCSV ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the advantage of specifying StartingCSV in the Subscription? The only thing I can think of is if we need a specific minimum 2.3.z release (e.g. 2.3.2 if it has working automated deployments).

svc := o.(*corev1.Service)
return len(svc.Labels["gateway.istio.io/managed"]) != 0
})
gatewayListenerChanged := predicate.Funcs{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Port and protocol shouldn't matter; the DNS record only changes if the host name changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Feb 18, 2023
@openshift-merge-robot openshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Feb 20, 2023
@Miciah
Copy link
Contributor Author

Miciah commented Feb 21, 2023

Latest push puts the ServiceMeshControlPlane CR back in the "openshift-ingress" namespace. Previously it was understood that the automated deployment feature didn't work if the ServiceMeshControlPlane CR and Gateway CR were in the same namespace; now it turns out that they must be in the same namespace.

@Miciah
Copy link
Contributor Author

Miciah commented Feb 21, 2023

Latest push adds commit c1c4ef6 to improve robustness of DNS record cleanup when a gateway is deleted.

}
}
// If this is an upsert, store the target hosted zone id in an
// annotation on the DNSRecord CR in case we later on we need the id and
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// annotation on the DNSRecord CR in case we later on we need the id and
// annotation on the DNSRecord CR in case we later on need the id and

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@Miciah Miciah changed the title WIP: Add support for Gateway API NE-1105: Add support for Gateway API Feb 21, 2023
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Feb 21, 2023
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Feb 21, 2023

@Miciah: This pull request references NE-1105 which is a valid jira issue.

Details

In response to this:

Add gatewayapi controller

Introduce a new "gatewayapi" controller, which creates the Gateway API CRDs when the "GatewayAPI" feature gate is enabled.

  • assets/gateway-api/gateway.networking.k8s.io_gatewayclasses.yaml:
  • assets/gateway-api/gateway.networking.k8s.io_gateways.yaml:
  • assets/gateway-api/gateway.networking.k8s.io_httproutes.yaml: New files.
  • manifests/00-cluster-role.yaml: Allow the operator to manage the Gateway API CRDs.
  • pkg/manifests/bindata.go: Regenerate.
  • pkg/manifests/manifests.go (GatewayClassCRDAsset, GatewayCRDAsset, HTTPRouteCRDAsset): New consts.
    (GatewayClassCRD, GatewayCRD, HTTPRouteCRD, NewCustomResourceDefinition): New functions.
  • pkg/manifests/manifests_test.go (TestManifests): Test GatewayClassCRD, GatewayCRD, and HTTPRouteCRD.
  • pkg/operator/controller/gatewayapi/controller.go: New file.
    (controllerName): New const.
    (log): New variable. Define a logger for the controller.
    (New): New function. Create an instance of the controller.
    (reconciler): New type. Store the state of a gatewayapi controller.
    (Reconcile): New method. Handle reconciliation requests for featuregates by checking for the "GatewayAPI" feature and ensuring the Gateway API CRDs exist if the feature is enabled.
    (featureIsEnabled): New function. Helper for Reconcile.
  • pkg/operator/controller/gatewayapi/controller_test.go: New file.
    (Test_Reconcile): New test. Verify that Reconcile behaves as expected.
    (fakeCache, fakeClientRecorder): New types, used in Test_Reconcile.
    (Get, List, Scheme, RESTMapper, Create, Delete, DeleteAllOf, Update, Patch, Status): New methods for fakeClientRecorder to implement the controller-runtime client.Client interface.
  • pkg/operator/controller/gatewayapi/crds.go: New file.
    (managedCRDs): New variable. Define the CRDs that this controller manages.
    (ensureCRD): New method. Ensure the specified CRD is present, using currentCRD, createCRD, and updateCRD.
    (ensureGatewayAPICRDs): Ensure the CRDs in managedCRDs are present, using ensureCRD.
    (currentCRD, createCRD, updateCRD): New methods.
    (crdChanged): New function, used by updateCRD.
  • pkg/operator/operator.go (New): Initialize the new gatewayapi controller.
  • go.mod:
  • vendor/*: Regenerate.

Add gatewayclass controller

Introduce a new "gatewayclass" controller, which watches gatewayclasses and installs the Service Mesh operator when a GatewayClass owned by OpenShift is first observed.

A GatewayClass is considered owned by OpenShift if its spec.controllerName field specifies "openshift.io/gateway-controller".

  • manifests/00-cluster-role.yaml: Allow the operator to manage the Gateway API CRs, the servicemeshoperator subscription, and servicemeshcontrolplanes.
  • go.mod: Add github.com/maistra/istio-operator, github.com/operator-framework/api, and sigs.k8s.io/gateway-api.
  • go.sum:
  • pkg/manifests/bindata.go:
  • vendor/*: Regenerate.
  • pkg/operator/client/client.go (init): Add apiextensionsv1, gatewayapiv1beta1, operatorsv1alpha1, maistrav1, and maistrav2 to the client scheme.
  • pkg/operator/controller/gatewayapi/controller.go (New): Add a config parameter.
    (Config): New type. Define configuration for the gatewayapi controller. For now, the only configuration is a list of dependent controllers, which for now includes only the gatewayclass controller.
    (reconciler): Add a config field with the controller configuration. Add a startControllers sync.Once field to ensure the gatewayapi controller only starts all dependent controllers once.
    (Reconcile): Start dependent controllers (i.e. the gatewayclass controller) after installing the Gateway API CRDs.
  • pkg/operator/controller/gatewayapi/controller_test.go (Test_Reconcile): Configure the reconciler with a fake gatewayclass controller.
    (TestReconcileOnlyStartsControllerOnce): New test. Verify that Reconcile only starts the gatewayclass controller once even if the gatewayapi controller gets multiple reconcile requests for the featuregate.
    (fakeController): New type, used in TestReconcileOnlyStartsControllerOnce.
    (Reconcile, Watch, Start, GetLogger): New methods for fakeController to implement the controller-runtime controller.Controller interface.
  • pkg/operator/controller/gatewayclass/controller.go: New file.
    (controllerName, OpenShiftGatewayClassControllerName): New consts.
    (NewUnmanaged): New function. Create a new gatewayclass controller that is not started automatically by the manager.
    (Config): New type. Store the configuration for a gatewayclass controller.
    (reconciler): New type. Store the state of a gatewayclass controller.
    (Reconcile): New method. Reconcile a gatewayclass by deploying OpenShift Service Mesh, using ensureServiceMeshOperatorSubscription and ensureServiceMeshControlPlane.
  • pkg/operator/controller/gatewayclass/servicemeshcontrolplane.go (ensureServiceMeshControlPlane): New method. Ensure a servicemeshcontrolplanes is present, using currentServiceMeshControlPlane, desiredServiceMeshControlPlane, createServiceMeshControlPlane, and updateServiceMeshControlPlane.
    (desiredServiceMeshControlPlane): New function.
    (currentServiceMeshControlPlane, createServiceMeshControlPlane, updateServiceMeshControlPlane): New methods.
    (serviceMeshControlPlaneChanged): New function, used by updateServiceMeshControlPlane.
  • pkg/operator/controller/gatewayclass/subscription.go (ensureServiceMeshOperatorSubscription): New method. Ensure a subscription for servicemeshoperator exists, using desiredSubscription, currentSubscription, createSubscription, and updateSubscription.
    (desiredSubscription): New function.
    (currentSubscription, createSubscription, updateSubscription): New methods.
    (subscriptionChanged): New function, used by updateSubscription.
  • pkg/operator/controller/names.go (ServiceMeshControlPlaneName): New function. Return the namespaced name for a ServiceMeshControlPlane CR that is associated with a GatewayClass CR.
  • pkg/operator/operator.go (New): Create the gatewayclass controller and pass it to the constructor for the gatewayapi controller so that the latter controller can start the former one when Gateway API is enabled.

ensureWildcardDNSRecord: Delete ic parameter

Replace the operatorv1.IngressController parameter of ensureWildcardDNSRecord with parameters for the DNSRecord name, labels, owner reference, domain, and endpoint publishing strategy, and similarly for currentWildcardDNSRecord, desiredWildcardDNSRecord, and deleteWildcardDNSRecord.

  • pkg/operator/controller/ingress/controller.go (ensureIngressDeleted): Update call to deleteWildcardDNSRecord with the appropriate arguments.
    (ensureIngressController): Update to call ensureWildcardDNSRecord with the appropriate arguments.
  • pkg/operator/controller/ingress/dns.go (ensureWildcardDNSRecord): Replace the ic parameter with name, dnsRecordLabels, ownerRef, domain, and endpointPublishingStrategy parameters. Update calls to desiredWildcardDNSRecord and currentWildcardDNSRecord with the appropriate arguments.
    (desiredWildcardDNSRecord): Replace the ic parameter with name, dnsRecordLabels, ownerRef, dnsRecordDomain, and endpointPublishingStrategy parameters.
    (currentWildcardDNSRecord, deleteWildcardDNSRecord): Replace the ic parameter with a name parameter.
  • pkg/operator/controller/ingress/dns_test.go (TestDesiredWildcardDNSRecord): Update call to desiredWildcardDNSRecord.

ensureWildcardDNSRecord: Delete receiver

Replace the reconciler receiver of ensureWildcardDNSRecord and deleteWildcardDNSRecord with a client parameter.

  • pkg/operator/controller/ingress/controller.go (ensureIngressDeleted): Update call to deleteWildcardDNSRecord.
    (ensureIngressController): Update to call ensureWildcardDNSRecord.
  • pkg/operator/controller/ingress/dns.go (ensureWildcardDNSRecord, currentWildcardDNSRecord, deleteWildcardDNSRecord, updateDNSRecord): Replace receiver with client parameter.

Rename toYaml to ToYaml and move it to pkg/util

  • pkg/operator/controller/ingress/dns_test.go (toYaml): Move from here...
  • pkg/util/yaml.go (ToYaml): ...to here. New file.
  • pkg/operator/controller/ingress/controller_test.go:
  • pkg/operator/controller/ingress/status_test.go: Import and call ToYaml using its new location.

dnsrecord: New package for managing DNSRecords

  • pkg/operator/controller/ingress/controller.go: Import the new dnsrecord package and update calls to manageDNSForDomain, deleteWildcardDNSRecord, currentWildcardDNSRecord, and ensureWildcardDNSRecord to use ManageDNSForDomain, DeleteWildcardDNSRecord, CurrentWildcardDNSRecord, and EnsureWildcardDNSRecord, respectively, from the new location.
  • pkg/operator/controller/ingress/dns.go: Move file...
  • pkg/resources/dnsrecord/dns.go: ...here.
    (log): New variable. Define a logger for the new package.
    (ensureWildcardDNSRecord): Rename function...
    (EnsureWildcardDNSRecord): ...to this.
    (currentWildcardDNSRecord): Rename function...
    (CurrentWildcardDNSRecord): ...to this.
    (deleteWildcardDNSRecord): Rename function...
    (DeleteWildcardDNSRecord): ...to this
    (manageDNSForDomain): Rename function...
    (ManageDNSForDomain): ...to this.
  • pkg/operator/controller/ingress/dns_test.go: Move file...
  • pkg/resources/dnsrecord/dns_test.go: ...here.
    (TestManageDNSForDomain): Update to call ManageDNSForDomain using its new name.

dns: Don't require an owning ingresscontroller

Reconcile even a dnsrecord that has no associated ingresscontroller.

  • pkg/operator/controller/dns/controller.go (Reconcile): Delete check for owning ingresscontroller.

dns: Reconcile dnsrecords in the operand namespace

Reconcile not only dnsrecords in the operator namespace but also dnsrecords in the operand namespace.

  • pkg/operator/controller/dns/controller.go (Config): Rename the Namespace field to CredentialsRequestNamespace. Add a DNSRecordNamespaces field.
    (ToDNSRecords): Check for dnsrecords in all namespaces listed in r.config.DNSRecordNamespaces.
  • pkg/operator/operator.go (New): Specify CredentialsRequestNamespace with the operator namespace and DNSRecordNamespaces with the operator and operand namespaces.

Add service-dns controller

Introduce a new "service-api" controller, which watches services, dnsrecords, and gateways and creates DNSRecord CRs for services that are associated with gateways that OpenShift manages.

  • pkg/operator/controller/names.go (GatewayDNSRecordName): New function. Return the namespaced name for a DNSRecord CR associated with a Gateway.
  • pkg/operator/controller/service-dns/controller.go: New file.
    (controllerName): New const.
    (log): New variable. Define a logger for the service-dns controller.
    (NewUnmanaged): New function. Create a new service-dns controller that is not started automatically by the manager.
    (Config): New type. Store configuration for the controller.
    (reconciler): New type. Store the state of a service-dns controller.
    (Reconcile): New method. Handle reconciliation requests for services by checking whether they are associated with OpenShift-managed gateways and creating or deleting DNSRecord CRs as appropriate.
  • pkg/operator/controller/service-dns/controller_test.go: New file.
    (Test_Reconcile): New test. Verify that Reconcile behaves as expected.
    (fakeCache, fakeClientRecorder): New types, used in Test_Reconcile.
    (Get, List, Scheme, RESTMapper, Create, Delete, DeleteAllOf, Update, Patch, Status): New methods for fakeClientRecorder to implement the controller-runtime client.Client interface.
  • pkg/operator/operator.go (New): Instantiate the new service-dns controller and pass it to the constructor for the gatewayapi controller so that the latter controller can start the former when Gateway API is enabled.
  • pkg/resources/dnsrecord/dns.go (EnsureWildcardDNSRecord): Update calls to CurrentWildcardDNSRecord to use CurrentDNSRecord instead.
    (EnsureDNSRecord): New function. Create a DNS record with the specified domain without prepending a wildcard prefix, using the new desiredDNSRecord function.
    (desiredWildcardDNSRecord): Factor general logic out of this function...
    (desiredDNSRecord): ...into this.
    (CurrentWildcardDNSRecord): Rename from this...
    (CurrentDNSRecord): ...to this.
    (DeleteWildcardDNSRecord): Rename from this...
    (DeleteDNSRecordand): ...to this.
  • pkg/operator/controller/ingress/controller.go (ensureIngressDeleted): Update calls to DeleteWildcardDNSRecord and CurrentWildcardDNSRecord to use DeleteDNSRecordand and CurrentDNSRecord, respectively, instead.
  • vendor/*: Regenerate.

dns/aws: Store target hosted zone id in annotation

When upserting a DNS record in Route 53, store the target hosted zone id of the ELB on the associated DNSRecord CR. If a subsequent lookup of this id fails for whatever reason, fall back to using the annotation value.

This change is necessary for Gateway API because Istio sometimes deletes the ELB before the ingress operator deletes the DNS record, and so the ELB no longer exists when the DNS record deletion logic needs to look up the target hosted zone id of the ELB.

  • pkg/dns/aws/dns.go (targetHostedZoneIdAnnotationKey): New const.
    (Config): Add Client field.
    (change): Use config.Client and targetHostedZoneIdAnnotationKey to annotate the DNSRecord CR with the target hosted zone id of the ELB on upsert and look up the id on deletion.
  • pkg/operator/controller/dns/controller.go (Reconcile): Get the DNSRecord CR before updating its status in case it has changed since the previous get.
    (createDNSProvider): Provide the client to the AWS DNS provider implementation.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Feb 22, 2023

@Miciah: This pull request references NE-1105 which is a valid jira issue.

Details

In response to this:

Add gatewayapi controller

Introduce a new "gatewayapi" controller, which creates the Gateway API CRDs when the "GatewayAPI" feature gate is enabled.

  • assets/gateway-api/gateway.networking.k8s.io_gatewayclasses.yaml:
  • assets/gateway-api/gateway.networking.k8s.io_gateways.yaml:
  • assets/gateway-api/gateway.networking.k8s.io_httproutes.yaml:
  • assets/gateway-api/gateway.networking.k8s.io_referencegrants.yaml: New files.
  • manifests/00-cluster-role.yaml: Allow the operator to manage the Gateway API CRDs.
  • pkg/manifests/bindata.go: Regenerate.
  • pkg/manifests/manifests.go (GatewayClassCRDAsset, GatewayCRDAsset, HTTPRouteCRDAsset, ReferenceGrantCRDAsset): New consts.
    (GatewayClassCRD, GatewayCRD, HTTPRouteCRD, ReferenceGrantCRD, NewCustomResourceDefinition): New functions.
  • pkg/manifests/manifests_test.go (TestManifests): Test GatewayClassCRD, GatewayCRD, HTTPRouteCRD, and ReferenceGrantCRD.
  • pkg/operator/controller/gatewayapi/controller.go: New file.
    (controllerName, featureGateName): New consts.
    (log): New variable. Define a logger for the controller.
    (New): New function. Create an instance of the controller.
    (reconciler): New type. Store the state of a gatewayapi controller.
    (Reconcile): New method. Handle reconciliation requests for featuregates by checking for the "GatewayAPI" feature and ensuring the Gateway API CRDs exist if the feature is enabled.
    (featureIsEnabled): New function. Helper for Reconcile.
  • pkg/operator/controller/gatewayapi/controller_test.go: New file.
    (Test_Reconcile): New test. Verify that Reconcile behaves as expected.
    (fakeCache, fakeClientRecorder): New types, used in Test_Reconcile.
    (Get, List, Scheme, RESTMapper, Create, Delete, DeleteAllOf, Update, Patch, Status): New methods for fakeClientRecorder to implement the controller-runtime client.Client interface.
  • pkg/operator/controller/gatewayapi/crds.go: New file.
    (managedCRDs): New variable. Define the CRDs that this controller manages.
    (ensureCRD): New method. Ensure the specified CRD is present, using currentCRD, createCRD, and updateCRD.
    (ensureGatewayAPICRDs): Ensure the CRDs in managedCRDs are present, using ensureCRD.
    (currentCRD, createCRD, updateCRD): New methods.
    (crdChanged): New function, used by updateCRD.
  • pkg/operator/operator.go (New): Initialize the new gatewayapi controller.
  • go.mod:
  • vendor/*: Regenerate.

Add gatewayclass controller

Introduce a new "gatewayclass" controller, which watches gatewayclasses and installs the Service Mesh operator when a GatewayClass owned by OpenShift is first observed.

A GatewayClass is considered owned by OpenShift if its spec.controllerName field specifies "openshift.io/gateway-controller".

  • manifests/00-cluster-role.yaml: Allow the operator to manage the Gateway API CRs, the servicemeshoperator subscription, and servicemeshcontrolplanes.
  • go.mod: Add github.com/maistra/istio-operator, github.com/operator-framework/api, and sigs.k8s.io/gateway-api.
  • go.sum:
  • pkg/manifests/bindata.go:
  • vendor/*: Regenerate.
  • pkg/operator/client/client.go (init): Add apiextensionsv1, gatewayapiv1beta1, operatorsv1alpha1, maistrav1, and maistrav2 to the client scheme.
  • pkg/operator/controller/gatewayapi/controller.go (New): Add a config parameter.
    (Config): New type. Define configuration for the gatewayapi controller. For now, the only configuration is a list of dependent controllers, which for now includes only the gatewayclass controller.
    (reconciler): Add a config field with the controller configuration. Add a startControllers sync.Once field to ensure the gatewayapi controller only starts all dependent controllers once.
    (Reconcile): Start dependent controllers (i.e. the gatewayclass controller) after installing the Gateway API CRDs.
  • pkg/operator/controller/gatewayapi/controller_test.go (Test_Reconcile): Configure the reconciler with a fake gatewayclass controller.
    (TestReconcileOnlyStartsControllerOnce): New test. Verify that Reconcile only starts the gatewayclass controller once even if the gatewayapi controller gets multiple reconcile requests for the featuregate.
    (fakeController): New type, used in TestReconcileOnlyStartsControllerOnce.
    (Reconcile, Watch, Start, GetLogger): New methods for fakeController to implement the controller-runtime controller.Controller interface.
  • pkg/operator/controller/gatewayclass/controller.go: New file.
    (controllerName, OpenShiftGatewayClassControllerName, OpenShiftDefaultGatewayClassName): New consts.
    (NewUnmanaged): New function. Create a new gatewayclass controller that is not started automatically by the manager.
    (Config): New type. Store the configuration for a gatewayclass controller.
    (reconciler): New type. Store the state of a gatewayclass controller.
    (Reconcile): New method. Reconcile a gatewayclass by deploying OpenShift Service Mesh, using ensureServiceMeshOperatorSubscription and ensureServiceMeshControlPlane.
  • pkg/operator/controller/gatewayclass/servicemeshcontrolplane.go (ensureServiceMeshControlPlane): New method. Ensure a servicemeshcontrolplanes is present, using currentServiceMeshControlPlane, desiredServiceMeshControlPlane, createServiceMeshControlPlane, and updateServiceMeshControlPlane.
    (desiredServiceMeshControlPlane): New function.
    (currentServiceMeshControlPlane, createServiceMeshControlPlane, updateServiceMeshControlPlane): New methods.
    (serviceMeshControlPlaneChanged): New function, used by updateServiceMeshControlPlane.
  • pkg/operator/controller/gatewayclass/subscription.go (ensureServiceMeshOperatorSubscription): New method. Ensure a subscription for servicemeshoperator exists, using desiredSubscription, currentSubscription, createSubscription, and updateSubscription.
    (desiredSubscription): New function.
    (currentSubscription, createSubscription, updateSubscription): New methods.
    (subscriptionChanged): New function, used by updateSubscription.
  • pkg/operator/controller/names.go (ServiceMeshControlPlaneName): New function. Return the namespaced name for a ServiceMeshControlPlane CR that is associated with a GatewayClass CR.
    (ServiceMeshSubscriptionName): New function. Return the namespaced name for a Subscription CR for installing OSSM.
  • pkg/operator/operator.go (New): Create the gatewayclass controller and pass it to the constructor for the gatewayapi controller so that the latter controller can start the former one when Gateway API is enabled.

ensureWildcardDNSRecord: Delete ic parameter

Replace the operatorv1.IngressController parameter of ensureWildcardDNSRecord with parameters for the DNSRecord name, labels, owner reference, domain, and endpoint publishing strategy, and similarly for currentWildcardDNSRecord, desiredWildcardDNSRecord, and deleteWildcardDNSRecord.

  • pkg/operator/controller/ingress/controller.go (ensureIngressDeleted): Update call to deleteWildcardDNSRecord with the appropriate arguments.
    (ensureIngressController): Update to call ensureWildcardDNSRecord with the appropriate arguments.
  • pkg/operator/controller/ingress/dns.go (ensureWildcardDNSRecord): Replace the ic parameter with name, dnsRecordLabels, ownerRef, domain, and endpointPublishingStrategy parameters. Update calls to desiredWildcardDNSRecord and currentWildcardDNSRecord with the appropriate arguments.
    (desiredWildcardDNSRecord): Replace the ic parameter with name, dnsRecordLabels, ownerRef, dnsRecordDomain, and endpointPublishingStrategy parameters.
    (currentWildcardDNSRecord, deleteWildcardDNSRecord): Replace the ic parameter with a name parameter.
  • pkg/operator/controller/ingress/dns_test.go (TestDesiredWildcardDNSRecord): Update call to desiredWildcardDNSRecord.

ensureWildcardDNSRecord: Delete receiver

Replace the reconciler receiver of ensureWildcardDNSRecord and deleteWildcardDNSRecord with a client parameter.

  • pkg/operator/controller/ingress/controller.go (ensureIngressDeleted): Update call to deleteWildcardDNSRecord.
    (ensureIngressController): Update to call ensureWildcardDNSRecord.
  • pkg/operator/controller/ingress/dns.go (ensureWildcardDNSRecord, currentWildcardDNSRecord, deleteWildcardDNSRecord, updateDNSRecord): Replace receiver with client parameter.

Rename toYaml to ToYaml and move it to pkg/util

  • pkg/operator/controller/ingress/dns_test.go (toYaml): Move from here...
  • pkg/util/yaml.go (ToYaml): ...to here. New file.
  • pkg/operator/controller/ingress/controller_test.go:
  • pkg/operator/controller/ingress/status_test.go: Import and call ToYaml using its new location.

dnsrecord: New package for managing DNSRecords

  • pkg/operator/controller/ingress/controller.go: Import the new dnsrecord package and update calls to manageDNSForDomain, deleteWildcardDNSRecord, currentWildcardDNSRecord, and ensureWildcardDNSRecord to use ManageDNSForDomain, DeleteWildcardDNSRecord, CurrentWildcardDNSRecord, and EnsureWildcardDNSRecord, respectively, from the new location.
  • pkg/operator/controller/ingress/dns.go: Move file...
  • pkg/resources/dnsrecord/dns.go: ...here.
    (log): New variable. Define a logger for the new package.
    (ensureWildcardDNSRecord): Rename function...
    (EnsureWildcardDNSRecord): ...to this.
    (currentWildcardDNSRecord): Rename function...
    (CurrentWildcardDNSRecord): ...to this.
    (deleteWildcardDNSRecord): Rename function...
    (DeleteWildcardDNSRecord): ...to this
    (manageDNSForDomain): Rename function...
    (ManageDNSForDomain): ...to this.
  • pkg/operator/controller/ingress/dns_test.go: Move file...
  • pkg/resources/dnsrecord/dns_test.go: ...here.
    (TestManageDNSForDomain): Update to call ManageDNSForDomain using its new name.

dns: Don't require an owning ingresscontroller

Reconcile even a dnsrecord that has no associated ingresscontroller.

  • pkg/operator/controller/dns/controller.go (Reconcile): Delete check for owning ingresscontroller.

dns: Reconcile dnsrecords in the operand namespace

Reconcile not only dnsrecords in the operator namespace but also dnsrecords in the operand namespace.

  • pkg/operator/controller/dns/controller.go (Config): Rename the Namespace field to CredentialsRequestNamespace. Add a DNSRecordNamespaces field.
    (ToDNSRecords): Check for dnsrecords in all namespaces listed in r.config.DNSRecordNamespaces.
  • pkg/operator/operator.go (New): Specify CredentialsRequestNamespace with the operator namespace and DNSRecordNamespaces with the operator and operand namespaces.

Add service-dns controller

Introduce a new "service-api" controller, which watches services, dnsrecords, and gateways and creates DNSRecord CRs for services that are associated with gateways that OpenShift manages.

  • pkg/operator/controller/names.go (GatewayDNSRecordName): New function. Return the namespaced name for a DNSRecord CR associated with a Gateway.
  • pkg/operator/controller/service-dns/controller.go: New file.
    (controllerName, gatewayNameLabelKey, managedByIstioLabelKey): New consts.
    (log): New variable. Define a logger for the service-dns controller.
    (NewUnmanaged): New function. Create a new service-dns controller that is not started automatically by the manager.
    (gatewayListenersHostnamesChanged): New function, used in NewUnmanaged.
    (Config): New type. Store configuration for the controller.
    (reconciler): New type. Store the state of a service-dns controller.
    (Reconcile): New method. Handle reconciliation requests for services by checking whether they are associated with OpenShift-managed gateways and creating or deleting DNSRecord CRs as appropriate, using the new getGatewayHostnames function and ensureDNSRecordsForGateway and deleteStaleDNSRecordsForGateway methods.
    (getGatewayHostnames): New function. Return the domains for a gateway listener.
    (ensureDNSRecordsForGateway): New method. Ensure DNSRecord CRs exist for the given domains, associated with the given gateway and service.
    (deleteStaleDNSRecordsForGateway): New method. Delete any DNSRecord CRs that are associated with the given gateway but have DNS names that are not in the given set of domains.
  • pkg/operator/controller/service-dns/controller_test.go: New file.
    (Test_Reconcile): New test. Verify that Reconcile behaves as expected.
    (fakeCache, fakeClientRecorder): New types, used in Test_Reconcile.
    (Get, List, Scheme, RESTMapper, Create, Delete, DeleteAllOf, Update, Patch, Status): New methods for fakeClientRecorder to implement the controller-runtime client.Client interface.
    (Test_gatewayListenersHostnamesChanged): New test. Verify that gatewayListenersHostnamesChanged behaves as expected.
  • pkg/operator/operator.go (New): Instantiate the new service-dns controller and pass it to the constructor for the gatewayapi controller so that the latter controller can start the former when Gateway API is enabled.
  • pkg/resources/dnsrecord/dns.go (EnsureWildcardDNSRecord): Update calls to CurrentWildcardDNSRecord to use CurrentDNSRecord instead.
    (EnsureDNSRecord): New function. Create a DNS record with the specified domain without prepending a wildcard prefix, using the new desiredDNSRecord function.
    (desiredWildcardDNSRecord): Factor general logic out of this function...
    (desiredDNSRecord): ...into this.
    (CurrentWildcardDNSRecord): Rename from this...
    (CurrentDNSRecord): ...to this.
    (DeleteWildcardDNSRecord): Rename from this...
    (DeleteDNSRecordand): ...to this.
  • pkg/operator/controller/ingress/controller.go (ensureIngressDeleted): Update calls to DeleteWildcardDNSRecord and CurrentWildcardDNSRecord to use DeleteDNSRecordand and CurrentDNSRecord, respectively, instead.
  • vendor/*: Regenerate.

dns/aws: Store target hosted zone id in annotation

When upserting a DNS record in Route 53, store the target hosted zone id of the ELB on the associated DNSRecord CR. If a subsequent lookup of this id fails for whatever reason, fall back to using the annotation value.

This change is necessary for Gateway API because Istio sometimes deletes the ELB before the ingress operator deletes the DNS record, and so the ELB no longer exists when the DNS record deletion logic needs to look up the target hosted zone id of the ELB.

  • pkg/dns/aws/dns.go (targetHostedZoneIdAnnotationKey): New const.
    (Config): Add Client field.
    (change): Use config.Client and targetHostedZoneIdAnnotationKey to annotate the DNSRecord CR with the target hosted zone id of the ELB on upsert and look up the id on deletion.
  • pkg/operator/controller/dns/controller.go (Reconcile): Get the DNSRecord CR before updating its status in case it has changed since the previous get.
    (createDNSProvider): Provide the client to the AWS DNS provider implementation.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

)

const (
controllerName = "service_dns_controller"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit you named this service-dns controller, but in reality, it's a Gateway API DNS controller at the moment, since it only reconciles services belonging to a Gateway auto deployment.

Is the grand plan to ever expand this past Gateway API? If not, would it be better to call this controller gatewayapi-dns to better reflect what it's accomplishing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point. How about calling it the "gateway-service-dns" controller? If you prefer "gateway-dns", I can go with that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either is fine with me, though, I was thinking of having gatewayapi-... in the name to help associate specifically to Gateway API, also keeping in mind your other controller is called gatewayapi. But yea, technically it is gateway-service-dns, since it's doing DNS for Gateways.

I have no strong opinions. Whatever you think would help describe the duty of the controller.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

labels := map[string]string{
gatewayNameLabelKey: gateway.Name,
}
for k, v := range service.Labels {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the motivation behind taking all of the service labels and placing them on the dns record?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figured the service labels likely have useful information for understanding how these resources relate to a given gateway or manager/controller. I can drop it if it isn't useful.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it doesn't hurt anything, I don't mind. Just was curious, maybe it would help us in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Come to think of it, I might have been inspired by Istio:

Annotations and labels on the Gateway will be copied to the Service and Deployment.

https://istio.io/latest/docs/tasks/traffic-management/ingress/gateway-api/#automated-deployment

// domains. Such DNSRecord CRs may exist if a hostname was modified or deleted
// on the gateway. deleteStaleDNSRecordsForGateway returns a list of any errors
// that result from deleting those DNSRecord CRs.
func (r *reconciler) deleteStaleDNSRecordsForGateway(ctx context.Context, gateway *gatewayapiv1beta1.Gateway, service *corev1.Service, domains sets.String) []error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit sets.String is supposedly deprecated. Goland says you should use a generic set instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use sets.String in many places, and we don't use generics anywhere. Maybe we can do a comprehensive update to replace sets.String with generics throughout the codebase as a followup?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, we can do it later.

Introduce a new "gatewayclass" controller, which watches gatewayclasses and
installs the Service Mesh operator when a GatewayClass owned by OpenShift
is first observed.

A GatewayClass is considered owned by OpenShift if its spec.controllerName
field specifies "openshift.io/gateway-controller".

* manifests/00-cluster-role.yaml: Allow the operator to manage the Gateway
API CRs, the servicemeshoperator subscription, and
servicemeshcontrolplanes.
* go.mod: Add github.com/maistra/istio-operator,
github.com/operator-framework/api, and sigs.k8s.io/gateway-api.
* go.sum:
* pkg/manifests/bindata.go:
* vendor/*: Regenerate.
* pkg/operator/client/client.go (init): Add apiextensionsv1,
gatewayapiv1beta1, operatorsv1alpha1, maistrav1, and maistrav2 to the
client scheme.
* pkg/operator/controller/gatewayapi/controller.go (New): Add a config
parameter.
(Config): New type.  Define configuration for the gatewayapi controller.
For now, the only configuration is a list of dependent controllers, which
for now includes only the gatewayclass controller.
(reconciler): Add a config field with the controller configuration.  Add a
startControllers sync.Once field to ensure the gatewayapi controller only
starts all dependent controllers once.
(Reconcile): Start dependent controllers (i.e. the gatewayclass controller)
after installing the Gateway API CRDs.
* pkg/operator/controller/gatewayapi/controller_test.go (Test_Reconcile):
Configure the reconciler with a fake gatewayclass controller.
(TestReconcileOnlyStartsControllerOnce): New test.  Verify that Reconcile
only starts the gatewayclass controller once even if the gatewayapi
controller gets multiple reconcile requests for the featuregate.
(fakeController): New type, used in TestReconcileOnlyStartsControllerOnce.
(Reconcile, Watch, Start, GetLogger): New methods for fakeController to
implement the controller-runtime controller.Controller interface.
* pkg/operator/controller/gatewayclass/controller.go: New file.
(controllerName, OpenShiftGatewayClassControllerName)
(OpenShiftDefaultGatewayClassName): New consts.
(NewUnmanaged): New function.  Create a new gatewayclass controller that is
not started automatically by the manager.
(Config): New type.  Store the configuration for a gatewayclass controller.
(reconciler): New type.  Store the state of a gatewayclass controller.
(Reconcile): New method.  Reconcile a gatewayclass by deploying OpenShift
Service Mesh, using ensureServiceMeshOperatorSubscription and
ensureServiceMeshControlPlane.
* pkg/operator/controller/gatewayclass/servicemeshcontrolplane.go
(ensureServiceMeshControlPlane): New method.  Ensure a
servicemeshcontrolplanes is present, using currentServiceMeshControlPlane,
desiredServiceMeshControlPlane, createServiceMeshControlPlane, and
updateServiceMeshControlPlane.
(desiredServiceMeshControlPlane): New function.
(currentServiceMeshControlPlane, createServiceMeshControlPlane)
(updateServiceMeshControlPlane): New methods.
(serviceMeshControlPlaneChanged): New function, used by
updateServiceMeshControlPlane.
* pkg/operator/controller/gatewayclass/subscription.go
(ensureServiceMeshOperatorSubscription): New method.  Ensure a subscription
for servicemeshoperator exists, using desiredSubscription,
currentSubscription, createSubscription, and updateSubscription.
(desiredSubscription): New function.
(currentSubscription, createSubscription, updateSubscription): New methods.
(subscriptionChanged): New function, used by updateSubscription.
* pkg/operator/controller/names.go (ServiceMeshControlPlaneName): New
function.  Return the namespaced name for a ServiceMeshControlPlane CR
that is associated with a GatewayClass CR.
(ServiceMeshSubscriptionName): New function.  Return the namespaced name
for a Subscription CR for installing OSSM.
* pkg/operator/operator.go (New): Create the gatewayclass controller and
pass it to the constructor for the gatewayapi controller so that the latter
controller can start the former one when Gateway API is enabled.
Replace the operatorv1.IngressController parameter of
ensureWildcardDNSRecord with parameters for the DNSRecord name, labels,
owner reference, domain, and endpoint publishing strategy, and similarly
for currentWildcardDNSRecord, desiredWildcardDNSRecord, and
deleteWildcardDNSRecord.

* pkg/operator/controller/ingress/controller.go (ensureIngressDeleted):
Update call to deleteWildcardDNSRecord with the appropriate arguments.
(ensureIngressController): Update to call ensureWildcardDNSRecord with the
appropriate arguments.
* pkg/operator/controller/ingress/dns.go (ensureWildcardDNSRecord): Replace
the ic parameter with name, dnsRecordLabels, ownerRef, domain, and
endpointPublishingStrategy parameters.  Update calls to
desiredWildcardDNSRecord and currentWildcardDNSRecord with the appropriate
arguments.
(desiredWildcardDNSRecord): Replace the ic parameter with name,
dnsRecordLabels, ownerRef, dnsRecordDomain, and endpointPublishingStrategy
parameters.
(currentWildcardDNSRecord, deleteWildcardDNSRecord): Replace the ic
parameter with a name parameter.
* pkg/operator/controller/ingress/dns_test.go
(TestDesiredWildcardDNSRecord): Update call to desiredWildcardDNSRecord.
Replace the reconciler receiver of ensureWildcardDNSRecord and
deleteWildcardDNSRecord with a client parameter.

* pkg/operator/controller/ingress/controller.go (ensureIngressDeleted):
Update call to deleteWildcardDNSRecord.
(ensureIngressController): Update to call ensureWildcardDNSRecord.
* pkg/operator/controller/ingress/dns.go (ensureWildcardDNSRecord)
(currentWildcardDNSRecord, deleteWildcardDNSRecord, updateDNSRecord):
Replace receiver with client parameter.
* pkg/operator/controller/ingress/dns_test.go (toYaml): Move from here...
* pkg/util/yaml.go (ToYaml): ...to here.  New file.
* pkg/operator/controller/ingress/controller_test.go:
* pkg/operator/controller/ingress/status_test.go: Import and call ToYaml
using its new location.
* pkg/operator/controller/ingress/controller.go: Import the new dnsrecord
package and update calls to manageDNSForDomain, deleteWildcardDNSRecord,
currentWildcardDNSRecord, and ensureWildcardDNSRecord to use
ManageDNSForDomain, DeleteWildcardDNSRecord, CurrentWildcardDNSRecord, and
EnsureWildcardDNSRecord, respectively, from the new location.
* pkg/operator/controller/ingress/dns.go: Move file...
* pkg/resources/dnsrecord/dns.go: ...here.
(log): New variable.  Define a logger for the new package.
(ensureWildcardDNSRecord): Rename function...
(EnsureWildcardDNSRecord): ...to this.
(currentWildcardDNSRecord): Rename function...
(CurrentWildcardDNSRecord): ...to this.
(deleteWildcardDNSRecord): Rename function...
(DeleteWildcardDNSRecord): ...to this
(manageDNSForDomain): Rename function...
(ManageDNSForDomain): ...to this.
* pkg/operator/controller/ingress/dns_test.go: Move file...
* pkg/resources/dnsrecord/dns_test.go: ...here.
(TestManageDNSForDomain): Update to call ManageDNSForDomain using its new
name.
Reconcile even a dnsrecord that has no associated ingresscontroller.

* pkg/operator/controller/dns/controller.go (Reconcile): Delete check for
owning ingresscontroller.
Reconcile not only dnsrecords in the operator namespace but also dnsrecords
in the operand namespace.

* pkg/operator/controller/dns/controller.go (Config): Rename the
"Namespace" field to "CredentialsRequestNamespace".  Add a
"DNSRecordNamespaces" field.
(ToDNSRecords): Check for dnsrecords in all namespaces listed in
r.config.DNSRecordNamespaces.
* pkg/operator/operator.go (New): Specify CredentialsRequestNamespace with
the operator namespace and DNSRecordNamespaces with the operator and
operand namespaces.
Introduce a new "gateway-service-dns" controller, which watches services,
dnsrecords, and gateways and creates DNSRecord CRs for services that are
associated with gateways that OpenShift manages.

* pkg/operator/controller/names.go (GatewayDNSRecordName): New function.
Return the namespaced name for a DNSRecord CR associated with a Gateway.
* pkg/operator/controller/gateway-service-dns/controller.go: New file.
(controllerName, gatewayNameLabelKey, managedByIstioLabelKey): New consts.
(log): New variable.  Define a logger for the gateway-service-dns
controller.
(NewUnmanaged): New function.  Create a new gateway-service-dns controller
that is not started automatically by the manager.
(gatewayListenersHostnamesChanged): New function, used in NewUnmanaged.
(Config): New type.  Store configuration for the controller.
(reconciler): New type.  Store the state of a gateway-service-dns
controller.
(Reconcile): New method.  Handle reconciliation requests for services by
checking whether they are associated with OpenShift-managed gateways and
creating or deleting DNSRecord CRs as appropriate, using the new
getGatewayHostnames function and ensureDNSRecordsForGateway and
deleteStaleDNSRecordsForGateway methods.
(getGatewayHostnames): New function.  Return the domains for a gateway
listener.
(ensureDNSRecordsForGateway): New method.  Ensure DNSRecord CRs exist for
the given domains, associated with the given gateway and service.
(deleteStaleDNSRecordsForGateway): New method.  Delete any DNSRecord CRs
that are associated with the given gateway but have DNS names that are not
in the given set of domains.
* pkg/operator/controller/gateway-service-dns/controller_test.go: New file.
(Test_Reconcile): New test.  Verify that Reconcile behaves as expected.
(fakeCache, fakeClientRecorder): New types, used in Test_Reconcile.
(Get, List, Scheme, RESTMapper, Create, Delete, DeleteAllOf, Update, Patch)
(Status): New methods for fakeClientRecorder to implement the
controller-runtime client.Client interface.
(Test_gatewayListenersHostnamesChanged): New test.  Verify that
gatewayListenersHostnamesChanged behaves as expected.
* pkg/operator/operator.go (New): Instantiate the new gateway-service-dns
controller and pass it to the constructor for the gatewayapi controller so
that the latter controller can start the former when Gateway API is
enabled.
* pkg/resources/dnsrecord/dns.go (EnsureWildcardDNSRecord): Update calls to
CurrentWildcardDNSRecord to use CurrentDNSRecord instead.
(EnsureDNSRecord): New function.  Create a DNS record with the specified
domain without prepending a wildcard prefix, using the new desiredDNSRecord
function.
(desiredWildcardDNSRecord): Factor general logic out of this function...
(desiredDNSRecord): ...into this.
(CurrentWildcardDNSRecord): Rename from this...
(CurrentDNSRecord): ...to this.
(DeleteWildcardDNSRecord): Rename from this...
(DeleteDNSRecordand): ...to this.
* pkg/operator/controller/ingress/controller.go (ensureIngressDeleted):
Update calls to DeleteWildcardDNSRecord and CurrentWildcardDNSRecord to use
DeleteDNSRecord and CurrentDNSRecord, respectively, instead.
* vendor/*: Regenerate.
When upserting a DNS record in Route 53, store the target hosted zone id of
the ELB on the associated DNSRecord CR.  If a subsequent lookup of this id
fails for whatever reason, fall back to using the annotation value.

This change is necessary for Gateway API because Istio sometimes deletes
the ELB before the ingress operator deletes the DNS record, and so the ELB
no longer exists when the DNS record deletion logic needs to look up the
target hosted zone id of the ELB.

* pkg/dns/aws/dns.go (targetHostedZoneIdAnnotationKey): New const.
(Config): Add Client field.
(change): Use config.Client and targetHostedZoneIdAnnotationKey to annotate
the DNSRecord CR with the target hosted zone id of the ELB on upsert and
look up the id on deletion.
* pkg/operator/controller/dns/controller.go (Reconcile): Get the DNSRecord
CR before updating its status in case it has changed since the previous
get.
(createDNSProvider): Provide the client to the AWS DNS provider
implementation.
@gcs278
Copy link
Contributor

gcs278 commented Feb 22, 2023

/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Feb 22, 2023
@gcs278
Copy link
Contributor

gcs278 commented Feb 22, 2023

/approve

@gcs278
Copy link
Contributor

gcs278 commented Feb 22, 2023

Thanks for all of the hard work in getting this done in a limited amount of time!

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 22, 2023

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: gcs278

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Feb 22, 2023
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 23, 2023

@Miciah: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-azure-ovn e8f3f45 link false /test e2e-azure-ovn

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@lihongan
Copy link
Contributor

/label qe-approved
did pre-merge testing and passed ( see https://issues.redhat.com/browse/NE-1226 )

@openshift-ci openshift-ci bot added the qe-approved Signifies that QE has signed off on this PR label Feb 23, 2023
@Miciah
Copy link
Contributor Author

Miciah commented Feb 23, 2023

I'm adding the "docs-approved" and "px-approved" labels myself because this is a dev preview feature that does not require product documentation or tech enablement.

/label docs-approved
/label px-approved

@openshift-ci openshift-ci bot added docs-approved Signifies that Docs has signed off on this PR px-approved Signifies that Product Support has signed off on this PR labels Feb 23, 2023
@openshift-merge-robot openshift-merge-robot merged commit 766d70c into openshift:master Feb 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. docs-approved Signifies that Docs has signed off on this PR jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged. px-approved Signifies that Product Support has signed off on this PR qe-approved Signifies that QE has signed off on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants