index.ts
Overview
This file serves as the Pulumi deployment entry point responsible for provisioning and configuring a Kubernetes cluster on Amazon EKS tailored for the ShapeShift Unchained platform. It orchestrates the following key operations:
EKS Cluster Provisioning: Uses the
EKSClusterLauncherutility to create an EKS cluster with parameters defined in Pulumi configuration.Namespace Management: Creates Kubernetes namespaces including a default namespace and environment-specific namespaces.
Docker Image Automation: Optionally builds and pushes Docker images to a configured Docker registry.
IPFS Cluster Deployment: Deploys the IPFS (InterPlanetary File System) cluster for decentralized file storage within the Kubernetes cluster.
Output Generation: Exposes important deployment outputs such as kubeconfig, namespaces, and domain information for use in downstream processes.
This file tightly integrates infrastructure provisioning with application deployment automation, enabling a scalable and secure blockchain service platform.
Detailed Explanation
Imports and Dependencies
Pulumi libraries: Core Pulumi SDK and Kubernetes provider.
EKSClusterLauncher: Utility to create EKS clusters with rich configuration.
BaseConfig: Base configuration interface imported from the project.
buildAndPushDockerImages: Utility to build and push Docker images.
deployIpfs: Function that deploys the IPFS cluster into Kubernetes.
Interface: Config
interface Config extends BaseConfig {
cluster: 'eks'
eks: Omit<EKSClusterLauncherArgs, 'rootDomainName'>
}
Extends a base configuration interface with cluster-specific settings.
Defines an
eksproperty that contains all EKS cluster launch parameters exceptrootDomainName(which is provided separately).The
clusterproperty explicitly sets the cluster type to'eks'.
Configuration Loading and Validation
const config = (() => {
try {
return new pulumi.Config('unchained').requireObject<Config>('common')
} catch (e) {
throw new pulumi.RunError(
`Could not find required configuration file. \n\tDid you copy the Pulumi.sample.yaml file to Pulumi.${pulumi.getStack()}.yaml and update the necessary configuration?`
)
}
})()
Loads the Pulumi configuration object under the namespace
'unchained'and key'common'.Throws a
RunErrorwith helpful instructions if the configuration file is missing.Immediately invoked function expression (IIFE) used to load config synchronously at module load time.
Required Configuration Validation
const missingRequiredConfig: Array<string> = []
if (!config.rootDomainName) missingRequiredConfig.push('rootDomainName')
if (!config.eks.nodeGroups) missingRequiredConfig.push('eks.nodeGroups')
if (missingRequiredConfig.length) {
throw new pulumi.RunError(
`Missing the following configuration values from Pulumi.${pulumi.getStack()}.yaml: ${missingRequiredConfig.join(', ')}`
)
}
Checks for presence of critical configuration values:
rootDomainNameandeks.nodeGroups.Throws an error if any required config values are missing, preventing deployment continuation.
Type Alias: Outputs
type Outputs = Record<string, any>
A generic dictionary type to store various outputs from the deployment.
Used to collect and return deployment artifacts such as kubeconfig and namespaces.
Main Exported Async Function
export = async (): Promise<Outputs> => {
...
}
Pulumi requires the entry point to export an async function that returns a promise resolving to deployment outputs.
This function contains the core deployment logic.
Step-by-Step Deployment Logic
Define Names:
const name = 'unchained' const defaultNamespace = 'unchained' const outputs: Outputs = {}Sets standard names for cluster and namespaces.
Initializes the outputs object.
Enforce
rootDomainName:if (!config.rootDomainName) throw new Error('rootDomainName required')Create EKS Cluster:
const cluster = await EKSClusterLauncher.create(name, { allAZs: config.eks.allAZs, autoscaling: config.eks.autoscaling, cidrBlock: config.eks.cidrBlock, email: config.eks.email, nodeGroups: config.eks.nodeGroups, profile: config.eks.profile, region: config.eks.region, rootDomainName: config.rootDomainName, traefik: config.eks.traefik, volumeSize: config.eks.volumeSize, })Calls
EKSClusterLauncher.createwith all relevant config parameters.This abstracts the details of EKS cluster provisioning, including node groups, autoscaling, networking, and ingress (via Traefik).
Save kubeconfig to outputs:
outputs.kubeconfig = cluster.kubeconfigCreate Kubernetes Provider:
const provider = new Provider('kube-provider', { kubeconfig: cluster.kubeconfig })Creates a Pulumi Kubernetes provider instance that uses the cluster's kubeconfig.
This provider is used to create Kubernetes resources within the newly created cluster.
Build and Push Docker Images (optional):
if (config.dockerhub) { buildAndPushDockerImages(config.dockerhub, name) }If Docker Hub credentials/config are provided, triggers building and pushing of Docker images.
Ensures the latest container images are available for deployment within the cluster.
Prepare Namespaces:
const namespaces: Array<string> = [defaultNamespace] if (config.additionalEnvironments?.length) { config.additionalEnvironments.forEach((env) => namespaces.push(`${defaultNamespace}-${env}`)) }Initializes namespace list with the default namespace.
Adds additional environment-specific namespaces if configured.
Create Kubernetes Namespaces:
namespaces.forEach(async (namespace) => { new core.v1.Namespace(namespace, { metadata: { name: namespace } }, { provider }) })Iterates over namespaces and creates each one using the Kubernetes provider.
Namespaces logically isolate workloads and resources.
Deploy IPFS Cluster:
deployIpfs({ namespace: 'unchained-infra', domain: config.rootDomainName, additionalDomain: process.env.ADDITIONAL_ROOT_DOMAIN_NAME, provider, })Deploys the IPFS cluster into the
'unchained-infra'namespace.Passes domain names and Kubernetes provider to the deployment function.
IPFS provides decentralized file storage capabilities as part of the infrastructure.
Set Outputs:
outputs.cluster = config.cluster outputs.dockerhub = config.dockerhub outputs.rootDomainName = config.rootDomainName outputs.namespaces = namespaces outputs.defaultNamespace = defaultNamespaceExposes key configuration and deployment data as outputs.
Return Outputs:
return outputs
Usage Example
To deploy the cluster using this file, use Pulumi CLI commands:
pulumi stack init dev
pulumi config set --stack dev unchained:common <path_to_config>
pulumi up --stack dev
This will trigger the provisioning of the EKS cluster, creation of namespaces, optional Docker image processing, and IPFS deployment.
Important Implementation Details
Configuration Validation: The file performs early validation of required configuration to avoid runtime errors during deployment.
Asynchronous Namespace Creation: Namespaces are created asynchronously in a
forEach. While this triggers creation concurrently, Pulumi manages resource dependencies internally.Decoupled IPFS Deployment: The IPFS deployment logic is abstracted into a separate module (
deployIpfs), improving modularity and separation of concerns.Docker Image Automation: Conditional build-and-push simplifies CI/CD integration by packaging application images during deployment.
Pulumi Provider Usage: By creating a Kubernetes provider with the new cluster's kubeconfig, all subsequent Kubernetes resources are correctly targeted to the freshly provisioned cluster.
Interaction with Other Parts of the System
Configuration (
BaseConfig): This file relies on a base configuration structure shared across the project.EKSClusterLauncher: Abstracts EKS cluster creation, allowing this file to focus on orchestration rather than low-level AWS details.Docker Utilities: The
buildAndPushDockerImagesfunction handles container image lifecycle management integrated into this deployment.IPFS Module: The
deployIpfsfunction is key to adding decentralized storage, deployed as part of this cluster setup.Pulumi Stack Configuration: This file depends on Pulumi stack configs (
Pulumi.<stack>.yaml) for environment-specific parameters.
Mermaid Diagram: Flowchart of Main Functions and Workflow
flowchart TD
A[Load & Validate Config] --> B[Create EKS Cluster via EKSClusterLauncher]
B --> C[Create Kubernetes Provider with kubeconfig]
C --> D{Is DockerHub Configured?}
D -- Yes --> E[Build and Push Docker Images]
D -- No --> F[Skip Docker Build/Push]
E --> F
F --> G[Create Kubernetes Namespaces]
G --> H[Deploy IPFS Cluster in 'unchained-infra' Namespace]
H --> I[Gather Outputs]
I --> J[Return Deployment Outputs]
Summary
This [index.ts](/projects/291/69091) file is the Pulumi deployment orchestrator that automates provisioning an EKS cluster, setting up Kubernetes namespaces, optionally building and pushing Docker images, and deploying an IPFS cluster for decentralized storage. It validates configuration, leverages modular utilities, and exposes key outputs for integration with other deployment components. The file is central to bootstrapping the infrastructure platform for ShapeShift Unchained’s blockchain services.