Kosko Framework

repository·master·Indexed 18 days ago

https://github.com/tommy351/kosko

A framework for organizing Kubernetes manifests using TypeScript or JavaScript. Kosko provides programmatic management of Kubernetes configurations with features for environment management, OpenAPI validation, code reuse, and linting to detect configuration issues. It includes the create-kosko CLI for bootstrapping applications, specialized templates like @kosko/template-deployed-service and @kosko/template-environment, and plugins such as @kosko/plugin-set-metadata.

Tokens
71.5K
Snippets
320
Records
394
Agent score
62%

What's inside Kosko

  1. Overview of Kosko

    master

    Kosko is a tool designed to help you organize Kubernetes manifests using TypeScript (or any language that compiles to JavaScript). It provides a programmatic way to manage Kubernetes configurations with several key capabilities:

    • Environment Management: Handle multiple environments within your configuration logic.
    • Validation: Validate manifests against Kubernetes OpenAPI definitions.
    • Code Reuse: Leverage TypeScript variables and functions to share logic across different components.
    • Linter/Analysis: Detect common Kubernetes configuration issues, such as missing namespaces, invalid pod selectors, or missing container probes.
  2. Configure environment-specific plugins

    master

    Kosko allows you to define plugins that only run within specific environments (e.g., dev). You can do this by adding a plugins array under the specific environment key in kosko.toml (e.g., [[environments.dev.plugins]]).

    Note on execution order: If a plugin is defined in both the global [[plugins]] section and an environment-specific section, it will be executed twice—once for the global scope and once for the environment scope.

    # Global plugin
    [[plugins]]
    name = "example"
    
    # Environment-specific plugin
    [[environments.dev.plugins]]
    name = "example"
  3. Define and access Component Variables

    master

    Component variables are specific to a single component and are defined in environments/<env>/<component>.js.

    To retrieve them, use the component() function from @kosko/env. This function returns a deep merge of the global variables for that environment and the specific component's variables. If a variable is needed by multiple components, it should be moved to the global configuration instead.

    // environments/prod/nginx.js
    export default {
      replicas: 3,
      imageVersion: "stable"
    };
    import env from "@kosko/env";
    
    const params = env.component("nginx");
    // Returns a deep merge of global and component variables:
    // {
    //   imageRegistry: "gcr.io/acme-prod",
    //   namespace: "prod",
    //   replicas: 3,
    //   imageVersion: "stable"
    // }
  4. Use nested manifests with arrays and functions

    master

    As of Kosko v1.0, arrays and functions returned within components are automatically flattened. This allows you to treat a collection of resources (like a Kubernetes Deployment and Service) as a single resource when composing components, rather than manually spreading them into an array.

    function createDatabase() {
      return [new Deployment(), new Service()];
    }
    
    // In v1.0, you can return the function call directly in the array
    module.exports = [new Deployment(), createDatabase()];
  5. How Kosko validation works

    master
    When running kosko generate or kosko validate, Kosko automatically invokes the validate() method on every exported manifest. This process checks for type correctness and field formatting. If a manifest fails validation, Kosko throws an error detailing the specific failure and the exact location of the invalid manifest within your project structure.
  6. Use Iterables in components

    master

    Kosko 3.0 supports the JavaScript iterable protocol. This allows you to export components using Set, Map, or generator functions instead of just arrays or single objects.

    // Using a Set
    export default new Set([new Deployment(), new Service()]);
    
    // Using a Generator function
    function* gen() {
      yield new Deployment();
      yield new Service();
    }
  7. Define and access Global Variables

    master

    Global variables are shared across all components in a specific environment. To define them, create an index.js file within your environment directory: environments/<env>/index.js.

    You can retrieve these variables using the global() function from the @kosko/env package.

    // environments/prod/index.js
    export default {
      imageRegistry: "gcr.io/acme-prod",
      namespace: "prod"
    };
    import env from "@kosko/env";
    
    const params = env.global();
    // Returns the object defined in environments/<env>/index.js
  8. How Kosko plugins work

    master

    A Kosko plugin is implemented as a factory function. This function receives a PluginContext and must return a Plugin object containing lifecycle hooks. These hooks are executed during the manifest generation process.

    Basic structure of a plugin:

    import type { Plugin, PluginContext } from "@kosko/plugin";
    
    export default function (ctx: PluginContext): Plugin {
      return {};
    }
    import type { Plugin, PluginContext } from "@kosko/plugin";
    
    export default function (ctx: PluginContext): Plugin {
      return {};
    }
  9. Initialize Environment in mixed CJS/ESM projects

    master

    In Node.js, ESM and CommonJS (CJS) have separate caches. If your project uses both, they will have two isolated instances of Environment. You must initialize them separately. It is highly recommended to stick to one module type.

    function setupEnv(env) {
      env.env = "dev";
      env.cwd = __dirname;
    }
    
    // CommonJS
    setupEnv(require("@kosko/env"));
    
    // ESM
    setupEnv((await import("@kosko/env")).default);