Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion internal/shim/placement/handle_allocation_candidates_e2e.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ func e2eTestAllocationCandidates(ctx context.Context, _ client.Client) error {
const testRC = "CUSTOM_CORTEX_E2E_CAND_RC"
const apiVersion = "placement 1.26"

// Probe: for non-passthrough modes, verify endpoint returns 501.
unimplemented, err := e2eProbeUnimplemented(ctx, sc, sc.Endpoint+"/allocation_candidates?resources=VCPU:1")
if err != nil {
return fmt.Errorf("probe: %w", err)
}
if unimplemented {
return nil
}

// Pre-cleanup: delete leftover test resources from a prior run.
log.Info("Pre-cleanup: deleting leftover test resources")
for _, cleanup := range []struct {
Expand Down Expand Up @@ -296,5 +305,5 @@ func e2eTestAllocationCandidates(ctx context.Context, _ client.Client) error {
}

func init() {
e2eTests = append(e2eTests, e2eTest{name: "allocation_candidates", run: e2eTestAllocationCandidates})
e2eTests = append(e2eTests, e2eTest{name: "allocation_candidates", run: e2eWrapWithModes(e2eTestAllocationCandidates)})
}
11 changes: 10 additions & 1 deletion internal/shim/placement/handle_allocations_e2e.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ func e2eTestAllocations(ctx context.Context, _ client.Client) error {
const userID = "e2e50000-0000-0000-0000-000000000001"
const apiVersion = "placement 1.28"

// Probe: for non-passthrough modes, verify endpoint returns 501.
unimplemented, err := e2eProbeUnimplemented(ctx, sc, sc.Endpoint+"/allocations/"+consumerUUID1)
if err != nil {
return fmt.Errorf("probe: %w", err)
}
if unimplemented {
return nil
}

// Pre-cleanup: delete allocations, resource provider, and resource class.
log.Info("Pre-cleanup: deleting leftover test resources")
for _, cleanup := range []struct {
Expand Down Expand Up @@ -476,5 +485,5 @@ func e2eTestAllocations(ctx context.Context, _ client.Client) error {
}

func init() {
e2eTests = append(e2eTests, e2eTest{name: "allocations", run: e2eTestAllocations})
e2eTests = append(e2eTests, e2eTest{name: "allocations", run: e2eWrapWithModes(e2eTestAllocations)})
}
11 changes: 10 additions & 1 deletion internal/shim/placement/handle_reshaper_e2e.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ func e2eTestReshaper(ctx context.Context, _ client.Client) error {
const userID = "e2e50000-0000-0000-0000-000000000001"
const apiVersion = "placement 1.30"

// Probe: for non-passthrough modes, verify endpoint returns 501.
unimplemented, err := e2eProbeUnimplemented(ctx, sc, sc.Endpoint+"/allocations/"+consumerUUID)
if err != nil {
return fmt.Errorf("probe: %w", err)
}
if unimplemented {
return nil
}

// Pre-cleanup: delete allocation, both RPs, and custom resource class.
log.Info("Pre-cleanup: deleting leftover test resources")
for _, cleanup := range []struct {
Expand Down Expand Up @@ -571,5 +580,5 @@ func e2eTestReshaper(ctx context.Context, _ client.Client) error {
}

func init() {
e2eTests = append(e2eTests, e2eTest{name: "reshaper", run: e2eTestReshaper})
e2eTests = append(e2eTests, e2eTest{name: "reshaper", run: e2eWrapWithModes(e2eTestReshaper)})
}
11 changes: 10 additions & 1 deletion internal/shim/placement/handle_resource_classes_e2e.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ func e2eTestResourceClasses(ctx context.Context, _ client.Client) error {

const testRC = "CUSTOM_CORTEX_E2E_RC"

// Probe: for non-passthrough modes, verify endpoint returns 501.
unimplemented, err := e2eProbeUnimplemented(ctx, sc, sc.Endpoint+"/resource_classes")
if err != nil {
return fmt.Errorf("probe: %w", err)
}
if unimplemented {
return nil
}

// Pre-cleanup: delete any leftover test resource class from a prior run.
log.Info("Pre-cleanup: deleting leftover test resource class", "class", testRC)
req, err := http.NewRequestWithContext(ctx,
Expand Down Expand Up @@ -226,5 +235,5 @@ func e2eTestResourceClasses(ctx context.Context, _ client.Client) error {
}

func init() {
e2eTests = append(e2eTests, e2eTest{name: "resource_classes", run: e2eTestResourceClasses})
e2eTests = append(e2eTests, e2eTest{name: "resource_classes", run: e2eWrapWithModes(e2eTestResourceClasses)})
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ func e2eTestResourceProviderAggregates(ctx context.Context, _ client.Client) err
const testAggUUID1 = "e2e30000-0000-0000-0000-000000000001"
const testAggUUID2 = "e2e30000-0000-0000-0000-000000000002"

// Probe: for non-passthrough modes, verify endpoint returns 501.
unimplemented, err := e2eProbeUnimplemented(ctx, sc, sc.Endpoint+"/resource_providers/"+testRPUUID+"/aggregates")
if err != nil {
return fmt.Errorf("probe: %w", err)
}
if unimplemented {
return nil
}

// Pre-cleanup: delete any leftover test resource provider from a prior run.
log.Info("Pre-cleanup: deleting leftover test resource provider", "uuid", testRPUUID)
req, err := http.NewRequestWithContext(ctx,
Expand Down Expand Up @@ -346,5 +355,5 @@ func e2eTestResourceProviderAggregates(ctx context.Context, _ client.Client) err
}

func init() {
e2eTests = append(e2eTests, e2eTest{name: "resource_provider_aggregates", run: e2eTestResourceProviderAggregates})
e2eTests = append(e2eTests, e2eTest{name: "resource_provider_aggregates", run: e2eWrapWithModes(e2eTestResourceProviderAggregates)})
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ func e2eTestResourceProviderAllocations(ctx context.Context, _ client.Client) er
const testRPUUID = "e2e10000-0000-0000-0000-000000000006"
const testRPName = "cortex-e2e-test-rp-alloc-view"

// Probe: for non-passthrough modes, verify endpoint returns 501.
unimplemented, err := e2eProbeUnimplemented(ctx, sc, sc.Endpoint+"/resource_providers/"+testRPUUID+"/allocations")
if err != nil {
return fmt.Errorf("probe: %w", err)
}
if unimplemented {
return nil
}

// Pre-cleanup: delete any leftover test resource provider from a prior run.
log.Info("Pre-cleanup: deleting leftover test resource provider", "uuid", testRPUUID)
req, err := http.NewRequestWithContext(ctx,
Expand Down Expand Up @@ -227,5 +236,5 @@ func e2eTestResourceProviderAllocations(ctx context.Context, _ client.Client) er
}

func init() {
e2eTests = append(e2eTests, e2eTest{name: "resource_provider_allocations", run: e2eTestResourceProviderAllocations})
e2eTests = append(e2eTests, e2eTest{name: "resource_provider_allocations", run: e2eWrapWithModes(e2eTestResourceProviderAllocations)})
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ func e2eTestResourceProviderInventories(ctx context.Context, _ client.Client) er
const testRC = "CUSTOM_CORTEX_E2E_INV_RC"
const apiVersion = "placement 1.26"

// Probe: for non-passthrough modes, verify endpoint returns 501.
unimplemented, err := e2eProbeUnimplemented(ctx, sc, sc.Endpoint+"/resource_providers/"+testRPUUID+"/inventories")
if err != nil {
return fmt.Errorf("probe: %w", err)
}
if unimplemented {
return nil
}

// Pre-cleanup: delete the resource provider (cascades inventories), then
// the custom resource class. Ignore 404/409.
log.Info("Pre-cleanup: deleting leftover test resources")
Expand Down Expand Up @@ -488,5 +497,5 @@ func e2eTestResourceProviderInventories(ctx context.Context, _ client.Client) er
}

func init() {
e2eTests = append(e2eTests, e2eTest{name: "resource_provider_inventories", run: e2eTestResourceProviderInventories})
e2eTests = append(e2eTests, e2eTest{name: "resource_provider_inventories", run: e2eWrapWithModes(e2eTestResourceProviderInventories)})
}
11 changes: 5 additions & 6 deletions internal/shim/placement/handle_resource_provider_traits.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
package placement

import (
"fmt"
"net/http"

hv1 "github.com/cobaltcore-dev/openstack-hypervisor-operator/api/v1"
Expand Down Expand Up @@ -33,7 +32,7 @@ func (s *Shim) HandleListResourceProviderTraits(w http.ResponseWriter, r *http.R
if !ok {
return
}
switch s.config.Features.ResourceProviderTraits.orDefault() {
switch s.featureModeFromConfOrHeader(r, s.config.Features.ResourceProviderTraits) {
case FeatureModePassthrough:
s.forward(w, r)
case FeatureModeHybrid:
Expand Down Expand Up @@ -92,13 +91,13 @@ func (s *Shim) HandleUpdateResourceProviderTraits(w http.ResponseWriter, r *http
if _, ok := requiredUUIDPathParam(w, r, "uuid"); !ok {
return
}
switch s.config.Features.ResourceProviderTraits.orDefault() {
switch s.featureModeFromConfOrHeader(r, s.config.Features.ResourceProviderTraits) {
case FeatureModePassthrough:
s.forward(w, r)
case FeatureModeHybrid:
s.forward(w, r)
case FeatureModeCRD:
http.Error(w, fmt.Sprintf("%s mode is not yet implemented for resource provider trait writes", s.config.Features.ResourceProviderTraits), http.StatusNotImplemented)
http.Error(w, "crd mode is not yet implemented for resource provider trait writes", http.StatusNotImplemented)
default:
http.Error(w, "unknown feature mode", http.StatusInternalServerError)
}
Expand All @@ -117,13 +116,13 @@ func (s *Shim) HandleDeleteResourceProviderTraits(w http.ResponseWriter, r *http
if _, ok := requiredUUIDPathParam(w, r, "uuid"); !ok {
return
}
switch s.config.Features.ResourceProviderTraits.orDefault() {
switch s.featureModeFromConfOrHeader(r, s.config.Features.ResourceProviderTraits) {
case FeatureModePassthrough:
s.forward(w, r)
case FeatureModeHybrid:
s.forward(w, r)
case FeatureModeCRD:
http.Error(w, fmt.Sprintf("%s mode is not yet implemented for resource provider trait writes", s.config.Features.ResourceProviderTraits), http.StatusNotImplemented)
http.Error(w, "crd mode is not yet implemented for resource provider trait writes", http.StatusNotImplemented)
default:
http.Error(w, "unknown feature mode", http.StatusInternalServerError)
}
Expand Down
11 changes: 10 additions & 1 deletion internal/shim/placement/handle_resource_provider_traits_e2e.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ func e2eTestResourceProviderTraits(ctx context.Context, _ client.Client) error {
}
log.Info("Successfully created openstack client for resource provider traits e2e test")

// Resource provider trait writes (PUT/DELETE) are not yet implemented in
// crd mode, and the test RP created via POST won't exist as a Hypervisor
// CRD either, so skip the entire test in crd mode.
rpTraitsMode := e2eCurrentMode(ctx)
if rpTraitsMode == FeatureModeCRD {
log.Info("Skipping resource provider traits e2e test because mode is crd (writes not implemented)")
return nil
}

const testRPUUID = "e2e10000-0000-0000-0000-000000000003"
const testRPName = "cortex-e2e-test-rp-traits"
const testTrait = "CUSTOM_CORTEX_E2E_RP_TRAIT"
Expand Down Expand Up @@ -382,5 +391,5 @@ func e2eTestResourceProviderTraits(ctx context.Context, _ client.Client) error {
}

func init() {
e2eTests = append(e2eTests, e2eTest{name: "resource_provider_traits", run: e2eTestResourceProviderTraits})
e2eTests = append(e2eTests, e2eTest{name: "resource_provider_traits", run: e2eWrapWithModes(e2eTestResourceProviderTraits)})
}
11 changes: 10 additions & 1 deletion internal/shim/placement/handle_resource_provider_usages_e2e.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ func e2eTestResourceProviderUsages(ctx context.Context, _ client.Client) error {
const testRPUUID = "e2e10000-0000-0000-0000-000000000005"
const testRPName = "cortex-e2e-test-rp-usages"

// Probe: for non-passthrough modes, verify endpoint returns 501.
unimplemented, err := e2eProbeUnimplemented(ctx, sc, sc.Endpoint+"/resource_providers/"+testRPUUID+"/usages")
if err != nil {
return fmt.Errorf("probe: %w", err)
}
if unimplemented {
return nil
}

// Pre-cleanup: delete any leftover test resource provider from a prior run.
log.Info("Pre-cleanup: deleting leftover test resource provider", "uuid", testRPUUID)
req, err := http.NewRequestWithContext(ctx,
Expand Down Expand Up @@ -227,5 +236,5 @@ func e2eTestResourceProviderUsages(ctx context.Context, _ client.Client) error {
}

func init() {
e2eTests = append(e2eTests, e2eTest{name: "resource_provider_usages", run: e2eTestResourceProviderUsages})
e2eTests = append(e2eTests, e2eTest{name: "resource_provider_usages", run: e2eWrapWithModes(e2eTestResourceProviderUsages)})
}
22 changes: 13 additions & 9 deletions internal/shim/placement/handle_resource_providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ func (s *Shim) HandleCreateResourceProvider(w http.ResponseWriter, r *http.Reque
ctx := r.Context()
log := logf.FromContext(ctx)

switch s.config.Features.ResourceProviders.orDefault() {
mode := s.featureModeFromConfOrHeader(r, s.config.Features.ResourceProviders)
switch mode {
case FeatureModePassthrough:
s.forward(w, r)
return
Expand Down Expand Up @@ -184,7 +185,7 @@ func (s *Shim) HandleCreateResourceProvider(w http.ResponseWriter, r *http.Reque
}

// No conflict — forward to upstream placement (hybrid) or reject (crd).
if s.config.Features.ResourceProviders.orDefault() == FeatureModeCRD {
if mode == FeatureModeCRD {
log.Info("crd mode: non-kvm resource provider create not supported", "name", req.Name)
http.Error(w, "resource provider not found", http.StatusNotFound)
return
Expand All @@ -209,7 +210,8 @@ func (s *Shim) HandleShowResourceProvider(w http.ResponseWriter, r *http.Request
ctx := r.Context()
log := logf.FromContext(ctx)

switch s.config.Features.ResourceProviders.orDefault() {
mode := s.featureModeFromConfOrHeader(r, s.config.Features.ResourceProviders)
switch mode {
case FeatureModePassthrough:
s.forward(w, r)
return
Expand All @@ -229,7 +231,7 @@ func (s *Shim) HandleShowResourceProvider(w http.ResponseWriter, r *http.Request
var hvs hv1.HypervisorList
err := s.List(ctx, &hvs, client.MatchingFields{idxHypervisorOpenStackId: uuid})
if apierrors.IsNotFound(err) || len(hvs.Items) == 0 {
if s.config.Features.ResourceProviders.orDefault() == FeatureModeCRD {
if mode == FeatureModeCRD {
log.Info("resource provider not found in kubernetes (crd mode)", "uuid", uuid)
http.Error(w, "resource provider not found", http.StatusNotFound)
return
Expand Down Expand Up @@ -278,7 +280,8 @@ func (s *Shim) HandleUpdateResourceProvider(w http.ResponseWriter, r *http.Reque
ctx := r.Context()
log := logf.FromContext(ctx)

switch s.config.Features.ResourceProviders.orDefault() {
mode := s.featureModeFromConfOrHeader(r, s.config.Features.ResourceProviders)
switch mode {
case FeatureModePassthrough:
s.forward(w, r)
return
Expand Down Expand Up @@ -315,7 +318,7 @@ func (s *Shim) HandleUpdateResourceProvider(w http.ResponseWriter, r *http.Reque
var hvs hv1.HypervisorList
err = s.List(ctx, &hvs, client.MatchingFields{idxHypervisorOpenStackId: uuid})
if apierrors.IsNotFound(err) || len(hvs.Items) == 0 {
if s.config.Features.ResourceProviders.orDefault() == FeatureModeCRD {
if mode == FeatureModeCRD {
log.Info("resource provider not found in kubernetes (crd mode)", "uuid", uuid)
http.Error(w, "resource provider not found", http.StatusNotFound)
return
Expand Down Expand Up @@ -373,7 +376,8 @@ func (s *Shim) HandleDeleteResourceProvider(w http.ResponseWriter, r *http.Reque
ctx := r.Context()
log := logf.FromContext(ctx)

switch s.config.Features.ResourceProviders.orDefault() {
mode := s.featureModeFromConfOrHeader(r, s.config.Features.ResourceProviders)
switch mode {
case FeatureModePassthrough:
s.forward(w, r)
return
Expand All @@ -393,7 +397,7 @@ func (s *Shim) HandleDeleteResourceProvider(w http.ResponseWriter, r *http.Reque
var hvs hv1.HypervisorList
err := s.List(ctx, &hvs, client.MatchingFields{idxHypervisorOpenStackId: uuid})
if apierrors.IsNotFound(err) || len(hvs.Items) == 0 {
if s.config.Features.ResourceProviders.orDefault() == FeatureModeCRD {
if mode == FeatureModeCRD {
log.Info("resource provider not found in kubernetes (crd mode)", "uuid", uuid)
http.Error(w, "resource provider not found", http.StatusNotFound)
return
Expand Down Expand Up @@ -448,7 +452,7 @@ type listResourceProvidersResponse struct {
//
// See: https://docs.openstack.org/api-ref/placement/#list-resource-providers
func (s *Shim) HandleListResourceProviders(w http.ResponseWriter, r *http.Request) {
switch s.config.Features.ResourceProviders.orDefault() {
switch s.featureModeFromConfOrHeader(r, s.config.Features.ResourceProviders) {
case FeatureModePassthrough:
s.forward(w, r)
case FeatureModeHybrid:
Expand Down
20 changes: 15 additions & 5 deletions internal/shim/placement/handle_resource_providers_e2e.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,24 @@ func e2eTestResourceProviders(ctx context.Context, cl client.Client) error {

// ==================== Phase 1: VMware path ====================

log.Info("=== VMware path: passthrough resource provider tests ===")
if err := e2eVMwareResourceProviders(ctx, sc); err != nil {
return fmt.Errorf("VMware path: %w", err)
// The VMware path creates synthetic test RPs against upstream placement.
// In crd mode there is no upstream, so skip it.
mode := e2eCurrentMode(ctx)
if mode == "" {
mode = config.Features.ResourceProviders.orDefault()
}
if mode != FeatureModeCRD {
log.Info("=== VMware path: passthrough resource provider tests ===")
if err := e2eVMwareResourceProviders(ctx, sc); err != nil {
return fmt.Errorf("VMware path: %w", err)
}
} else {
log.Info("Skipping VMware path because mode is crd (no upstream placement)")
}

// ==================== Phase 2: KVM path ====================

if config.Features.ResourceProviders.orDefault() == FeatureModePassthrough {
if mode == FeatureModePassthrough {
log.Info("Skipping KVM resource provider e2e tests because resourceProviders mode is passthrough")
} else {
log.Info("=== KVM path: hypervisor-backed resource provider tests ===")
Expand Down Expand Up @@ -506,5 +516,5 @@ func e2eKVMResourceProviders(ctx context.Context, sc *gophercloud.ServiceClient,
}

func init() {
e2eTests = append(e2eTests, e2eTest{name: "resource_providers", run: e2eTestResourceProviders})
e2eTests = append(e2eTests, e2eTest{name: "resource_providers", run: e2eWrapWithModes(e2eTestResourceProviders)})
}
2 changes: 1 addition & 1 deletion internal/shim/placement/handle_root.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (s *Shim) HandleGetRoot(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
log := logf.FromContext(ctx)

switch s.config.Features.Root.orDefault() {
switch s.featureModeFromConfOrHeader(r, s.config.Features.Root) {
case FeatureModePassthrough:
log.Info("forwarding GET / to upstream placement")
s.forward(w, r)
Expand Down
2 changes: 1 addition & 1 deletion internal/shim/placement/handle_root_e2e.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,5 @@ func e2eTestGetRoot(ctx context.Context, _ client.Client) error {
}

func init() {
e2eTests = append(e2eTests, e2eTest{name: "root", run: e2eTestGetRoot})
e2eTests = append(e2eTests, e2eTest{name: "root", run: e2eWrapWithModes(e2eTestGetRoot)})
}
Loading
Loading