Skip to content
This repository was archived by the owner on Feb 11, 2025. It is now read-only.

Commit fd7045e

Browse files
authored
Merge pull request #62 from displague/ignore-422-vlan-already
ignore vlan attachment API responses "422 Virtual network foo already…"
2 parents a52bd97 + 89f2b16 commit fd7045e

File tree

5 files changed

+35
-16
lines changed

5 files changed

+35
-16
lines changed

apis/vlan/v1alpha1/virtualnetwork_types.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ type VirtualNetworkStatus struct {
3939
// +kubebuilder:printcolumn:name="READY",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status"
4040
// +kubebuilder:printcolumn:name="SYNCED",type="string",JSONPath=".status.conditions[?(@.type=='Synced')].status"
4141
// +kubebuilder:printcolumn:name="ID",type="string",JSONPath=".status.atProvider.id"
42-
// +kubebuilder:printcolumn:name="HOSTNAME",type="string",JSONPath=".spec.forProvider.hostname"
43-
// +kubebuilder:printcolumn:name="FACILITY",type="string",JSONPath=".status.atProvider.facility"
42+
// +kubebuilder:printcolumn:name="FACILITY",type="string",JSONPath=".status.atProvider.facilityCode"
4443
// +kubebuilder:printcolumn:name="RECLAIM-POLICY",type="string",JSONPath=".spec.reclaimPolicy"
4544
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
4645
// +kubebuilder:subresource:status
@@ -69,8 +68,11 @@ type VirtualNetworkList struct {
6968
// LateInitialization should update the parameter after creation.
7069
type VirtualNetworkParameters struct {
7170
// +immutable
72-
// +required
73-
Facility string `json:"facility"`
71+
// +optional
72+
Facility string `json:"facility,omitempty"`
73+
74+
// +optional
75+
Metro string `json:"metro,omitempty"`
7476

7577
// +optional
7678
Description *string `json:"description,omitempty"`
@@ -82,6 +84,6 @@ type VirtualNetworkObservation struct {
8284
ID string `json:"id"`
8385
Href string `json:"href,omitempty"`
8486
VXLAN int `json:"vxlan,omitempty"`
85-
FacilityCode string `json:"facility_code,omitempty"`
87+
FacilityCode string `json:"facilityCode,omitempty"`
8688
CreatedAt *metav1.Time `json:"createdAt,omitempty"`
8789
}

package/crds/vlan.metal.equinix.com_virtualnetworks.yaml

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@ spec:
1616
- JSONPath: .status.atProvider.id
1717
name: ID
1818
type: string
19-
- JSONPath: .spec.forProvider.hostname
20-
name: HOSTNAME
21-
type: string
22-
- JSONPath: .status.atProvider.facility
19+
- JSONPath: .status.atProvider.facilityCode
2320
name: FACILITY
2421
type: string
2522
- JSONPath: .spec.reclaimPolicy
@@ -69,8 +66,8 @@ spec:
6966
type: string
7067
facility:
7168
type: string
72-
required:
73-
- facility
69+
metro:
70+
type: string
7471
type: object
7572
providerConfigRef:
7673
description: ProviderConfigReference specifies how the provider that will be used to create, observe, update, and delete this managed resource should be configured.
@@ -115,7 +112,7 @@ spec:
115112
createdAt:
116113
format: date-time
117114
type: string
118-
facility_code:
115+
facilityCode:
119116
type: string
120117
href:
121118
type: string

pkg/clients/metal.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"encoding/json"
2222
"fmt"
2323
"net/http"
24+
"strings"
2425

2526
"github.com/crossplane/crossplane-runtime/pkg/resource"
2627
"github.com/packethost/packngo"
@@ -42,6 +43,11 @@ type Client struct {
4243
Client *packngo.Client
4344
}
4445

46+
const (
47+
errVirtualNetworkAlreadyContents = " already "
48+
errVirtualNetworkAlreadyPrefix = "Virtual network"
49+
)
50+
4551
// NewCredentialsFromJSON parses JSON bytes returning an Equinix Metal Credentials configuration
4652
func NewCredentialsFromJSON(j []byte) (*Credentials, error) {
4753
config := &Credentials{}
@@ -113,3 +119,16 @@ func IsNotFound(err error) bool {
113119
}
114120
return false
115121
}
122+
123+
// IsAlreadyDone returns true if, during VLAN assignment operations, the API
124+
// returns an error like "422 Virtual network 1182 already assigned" or "422
125+
// Virtual network 1182 already unassigned"
126+
func IsAlreadyDone(err error) bool {
127+
if e, ok := err.(*packngo.ErrorResponse); ok && e.Response != nil {
128+
errsInOne := strings.Join(append(e.Errors, e.SingleError), "")
129+
return e.Response.StatusCode == http.StatusUnprocessableEntity &&
130+
strings.Contains(errsInOne, errVirtualNetworkAlreadyContents) &&
131+
strings.HasPrefix(errsInOne, errVirtualNetworkAlreadyPrefix)
132+
}
133+
return false
134+
}

pkg/clients/vlan/virtualnetwork.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ func NewClient(ctx context.Context, config *clients.Credentials) (ClientWithDefa
7676
func CreateFromVirtualNetwork(d *v1alpha1.VirtualNetwork, projectID string) *packngo.VirtualNetworkCreateRequest {
7777
return &packngo.VirtualNetworkCreateRequest{
7878
Facility: d.Spec.ForProvider.Facility,
79+
Metro: d.Spec.ForProvider.Metro,
7980
Description: emptyIfNil(d.Spec.ForProvider.Description),
8081
ProjectID: projectID,
8182
}

pkg/controller/ports/assignment/managed.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ package assignment
1818

1919
import (
2020
"context"
21-
"strings"
21+
"path"
2222

2323
"github.com/packethost/packngo"
2424
"github.com/pkg/errors"
@@ -127,7 +127,7 @@ func (e *external) Observe(ctx context.Context, mg resource.Managed) (managed.Ex
127127
}
128128

129129
for _, net := range port.AttachedVirtualNetworks {
130-
if strings.TrimPrefix(net.Href, "/virtual-networks/") == a.Spec.ForProvider.VirtualNetworkID {
130+
if path.Base(net.Href) == a.Spec.ForProvider.VirtualNetworkID {
131131
a.Status.SetConditions(xpv1.Available())
132132
o.ResourceExists = true
133133
}
@@ -144,7 +144,7 @@ func (e *external) Create(ctx context.Context, mg resource.Managed) (managed.Ext
144144
}
145145
a.Status.SetConditions(xpv1.Creating())
146146
_, _, err := e.client.Assign(&packngo.PortAssignRequest{PortID: meta.GetExternalName(a), VirtualNetworkID: a.Spec.ForProvider.VirtualNetworkID})
147-
return managed.ExternalCreation{}, errors.Wrap(err, errCreateAssignment)
147+
return managed.ExternalCreation{}, errors.Wrap(resource.Ignore(packetclient.IsAlreadyDone, err), errCreateAssignment)
148148
}
149149

150150
func (e *external) Update(ctx context.Context, mg resource.Managed) (managed.ExternalUpdate, error) {
@@ -159,5 +159,5 @@ func (e *external) Delete(ctx context.Context, mg resource.Managed) error {
159159
}
160160
a.SetConditions(xpv1.Deleting())
161161
_, _, err := e.client.Unassign(&packngo.PortAssignRequest{PortID: meta.GetExternalName(a), VirtualNetworkID: a.Spec.ForProvider.VirtualNetworkID})
162-
return errors.Wrap(resource.Ignore(packetclient.IsNotFound, err), errDeleteAssignment)
162+
return errors.Wrap(resource.IgnoreAny(err, packetclient.IsNotFound, packetclient.IsAlreadyDone), errDeleteAssignment)
163163
}

0 commit comments

Comments
 (0)