forked from cilium/cilium
-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathtypes.go
More file actions
234 lines (193 loc) · 6.63 KB
/
Copy pathtypes.go
File metadata and controls
234 lines (193 loc) · 6.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Cilium
package types
import (
"slices"
"strings"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
"github.com/cilium/cilium/pkg/ipam/types"
)
const (
// ProviderPrefix is the prefix used to indicate that a k8s ProviderID
// represents an Azure resource
ProviderPrefix = "azure://"
// InterfaceAddressLimit is the maximum number of addresses on an interface
//
//
// For more information:
// https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/azure-subscription-service-limits?toc=%2fazure%2fvirtual-network%2ftoc.json#networking-limits
InterfaceAddressLimit = 256
// StateSucceeded is the address state for a successfully provisioned address
StateSucceeded = "succeeded"
// Resource type names for Azure resources
resourceTypeVirtualMachines = "virtualMachines"
resourceTypeVirtualMachineScaleSets = "virtualMachineScaleSets"
)
// AzureSpec is the Azure specification of a node running via the Azure IPAM
//
// The Azure specification can either be provided explicitly by the user or the
// cilium agent running on the node can be instructed to create the CiliumNode
// custom resource along with an Azure specification when the node registers
// itself to the Kubernetes cluster.
// This struct is embedded into v2.CiliumNode
//
// +k8s:deepcopy-gen=true
type AzureSpec struct {
// InterfaceName is the name of the interface the cilium-operator
// will use to allocate all the IPs on
//
// +kubebuilder:validation:Optional
InterfaceName string `json:"interface-name,omitempty"`
}
// AzureStatus is the status of Azure addressing of the node.
// This struct is embedded into v2.CiliumNode
//
// +k8s:deepcopy-gen=true
type AzureStatus struct {
// Interfaces is the list of interfaces on the node
//
// +optional
Interfaces []AzureInterface `json:"interfaces,omitempty"`
}
// SetInterfaces replaces Interfaces with a copy of ifaces sorted
// deterministically by ID.
//
// Interfaces must be kept sorted by ID: the generated AzureStatus.DeepEqual
// compares the slice index-by-index, and the operator's status-update path
// relies on that DeepEqual to skip no-op CiliumNode /status writes. Any code
// that populates Interfaces from a non-deterministically ordered source (e.g.
// Go map iteration) MUST use this method rather than assigning the field
// directly, to preserve that invariant.
func (s *AzureStatus) SetInterfaces(ifaces []AzureInterface) {
sorted := slices.Clone(ifaces)
slices.SortFunc(sorted, func(a, b AzureInterface) int {
return strings.Compare(a.ID, b.ID)
})
s.Interfaces = sorted
}
// AzureAddress is an IP address assigned to an AzureInterface
type AzureAddress struct {
// IP is the ip address of the address
IP string `json:"ip,omitempty"`
// Subnet is the subnet the address belongs to
Subnet string `json:"subnet,omitempty"`
// State is the provisioning state of the address
State string `json:"state,omitempty"`
}
// AzureInterface represents an Azure Interface
//
// +k8s:deepcopy-gen=true
type AzureInterface struct {
// ID is the identifier
//
// +optional
ID string `json:"id,omitempty"`
// Name is the name of the interface
//
// +optional
Name string `json:"name,omitempty"`
// MAC is the mac address
//
// +optional
MAC string `json:"mac,omitempty"`
// State is the provisioning state
//
// +optional
State string `json:"state,omitempty"`
// Addresses is the list of all IPs associated with the interface,
// including all secondary addresses
//
// +optional
Addresses []AzureAddress `json:"addresses,omitempty"`
// SecurityGroup is the security group associated with the interface
SecurityGroup string `json:"security-group,omitempty"`
// GatewayIP is the interface's subnet's default route
//
// OBSOLETE: This field is obsolete, please use Gateway field instead.
//
// +optional
GatewayIP string `json:"GatewayIP"`
// Gateway is the interface's subnet's default route
//
// +optional
Gateway string `json:"gateway"`
// CIDR is the range that the interface belongs to.
//
// +optional
CIDR string `json:"cidr,omitempty"`
// vmssName is set by extractIDs() and is never serialized (json:"-"), so it
// is excluded from DeepEqual to avoid spurious diffs against apiserver copies.
// +deepequal-gen=false
vmssName string `json:"-"`
// vmID is the ID of the virtual machine
//
// +deepequal-gen=false
vmID string `json:"-"`
// resourceGroup is the resource group the interface belongs to
//
// +deepequal-gen=false
resourceGroup string `json:"-"`
}
func (a *AzureInterface) DeepCopyInterface() types.Interface {
return a.DeepCopy()
}
// SetID sets the Azure interface ID, as well as extracting other fields from
// the ID itself.
func (a *AzureInterface) SetID(id string) {
a.ID = id
a.extractIDs()
}
// InterfaceID returns the identifier of the interface
func (a *AzureInterface) InterfaceID() string {
return a.ID
}
// extractIDs extracts resource group name, VMSS name, and VM ID from the network interface Azure resource ID
func (a *AzureInterface) extractIDs() {
resourceID, err := arm.ParseResourceID(a.ID)
if err != nil {
// If parsing fails, leave fields empty
return
}
// Extract resource group name directly from the parsed ID
a.resourceGroup = resourceID.ResourceGroupName
// For VMSS instances, walk up the parent chain to extract VMSS name and VM ID
// Resource ID structure for VMSS VM interfaces:
// /subscriptions/xxx/resourceGroups/yyy/providers/Microsoft.Compute/virtualMachineScaleSets/ssss/virtualMachines/vvv/networkInterfaces/iii
current := resourceID
for current != nil {
resourceType := current.ResourceType
if len(resourceType.Types) == 0 {
current = current.Parent
continue
}
lastType := resourceType.Types[len(resourceType.Types)-1]
if strings.EqualFold(lastType, resourceTypeVirtualMachines) {
a.vmID = current.Name
}
if strings.EqualFold(lastType, resourceTypeVirtualMachineScaleSets) {
a.vmssName = current.Name
}
current = current.Parent
}
}
// GetResourceGroup returns the resource group the interface belongs to
func (a *AzureInterface) GetResourceGroup() string {
return a.resourceGroup
}
// GetVMScaleSetName returns the VM scale set name the interface belongs to
func (a *AzureInterface) GetVMScaleSetName() string {
return a.vmssName
}
// GetVMID returns the VM ID the interface belongs to
func (a *AzureInterface) GetVMID() string {
return a.vmID
}
// ForeachAddress iterates over all addresses and calls fn
func (a *AzureInterface) ForeachAddress(id string, fn types.AddressIterator) error {
for _, address := range a.Addresses {
if err := fn(id, a.ID, address.IP, address.Subnet, address); err != nil {
return err
}
}
return nil
}