region

module
v1.14.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 12, 2026 License: Apache-2.0

README

Region

Centralized region discovery and routing service.

Architecture

We provide a composable suite of different micro-services that provide different functionality.

Hardware provisioning can come in a number of different flavors, namely bare-metal, managed Kubernetes etc. These services have a common requirement on a compute cloud/region to provision projects, users, roles, networking etc. in order to function.

A Note on Security

At present this region controller is monolithic, offering region discovery and routing to allow scoped provisioning and deprovisioning or the aforementioned hardware prerequisites.

Given this service holds elevated privilege credentials to all of those clouds, it make it somewhat of a honey pot. Eventually, the goal is to have this act as a purely discovery and routing service, and platform specific region controllers live in those platforms, including their credentials. The end goal being the compromise of one, doesn't affect the others, limiting blast radius, and not having to disseminate credentials across the internet, they would reside locally in the cloud platform's AS to improve security guarantees.

Supported Providers

OpenStack

OpenStack is an open source cloud provider that allows on premise provisioning of virtual and physical infrastructure. It allows a vertically integrated stack from server to application, so you have full control over the platform. This obviously entails a support crew to keep it up and running!

For further info see the OpenStack provider documentation.

Kubernetes

Kubernetes regions allow Kubernetes clusters from any cloud provider to be consumed and increase capacity without the hassle of physical infrastructure. Kubernetes regions are exposed to end users with virtual Kubernetes clusters.

For further info see the Kubernetes provider documentation.

Installation

Prerequisites

The use the Kubernetes service you first need to install:

Installing the Service

The region service is typically installed with Helm as follows:

region:
  ingress:
    host: region.unikorn-cloud.org
    clusterIssuer: letsencrypt-production
    externalDns: true
  oidc:
    issuer: https://identity.unikorn-cloud.org
regions:
- name: gb-north-1
  provider: openstack
  openstack:
    endpoint: https://my-openstack-endpoint.com:5000
    serviceAccountSecret:
      namespace: unikorn-region
      name: gb-north-1-credentials # See the provider setup section

The configures the service to be exposed on the specified host using an ingress with TLS and DDNS.

The OIDC configuration allows token validation at the API.

Regions define cloud instances to expose to clients.

Running Tests

Local Testing
  1. Set up your environment configuration:

    Copy the example config and update with your values:

    cp test/.env.example test/.env
    

    Or create environment-specific files (not tracked in git):

    # Create .env.dev with your dev credentials
    cp test/.env.example test/.env.dev
    # Edit test/.env.dev with dev values
    
    # Create .env.uat with your UAT credentials
    cp test/.env.example test/.env.uat
    # Edit test/.env.uat with UAT values
    
    # Use the appropriate environment
    cp test/.env.dev test/.env    # For dev environment
    cp test/.env.uat test/.env    # For UAT environment
    
  2. Configure the required values in test/.env:

    • API_BASE_URL - Region API server URL
    • API_AUTH_TOKEN - Service token from console
    • TEST_ORG_ID, TEST_PROJECT_ID, TEST_REGION_ID - Test data IDs
  3. Run tests:

    make test-api                                              # Run all tests
    make test-api-verbose                                      # Verbose output
    make test-api-focus FOCUS="should return all available"   # Run focused tests
    

Note: The .env, .env.dev, and .env.uat files are gitignored and contain sensitive credentials. They should never be committed to the repository.

GitHub Actions

Trigger the workflow manually from the Actions tab:

  1. Go to ActionsAPI Tests
  2. Click Run workflow
  3. Check which environments to test:
    • Run Dev tests (checked by default)
    • Run UAT tests (unchecked by default)
    • Can run one, both, or neither
  4. View results in the workflow run and download test artifacts

Contract Testing

Contract tests verify that the provider service meets consumer expectations defined in the Pact Broker.

Prerequisites
  1. Install Pact FFI library (macOS):

    brew tap pact-foundation/pact-ruby-standalone
    brew install pact-ruby-standalone
    mkdir -p $HOME/Library/pact
    cp /usr/local/opt/pact-ruby-standalone/libexec/lib/*.dylib $HOME/Library/pact/
    
  2. Start Pact Broker (optional, for local testing):

Download the Uni-core repo and run the following command from its root dir:

make pact-broker-start
Running Consumer Contract Tests

Run consumer tests locally:

make test-contracts-consumer

Run with verbose output:

make test-contracts-consumer-verbose

Publish consumer pact files to Pact Broker (requires Docker):

make publish-contracts-consumer

Run consumer tests and publish in CI:

make test-contracts-consumer-ci

Check if a version can be safely deployed:

make can-i-deploy

Record a deployment to an environment:

make record-deployment
Running Provider Contract Tests

Run verification against pacts from the Pact Broker (this assumes you have already run and published the consumer tests to the broker):

make test-contracts-provider

Run verification against a local pact file (pact for the consumer when testing without a broker):

make test-contracts-provider-local PACT_FILE=/path/to/pact.json

Run with verbose output:

make test-contracts-provider-verbose
Automated Provider Verification (Webhook)

The repository includes a webhook-triggered workflow (.github/workflows/pact-verification.yaml) that automatically verifies contracts when consumers publish new pacts.

How it works:

  1. Consumer (e.g., uni-compute) publishes a new pact to Pact Broker
  2. Pact Broker webhook triggers this repository's GitHub Actions workflow
  3. Provider verification runs automatically against the new contract
  4. Results are published back to Pact Broker
  5. Consumer's can-i-deploy check can now validate compatibility

Setup: The webhook is configured in the Pact Broker by the consumer service. See uni-compute's README for webhook setup instructions.

Workflow trigger:

on:
  repository_dispatch:
    types: [pact_verification]

This workflow receives metadata about which pact to verify and runs make test-contracts-provider-ci to verify and publish results.

Writing Consumer Tests

Consumer tests define uni-region's expectations when calling external APIs (like uni-identity). Tests are located in test/contracts/consumer/{provider}/.

Structure:

  • suite_test.go - Ginkgo test suite setup
  • {feature}_test.go - Consumer contract tests for specific features (e.g., rbac_test.go, allocations_test.go)

Basic Pattern:

  1. Test Setup:

    mockProvider, err := consumer.NewV2Pact(consumer.MockHTTPProviderConfig{
        Consumer: "uni-region",
        Provider: "uni-identity",
        PactDir:  "./pacts",
    })
    
  2. Define Interactions:

    err := mockProvider.
        AddInteraction().
        Given("organization exists with global read permission").
        UponReceiving("a request to get organization ACL").
        WithRequest(http.MethodGet, "/api/v1/organizations/test-org/acl").
        WillRespondWith(http.StatusOK, func(b *consumer.V2ResponseBuilder) {
            b.JSONBody(matchers.StructMatcher{
                "scopes": matchers.EachLike(map[string]interface{}{
                    "name": matchers.String("global"),
                    // ... more fields
                }, 1),
            })
        }).
        ExecuteTest(nil, func(config consumer.MockServerConfig) error {
            // Execute actual API call here
            return nil
        })
    
  3. Test Organization:

    • Group related tests by feature (RBAC, allocations, etc.)
    • Use descriptive "Given", "UponReceiving" phrases
    • Test both success and error scenarios
    • Use Pact matchers for flexible matching

Example: See test/contracts/consumer/identity/ for complete examples of RBAC and allocation consumer tests.

Writing Provider Tests

Provider tests are located in test/contracts/provider/{consumer}/. Each consumer has:

  • verify_test.go - Main test setup and verification
  • states.go - State handlers for setting up test data
  • middleware.go - Test-specific middleware (e.g., mock ACL)

Basic Pattern:

  1. Test Structure (verify_test.go):

    • Uses Ginkgo/Gomega for BDD-style tests
    • Starts a test server in BeforeEach
    • Creates state handlers mapping Pact states to setup functions
    • Runs verification using provider.NewVerifier()
  2. State Handlers (states.go):

    • Implement parameterized state handlers that accept organization ID and other parameters
    • Use StateManager to create/cleanup Kubernetes resources
    • Follow the builder pattern for creating test resources (see RegionBuilder)
  3. Example State Handler:

    func (sm *StateManager) HandleOrganizationState(ctx context.Context, setup bool, params map[string]interface{}) error {
        orgID := getStringParam(params, ParamOrganizationID, "test-org")
        regionType := getStringParam(params, ParamRegionType, "")
    
        if setup {
            return sm.setupRegions(ctx, orgID, regionType)
        }
        return sm.cleanupAllRegions(ctx)
    }
    
  4. State Constants:

    • Define state names as constants (must match consumer contract states)
    • Use parameter keys for passing data to state handlers

See test/contracts/provider/compute/ for a complete example following this pattern.

Running All Contract Tests

Run both consumer and provider tests together:

make test-contracts

This is useful for ensuring both your consumer expectations and provider implementations are working correctly before publishing to the Pact Broker.

What Next?

The region controller is useless as it is, and requires a service provider to use it to yield a consumable resource. Try out the Kubernetes service.

Directories

Path Synopsis
cmd
pkg
apis/unikorn/v1alpha1
+k8s:deepcopy-gen=package,register +groupName=region.unikorn-cloud.org
+k8s:deepcopy-gen=package,register +groupName=region.unikorn-cloud.org
file-storage/provisioners/types/mock
Code generated by MockGen.
Code generated by MockGen.
handler/image/mock
Code generated by MockGen.
Code generated by MockGen.
handler/server/mock
Code generated by MockGen.
Code generated by MockGen.
handler/storage/mock
Code generated by MockGen.
Code generated by MockGen.
openapi
Package openapi provides primitives to interact with the openapi HTTP API.
Package openapi provides primitives to interact with the openapi HTTP API.
providers/internal/openstack/mock
Code generated by MockGen.
Code generated by MockGen.
test
api
api/scripts command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL