diff --git a/apis/network/v1alpha3/register.go b/apis/network/v1alpha3/register.go index a169787d..6a4bf261 100644 --- a/apis/network/v1alpha3/register.go +++ b/apis/network/v1alpha3/register.go @@ -53,7 +53,16 @@ var ( SubnetGroupVersionKind = SchemeGroupVersion.WithKind(SubnetKind) ) +// ExpressRouteCircuits type metadata. +var ( + ExpressRouteCircuitsKind = reflect.TypeOf(ExpressRouteCircuits{}).Name() + ExpressRouteCircuitsGroupKind = schema.GroupKind{Group: Group, Kind: ExpressRouteCircuitsKind}.String() + ExpressRouteCircuitsKindAPIVersion = ExpressRouteCircuitsKind + "." + SchemeGroupVersion.String() + ExpressRouteCircuitsGroupVersionKind = SchemeGroupVersion.WithKind(ExpressRouteCircuitsKind) +) + func init() { SchemeBuilder.Register(&VirtualNetwork{}, &VirtualNetworkList{}) SchemeBuilder.Register(&Subnet{}, &SubnetList{}) + SchemeBuilder.Register(&ExpressRouteCircuits{}, &ExpressRouteCircuitsList{}) } diff --git a/apis/network/v1alpha3/types.go b/apis/network/v1alpha3/types.go index cc8b8f43..a7eb5839 100644 --- a/apis/network/v1alpha3/types.go +++ b/apis/network/v1alpha3/types.go @@ -226,3 +226,104 @@ type SubnetList struct { metav1.ListMeta `json:"metadata,omitempty"` Items []Subnet `json:"items"` } + +// ExpressRouteCircuitsPropertiesFormat defines properties of a ExpressRouteCircuits. +type ExpressRouteCircuitsPropertiesFormat struct { + + // ServiceProviderName - Flag denoting service provider name. + ServiceProviderName *string `json:"serviceProviderName,omitempty"` + + // BandwidthInMbps - Flag denotes bandwithwidth in Mbps. + BandwidthInMbps *int32 `json:"bandwidthInMbps,omitempty"` + + // PeeringLocation - Flag denotes peering location. + PeeringLocation *string `json:"peeringLocation,omitempty"` + + // AllowClassicOperations - Flag denotes allow classic operations. + AllowClassicOperations *bool `json:"allowClassicOperations,omitempty"` + + // GlobalReachEnabled - Flag denoting Global reach status. + GlobalReachEnabled *bool `json:"globalReachEnabled,omitempty"` +} + +// SKU contains SKU in an ExpressRouteCircuit. +type SKU struct { + // Tier - The tier of the SKU. Possible values include: 'ExpressRouteCircuitSkuTierStandard', 'ExpressRouteCircuitSkuTierPremium', 'ExpressRouteCircuitSkuTierBasic', 'ExpressRouteCircuitSkuTierLocal' + Tier string `json:"tier,omitempty"` + // Family - The family of the SKU. Possible values include: 'UnlimitedData', 'MeteredData' + Family string `json:"family,omitempty"` +} + +// A ExpressRouteCircuitsSpec defines the desired state of a ExpressRouteCircuits. +type ExpressRouteCircuitsSpec struct { + xpv1.ResourceSpec `json:",inline"` + + // Location - Location of the ExpressRouteCircuit. + Location string `json:"location,omitempty"` + + // SKU - SKU for ExpressRouteCircuit. + Sku SKU `json:"sku,omitempty"` + + // Tags - Resource tags. + // +optional + Tags map[string]string `json:"tags,omitempty"` + + // CircuitName - Name of the expressroutecircuit + CircuitName string `json:"circuitName,omitempty"` + + // ResourceGroupName - Name of the ExpressRouteCircuits's resource group. + ResourceGroupName string `json:"resourceGroupName,omitempty"` + + // ResourceGroupNameRef - Name of the ExpressRouteCircuits's resource group. + ResourceGroupNameRef string `json:"resourceGroupNameRef,omitempty"` + + // ExpressRouteCircuitsPropertiesFormat - Properties of the subnet. + ExpressRouteCircuitsPropertiesFormat `json:"properties"` +} + +// A ExpressRouteCircuitsStatus represents the observed state of a ExpressRouteCircuits. +type ExpressRouteCircuitsStatus struct { + xpv1.ResourceStatus `json:",inline"` + + // State of this ExpressRouteCircuits. + State string `json:"state,omitempty"` + + // A Message providing detail about the state of this ExpressRouteCircuits, if any. + Message string `json:"message,omitempty"` + + // Etag - A unique string that changes whenever the resource is updated. + Etag string `json:"etag,omitempty"` + + // ID of this ExpressRouteCircuits. + ID string `json:"id,omitempty"` + + // Purpose - A string identifying the intention of use for this subnet based + // on delegations and other user-defined properties. + Purpose string `json:"purpose,omitempty"` +} + +// +kubebuilder:object:root=true + +// A ExpressRouteCircuits is a managed resource that represents an Azure ExpressRouteCircuits. +// +kubebuilder:printcolumn:name="READY",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" +// +kubebuilder:printcolumn:name="SYNCED",type="string",JSONPath=".status.conditions[?(@.type=='Synced')].status" +// +kubebuilder:printcolumn:name="STATE",type="string",JSONPath=".status.state" +// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster,categories={crossplane,managed,azure} +type ExpressRouteCircuits struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ExpressRouteCircuitsSpec `json:"spec"` + Status ExpressRouteCircuitsStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// ExpressRouteCircuitsList contains a list of ExpressRouteCircuits items +type ExpressRouteCircuitsList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ExpressRouteCircuits `json:"items"` +} diff --git a/apis/network/v1alpha3/zz_generated.deepcopy.go b/apis/network/v1alpha3/zz_generated.deepcopy.go index ef171c5a..11d20ea3 100644 --- a/apis/network/v1alpha3/zz_generated.deepcopy.go +++ b/apis/network/v1alpha3/zz_generated.deepcopy.go @@ -45,6 +45,161 @@ func (in *AddressSpace) DeepCopy() *AddressSpace { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExpressRouteCircuits) DeepCopyInto(out *ExpressRouteCircuits) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExpressRouteCircuits. +func (in *ExpressRouteCircuits) DeepCopy() *ExpressRouteCircuits { + if in == nil { + return nil + } + out := new(ExpressRouteCircuits) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ExpressRouteCircuits) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExpressRouteCircuitsList) DeepCopyInto(out *ExpressRouteCircuitsList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ExpressRouteCircuits, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExpressRouteCircuitsList. +func (in *ExpressRouteCircuitsList) DeepCopy() *ExpressRouteCircuitsList { + if in == nil { + return nil + } + out := new(ExpressRouteCircuitsList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ExpressRouteCircuitsList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExpressRouteCircuitsPropertiesFormat) DeepCopyInto(out *ExpressRouteCircuitsPropertiesFormat) { + *out = *in + if in.ServiceProviderName != nil { + in, out := &in.ServiceProviderName, &out.ServiceProviderName + *out = new(string) + **out = **in + } + if in.BandwidthInMbps != nil { + in, out := &in.BandwidthInMbps, &out.BandwidthInMbps + *out = new(int32) + **out = **in + } + if in.PeeringLocation != nil { + in, out := &in.PeeringLocation, &out.PeeringLocation + *out = new(string) + **out = **in + } + if in.AllowClassicOperations != nil { + in, out := &in.AllowClassicOperations, &out.AllowClassicOperations + *out = new(bool) + **out = **in + } + if in.GlobalReachEnabled != nil { + in, out := &in.GlobalReachEnabled, &out.GlobalReachEnabled + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExpressRouteCircuitsPropertiesFormat. +func (in *ExpressRouteCircuitsPropertiesFormat) DeepCopy() *ExpressRouteCircuitsPropertiesFormat { + if in == nil { + return nil + } + out := new(ExpressRouteCircuitsPropertiesFormat) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExpressRouteCircuitsSpec) DeepCopyInto(out *ExpressRouteCircuitsSpec) { + *out = *in + in.ResourceSpec.DeepCopyInto(&out.ResourceSpec) + out.Sku = in.Sku + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + in.ExpressRouteCircuitsPropertiesFormat.DeepCopyInto(&out.ExpressRouteCircuitsPropertiesFormat) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExpressRouteCircuitsSpec. +func (in *ExpressRouteCircuitsSpec) DeepCopy() *ExpressRouteCircuitsSpec { + if in == nil { + return nil + } + out := new(ExpressRouteCircuitsSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExpressRouteCircuitsStatus) DeepCopyInto(out *ExpressRouteCircuitsStatus) { + *out = *in + in.ResourceStatus.DeepCopyInto(&out.ResourceStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExpressRouteCircuitsStatus. +func (in *ExpressRouteCircuitsStatus) DeepCopy() *ExpressRouteCircuitsStatus { + if in == nil { + return nil + } + out := new(ExpressRouteCircuitsStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SKU) DeepCopyInto(out *SKU) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SKU. +func (in *SKU) DeepCopy() *SKU { + if in == nil { + return nil + } + out := new(SKU) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceEndpointPropertiesFormat) DeepCopyInto(out *ServiceEndpointPropertiesFormat) { *out = *in diff --git a/apis/network/v1alpha3/zz_generated.managed.go b/apis/network/v1alpha3/zz_generated.managed.go index f1c3e456..c3a335e9 100644 --- a/apis/network/v1alpha3/zz_generated.managed.go +++ b/apis/network/v1alpha3/zz_generated.managed.go @@ -20,6 +20,62 @@ package v1alpha3 import xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" +// GetCondition of this ExpressRouteCircuits. +func (mg *ExpressRouteCircuits) GetCondition(ct xpv1.ConditionType) xpv1.Condition { + return mg.Status.GetCondition(ct) +} + +// GetDeletionPolicy of this ExpressRouteCircuits. +func (mg *ExpressRouteCircuits) GetDeletionPolicy() xpv1.DeletionPolicy { + return mg.Spec.DeletionPolicy +} + +// GetProviderConfigReference of this ExpressRouteCircuits. +func (mg *ExpressRouteCircuits) GetProviderConfigReference() *xpv1.Reference { + return mg.Spec.ProviderConfigReference +} + +/* +GetProviderReference of this ExpressRouteCircuits. +Deprecated: Use GetProviderConfigReference. +*/ +func (mg *ExpressRouteCircuits) GetProviderReference() *xpv1.Reference { + return mg.Spec.ProviderReference +} + +// GetWriteConnectionSecretToReference of this ExpressRouteCircuits. +func (mg *ExpressRouteCircuits) GetWriteConnectionSecretToReference() *xpv1.SecretReference { + return mg.Spec.WriteConnectionSecretToReference +} + +// SetConditions of this ExpressRouteCircuits. +func (mg *ExpressRouteCircuits) SetConditions(c ...xpv1.Condition) { + mg.Status.SetConditions(c...) +} + +// SetDeletionPolicy of this ExpressRouteCircuits. +func (mg *ExpressRouteCircuits) SetDeletionPolicy(r xpv1.DeletionPolicy) { + mg.Spec.DeletionPolicy = r +} + +// SetProviderConfigReference of this ExpressRouteCircuits. +func (mg *ExpressRouteCircuits) SetProviderConfigReference(r *xpv1.Reference) { + mg.Spec.ProviderConfigReference = r +} + +/* +SetProviderReference of this ExpressRouteCircuits. +Deprecated: Use SetProviderConfigReference. +*/ +func (mg *ExpressRouteCircuits) SetProviderReference(r *xpv1.Reference) { + mg.Spec.ProviderReference = r +} + +// SetWriteConnectionSecretToReference of this ExpressRouteCircuits. +func (mg *ExpressRouteCircuits) SetWriteConnectionSecretToReference(r *xpv1.SecretReference) { + mg.Spec.WriteConnectionSecretToReference = r +} + // GetCondition of this Subnet. func (mg *Subnet) GetCondition(ct xpv1.ConditionType) xpv1.Condition { return mg.Status.GetCondition(ct) diff --git a/apis/network/v1alpha3/zz_generated.managedlist.go b/apis/network/v1alpha3/zz_generated.managedlist.go index d10ff992..8eed653a 100644 --- a/apis/network/v1alpha3/zz_generated.managedlist.go +++ b/apis/network/v1alpha3/zz_generated.managedlist.go @@ -20,6 +20,15 @@ package v1alpha3 import resource "github.com/crossplane/crossplane-runtime/pkg/resource" +// GetItems of this ExpressRouteCircuitsList. +func (l *ExpressRouteCircuitsList) GetItems() []resource.Managed { + items := make([]resource.Managed, len(l.Items)) + for i := range l.Items { + items[i] = &l.Items[i] + } + return items +} + // GetItems of this SubnetList. func (l *SubnetList) GetItems() []resource.Managed { items := make([]resource.Managed, len(l.Items)) diff --git a/examples/network/expressroutecircuits.yaml b/examples/network/expressroutecircuits.yaml new file mode 100644 index 00000000..cb78196e --- /dev/null +++ b/examples/network/expressroutecircuits.yaml @@ -0,0 +1,18 @@ +apiVersion: network.azure.crossplane.io/v1alpha3 +kind: ExpressRouteCircuits +metadata: + name: example-vn +spec: + resourceGroupName: test-exp + location: West US 2 + properties: + allowClassicOperations: False + bandwidthInMbps: 50 + globalReachEnabled: True + peeringLocation: Chennai2 + serviceProviderName: Airtel + sku: + family: MeteredData + tier: Standard + providerConfigRef: + name: default \ No newline at end of file diff --git a/package/crds/network.azure.crossplane.io_expressroutecircuits.yaml b/package/crds/network.azure.crossplane.io_expressroutecircuits.yaml new file mode 100644 index 00000000..a19d621c --- /dev/null +++ b/package/crds/network.azure.crossplane.io_expressroutecircuits.yaml @@ -0,0 +1,196 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.0 + creationTimestamp: null + name: expressroutecircuits.network.azure.crossplane.io +spec: + group: network.azure.crossplane.io + names: + categories: + - crossplane + - managed + - azure + kind: ExpressRouteCircuits + listKind: ExpressRouteCircuitsList + plural: expressroutecircuits + singular: expressroutecircuits + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: READY + type: string + - jsonPath: .status.conditions[?(@.type=='Synced')].status + name: SYNCED + type: string + - jsonPath: .status.state + name: STATE + type: string + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1alpha3 + schema: + openAPIV3Schema: + description: A ExpressRouteCircuits is a managed resource that represents an Azure ExpressRouteCircuits. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: A ExpressRouteCircuitsSpec defines the desired state of a Subnet. + properties: + circuitName: + description: CircuitName - Name of the expressroutecircuit + type: string + deletionPolicy: + description: DeletionPolicy specifies what will happen to the underlying external when this managed resource is deleted - either "Delete" or "Orphan" the external resource. The "Delete" policy is the default when no policy is specified. + enum: + - Orphan + - Delete + type: string + location: + description: Location - Location of the ExpressRouteCircuit. + type: string + properties: + description: ExpressRouteCircuitsPropertiesFormat - Properties of the subnet. + properties: + allowClassicOperations: + description: AllowClassicOperations - Flag denotes allow classic operations. + type: boolean + bandwidthInMbps: + description: BandwidthInMbps - Flag denotes bandwithwidth in Mbps. + format: int32 + type: integer + globalReachEnabled: + description: GlobalReachEnabled - Flag denoting Global reach status. + type: boolean + peeringLocation: + description: PeeringLocation - Flag denotes peering location. + type: string + serviceProviderName: + description: ServiceProviderName - Flag denoting service provider name. + type: string + type: object + providerConfigRef: + description: ProviderConfigReference specifies how the provider that will be used to create, observe, update, and delete this managed resource should be configured. + properties: + name: + description: Name of the referenced object. + type: string + required: + - name + type: object + providerRef: + description: 'ProviderReference specifies the provider that will be used to create, observe, update, and delete this managed resource. Deprecated: Please use ProviderConfigReference, i.e. `providerConfigRef`' + properties: + name: + description: Name of the referenced object. + type: string + required: + - name + type: object + resourceGroupName: + description: ResourceGroupName - Name of the Subnet's resource group. + type: string + resourceGroupNameRef: + description: ResourceGroupNameRef - Name of the Subnet's resource group. + type: string + sku: + description: SKU - SKU for ExpressRouteCircuit. + properties: + family: + description: 'Family - The family of the SKU. Possible values include: ''UnlimitedData'', ''MeteredData''' + type: string + tier: + description: 'Tier - The tier of the SKU. Possible values include: ''ExpressRouteCircuitSkuTierStandard'', ''ExpressRouteCircuitSkuTierPremium'', ''ExpressRouteCircuitSkuTierBasic'', ''ExpressRouteCircuitSkuTierLocal''' + type: string + type: object + tags: + additionalProperties: + type: string + description: Tags - Resource tags. + type: object + writeConnectionSecretToRef: + description: WriteConnectionSecretToReference specifies the namespace and name of a Secret to which any connection details for this managed resource should be written. Connection details frequently include the endpoint, username, and password required to connect to the managed resource. + properties: + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - name + - namespace + type: object + required: + - properties + type: object + status: + description: A ExpressRouteCircuitsStatus represents the observed state of a Subnet. + properties: + conditions: + description: Conditions of the resource. + items: + description: A Condition that may apply to a resource. + properties: + lastTransitionTime: + description: LastTransitionTime is the last time this condition transitioned from one status to another. + format: date-time + type: string + message: + description: A Message containing details about this condition's last transition from one status to another, if any. + type: string + reason: + description: A Reason for this condition's last transition from one status to another. + type: string + status: + description: Status of this condition; is it currently True, False, or Unknown? + type: string + type: + description: Type of this condition. At most one of each condition type may apply to a resource at any point in time. + type: string + required: + - lastTransitionTime + - reason + - status + - type + type: object + type: array + etag: + description: Etag - A unique string that changes whenever the resource is updated. + type: string + id: + description: ID of this Subnet. + type: string + message: + description: A Message providing detail about the state of this Subnet, if any. + type: string + purpose: + description: Purpose - A string identifying the intention of use for this subnet based on delegations and other user-defined properties. + type: string + state: + description: State of this ExpressRouteCircuits. + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/pkg/clients/network/network.go b/pkg/clients/network/network.go index 62add6f9..1ea6c738 100644 --- a/pkg/clients/network/network.go +++ b/pkg/clients/network/network.go @@ -106,3 +106,48 @@ func UpdateSubnetStatusFromAzure(v *v1alpha3.Subnet, az networkmgmt.Subnet) { v.Status.ID = azure.ToString(az.ID) v.Status.Purpose = azure.ToString(az.Purpose) } + +// NewExpressRouteCircuitsParameters returns an Azure ExpressRouteCircuits object from a expressroutecircuits spec +func NewExpressRouteCircuitsParameters(d *v1alpha3.ExpressRouteCircuits) networkmgmt.ExpressRouteCircuit { + return networkmgmt.ExpressRouteCircuit{ + Location: azure.ToStringPtr(d.Spec.Location), + Tags: azure.ToStringPtrMap(d.Spec.Tags), + Sku: &networkmgmt.ExpressRouteCircuitSku{ + Name: azure.ToStringPtr(d.Spec.Sku.Tier + "_" + d.Spec.Sku.Family), + Tier: networkmgmt.ExpressRouteCircuitSkuTier(d.Spec.Sku.Tier), + Family: networkmgmt.ExpressRouteCircuitSkuFamily(d.Spec.Sku.Family), + }, + ExpressRouteCircuitPropertiesFormat: &networkmgmt.ExpressRouteCircuitPropertiesFormat{ + ServiceProviderProperties: &networkmgmt.ExpressRouteCircuitServiceProviderProperties{ + ServiceProviderName: d.Spec.ExpressRouteCircuitsPropertiesFormat.ServiceProviderName, + BandwidthInMbps: d.Spec.ExpressRouteCircuitsPropertiesFormat.BandwidthInMbps, + PeeringLocation: d.Spec.ExpressRouteCircuitsPropertiesFormat.PeeringLocation, + }, + GlobalReachEnabled: d.Spec.ExpressRouteCircuitsPropertiesFormat.GlobalReachEnabled, + AllowClassicOperations: d.Spec.ExpressRouteCircuitsPropertiesFormat.AllowClassicOperations, + }, + } +} + +// UpdateExpressRouteCircuitStatusFromAzure updates the status related to the external +func UpdateExpressRouteCircuitStatusFromAzure(v *v1alpha3.ExpressRouteCircuits, az networkmgmt.ExpressRouteCircuit) { + v.Status.State = azure.ToString(az.ExpressRouteCircuitPropertiesFormat.ProvisioningState) + v.Status.Etag = azure.ToString(az.Etag) + v.Status.ID = azure.ToString(az.ID) +} + +// ExpressRouteCircuitNeedsUpdate determines if a express route circuit needs to be updated +func ExpressRouteCircuitNeedsUpdate(kube *v1alpha3.ExpressRouteCircuits, az networkmgmt.ExpressRouteCircuit) bool { + up := NewExpressRouteCircuitsParameters(kube) + switch { + case !reflect.DeepEqual(up.ExpressRouteCircuitPropertiesFormat.AllowClassicOperations, az.ExpressRouteCircuitPropertiesFormat.AllowClassicOperations): + return true + case !reflect.DeepEqual(up.Sku.Tier, az.Sku.Tier): + return true + case !reflect.DeepEqual(up.Sku.Family, az.Sku.Family): + return true + case !reflect.DeepEqual(up.ExpressRouteCircuitPropertiesFormat.ServiceProviderProperties.BandwidthInMbps, az.ExpressRouteCircuitPropertiesFormat.ServiceProviderProperties.BandwidthInMbps): + return true + } + return false +} diff --git a/pkg/controller/azure.go b/pkg/controller/azure.go index 9386fc82..3f4f00d1 100644 --- a/pkg/controller/azure.go +++ b/pkg/controller/azure.go @@ -35,6 +35,7 @@ import ( "github.com/crossplane/provider-azure/pkg/controller/database/postgresqlserverconfiguration" "github.com/crossplane/provider-azure/pkg/controller/database/postgresqlserverfirewallrule" "github.com/crossplane/provider-azure/pkg/controller/database/postgresqlservervirtualnetworkrule" + "github.com/crossplane/provider-azure/pkg/controller/network/expressroutecircuits" "github.com/crossplane/provider-azure/pkg/controller/network/subnet" "github.com/crossplane/provider-azure/pkg/controller/network/virtualnetwork" "github.com/crossplane/provider-azure/pkg/controller/resourcegroup" @@ -47,6 +48,7 @@ func Setup(mgr ctrl.Manager, l logging.Logger, rl workqueue.RateLimiter, poll ti for _, setup := range []func(ctrl.Manager, logging.Logger, workqueue.RateLimiter, time.Duration) error{ cache.SetupRedis, compute.SetupAKSCluster, + expressroutecircuits.Setup, mysqlserver.Setup, mysqlserverfirewallrule.Setup, mysqlservervirtualnetworkrule.Setup, diff --git a/pkg/controller/network/expressroutecircuits/managed.go b/pkg/controller/network/expressroutecircuits/managed.go new file mode 100644 index 00000000..4d5e2ec5 --- /dev/null +++ b/pkg/controller/network/expressroutecircuits/managed.go @@ -0,0 +1,161 @@ +/* +Copyright 2021 The Crossplane Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package expressroutecircuits + +import ( + "context" + + azurenetwork "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-06-01/network" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-06-01/network/networkapi" + "github.com/pkg/errors" + "k8s.io/client-go/util/workqueue" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" + + xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" + "github.com/crossplane/crossplane-runtime/pkg/event" + "github.com/crossplane/crossplane-runtime/pkg/logging" + "github.com/crossplane/crossplane-runtime/pkg/meta" + "github.com/crossplane/crossplane-runtime/pkg/ratelimiter" + "github.com/crossplane/crossplane-runtime/pkg/reconciler/managed" + "github.com/crossplane/crossplane-runtime/pkg/resource" + + "github.com/crossplane/provider-azure/apis/network/v1alpha3" + azureclients "github.com/crossplane/provider-azure/pkg/clients" + "github.com/crossplane/provider-azure/pkg/clients/network" +) + +// Error strings. +const ( + errNotExpressRouteCircuits = "managed resource is not an ExpressRouteCircuits" + errCreateExpressRouteCircuits = "cannot create ExpressRouteCircuits" + errUpdateExpressRouteCircuits = "cannot update ExpressRouteCircuits" + errGetExpressRouteCircuits = "cannot get ExpressRouteCircuits" + errDeleteExpressRouteCircuits = "cannot delete ExpressRouteCircuits" +) + +// Setup adds a controller that reconciles ExpressRouteCircuits. +func Setup(mgr ctrl.Manager, l logging.Logger, rl workqueue.RateLimiter) error { + name := managed.ControllerName(v1alpha3.ExpressRouteCircuitsGroupKind) + + return ctrl.NewControllerManagedBy(mgr). + Named(name). + WithOptions(controller.Options{ + RateLimiter: ratelimiter.NewDefaultManagedRateLimiter(rl), + }). + For(&v1alpha3.ExpressRouteCircuits{}). + Complete(managed.NewReconciler(mgr, + resource.ManagedKind(v1alpha3.ExpressRouteCircuitsGroupVersionKind), + managed.WithConnectionPublishers(), + managed.WithExternalConnecter(&connecter{client: mgr.GetClient()}), + managed.WithReferenceResolver(managed.NewAPISimpleReferenceResolver(mgr.GetClient())), + managed.WithLogger(l.WithValues("controller", name)), + managed.WithRecorder(event.NewAPIRecorder(mgr.GetEventRecorderFor(name))))) +} + +type connecter struct { + client client.Client +} + +func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) { + creds, auth, err := azureclients.GetAuthInfo(ctx, c.client, mg) + if err != nil { + return nil, err + } + cl := azurenetwork.NewExpressRouteCircuitsClient(creds[azureclients.CredentialsKeySubscriptionID]) + cl.Authorizer = auth + return &external{client: cl}, nil +} + +type external struct { + client networkapi.ExpressRouteCircuitsClientAPI +} + +func (e *external) Observe(ctx context.Context, mg resource.Managed) (managed.ExternalObservation, error) { + exp, ok := mg.(*v1alpha3.ExpressRouteCircuits) + if !ok { + return managed.ExternalObservation{}, errors.New(errNotExpressRouteCircuits) + } + + az, err := e.client.Get(ctx, exp.Spec.ResourceGroupName, meta.GetExternalName(exp)) + + if azureclients.IsNotFound(err) { + return managed.ExternalObservation{ResourceExists: false}, nil + } + if err != nil { + return managed.ExternalObservation{}, errors.Wrap(err, errGetExpressRouteCircuits) + } + + network.UpdateExpressRouteCircuitStatusFromAzure(exp, az) + exp.SetConditions(xpv1.Available()) + + o := managed.ExternalObservation{ + ResourceExists: true, + ConnectionDetails: managed.ConnectionDetails{}, + } + + return o, nil +} + +func (e *external) Create(ctx context.Context, mg resource.Managed) (managed.ExternalCreation, error) { + exp, ok := mg.(*v1alpha3.ExpressRouteCircuits) + if !ok { + return managed.ExternalCreation{}, errors.New(errNotExpressRouteCircuits) + } + + exp.Status.SetConditions(xpv1.Creating()) + + ercParams := network.NewExpressRouteCircuitsParameters(exp) + if _, err := e.client.CreateOrUpdate(ctx, exp.Spec.ResourceGroupName, meta.GetExternalName(exp), ercParams); err != nil { + return managed.ExternalCreation{}, errors.Wrap(err, errCreateExpressRouteCircuits) + } + + return managed.ExternalCreation{}, nil +} + +func (e *external) Update(ctx context.Context, mg resource.Managed) (managed.ExternalUpdate, error) { + exp, ok := mg.(*v1alpha3.ExpressRouteCircuits) + if !ok { + return managed.ExternalUpdate{}, errors.New(errNotExpressRouteCircuits) + } + + az, err := e.client.Get(ctx, exp.Spec.ResourceGroupName, meta.GetExternalName(exp)) + if err != nil { + return managed.ExternalUpdate{}, errors.Wrap(err, errGetExpressRouteCircuits) + } + + if network.ExpressRouteCircuitNeedsUpdate(exp, az) { + ercParams := network.NewExpressRouteCircuitsParameters(exp) + if _, err := e.client.CreateOrUpdate(ctx, exp.Spec.ResourceGroupName, meta.GetExternalName(exp), ercParams); err != nil { + return managed.ExternalUpdate{}, errors.Wrap(err, errUpdateExpressRouteCircuits) + } + } + return managed.ExternalUpdate{}, nil +} + +func (e *external) Delete(ctx context.Context, mg resource.Managed) error { + exp, ok := mg.(*v1alpha3.ExpressRouteCircuits) + if !ok { + return errors.New(errNotExpressRouteCircuits) + } + + mg.SetConditions(xpv1.Deleting()) + + _, err := e.client.Delete(ctx, exp.Spec.ResourceGroupName, meta.GetExternalName(exp)) + return errors.Wrap(resource.Ignore(azureclients.IsNotFound, err), errDeleteExpressRouteCircuits) +}