Skip to content

Commit

Permalink
Expose default primary PrivateEndpoint privateIpAddress (#4107)
Browse files Browse the repository at this point in the history
* Expose default primary PrivateEndpoint privateIpAdress

* Add checks for map access

* Add nil check

* Update asoctl/go.mod

* Add checks and OperatorSpec property name refactor

* PR feedback

* Fix gitignore

---------

Co-authored-by: Matthew Christopher <matthchr@users.noreply.github.com>
  • Loading branch information
super-harsh and matthchr authored Jun 22, 2024
1 parent 2da28d4 commit abcd57a
Show file tree
Hide file tree
Showing 17 changed files with 4,040 additions and 1,848 deletions.
122 changes: 121 additions & 1 deletion v2/api/network/customizations/private_endpoints_extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,21 @@ import (
"context"
"fmt"

"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork"
"github.com/go-logr/logr"
"github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/conversion"

network "github.com/Azure/azure-service-operator/v2/api/network/v1api20220701/storage"

"github.com/Azure/azure-service-operator/v2/internal/genericarmclient"
. "github.com/Azure/azure-service-operator/v2/internal/logging"
"github.com/Azure/azure-service-operator/v2/internal/resolver"
"github.com/Azure/azure-service-operator/v2/internal/util/to"
"github.com/Azure/azure-service-operator/v2/pkg/genruntime"
"github.com/Azure/azure-service-operator/v2/pkg/genruntime/configmaps"
"github.com/Azure/azure-service-operator/v2/pkg/genruntime/extensions"
)

Expand Down Expand Up @@ -60,3 +66,117 @@ func (extension *PrivateEndpointExtension) PostReconcileCheck(

return extensions.PostReconcileCheckResultSuccess(), nil
}

func (extension *PrivateEndpointExtension) ExportKubernetesResources(
ctx context.Context,
obj genruntime.MetaObject,
armClient *genericarmclient.GenericClient,
log logr.Logger,
) ([]client.Object, error) {
// This has to be the current hub storage version. It will need to be updated
// if the hub storage version changes.
endpoint, ok := obj.(*network.PrivateEndpoint)
if !ok {
return nil, errors.Errorf("cannot run on unknown resource type %T, expected *network.PrivateEndpoint", obj)
}

// Type assert that we are the hub type. This will fail to compile if
// the hub type has been changed but this extension has not
var _ conversion.Hub = endpoint

hasIpConfiguration := hasConfigMaps(endpoint)
if !hasIpConfiguration {
log.V(Debug).Info("no configmap retrieval to perform as operatorSpec is empty")
return nil, nil
}

if endpoint.Status.NetworkInterfaces == nil || len(endpoint.Status.NetworkInterfaces) == 0 {
log.V(Debug).Info("no configmap retrieval to perform as there are no NetworkInterfaces attached")
return nil, nil
}

if endpoint.Status.NetworkInterfaces[0].Id == nil {
log.V(Debug).Info("no configmap retrieval to perform, failed to fetch the attached NetworkInterfaces")
return nil, nil
}

nicID, err := arm.ParseResourceID(*endpoint.Status.NetworkInterfaces[0].Id)
if err != nil {
return nil, err
}

// The default primary ip configuration for PrivateEndpoint is on NetworkInterfaceController. Hence, we fetch it from there.
var interfacesClient *armnetwork.InterfacesClient
interfacesClient, err = armnetwork.NewInterfacesClient(nicID.SubscriptionID, armClient.Creds(), armClient.ClientOptions())
if err != nil {
return nil, errors.Wrapf(err, "failed to create new NetworkInterfacesClient")
}

var resp armnetwork.InterfacesClientGetResponse
resp, err = interfacesClient.Get(ctx, nicID.ResourceGroupName, nicID.Name, nil)
if err != nil {
return nil, errors.Wrapf(err, "failed getting NetworkInterfaceController")
}

configsByName := configByName(log, resp.Interface)
configs, err := configMapToWrite(endpoint, configsByName)
if err != nil {
return nil, err
}

return configmaps.SliceToClientObjectSlice(configs), nil
}

func configByName(log logr.Logger, nic armnetwork.Interface) map[string]string {
result := make(map[string]string)

if nic.Properties != nil && nic.Properties.IPConfigurations != nil {
for _, ipConfiguration := range nic.Properties.IPConfigurations {
if ipConfiguration.Properties == nil || ipConfiguration.Properties.PrivateIPAddress == nil {
log.V(Debug).Info("skipping IPConfiguration properties nil for IPConfiguration")
continue
}

if to.Value(ipConfiguration.Properties.Primary) == false {
// This ipConfiguration is not primary
continue
}

result["primaryNICPrivateIPAddress"] = *nic.Properties.IPConfigurations[0].Properties.PrivateIPAddress
break
}
}

return result
}

func configMapToWrite(obj *network.PrivateEndpoint, configs map[string]string) ([]*v1.ConfigMap, error) {
operatorSpecConfigs := obj.Spec.OperatorSpec.ConfigMaps
if operatorSpecConfigs == nil {
return nil, errors.Errorf("unexpected nil operatorspec")
}

collector := configmaps.NewCollector(obj.Namespace)

primaryNICPrivateIPAddress, ok := configs["primaryNICPrivateIPAddress"]
if ok {
collector.AddValue(operatorSpecConfigs.PrimaryNicPrivateIpAddress, primaryNICPrivateIPAddress)
}

return collector.Values()
}

func hasConfigMaps(endpoint *network.PrivateEndpoint) bool {
if endpoint.Spec.OperatorSpec == nil || endpoint.Spec.OperatorSpec.ConfigMaps == nil {
return false
}

hasIPConfiguration := false
configMaps := endpoint.Spec.OperatorSpec.ConfigMaps

if configMaps != nil && configMaps.PrimaryNicPrivateIpAddress != nil {
hasIPConfiguration = true
}

return hasIPConfiguration
}
147 changes: 146 additions & 1 deletion v2/api/network/v1api20220701/private_endpoint_types_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit abcd57a

Please sign in to comment.