-
Notifications
You must be signed in to change notification settings - Fork 431
/
publicips.go
150 lines (126 loc) · 4.47 KB
/
publicips.go
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
/*
Copyright 2019 The Kubernetes 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 publicips
import (
"context"
"strings"
"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-02-01/network"
"github.com/Azure/go-autorest/autorest/to"
"github.com/go-logr/logr"
"github.com/pkg/errors"
infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1alpha4"
"sigs.k8s.io/cluster-api-provider-azure/azure"
"sigs.k8s.io/cluster-api-provider-azure/azure/converters"
"sigs.k8s.io/cluster-api-provider-azure/util/tele"
)
// PublicIPScope defines the scope interface for a public IP service.
type PublicIPScope interface {
logr.Logger
azure.ClusterDescriber
PublicIPSpecs() []azure.PublicIPSpec
}
// Service provides operations on Azure resources.
type Service struct {
Scope PublicIPScope
Client
}
// New creates a new service.
func New(scope PublicIPScope) *Service {
return &Service{
Scope: scope,
Client: NewClient(scope),
}
}
// Reconcile gets/creates/updates a public ip.
func (s *Service) Reconcile(ctx context.Context) error {
ctx, span := tele.Tracer().Start(ctx, "publicips.Service.Reconcile")
defer span.End()
for _, ip := range s.Scope.PublicIPSpecs() {
s.Scope.V(2).Info("creating public IP", "public ip", ip.Name)
// only set DNS properties if there is a DNS name specified
addressVersion := network.IPVersionIPv4
if ip.IsIPv6 {
addressVersion = network.IPVersionIPv6
}
// only set DNS properties if there is a DNS name specified
var dnsSettings *network.PublicIPAddressDNSSettings
if ip.DNSName != "" {
dnsSettings = &network.PublicIPAddressDNSSettings{
DomainNameLabel: to.StringPtr(strings.Split(ip.DNSName, ".")[0]),
Fqdn: to.StringPtr(ip.DNSName),
}
}
err := s.Client.CreateOrUpdate(
ctx,
s.Scope.ResourceGroup(),
ip.Name,
network.PublicIPAddress{
Tags: converters.TagsToMap(infrav1.Build(infrav1.BuildParams{
ClusterName: s.Scope.ClusterName(),
Lifecycle: infrav1.ResourceLifecycleOwned,
Name: to.StringPtr(ip.Name),
Additional: s.Scope.AdditionalTags(),
})),
Sku: &network.PublicIPAddressSku{Name: network.PublicIPAddressSkuNameStandard},
Name: to.StringPtr(ip.Name),
Location: to.StringPtr(s.Scope.Location()),
PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{
PublicIPAddressVersion: addressVersion,
PublicIPAllocationMethod: network.IPAllocationMethodStatic,
DNSSettings: dnsSettings,
},
},
)
if err != nil {
return errors.Wrap(err, "cannot create public IP")
}
s.Scope.V(2).Info("successfully created public IP", "public ip", ip.Name)
}
return nil
}
// Delete deletes the public IP with the provided scope.
func (s *Service) Delete(ctx context.Context) error {
ctx, span := tele.Tracer().Start(ctx, "publicips.Service.Delete")
defer span.End()
for _, ip := range s.Scope.PublicIPSpecs() {
managed, err := s.isIPManaged(ctx, ip.Name)
if err != nil && !azure.ResourceNotFound(err) {
return errors.Wrap(err, "could not get public IP management state")
}
if !managed {
s.Scope.V(2).Info("Skipping IP deletion for unmanaged public IP", "public ip", ip.Name)
continue
}
s.Scope.V(2).Info("deleting public IP", "public ip", ip.Name)
err = s.Client.Delete(ctx, s.Scope.ResourceGroup(), ip.Name)
if err != nil && azure.ResourceNotFound(err) {
// already deleted
continue
}
if err != nil {
return errors.Wrapf(err, "failed to delete public IP %s in resource group %s", ip.Name, s.Scope.ResourceGroup())
}
s.Scope.V(2).Info("deleted public IP", "public ip", ip.Name)
}
return nil
}
// isIPManaged returns true if the IP has an owned tag with the cluster name as value,
// meaning that the IP's lifecycle is managed.
func (s *Service) isIPManaged(ctx context.Context, ipName string) (bool, error) {
ip, err := s.Client.Get(ctx, s.Scope.ResourceGroup(), ipName)
if err != nil {
return false, err
}
tags := converters.MapToTags(ip.Tags)
return tags.HasOwned(s.Scope.ClusterName()), nil
}