-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathclient.go
More file actions
218 lines (184 loc) · 8.41 KB
/
client.go
File metadata and controls
218 lines (184 loc) · 8.41 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
/*
Copyright 2017 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 stackit
import (
"context"
"errors"
"fmt"
"io"
"net/http"
"os"
"strings"
stackitconfig "github.com/stackitcloud/cloud-provider-stackit/pkg/stackit/config"
sdkconfig "github.com/stackitcloud/stackit-sdk-go/core/config"
oapiError "github.com/stackitcloud/stackit-sdk-go/core/oapierror"
iaas "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api"
loadbalancer "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer/v2api"
"gopkg.in/yaml.v3"
"k8s.io/apimachinery/pkg/util/wait"
"github.com/stackitcloud/cloud-provider-stackit/pkg/version"
"github.com/spf13/pflag"
"k8s.io/klog/v2"
)
// userAgentData is used to add extra information to the STACKIT SDK user-agent
var (
userAgentData []string
ErrorNotFound = errors.New("not found")
)
// AddExtraFlags is called by the main package to add component specific command line flags
func AddExtraFlags(fs *pflag.FlagSet) {
fs.StringArrayVar(&userAgentData, "user-agent", nil, "Extra data to add to STACKIT SDK user-agent. Use multiple times to add more than one component.")
}
type IaasClient interface {
CreateVolume(context.Context, *iaas.CreateVolumePayload) (*iaas.Volume, error)
DeleteVolume(ctx context.Context, volumeID string) error
AttachVolume(ctx context.Context, instanceID, volumeID string) (string, error)
ListVolumes(ctx context.Context, limit int, startingToken string) ([]iaas.Volume, string, error)
WaitDiskAttached(ctx context.Context, instanceID string, volumeID string) error
DetachVolume(ctx context.Context, instanceID, volumeID string) error
WaitDiskDetached(ctx context.Context, instanceID string, volumeID string) error
WaitVolumeTargetStatus(ctx context.Context, volumeID string, tStatus []string, tSize int64) error
GetVolume(ctx context.Context, volumeID string) (*iaas.Volume, error)
GetVolumesByName(ctx context.Context, name string) ([]iaas.Volume, error)
GetVolumeByName(ctx context.Context, name string) (*iaas.Volume, error)
CreateSnapshot(ctx context.Context, name, volID string, tags map[string]string) (*iaas.Snapshot, error)
ListSnapshots(ctx context.Context, filters map[string]string) ([]iaas.Snapshot, string, error)
DeleteSnapshot(ctx context.Context, snapID string) error
GetSnapshotByID(ctx context.Context, snapshotID string) (*iaas.Snapshot, error)
WaitSnapshotReady(ctx context.Context, snapshotID string) (*string, error)
CreateBackup(ctx context.Context, name, volID, snapshotID string, tags map[string]string) (*iaas.Backup, error)
ListBackups(ctx context.Context, filters map[string]string) ([]iaas.Backup, error)
DeleteBackup(ctx context.Context, backupID string) error
GetBackupByID(ctx context.Context, backupID string) (*iaas.Backup, error)
WaitBackupReady(ctx context.Context, backupID string, snapshotSize int64, backupMaxDurationSecondsPerGB int) (*string, error)
GetInstanceByID(ctx context.Context, instanceID string) (*iaas.Server, error)
ExpandVolume(ctx context.Context, volumeID string, status string, size int64) error
GetBlockStorageOpts() stackitconfig.BlockStorageOpts
WaitVolumeTargetStatusWithCustomBackoff(ctx context.Context, volumeID string, targetStatus []string, backoff *wait.Backoff) error
}
type LoadbalancerClient interface {
GetLoadBalancer(ctx context.Context, projectID string, name string) (*loadbalancer.LoadBalancer, error)
// DeleteLoadBalancer returns no error if the load balancer doesn't exist.
DeleteLoadBalancer(ctx context.Context, projectID string, name string) error
// CreateLoadBalancer returns ErrorNotFound if the project is not enabled.
CreateLoadBalancer(ctx context.Context, projectID string, loadbalancer *loadbalancer.CreateLoadBalancerPayload) (*loadbalancer.LoadBalancer, error)
UpdateLoadBalancer(ctx context.Context, projectID, name string, update *loadbalancer.UpdateLoadBalancerPayload) (*loadbalancer.LoadBalancer, error)
UpdateTargetPool(ctx context.Context, projectID string, name string, targetPoolName string, payload loadbalancer.UpdateTargetPoolPayload) error
CreateCredentials(ctx context.Context, projectID string, payload loadbalancer.CreateCredentialsPayload) (*loadbalancer.CreateCredentialsResponse, error)
ListCredentials(ctx context.Context, projectID string) (*loadbalancer.ListCredentialsResponse, error)
GetCredentials(ctx context.Context, projectID string, credentialRef string) (*loadbalancer.GetCredentialsResponse, error)
UpdateCredentials(ctx context.Context, projectID, credentialRef string, payload loadbalancer.UpdateCredentialsPayload) error
DeleteCredentials(ctx context.Context, projectID string, credentialRef string) error
}
// NodeClient is the API client wrapper for the cloud-controller-manager's node-controller
type NodeClient interface {
GetServer(ctx context.Context, projectID, region, serverID string) (*iaas.Server, error)
DeleteServer(ctx context.Context, projectID, region, serverID string) error
CreateServer(ctx context.Context, projectID string, region string, create *iaas.CreateServerPayload) (*iaas.Server, error)
UpdateServer(ctx context.Context, projectID, region, serverID string, update *iaas.UpdateServerPayload) (*iaas.Server, error)
ListServers(ctx context.Context, projectID, region string) (*[]iaas.Server, error)
}
type iaasClient struct {
iaas iaas.DefaultAPI
projectID string
region string
bsOpts stackitconfig.BlockStorageOpts
}
type lbClient struct {
client loadbalancer.DefaultAPI
region string
}
type nodeClient struct {
client *iaas.APIClient
}
//nolint:gocritic // The openstack package currently shadows but will be renamed anyway.
func (os *iaasClient) GetBlockStorageOpts() stackitconfig.BlockStorageOpts {
return os.bsOpts
}
func GetConfig(reader io.Reader) (stackitconfig.CSIConfig, error) {
var cfg stackitconfig.CSIConfig
content, err := io.ReadAll(reader)
if err != nil {
klog.ErrorS(err, "Failed to read config content")
return cfg, err
}
err = yaml.Unmarshal(content, &cfg)
if err != nil {
klog.ErrorS(err, "Failed to parse config as YAML")
return cfg, err
}
return cfg, nil
}
func GetConfigFromFile(path string) (stackitconfig.CSIConfig, error) {
var cfg stackitconfig.CSIConfig
config, err := os.Open(path)
if err != nil {
klog.ErrorS(err, "Failed to open stackitconfig file", "path", path)
return cfg, err
}
defer config.Close()
return GetConfig(config)
}
// CreateSTACKITProvider creates STACKIT Instance
func CreateSTACKITProvider(client iaas.DefaultAPI, cfg *stackitconfig.CSIConfig) (IaasClient, error) {
region := os.Getenv("STACKIT_REGION")
if region == "" {
panic("STACKIT_REGION environment variable not set")
}
// Init iaasClient
instance := &iaasClient{
iaas: client,
bsOpts: cfg.BlockStorage,
projectID: cfg.Global.ProjectID,
region: region,
}
return instance, nil
}
func CreateIaaSClient(cfg *stackitconfig.CSIConfig) (iaas.DefaultAPI, error) {
var userAgent []string
var opts []sdkconfig.ConfigurationOption
userAgent = append(userAgent, fmt.Sprintf("%s/%s", "block-storage-csi-driver", version.Version))
for _, data := range userAgentData {
// Prepend userAgents
userAgent = append([]string{data}, userAgent...)
}
klog.V(4).Infof("Using user-agent: %s", userAgent)
if cfg.Global.APIEndpoints.IaasAPI != "" {
opts = append(opts, sdkconfig.WithEndpoint(cfg.Global.APIEndpoints.IaasAPI))
}
opts = append(opts, sdkconfig.WithUserAgent(strings.Join(userAgent, " ")))
client, err := iaas.NewAPIClient(opts...)
if err != nil {
return nil, err
}
return client.DefaultAPI, nil
}
func NewLoadbalancerClient(cl loadbalancer.DefaultAPI, region string) (LoadbalancerClient, error) {
return &lbClient{
client: cl,
region: region,
}, nil
}
func NewNodeClient(cl *iaas.APIClient) (NodeClient, error) {
return &nodeClient{client: cl}, nil
}
func isOpenAPINotFound(err error) bool {
apiErr := &oapiError.GenericOpenAPIError{}
if !errors.As(err, &apiErr) {
return false
}
return apiErr.StatusCode == http.StatusNotFound
}
func IsNotFound(err error) bool {
return errors.Is(err, ErrorNotFound)
}