Skip to main content

REST API

Infra Operator AWS can be run as a REST API server, allowing you to manage AWS infrastructure via HTTP requests.

Starting the Server

Command:

# Start on default port (8080)
./infra-operator serve

# Custom port
./infra-operator serve --port 3000

# With API key authentication
./infra-operator serve --api-keys "my-secret-key"

# With LocalStack endpoint
./infra-operator serve --endpoint http://localhost:4566

Available Flags

FlagDescriptionDefault
--port, -pServer port8080
--hostServer host0.0.0.0
--state-dirState directory~/.infra-operator/state
--regionAWS regionus-east-1
--endpointAWS endpoint (LocalStack)-
--api-keysAPI keys (comma-separated)-
--cors-originsAllowed CORS origins*

Authentication

When --api-keys is provided, all requests must include authentication:

# Via X-API-Key header
curl -H "X-API-Key: my-key" http://localhost:8080/api/v1/resources

# Via Bearer token
curl -H "Authorization: Bearer my-key" http://localhost:8080/api/v1/resources

Endpoints

Health Check

Command:

GET /health

Response:

{
"success": true,
"data": {
"status": "healthy",
"version": "1.0.1",
"timestamp": "2025-11-26T12:00:00Z"
}
}

Plan (Execution Plan)

Generates a plan showing what would be created, updated, or deleted.

Command:

POST /api/v1/plan
Content-Type: application/yaml

Request (YAML):

apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: VPC
metadata:
name: my-vpc
spec:
cidrBlock: "10.0.0.0/16"

Request (JSON):

{
"resources": [
{
"apiVersion": "aws-infra-operator.runner.codes/v1alpha1",
"kind": "VPC",
"metadata": { "name": "my-vpc" },
"spec": { "cidrBlock": "10.0.0.0/16" }
}
]
}

Response:

{
"success": true,
"data": {
"toCreate": [
{ "kind": "VPC", "name": "my-vpc", "action": "create" }
],
"toUpdate": [],
"toDelete": [],
"noChange": [],
"summary": {
"create": 1,
"update": 0,
"delete": 0,
"noChange": 0
}
}
}

Apply (Apply Resources)

Creates or updates resources in AWS.

Command:

POST /api/v1/apply
Content-Type: application/yaml

Request:

apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: ComputeStack
metadata:
name: my-environment
spec:
vpcCIDR: "10.100.0.0/16"
bastionInstance:
enabled: true
instanceType: t3.micro

Response:

{
"success": true,
"data": {
"created": [
{
"kind": "ComputeStack",
"name": "my-environment",
"awsResources": {
"vpcId": "vpc-0abc123",
"publicSubnetId": "subnet-0def456",
"internetGatewayId": "igw-0ghi789"
}
}
],
"updated": [],
"failed": [],
"skipped": [],
"summary": {
"created": 1,
"updated": 0,
"failed": 0,
"skipped": 0
}
}
}

Delete (Delete Resources)

Removes resources from AWS.

Command:

DELETE /api/v1/resources
Content-Type: application/yaml

or

Command:

POST /api/v1/delete
Content-Type: application/yaml

Request:

apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: ComputeStack
metadata:
name: my-environment
spec:
vpcCIDR: "10.100.0.0/16"

Response:

{
"success": true,
"data": {
"deleted": [
{ "kind": "ComputeStack", "name": "my-environment" }
],
"failed": [],
"skipped": [],
"summary": {
"deleted": 1,
"failed": 0,
"skipped": 0
}
}
}

Get (List Resources)

Lists resources from local state.

Command:

# All resources
GET /api/v1/resources

# By type
GET /api/v1/resources/VPC
GET /api/v1/resources/ComputeStack

# Shortcuts
GET /api/v1/vpcs
GET /api/v1/compute-stacks
GET /api/v1/ec2-instances

Response:

{
"success": true,
"data": {
"resources": [
{
"apiVersion": "aws-infra-operator.runner.codes/v1alpha1",
"kind": "VPC",
"name": "my-vpc",
"awsResources": {
"vpcId": "vpc-0abc123"
},
"status": {
"ready": true,
"state": "available"
},
"createdAt": "2025-11-26T12:00:00Z",
"updatedAt": "2025-11-26T12:00:00Z"
}
],
"count": 1
}
}

Practical Examples

1. Create Complete Infrastructure via API

Command:

# Create ComputeStack
curl -X POST http://localhost:8080/api/v1/apply \
-H "Content-Type: application/yaml" \
--data-binary @- << 'EOF'
apiVersion: aws-infra-operator.runner.codes/v1alpha1
kind: ComputeStack
metadata:
name: production
namespace: infra
spec:
vpcCIDR: "10.50.0.0/16"
bastionInstance:
enabled: true
instanceType: t3.micro
userData: |
#!/bin/bash
yum update -y
yum install -y docker
EOF

2. Integrate with CI/CD (GitLab/GitHub Actions)

Example:

# .gitlab-ci.yml
deploy:
script:
- |
curl -X POST $INFRA_API_URL/api/v1/apply \
-H "X-API-Key: $INFRA_API_KEY" \
-H "Content-Type: application/yaml" \
--data-binary @infrastructure.yaml

3. Automation Script

Command:

#!/bin/bash
API_URL="http://localhost:8080"

# Plan
echo "Generating plan..."
curl -s -X POST "$API_URL/api/v1/plan" \
-H "Content-Type: application/yaml" \
--data-binary @infra.yaml | jq .

# Confirm and apply
read -p "Apply? (y/n) " confirm
if [ "$confirm" = "y" ]; then
curl -s -X POST "$API_URL/api/v1/apply" \
-H "Content-Type: application/yaml" \
--data-binary @infra.yaml | jq .
fi

4. Python SDK

Example:

import requests
import yaml

API_URL = "http://localhost:8080"
API_KEY = "my-key"

def plan(resources):
resp = requests.post(
f"{API_URL}/api/v1/plan",
headers={
"X-API-Key": API_KEY,
"Content-Type": "application/yaml"
},
data=yaml.dump_all(resources)
)
return resp.json()

def apply(resources):
resp = requests.post(
f"{API_URL}/api/v1/apply",
headers={
"X-API-Key": API_KEY,
"Content-Type": "application/yaml"
},
data=yaml.dump_all(resources)
)
return resp.json()

# Usage
vpc = {
"apiVersion": "aws-infra-operator.runner.codes/v1alpha1",
"kind": "VPC",
"metadata": {"name": "my-vpc"},
"spec": {"cidrBlock": "10.0.0.0/16"}
}

result = plan([vpc])
print(f"Resources to create: {result['data']['summary']['create']}")

Response Structure

Success Response

JSON:

{
"success": true,
"data": { ... }
}

Error Response

JSON:

{
"success": false,
"error": {
"code": "INVALID_REQUEST",
"message": "Error description",
"details": "Additional details"
}
}

Error Codes

CodeDescription
INVALID_REQUESTMalformed request
NO_RESOURCESNo resources provided
UNAUTHORIZEDAPI key not provided
INVALID_API_KEYInvalid API key
PLAN_FAILEDError generating plan
APPLY_FAILEDError applying resources
DELETE_FAILEDError deleting resources
GET_FAILEDError listing resources
RATE_LIMITEDToo many requests
INTERNAL_ERRORInternal server error

Comparison: K8s vs CLI vs API

FeatureKubernetesCLIAPI
DependencyK8s ClusterNoneNone
AuthenticationRBACAWS CredentialsAPI Key + AWS
Stateetcd (CRDs)Local fileLocal file
Integrationkubectl, ArgoCDShell scriptsHTTP clients
Multi-tenantNamespacesDirectoriesAPI Keys
Use CaseGitOps, K8s-native IaCLocal automationCI/CD, SDKs

Troubleshooting

Server won't start

Command:

# Check if port is in use
lsof -i :8080

# Check logs
./infra-operator serve 2>&1 | tee server.log

AWS authentication error

Command:

# Verify credentials
aws sts get-caller-identity

# Use LocalStack for testing
./infra-operator serve --endpoint http://localhost:4566

CORS blocked

Command:

# Allow specific origins
./infra-operator serve --cors-origins "http://localhost:3000,https://myapp.com"

Next Steps