@@ -17,9 +17,11 @@ package functional
1717
1818import (
1919 "errors"
20+ "fmt"
2021
2122 . "github.com/onsi/ginkgo/v2" //revive:disable:dot-imports
2223 . "github.com/onsi/gomega" //revive:disable:dot-imports
24+ baremetalv1 "github.com/openstack-k8s-operators/openstack-baremetal-operator/api/v1beta1"
2325 k8s_errors "k8s.io/apimachinery/pkg/api/errors"
2426 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2527 "k8s.io/apimachinery/pkg/types"
@@ -127,6 +129,23 @@ var _ = Describe("OpenStackProvisionServer Webhook", func() {
127129 })
128130 })
129131
132+ When ("Creating ProvisionServer with port 0 (auto-assign)" , func () {
133+ It ("should auto-assign a valid port via the defaulting webhook" , func () {
134+ spec := map [string ]interface {}{
135+ "osImage" : "edpm-hardened-uefi.qcow2" ,
136+ "osContainerImageUrl" : "quay.io/podified-antelope-centos9/edpm-hardened-uefi:current-podified" ,
137+ "apacheImageUrl" : "registry.redhat.io/ubi9/httpd-24:latest" ,
138+ "agentImageUrl" : "quay.io/openstack-k8s-operators/openstack-baremetal-operator-agent:latest" ,
139+ "port" : int64 (0 ),
140+ }
141+ DeferCleanup (th .DeleteInstance , CreateProvisionServer (provisionServerName , spec ))
142+
143+ instance := GetProvisionServerDirect (provisionServerName )
144+ Expect (instance .Spec .Port ).Should (BeNumerically (">=" , baremetalv1 .ProvisionServerPortStart ))
145+ Expect (instance .Spec .Port ).Should (BeNumerically ("<=" , baremetalv1 .ProvisionServerPortEnd ))
146+ })
147+ })
148+
130149 When ("Creating ProvisionServer with duplicate port" , func () {
131150 var provisionServer2Name types.NamespacedName
132151
@@ -204,4 +223,43 @@ var _ = Describe("OpenStackProvisionServer Webhook", func() {
204223 Expect (instance .Spec .AgentImageURL ).ShouldNot (BeEmpty ())
205224 })
206225 })
226+
227+ When ("Port range is exhausted" , func () {
228+ BeforeEach (func () {
229+ spec := map [string ]interface {}{
230+ "osImage" : "edpm-hardened-uefi.qcow2" ,
231+ "osContainerImageUrl" : "quay.io/podified-antelope-centos9/edpm-hardened-uefi:current-podified" ,
232+ "apacheImageUrl" : "registry.redhat.io/ubi9/httpd-24:latest" ,
233+ "agentImageUrl" : "quay.io/openstack-k8s-operators/openstack-baremetal-operator-agent:latest" ,
234+ }
235+ portCount := baremetalv1 .ProvisionServerPortEnd - baremetalv1 .ProvisionServerPortStart + 1
236+ for i := 0 ; i < int (portCount ); i ++ {
237+ name := types.NamespacedName {
238+ Name : fmt .Sprintf ("provserver-exhaust-%d" , i ),
239+ Namespace : namespace ,
240+ }
241+ DeferCleanup (th .DeleteInstance , CreateProvisionServer (name , spec ))
242+ }
243+ })
244+
245+ It ("should reject creation when no ports are available" , func () {
246+ raw := map [string ]interface {}{
247+ "apiVersion" : "baremetal.openstack.org/v1beta1" ,
248+ "kind" : "OpenStackProvisionServer" ,
249+ "metadata" : map [string ]interface {}{
250+ "name" : "provserver-over-limit" ,
251+ "namespace" : namespace ,
252+ },
253+ "spec" : map [string ]interface {}{
254+ "osImage" : "edpm-hardened-uefi.qcow2" ,
255+ "osContainerImageUrl" : "quay.io/podified-antelope-centos9/edpm-hardened-uefi:current-podified" ,
256+ "apacheImageUrl" : "registry.redhat.io/ubi9/httpd-24:latest" ,
257+ "agentImageUrl" : "quay.io/openstack-k8s-operators/openstack-baremetal-operator-agent:latest" ,
258+ },
259+ }
260+ unstructuredObj := & unstructured.Unstructured {Object : raw }
261+ err := k8sClient .Create (ctx , unstructuredObj )
262+ Expect (err ).Should (HaveOccurred ())
263+ })
264+ })
207265})
0 commit comments