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

Commit 71195a8

Browse files
michal-gubrickymatofeder
authored andcommitted
Add image import functionality
Signed-off-by: michal.gubricky <[email protected]>
1 parent fcb446f commit 71195a8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+7485
-13
lines changed

config/rbac/role.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ kind: ClusterRole
44
metadata:
55
name: manager-role
66
rules:
7+
- apiGroups:
8+
- ""
9+
resources:
10+
- secrets
11+
verbs:
12+
- get
13+
- list
14+
- update
15+
- watch
716
- apiGroups:
817
- infrastructure.clusterstack.x-k8s.io
918
resources:

go.mod

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@ go 1.21
44

55
require (
66
github.com/SovereignCloudStack/cluster-stack-operator v0.1.0-alpha.1
7+
github.com/gophercloud/gophercloud v1.7.0
8+
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56
79
github.com/onsi/ginkgo/v2 v2.13.2
810
github.com/onsi/gomega v1.30.0
911
gopkg.in/yaml.v2 v2.4.0
12+
k8s.io/api v0.28.4
1013
k8s.io/apimachinery v0.28.4
1114
k8s.io/client-go v0.28.4
1215
sigs.k8s.io/cluster-api v1.6.0
1316
sigs.k8s.io/cluster-api-provider-openstack v0.9.0
1417
sigs.k8s.io/controller-runtime v0.16.3
18+
sigs.k8s.io/yaml v1.4.0
1519
)
1620

1721
require (
@@ -41,12 +45,13 @@ require (
4145
github.com/google/gofuzz v1.2.0 // indirect
4246
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
4347
github.com/google/uuid v1.3.1 // indirect
44-
github.com/gophercloud/gophercloud v1.7.0 // indirect
48+
github.com/hashicorp/go-uuid v1.0.3 // indirect
4549
github.com/imdario/mergo v0.3.15 // indirect
4650
github.com/josharian/intern v1.0.0 // indirect
4751
github.com/json-iterator/go v1.1.12 // indirect
4852
github.com/mailru/easyjson v0.7.7 // indirect
4953
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
54+
github.com/mitchellh/go-homedir v1.1.0 // indirect
5055
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
5156
github.com/modern-go/reflect2 v1.0.2 // indirect
5257
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
@@ -73,13 +78,11 @@ require (
7378
google.golang.org/protobuf v1.31.0 // indirect
7479
gopkg.in/inf.v0 v0.9.1 // indirect
7580
gopkg.in/yaml.v3 v3.0.1 // indirect
76-
k8s.io/api v0.28.4 // indirect
7781
k8s.io/apiextensions-apiserver v0.28.4 // indirect
7882
k8s.io/component-base v0.28.4 // indirect
7983
k8s.io/klog/v2 v2.100.1 // indirect
8084
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
8185
k8s.io/utils v0.0.0-20230505201702-9f6742963106 // indirect
8286
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
8387
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
84-
sigs.k8s.io/yaml v1.4.0 // indirect
8588
)

go.sum

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,13 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJY
9494
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
9595
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
9696
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
97+
github.com/gophercloud/gophercloud v1.3.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
9798
github.com/gophercloud/gophercloud v1.7.0 h1:fyJGKh0LBvIZKLvBWvQdIgkaV5yTM3Jh9EYUh+UNCAs=
9899
github.com/gophercloud/gophercloud v1.7.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
99-
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
100-
github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
100+
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 h1:sH7xkTfYzxIEgzq1tDHIMKRh1vThOEOGNsettdEeLbE=
101+
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56/go.mod h1:VSalo4adEk+3sNkmVJLnhHoOyOYYS8sTWLG4mv5BKto=
102+
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
103+
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
101104
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
102105
github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM=
103106
github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
@@ -119,10 +122,8 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0
119122
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
120123
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
121124
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
122-
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
123-
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
124-
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
125-
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
125+
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
126+
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
126127
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
127128
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
128129
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -173,6 +174,7 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
173174
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
174175
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
175176
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
177+
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
176178
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
177179
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
178180
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
@@ -196,6 +198,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
196198
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
197199
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
198200
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
201+
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
199202
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
200203
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
201204
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -207,6 +210,7 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
207210
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
208211
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
209212
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
213+
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
210214
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
211215
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
212216
golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0=
@@ -216,8 +220,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
216220
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
217221
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
218222
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
219-
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
220-
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
223+
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
221224
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
222225
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
223226
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -228,16 +231,22 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
228231
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
229232
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
230233
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
234+
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
235+
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
231236
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
237+
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
232238
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
233239
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
234240
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
241+
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
235242
golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8=
236243
golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww=
237244
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
238245
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
239246
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
240247
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
248+
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
249+
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
241250
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
242251
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
243252
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
@@ -248,6 +257,7 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
248257
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
249258
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
250259
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
260+
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
251261
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
252262
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
253263
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

internal/controller/openstacknodeimagerelease_controller.go

Lines changed: 156 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,18 @@ package controller
1919

2020
import (
2121
"context"
22+
"fmt"
23+
"time"
2224

2325
apiv1alpha1 "github.com/sovereignCloudStack/cluster-stack-provider-openstack/api/v1alpha1"
2426
"k8s.io/apimachinery/pkg/runtime"
2527
ctrl "sigs.k8s.io/controller-runtime"
2628
"sigs.k8s.io/controller-runtime/pkg/client"
2729
"sigs.k8s.io/controller-runtime/pkg/log"
30+
"github.com/gophercloud/gophercloud"
31+
"github.com/gophercloud/gophercloud/openstack"
32+
"github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
33+
"github.com/gophercloud/gophercloud/openstack/imageservice/v2/imageimport"
2834
)
2935

3036
// OpenStackNodeImageReleaseReconciler reconciles a OpenStackNodeImageRelease object.
@@ -33,9 +39,72 @@ type OpenStackNodeImageReleaseReconciler struct {
3339
Scheme *runtime.Scheme
3440
}
3541

42+
func findImageByName(imagesClient *gophercloud.ServiceClient, imageName string) (string, error) {
43+
var imageID string
44+
45+
listOpts := images.ListOpts{
46+
Name: imageName,
47+
}
48+
49+
allPages, err := images.List(imagesClient, listOpts).AllPages()
50+
imageList, err := images.ExtractImages(allPages)
51+
for _, image := range imageList {
52+
if image.Name == imageName {
53+
imageID = image.ID
54+
break
55+
}
56+
}
57+
58+
if err != nil {
59+
return "", err
60+
}
61+
62+
return imageID, nil
63+
}
64+
65+
func waitForImageActive(client *gophercloud.ServiceClient, imageID string, interval time.Duration, timeout time.Duration) (bool, error) {
66+
startTime := time.Now()
67+
68+
for {
69+
image, err := images.Get(client, imageID).Extract()
70+
if err != nil {
71+
return false, err
72+
}
73+
74+
if image.Status == "active" {
75+
return true, nil
76+
}
77+
78+
if time.Since(startTime) > timeout {
79+
return false, fmt.Errorf("Timeout waiting for image to become active")
80+
}
81+
82+
time.Sleep(interval)
83+
}
84+
}
85+
86+
func createImage(imageClient *gophercloud.ServiceClient, createOpts images.CreateOpts) (*images.Image, error) {
87+
image, err := images.Create(imageClient, createOpts).Extract()
88+
if err != nil {
89+
return nil, err
90+
}
91+
92+
return image, nil
93+
}
94+
95+
func importImage(imageClient *gophercloud.ServiceClient, imageID string, createOpts imageimport.CreateOpts) error {
96+
err := imageimport.Create(imageClient, imageID, createOpts).ExtractErr()
97+
if err != nil {
98+
return err
99+
}
100+
101+
return nil
102+
}
103+
36104
//+kubebuilder:rbac:groups=infrastructure.clusterstack.x-k8s.io,resources=openstacknodeimagereleases,verbs=get;list;watch;create;update;patch;delete
37105
//+kubebuilder:rbac:groups=infrastructure.clusterstack.x-k8s.io,resources=openstacknodeimagereleases/status,verbs=get;update;patch
38106
//+kubebuilder:rbac:groups=infrastructure.clusterstack.x-k8s.io,resources=openstacknodeimagereleases/finalizers,verbs=update
107+
//+kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;update
39108

40109
// Reconcile is part of the main kubernetes reconciliation loop which aims to
41110
// move the current state of the cluster closer to the desired state.
@@ -47,10 +116,95 @@ type OpenStackNodeImageReleaseReconciler struct {
47116
// For more details, check Reconcile and its Result here:
48117
// - https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/reconcile
49118
func (r *OpenStackNodeImageReleaseReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
50-
_ = log.FromContext(ctx)
119+
logger := log.FromContext(ctx)
51120

52121
openstacknodeimagerelease := apiv1alpha1.OpenStackNodeImageRelease{}
53-
_ = r.Client.Get(ctx, req.NamespacedName, &openstacknodeimagerelease)
122+
err := r.Client.Get(ctx, req.NamespacedName, &openstacknodeimagerelease)
123+
if err != nil {
124+
return ctrl.Result{}, fmt.Errorf("Failed to get OpenStackNodeImageRelease %s/%s: %w", req.Namespace, req.Name, err)
125+
}
126+
127+
var (
128+
imageStatus bool = false
129+
secretName string = openstacknodeimagerelease.Spec.IdentityRef.Name
130+
secretNamespace string = "default"
131+
cloudName string = openstacknodeimagerelease.Spec.CloudName
132+
imageName string = openstacknodeimagerelease.Spec.Name
133+
imageURL string = openstacknodeimagerelease.Spec.URL
134+
)
135+
136+
cloud, err := getCloudFromSecret(ctx, r.Client, secretNamespace, secretName, cloudName)
137+
if err != nil {
138+
return ctrl.Result{}, err
139+
}
140+
var (
141+
username string = cloud.AuthInfo.Username
142+
authURL string = cloud.AuthInfo.AuthURL
143+
projectID string = cloud.AuthInfo.ProjectID
144+
userDomainName string = cloud.AuthInfo.UserDomainName
145+
password string = cloud.AuthInfo.Password
146+
)
147+
148+
// Authenticate
149+
authOpts := gophercloud.AuthOptions{
150+
IdentityEndpoint: authURL,
151+
Username: username,
152+
Password: password,
153+
DomainName: userDomainName,
154+
TenantID: projectID,
155+
}
156+
157+
provider, err := openstack.AuthenticatedClient(authOpts)
158+
if err != nil {
159+
fmt.Errorf("Error authenticating with OpenStack: %v", err)
160+
}
161+
162+
// Create an Image service client
163+
imageClient, err := openstack.NewImageServiceV2(provider, gophercloud.EndpointOpts{
164+
Region: cloud.RegionName,
165+
})
166+
167+
imageID, err := findImageByName(imageClient, imageName)
168+
if err != nil {
169+
fmt.Errorf("Error finding image: %w", err)
170+
} else {
171+
if imageID == "" {
172+
visibility := images.ImageVisibilityShared
173+
174+
createOptsImage := images.CreateOpts{
175+
Name: imageName,
176+
ContainerFormat: "bare",
177+
DiskFormat: "iso",
178+
Visibility: &visibility,
179+
}
180+
181+
image, err := createImage(imageClient, createOptsImage)
182+
if err != nil {
183+
return ctrl.Result{}, err
184+
}
185+
186+
createOpts := imageimport.CreateOpts{
187+
Name: imageimport.WebDownloadMethod,
188+
URI: imageURL,
189+
}
190+
imageID = image.ID
191+
192+
// Handle error during image import
193+
err = importImage(imageClient, image.ID, createOpts)
194+
if err != nil {
195+
return ctrl.Result{}, err
196+
}
197+
}
198+
}
199+
200+
// Check if image is active
201+
imageStatus, err = waitForImageActive(imageClient, imageID, 5*time.Second, 10*time.Minute)
202+
if err != nil {
203+
fmt.Errorf("Error waiting for image to become active:", err)
204+
}
205+
if imageStatus {
206+
logger.Info("Image is active.")
207+
}
54208

55209
return ctrl.Result{}, nil
56210
}

0 commit comments

Comments
 (0)