/
manager.go
224 lines (208 loc) · 7.53 KB
/
manager.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
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
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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.
// Code generated by ack-generate. DO NOT EDIT.
package model
import (
"context"
"fmt"
ackerr "github.com/aws/aws-controllers-k8s/pkg/errors"
corev1 "k8s.io/api/core/v1"
ackv1alpha1 "github.com/aws/aws-controllers-k8s/apis/core/v1alpha1"
ackcompare "github.com/aws/aws-controllers-k8s/pkg/compare"
ackcfg "github.com/aws/aws-controllers-k8s/pkg/config"
ackmetrics "github.com/aws/aws-controllers-k8s/pkg/metrics"
acktypes "github.com/aws/aws-controllers-k8s/pkg/types"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/go-logr/logr"
svcsdk "github.com/aws/aws-sdk-go/service/apigatewayv2"
svcsdkapi "github.com/aws/aws-sdk-go/service/apigatewayv2/apigatewayv2iface"
)
// +kubebuilder:rbac:groups=apigatewayv2.services.k8s.aws,resources=models,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=apigatewayv2.services.k8s.aws,resources=models/status,verbs=get;update;patch
// +kubebuilder:rbac:groups="",resources=namespaces,verbs=get;list;watch
// +kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch
// resourceManager is responsible for providing a consistent way to perform
// CRUD operations in a backend AWS service API for Book custom resources.
type resourceManager struct {
// cfg is a copy of the ackcfg.Config object passed on start of the service
// controller
cfg ackcfg.Config
// log refers to the logr.Logger object handling logging for the service
// controller
log logr.Logger
// metrics contains a collection of Prometheus metric objects that the
// service controller and its reconcilers track
metrics *ackmetrics.Metrics
// rr is the AWSResourceReconciler which can be used for various utility
// functions such as querying for Secret values given a SecretReference
rr acktypes.AWSResourceReconciler
// awsAccountID is the AWS account identifier that contains the resources
// managed by this resource manager
awsAccountID ackv1alpha1.AWSAccountID
// The AWS Region that this resource manager targets
awsRegion ackv1alpha1.AWSRegion
// sess is the AWS SDK Session object used to communicate with the backend
// AWS service API
sess *session.Session
// sdk is a pointer to the AWS service API interface exposed by the
// aws-sdk-go/services/{alias}/{alias}iface package.
sdkapi svcsdkapi.ApiGatewayV2API
}
// concreteResource returns a pointer to a resource from the supplied
// generic AWSResource interface
func (rm *resourceManager) concreteResource(
res acktypes.AWSResource,
) *resource {
// cast the generic interface into a pointer type specific to the concrete
// implementing resource type managed by this resource manager
return res.(*resource)
}
// ReadOne returns the currently-observed state of the supplied AWSResource in
// the backend AWS service API.
func (rm *resourceManager) ReadOne(
ctx context.Context,
res acktypes.AWSResource,
) (acktypes.AWSResource, error) {
r := rm.concreteResource(res)
if r.ko == nil {
// Should never happen... if it does, it's buggy code.
panic("resource manager's ReadOne() method received resource with nil CR object")
}
observed, err := rm.sdkFind(ctx, r)
if err != nil {
return rm.onError(r, err)
}
return rm.onSuccess(observed)
}
// Create attempts to create the supplied AWSResource in the backend AWS
// service API, returning an AWSResource representing the newly-created
// resource
func (rm *resourceManager) Create(
ctx context.Context,
res acktypes.AWSResource,
) (acktypes.AWSResource, error) {
r := rm.concreteResource(res)
if r.ko == nil {
// Should never happen... if it does, it's buggy code.
panic("resource manager's Create() method received resource with nil CR object")
}
created, err := rm.sdkCreate(ctx, r)
if err != nil {
return rm.onError(r, err)
}
return rm.onSuccess(created)
}
// Update attempts to mutate the supplied desired AWSResource in the backend AWS
// service API, returning an AWSResource representing the newly-mutated
// resource.
// Note for specialized logic implementers can check to see how the latest
// observed resource differs from the supplied desired state. The
// higher-level reonciler determines whether or not the desired differs
// from the latest observed and decides whether to call the resource
// manager's Update method
func (rm *resourceManager) Update(
ctx context.Context,
resDesired acktypes.AWSResource,
resLatest acktypes.AWSResource,
diffReporter *ackcompare.Reporter,
) (acktypes.AWSResource, error) {
desired := rm.concreteResource(resDesired)
latest := rm.concreteResource(resLatest)
if desired.ko == nil || latest.ko == nil {
// Should never happen... if it does, it's buggy code.
panic("resource manager's Update() method received resource with nil CR object")
}
updated, err := rm.sdkUpdate(ctx, desired, latest, diffReporter)
if err != nil {
return rm.onError(latest, err)
}
return rm.onSuccess(updated)
}
// Delete attempts to destroy the supplied AWSResource in the backend AWS
// service API.
func (rm *resourceManager) Delete(
ctx context.Context,
res acktypes.AWSResource,
) error {
r := rm.concreteResource(res)
if r.ko == nil {
// Should never happen... if it does, it's buggy code.
panic("resource manager's Update() method received resource with nil CR object")
}
return rm.sdkDelete(ctx, r)
}
// ARNFromName returns an AWS Resource Name from a given string name. This
// is useful for constructing ARNs for APIs that require ARNs in their
// GetAttributes operations but all we have (for new CRs at least) is a
// name for the resource
func (rm *resourceManager) ARNFromName(name string) string {
return fmt.Sprintf(
"arn:aws:apigatewayv2:%s:%s:%s",
rm.awsRegion,
rm.awsAccountID,
name,
)
}
// newResourceManager returns a new struct implementing
// acktypes.AWSResourceManager
func newResourceManager(
cfg ackcfg.Config,
log logr.Logger,
metrics *ackmetrics.Metrics,
rr acktypes.AWSResourceReconciler,
sess *session.Session,
id ackv1alpha1.AWSAccountID,
region ackv1alpha1.AWSRegion,
) (*resourceManager, error) {
return &resourceManager{
cfg: cfg,
log: log,
metrics: metrics,
rr: rr,
awsAccountID: id,
awsRegion: region,
sess: sess,
sdkapi: svcsdk.New(sess),
}, nil
}
// onError updates resource conditions and returns updated resource
// it returns nil if no condition is updated.
func (rm *resourceManager) onError(
r *resource,
err error,
) (acktypes.AWSResource, error) {
r1, updated := rm.updateConditions(r, err)
if !updated {
return r, err
}
for _, condition := range r1.Conditions() {
if condition.Type == ackv1alpha1.ConditionTypeTerminal &&
condition.Status == corev1.ConditionTrue {
// resource is in Terminal condition
// return Terminal error
return r1, ackerr.Terminal
}
}
return r1, err
}
// onSuccess updates resource conditions and returns updated resource
// it returns the supplied resource if no condition is updated.
func (rm *resourceManager) onSuccess(
r *resource,
) (acktypes.AWSResource, error) {
r1, updated := rm.updateConditions(r, nil)
if !updated {
return r, nil
}
return r1, nil
}