orchestration

package
v0.3.8-beta Latest Latest
Warning

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

Go to latest
Published: Aug 30, 2025 License: GPL-3.0 Imports: 26 Imported by: 0

README

Cloud Orchestration Package

The orchestration package provides the top-level coordination logic for deploying and managing an entire microservice architecture on Google Cloud. It integrates the servicemanager, iam, and deployment packages into a cohesive, phase-based workflow.

Overview

This package implements a powerful and scalable architectural pattern centered around a Service Director. Instead of running all infrastructure and deployment logic from a local machine or a single CI/CD job, this package first deploys a central "Service Director" application into your cloud environment. This director then acts as a remote agent, receiving commands via Pub/Sub to manage the lifecycle of other services and resources.

This decoupled, event-driven approach provides enhanced security, scalability, and resilience against transient failures.

The Conductor Workflow

The Conductor is the main, user-facing entry point. It executes a multi-phase workflow to stand up an entire environment. The workflow is designed to be efficient by running long-running tasks in parallel and robust by explicitly waiting for cloud resource propagation.

The standard, end-to-end workflow is:

  1. Phase 1: Setup IAM: The local Conductor creates all necessary service account identities (for both the Service Director and the applications). It then enters a polling loop to wait for these new accounts to propagate and become visible across all of Google Cloud's systems. This is a critical prerequisite step.

  2. Phase 2: Parallel Build & Remote Setup: The Conductor starts two long-running operations at the same time:

    • Task A (Local Build): It builds all the container images for the dataflow applications.
    • Task B (Remote Setup): It deploys the ServiceDirector application to Cloud Run. Once the director is healthy, the Conductor commands it to create all necessary cloud resources (e.g., Pub/Sub topics) and apply the IAM policies that link the application service accounts to those resources.
  3. Phase 3: Verify IAM Policy Propagation: After the ServiceDirector signals that its work is complete, the Conductor enters another polling loop. This time, it waits for the IAM policy bindings (applied by the remote director) to become globally consistent and visible.

  4. Phase 4: Final Deployment: Once the container images from Task A are ready and the IAM policies from Phase 3 are verified, the Conductor performs the final, quick step of deploying the application services using their pre-built images.

Key Components

  • Conductor: The highest-level orchestrator. It manages the sequence of deployment phases, including the parallel execution of builds and remote setup. Its behavior is controlled by ConductorOptions, which allow phases to be skipped for partial or targeted deployments.

  • Orchestrator: A specialized "worker" component used by the Conductor. It handles the practical tasks of deploying services (using the deployment package) and managing the event-driven Pub/Sub communication with the deployed ServiceDirector.

  • IAMOrchestrator: Another specialized "worker" dedicated to IAM. Its responsibilities are now focused on the identity lifecycle: creating service accounts, managing their project-level roles, and verifying the propagation of both identities and policies.

Testing Strategy

The orchestration package uses a two-tiered testing strategy to ensure correctness and stability.

1. Emulator-Based Integration Test (orchestrator_integration_test.go)

This test is designed to be fast and run without a real cloud connection.

  • Purpose: To verify the core command-and-reply communication loop between the Orchestrator and the ServiceDirector.
  • Mechanism: It runs the ServiceDirector as an in-memory goroutine within the test itself. All communication happens via a Pub/Sub emulator. All IAM and service management clients are replaced with mocks, isolating the test to its core responsibility.
2. Cloud E2E Integration Test (orchestrator_dataflow_test.go)

This is the comprehensive, end-to-end test that validates the entire Conductor workflow against real Google Cloud services.

  • Purpose: To prove that the Conductor can successfully orchestrate a full, parallel build-and-deploy of a realistic multi-service application.
  • Mechanism:
    • It uses a service account pool (TestIAMClient) to manage identities efficiently and avoid creating new service accounts on every test run.
    • The test hydrates its architecture configuration at runtime, injecting the real email addresses of the pooled service accounts before the deployment begins.
    • It builds and deploys a real ServiceDirector application from a test-specific main package, which is configured to use a self-contained Go module. This module requires a stable, versioned release of the main repository, ensuring the build is isolated and reproducible.

Documentation

Index

Constants

View Source
const ServiceDirector = "service-director"

Variables

This section is empty.

Functions

func CleanStaleConfigs

func CleanStaleConfigs(arch *servicemanager.MicroserviceArchitecture, logger zerolog.Logger) error

CleanStaleConfigs removes any leftover resources.yaml or services.yaml files from the source directories of all services defined in the architecture. This ensures every deployment starts from a clean state.

func GenerateAndWriteServiceSpecificConfigs

func GenerateAndWriteServiceSpecificConfigs(arch *servicemanager.MicroserviceArchitecture, logger zerolog.Logger) error

REFACTOR: This new function handles the copying of service-specific templates. GenerateAndWriteServiceSpecificConfigs iterates through all services and copies their defined configuration templates into their respective build directories.

func PrepareServiceDirectorSource

func PrepareServiceDirectorSource(arch *servicemanager.MicroserviceArchitecture, logger zerolog.Logger) error

PrepareServiceDirectorSource marshals the arch to YAML and copies the resulting services.yaml file into the ServiceDirector's source code directory so it can be included in the build.

func ReadResourceMappings

func ReadResourceMappings(spec *servicemanager.CloudResourcesSpec) map[string]string

ReadResourceMappings extract the lookup names from a CloudResourcesSpec.

func WriteServiceConfigFiles

func WriteServiceConfigFiles(
	filesToWrite []ServiceConfig,
	logger zerolog.Logger,
) error

WriteServiceConfigFiles writes the generated configurations to their respective service directories.

Types

type Command

type Command struct {
	Instruction CommandInstruction `json:"instruction"`
	Payload     json.RawMessage    `json:"payload"`
}

type CommandInstruction

type CommandInstruction string
const (
	Setup          CommandInstruction = "dataflow-setup"
	Teardown       CommandInstruction = "teardown"
	SetupDependent CommandInstruction = "dependent-resource-setup"
)

type CompletionEvent

type CompletionEvent struct {
	Status       CompletionStatus             `json:"status"`
	Value        string                       `json:"value"`
	ErrorMessage string                       `json:"error_message,omitempty"`
	AppliedIAM   map[string]iam.PolicyBinding `json:"applied_iam,omitempty"`
}

type CompletionStatus

type CompletionStatus string
const (
	ServiceDirectorReady CompletionStatus = "setup_complete"
	DataflowComplete     CompletionStatus = "dataflow_complete"
)

type Conductor

type Conductor struct {
	// contains filtered or unexported fields
}

Conductor manages the high-level orchestration of a full microservice architecture deployment.

func NewConductor

NewConductor creates and initializes a new Conductor with specific options.

func (*Conductor) GenerateIAMPlan

func (c *Conductor) GenerateIAMPlan(iamPlanYAML string) error

GenerateIAMPlan creates the full IAM plan and writes it to a YAML file.

func (*Conductor) Preflight

func (c *Conductor) Preflight(ctx context.Context) error

Preflight runs permission checks for the identity executing the Conductor.

func (*Conductor) Run

func (c *Conductor) Run(ctx context.Context) error

Run executes the full, multi-phase orchestration workflow in the correct sequence.

func (*Conductor) Teardown

func (c *Conductor) Teardown(ctx context.Context) error

Teardown cleans up all resources and services created by the Conductor.

type ConductorOptions

type ConductorOptions struct {
	CheckPrerequisites      bool
	PreflightServiceConfigs bool
	SetupIAM                bool
	BuildAndDeployServices  bool
	TriggerRemoteSetup      bool
	VerifyDataflowIAM       bool
	DirectorURLOverride     string
	SAPollTimeout           time.Duration
	PolicyPollTimeout       time.Duration
}

ConductorOptions provides flags and configuration to control the orchestration workflow.

type DependentSetupPayload

type DependentSetupPayload struct {
	DataflowName string            `json:"dataflow_name"`
	ServiceURLs  map[string]string `json:"service_urls"`
}

DependentSetupPayload contains the dataflow name and the map of deployed service URLs.

type DeploymentManager

type DeploymentManager struct {
	// contains filtered or unexported fields
}

DeploymentManager handles the logic of building and deploying containerized services. It has no knowledge of remote orchestration or Pub/Sub.

func NewDeploymentManager

NewDeploymentManager creates a new manager for local build and deploy operations.

func (*DeploymentManager) BuildAllServices

func (m *DeploymentManager) BuildAllServices(ctx context.Context) (map[string]string, error)

BuildAllServices builds all services defined in the architecture in parallel. It returns a map of service names to their final container image URIs.

func (*DeploymentManager) DeployApplicationServices

func (m *DeploymentManager) DeployApplicationServices(ctx context.Context, dataflowName string, saEmails map[string]string, builtImages map[string]string, directorURL string) (map[string]string, error)

DeployApplicationServices deploys all services for a given dataflow in parallel.

type EmbeddedArchitectureLoader

type EmbeddedArchitectureLoader struct {
	// contains filtered or unexported fields
}

EmbeddedArchitectureLoader is a simple implementation of the servicemanager.ArchitectureIO interface that works with a pre-existing, in-memory MicroserviceArchitecture struct. This is primarily useful for scenarios where the architecture is defined statically, for example, from a `go:embed` directive.

func NewEmbeddedArchitectureLoader

func NewEmbeddedArchitectureLoader(arch *servicemanager.MicroserviceArchitecture) *EmbeddedArchitectureLoader

NewEmbeddedArchitectureLoader creates a new loader that serves a pre-parsed architecture.

func (*EmbeddedArchitectureLoader) LoadArchitecture

LoadArchitecture simply returns the pre-parsed architecture from the embedded data.

func (*EmbeddedArchitectureLoader) LoadResourceGroup

LoadResourceGroup is not implemented for the embedded loader.

func (*EmbeddedArchitectureLoader) WriteProvisionedResources

WriteProvisionedResources is not implemented for the embedded loader.

type FoundationalSetupPayload

type FoundationalSetupPayload struct {
	DataflowName string `json:"dataflow_name"`
}

FoundationalSetupPayload is the payload for the initial 'dataflow-setup' command.

type IAMOrchestrator

type IAMOrchestrator struct {
	// contains filtered or unexported fields
}

IAMOrchestrator is responsible for the high-level orchestration of all IAM policies for an architecture.

func NewIAMOrchestrator

func NewIAMOrchestrator(ctx context.Context, arch *servicemanager.MicroserviceArchitecture, logger zerolog.Logger, clientOpts ...option.ClientOption) (*IAMOrchestrator, error)

NewIAMOrchestrator creates a new orchestrator focused solely on IAM.

func (*IAMOrchestrator) ApplyProjectLevelIAMForDataflow

func (o *IAMOrchestrator) ApplyProjectLevelIAMForDataflow(ctx context.Context, dataflowName string, saEmails map[string]string) error

ApplyProjectLevelIAMForDataflow plans and applies all project-level IAM roles for a dataflow's services. Note: This function only applies the roles; it does not wait for them to propagate.

func (*IAMOrchestrator) EnsureDataflowSAsExist

func (o *IAMOrchestrator) EnsureDataflowSAsExist(ctx context.Context, dataflowName string) (map[string]string, error)

EnsureDataflowSAsExist creates the necessary service accounts for a dataflow.

func (*IAMOrchestrator) GetProjectNumber

func (o *IAMOrchestrator) GetProjectNumber(ctx context.Context, projectID string) (string, error)

GetProjectNumber retrieves the numeric ID for a given project ID string.

func (*IAMOrchestrator) PollForSAExistence

func (o *IAMOrchestrator) PollForSAExistence(ctx context.Context, accountEmail string, timeout time.Duration) error

PollForSAExistence waits for a newly created service account to propagate throughout Google Cloud.

func (*IAMOrchestrator) PreflightChecks

func (o *IAMOrchestrator) PreflightChecks(ctx context.Context) error

PreflightChecks verifies that the identity running the Conductor has the minimum necessary permissions to perform its verification steps.

func (*IAMOrchestrator) SetupServiceDirectorIAM

func (o *IAMOrchestrator) SetupServiceDirectorIAM(ctx context.Context) (map[string]string, error)

SetupServiceDirectorIAM ensures the ServiceDirector's SA exists and grants it necessary project-level roles.

func (*IAMOrchestrator) Teardown

func (o *IAMOrchestrator) Teardown(ctx context.Context) error

Teardown cleans up service accounts created during the orchestration run.

func (*IAMOrchestrator) VerifyProjectLevelIAMForDataflow

func (o *IAMOrchestrator) VerifyProjectLevelIAMForDataflow(ctx context.Context, dataflowName string, saEmails map[string]string, verificationTimeout time.Duration) error

VerifyProjectLevelIAMForDataflow polls project-level IAM policies until they reflect the planned state.

func (*IAMOrchestrator) VerifyResourceLevelIAMForDataflow

func (o *IAMOrchestrator) VerifyResourceLevelIAMForDataflow(ctx context.Context, dataflowName string, saEmails map[string]string, verificationTimeout time.Duration) error

VerifyResourceLevelIAMForDataflow polls resource-level IAM policies until they reflect the planned state.

func (*IAMOrchestrator) VerifyServiceDirectorIAM

func (o *IAMOrchestrator) VerifyServiceDirectorIAM(ctx context.Context, saEmails map[string]string, verificationTimeout time.Duration) error

VerifyServiceDirectorIAM polls the project-level IAM policies for the ServiceDirector until they are effective.

type PlanEntry

type PlanEntry struct {
	Source  string         `yaml:"source"`
	Binding iam.IAMBinding `yaml:"binding"`
	Reason  string         `yaml:"reason"`
}

PlanEntry is a richer struct for the IAM plan file, including the reason for the binding.

type PreflightValidator

type PreflightValidator struct {
	// contains filtered or unexported fields
}

PreflightValidator runs local tests against service source code to validate generated configuration files before a build or deployment is attempted.

func NewPreflightValidator

func NewPreflightValidator(arch *servicemanager.MicroserviceArchitecture, logger zerolog.Logger) *PreflightValidator

NewPreflightValidator creates a new validator.

func (*PreflightValidator) GenerateTestEnvForService

func (v *PreflightValidator) GenerateTestEnvForService(serviceName string) []string

GenerateTestEnvForService inspects the hydrated architecture to find all resources linked to a specific service and generates the environment variables for its pre-flight test.

func (*PreflightValidator) Run

func (v *PreflightValidator) Run() error

Run executes `go test` in each service's directory. It dynamically determines the expected resource names from the architecture and passes them to the test process as environment variables.

type RemoteDirectorClient

type RemoteDirectorClient struct {
	// contains filtered or unexported fields
}

RemoteDirectorClient manages all asynchronous communication with the remote ServiceDirector.

func NewRemoteDirectorClient

func NewRemoteDirectorClient(ctx context.Context, arch *servicemanager.MicroserviceArchitecture, logger zerolog.Logger, clientOpts ...option.ClientOption) (*RemoteDirectorClient, error)

NewRemoteDirectorClient creates a new client for communicating with the ServiceDirector.

func (*RemoteDirectorClient) Teardown

func (c *RemoteDirectorClient) Teardown(ctx context.Context) error

Teardown cleans up the client's Pub/Sub resources.

func (*RemoteDirectorClient) TriggerDependentSetup

func (c *RemoteDirectorClient) TriggerDependentSetup(ctx context.Context, dataflowName string, serviceURLs map[string]string) (CompletionEvent, error)

TriggerDependentSetup sends the command to set up dependent resources and waits for completion.

func (*RemoteDirectorClient) TriggerFoundationalSetup

func (c *RemoteDirectorClient) TriggerFoundationalSetup(ctx context.Context, dataflowName string) (CompletionEvent, error)

TriggerFoundationalSetup sends the command to set up foundational resources and waits for completion.

type ServiceConfig

type ServiceConfig struct {
	ServiceName string
	FilePath    string
	Config      servicemanager.CloudResourcesSpec
}

func GenerateServiceConfigs

func GenerateServiceConfigs(arch *servicemanager.MicroserviceArchitecture) ([]ServiceConfig, error)

GenerateServiceConfigs creates service-specific YAML configs based on the architecture.

Jump to

Keyboard shortcuts

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