UNPKG

@starship-ci/generator

Version:

Kubernetes manifest generator for Starship deployments

300 lines (299 loc) 10.5 kB
import * as fs from 'fs'; import * as path from 'path'; import { DefaultsManager } from '../../../defaults'; import * as helpers from '../../../helpers'; /** * Keys ConfigMap generator * Handles the global keys.json configuration */ export class KeysConfigMapGenerator { config; projectRoot; constructor(config, projectRoot = process.cwd()) { this.config = config; this.projectRoot = projectRoot; } generate() { const keysFilePath = path.join(this.projectRoot, 'configs', 'keys.json'); if (!fs.existsSync(keysFilePath)) { console.warn(`Warning: 'configs/keys.json' not found. Skipping Keys ConfigMap.`); return []; } try { const keysFileContent = fs.readFileSync(keysFilePath, 'utf-8'); return [ { apiVersion: 'v1', kind: 'ConfigMap', metadata: { name: 'keys', labels: { ...helpers.getCommonLabels(this.config), 'app.kubernetes.io/component': 'configmap', 'app.kubernetes.io/part-of': 'global', 'app.kubernetes.io/name': 'keys' } }, data: { 'keys.json': keysFileContent } } ]; } catch (error) { console.warn(`Warning: Could not read 'configs/keys.json'. Error: ${error.message}. Skipping.`); return []; } } } /** * Global Scripts ConfigMap generator * Handles the shared scripts from scripts/default directory */ export class GlobalScriptsConfigMapGenerator { config; projectRoot; constructor(config, projectRoot = process.cwd()) { this.config = config; this.projectRoot = projectRoot; } generate() { const scriptsDir = path.join(this.projectRoot, 'scripts', 'default'); if (!fs.existsSync(scriptsDir)) { return []; } const data = {}; try { const scriptFiles = fs .readdirSync(scriptsDir) .filter((file) => file.endsWith('.sh')); if (scriptFiles.length === 0) { return []; } scriptFiles.forEach((fileName) => { const filePath = path.join(scriptsDir, fileName); data[fileName] = fs.readFileSync(filePath, 'utf-8'); }); } catch (error) { console.warn(`Warning: Could not read global scripts directory. Error: ${error.message}. Skipping.`); return []; } return [ { apiVersion: 'v1', kind: 'ConfigMap', metadata: { name: 'setup-scripts', labels: { ...helpers.getCommonLabels(this.config), 'app.kubernetes.io/component': 'configmap', 'app.kubernetes.io/part-of': 'global', 'app.kubernetes.io/name': 'setup-scripts' } }, data } ]; } } /** * Chain-specific setup scripts ConfigMap generator */ export class SetupScriptsConfigMapGenerator { config; chain; scriptManager; constructor(chain, config, scriptManager) { this.config = config; this.chain = chain; this.scriptManager = scriptManager; } generate() { const scripts = this.chain.scripts; if (!scripts || Object.keys(scripts).length === 0) { return []; } const data = {}; Object.entries(scripts).forEach(([key, script]) => { if (!script) return; const scriptName = script.name || `${key}.sh`; try { data[scriptName] = this.scriptManager.getScriptContent(script); } catch (error) { console.warn(`Warning: Could not load script ${scriptName}. Error: ${error.message}. Skipping.`); } }); if (Object.keys(data).length === 0) { return []; } return [ { apiVersion: 'v1', kind: 'ConfigMap', metadata: { name: `setup-scripts-${helpers.getHostname(this.chain)}`, labels: { ...helpers.getCommonLabels(this.config), 'app.kubernetes.io/component': 'chain', 'app.kubernetes.io/name': `setup-scripts-${helpers.getHostname(this.chain)}`, 'app.kubernetes.io/part-of': helpers.getChainId(this.chain), 'app.kubernetes.io/role': 'setup-scripts', 'starship.io/chain-name': this.chain.name, 'starship.io/chain-id': helpers.getChainId(this.chain) } }, data } ]; } } /** * Genesis patch ConfigMap generator */ export class GenesisPatchConfigMapGenerator { config; chain; constructor(chain, config) { this.config = config; this.chain = chain; } generate() { if (!this.chain.genesis) { return []; } return [ { apiVersion: 'v1', kind: 'ConfigMap', metadata: { name: `patch-${helpers.getHostname(this.chain)}`, labels: { ...helpers.getCommonLabels(this.config), 'app.kubernetes.io/component': 'chain', 'app.kubernetes.io/name': this.chain.name, 'app.kubernetes.io/part-of': helpers.getChainId(this.chain), 'app.kubernetes.io/role': 'genesis-patch', 'starship.io/chain-name': this.chain.name, 'starship.io/chain-id': helpers.getChainId(this.chain) } }, data: { 'genesis.json': JSON.stringify(this.chain.genesis, null, 2) } } ]; } } /** * ICS Consumer Proposal ConfigMap generator */ export class IcsConsumerProposalConfigMapGenerator { config; chain; defaultsManager; constructor(chain, config) { this.config = config; this.chain = chain; this.defaultsManager = new DefaultsManager(); } generate() { if (!this.chain.ics?.enabled || !this.chain.ics.provider) { return []; } const providerChain = this.config.chains.find((c) => c.id === this.chain.ics.provider); if (!providerChain) { console.warn(`Warning: ICS Provider chain '${this.chain.ics.provider}' not found. Skipping ICS proposal for '${this.chain.id}'.`); return []; } const processedProviderChain = this.defaultsManager.processChain(providerChain); const proposal = { title: `Add ${this.chain.name} consumer chain`, summary: `Add ${this.chain.name} consumer chain with id ${helpers.getChainId(this.chain)}`, chain_id: helpers.getChainId(this.chain), initial_height: { revision_height: 1, revision_number: 1 }, genesis_hash: 'd86d756e10118e66e6805e9cc476949da2e750098fcc7634fd0cc77f57a0b2b0', binary_hash: '376cdbd3a222a3d5c730c9637454cd4dd925e2f9e2e0d0f3702fc922928583f1', spawn_time: '2023-02-28T20:40:00.000000Z', unbonding_period: 294000000000, ccv_timeout_period: 259920000000, transfer_timeout_period: 18000000000, consumer_redistribution_fraction: '0.75', blocks_per_distribution_transmission: 10, historical_entries: 100, distribution_transmission_channel: '', top_N: 95, validators_power_cap: 0, validator_set_cap: 0, allowlist: [], denylist: [], deposit: `10000${processedProviderChain.denom}` }; return [ { apiVersion: 'v1', kind: 'ConfigMap', metadata: { name: `consumer-proposal-${helpers.getHostname(this.chain)}`, labels: { ...helpers.getCommonLabels(this.config), 'app.kubernetes.io/component': 'chain', 'app.kubernetes.io/name': this.chain.name, 'app.kubernetes.io/part-of': helpers.getChainId(this.chain), 'app.kubernetes.io/role': 'ics-proposal', 'starship.io/chain-name': this.chain.name, 'starship.io/chain-id': helpers.getChainId(this.chain) } }, data: { 'proposal.json': JSON.stringify(proposal, null, 2) } } ]; } } /** * Main ConfigMap generator orchestrator for Cosmos chains */ export class CosmosConfigMapGenerator { config; chain; scriptManager; generators; constructor(chain, config, scriptManager) { this.config = config; this.chain = chain; this.scriptManager = scriptManager; this.generators = [ new SetupScriptsConfigMapGenerator(this.chain, this.config, this.scriptManager), new GenesisPatchConfigMapGenerator(this.chain, this.config), new IcsConsumerProposalConfigMapGenerator(this.chain, this.config) ]; } generate() { return this.generators.flatMap((generator) => generator.generate()); } } /** * Global ConfigMap generator orchestrator * Handles ConfigMaps that are shared across all chains */ export class GlobalConfigMapGenerator { config; generators; constructor(config, projectRoot) { this.config = config; this.generators = [ new KeysConfigMapGenerator(this.config, projectRoot), new GlobalScriptsConfigMapGenerator(this.config, projectRoot) ]; } generate() { return this.generators.flatMap((generator) => generator.generate()); } }