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:

This file tightly integrates infrastructure provisioning with application deployment automation, enabling a scalable and secure blockchain service platform.


Detailed Explanation

Imports and Dependencies


Interface: Config

interface Config extends BaseConfig {
  cluster: 'eks'
  eks: Omit<EKSClusterLauncherArgs, 'rootDomainName'>
}

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?`
    )
  }
})()

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(', ')}`
  )
}

Type Alias: Outputs

type Outputs = Record<string, any>

Main Exported Async Function

export = async (): Promise<Outputs> => {
  ...
}

Step-by-Step Deployment Logic

  1. Define Names:

    const name = 'unchained'
    const defaultNamespace = 'unchained'
    const outputs: Outputs = {}
    
    • Sets standard names for cluster and namespaces.

    • Initializes the outputs object.

  2. Enforce rootDomainName:

    if (!config.rootDomainName) throw new Error('rootDomainName required')
    
  3. 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.create with all relevant config parameters.

    • This abstracts the details of EKS cluster provisioning, including node groups, autoscaling, networking, and ingress (via Traefik).

  4. Save kubeconfig to outputs:

    outputs.kubeconfig = cluster.kubeconfig
    
  5. Create 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.

  6. 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.

  7. 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.

  8. 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.

  9. 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.

  10. Set Outputs:

    outputs.cluster = config.cluster
    outputs.dockerhub = config.dockerhub
    outputs.rootDomainName = config.rootDomainName
    outputs.namespaces = namespaces
    outputs.defaultNamespace = defaultNamespace
    
    • Exposes key configuration and deployment data as outputs.

  11. 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


Interaction with Other Parts of the System


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.