CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-kubernetes--client-node

Comprehensive Node.js client library for interacting with Kubernetes clusters with full API coverage and TypeScript support

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

utilities.mddocs/

Object Management and Utilities

Generic object management, YAML processing, health checking, patch strategies, and utility functions for working with Kubernetes resources and cluster operations.

Capabilities

KubernetesObjectApi

Generic API for working with any Kubernetes object type without needing specific API client classes.

/**
 * Generic API for any Kubernetes object type
 */
class KubernetesObjectApi {
  /**
   * Create instance from KubeConfig
   */
  static makeApiClient(kc: KubeConfig): KubernetesObjectApi;
  
  /**
   * Create a Kubernetes object
   * @param spec - Kubernetes object specification to create
   * @param pretty - Pretty-print the output
   * @param dryRun - Dry run mode ('All' or 'Server')
   * @param fieldManager - Field manager name for server-side apply
   * @param options - Optional configuration options
   * @returns Promise that resolves to created object
   */
  create<T extends KubernetesObject>(
    spec: T,
    pretty?: string,
    dryRun?: string,
    fieldManager?: string,
    options?: Configuration
  ): Promise<T>;
  
  /**
   * Delete a Kubernetes object
   * @param spec - Kubernetes object to delete
   * @param pretty - Pretty-print the output
   * @param dryRun - Dry run mode
   * @param gracePeriodSeconds - Grace period for deletion
   * @param orphanDependents - Whether to orphan dependents
   * @param propagationPolicy - Propagation policy for deletion
   * @param options - Optional configuration options
   * @returns Promise that resolves to deletion status
   */
  delete(
    spec: KubernetesObject,
    pretty?: string,
    dryRun?: string,
    gracePeriodSeconds?: number,
    orphanDependents?: boolean,
    propagationPolicy?: string,
    options?: Configuration
  ): Promise<V1Status>;
  
  /**
   * Read a Kubernetes object
   * @param spec - Kubernetes object header (only metadata.name and metadata.namespace used)
   * @param pretty - Pretty-print the output
   * @param exact - Should the export be exact
   * @param exportt - Should this request return an export
   * @param options - Optional configuration options
   * @returns Promise that resolves to object
   */
  read<T extends KubernetesObject>(
    spec: KubernetesObjectHeader<T>,
    pretty?: string,
    exact?: boolean,
    exportt?: boolean,
    options?: Configuration
  ): Promise<T>;
  
  /**
   * Patch a Kubernetes object
   * @param spec - Kubernetes object to patch
   * @param pretty - Pretty-print the output
   * @param dryRun - Dry run mode
   * @param fieldManager - Field manager name
   * @param force - Force the patch
   * @param patchStrategy - Patch strategy to use
   * @param options - Optional configuration options
   * @returns Promise that resolves to patched object
   */
  patch<T extends KubernetesObject>(
    spec: T,
    pretty?: string,
    dryRun?: string,
    fieldManager?: string,
    force?: boolean,
    patchStrategy?: PatchStrategy,
    options?: Configuration
  ): Promise<T>;
  
  /**
   * Replace a Kubernetes object
   * @param spec - Kubernetes object to replace
   * @param pretty - Pretty-print the output
   * @param dryRun - Dry run mode
   * @param fieldManager - Field manager name
   * @param options - Optional configuration options
   * @returns Promise that resolves to replaced object
   */
  replace<T extends KubernetesObject>(
    spec: T,
    pretty?: string,
    dryRun?: string,
    fieldManager?: string,
    options?: Configuration
  ): Promise<T>;
  
  /**
   * List Kubernetes objects
   * @param apiVersion - API version (e.g., 'v1', 'apps/v1')
   * @param kind - Object kind (e.g., 'Pod', 'Deployment')
   * @param namespace - Optional namespace filter
   * @param pretty - Pretty-print the output
   * @param allowWatchBookmarks - Allow watch bookmarks
   * @param _continue - Continue token for pagination
   * @param fieldSelector - Field selector for filtering
   * @param labelSelector - Label selector for filtering
   * @param limit - Maximum number of items to return
   * @param resourceVersion - Resource version for consistency
   * @param resourceVersionMatch - Resource version match strategy
   * @param sendInitialEvents - Send initial events for watch
   * @param timeoutSeconds - Request timeout
   * @param watch - Watch for changes
   * @returns Promise that resolves to object list
   */
  list(
    apiVersion: string,
    kind: string,
    namespace?: string,
    pretty?: string,
    allowWatchBookmarks?: boolean,
    _continue?: string,
    fieldSelector?: string,
    labelSelector?: string,
    limit?: number,
    resourceVersion?: string,
    resourceVersionMatch?: string,
    sendInitialEvents?: boolean,
    timeoutSeconds?: number,
    watch?: boolean
  ): Promise<KubernetesObject>;
}

type KubernetesApiAction = 'create' | 'delete' | 'patch' | 'read' | 'list' | 'replace';

type KubernetesObjectHeader<T extends KubernetesObject> = Pick<T, 'apiVersion' | 'kind'> & {
  metadata: {
    name: string;
    namespace?: string;
  };
};

Usage Examples:

import { KubeConfig, KubernetesObjectApi } from '@kubernetes/client-node';

const kc = new KubeConfig();
kc.loadFromDefault();

const k8sObjectApi = KubernetesObjectApi.makeApiClient(kc);

// Create any type of Kubernetes object
const createObject = async () => {
  const configMap = {
    apiVersion: 'v1',
    kind: 'ConfigMap',
    metadata: {
      name: 'my-config',
      namespace: 'default'
    },
    data: {
      'config.json': JSON.stringify({ app: 'my-app', version: '1.0' })
    }
  };
  
  try {
    const created = await k8sObjectApi.create(configMap);
    console.log('Created ConfigMap:', created.metadata?.name);
  } catch (error) {
    console.error('Failed to create ConfigMap:', error);
  }
};

// Read any object by reference
const readObject = async () => {
  const objectRef = {
    apiVersion: 'v1',
    kind: 'Pod',
    metadata: {
      name: 'my-pod',
      namespace: 'default'
    }
  };
  
  try {
    const pod = await k8sObjectApi.read(objectRef);
    console.log('Pod status:', pod.status?.phase);
  } catch (error) {
    console.error('Failed to read pod:', error);
  }
};

// Patch objects with different strategies
const patchObject = async () => {
  const objectRef = {
    apiVersion: 'apps/v1',
    kind: 'Deployment',
    metadata: {
      name: 'my-deployment',
      namespace: 'default'
    }
  };
  
  const patch = {
    spec: {
      replicas: 5
    }
  };
  
  try {
    const patched = await k8sObjectApi.patch(
      objectRef,
      patch,
      undefined, // pretty
      undefined, // dryRun
      'my-controller' // fieldManager
    );
    console.log('Deployment scaled to:', patched.spec?.replicas);
  } catch (error) {
    console.error('Failed to patch deployment:', error);
  }
};

// List objects of any type
const listObjects = async () => {
  try {
    const services = await k8sObjectApi.list(
      'v1',        // apiVersion
      'Service',   // kind
      'default',   // namespace
      undefined,   // pretty
      undefined,   // allowWatchBookmarks
      undefined,   // continue
      undefined,   // fieldSelector
      'app=web'    // labelSelector
    );
    
    console.log('Found services:', services.items?.length);
  } catch (error) {
    console.error('Failed to list services:', error);
  }
};

// Delete objects with options
const deleteObject = async () => {
  const objectRef = {
    apiVersion: 'batch/v1',
    kind: 'Job',
    metadata: {
      name: 'completed-job',
      namespace: 'default'
    }
  };
  
  try {
    const status = await k8sObjectApi.delete(
      objectRef,
      undefined, // pretty
      undefined, // dryRun
      0,         // gracePeriodSeconds (immediate deletion)
      false,     // orphanDependents
      'Background' // propagationPolicy
    );
    console.log('Deletion status:', status.status);
  } catch (error) {
    console.error('Failed to delete job:', error);
  }
};

// Generic object management functions
const manageCustomResource = async () => {
  const customResource = {
    apiVersion: 'apps.example.com/v1',
    kind: 'MyApp',
    metadata: {
      name: 'my-app-instance',
      namespace: 'production'
    },
    spec: {
      replicas: 3,
      image: 'my-app:v1.2.3',
      environment: 'production'
    }
  };
  
  try {
    // Create
    const created = await k8sObjectApi.create(customResource);
    console.log('Custom resource created');
    
    // Update
    customResource.spec.replicas = 5;
    const updated = await k8sObjectApi.replace(customResource);
    console.log('Custom resource updated');
    
    // Clean up
    await k8sObjectApi.delete(customResource);
    console.log('Custom resource deleted');
  } catch (error) {
    console.error('Custom resource management failed:', error);
  }
};

YAML Utilities

YAML parsing and serialization utilities for working with Kubernetes manifest files.

/**
 * Parse YAML string to JavaScript object
 * @param data - YAML string to parse
 * @param opts - YAML parsing options
 * @returns Parsed object
 */
function loadYaml<T>(data: string, opts?: yaml.LoadOptions): T;

/**
 * Parse multiple YAML documents from a single string
 * @param data - YAML string containing multiple documents
 * @param opts - YAML parsing options
 * @returns Array of parsed objects
 */
function loadAllYaml(data: string, opts?: yaml.LoadOptions): any[];

/**
 * Serialize JavaScript object to YAML string
 * @param object - Object to serialize
 * @param opts - YAML serialization options
 * @returns YAML string
 */
function dumpYaml(object: any, opts?: yaml.DumpOptions): string;

Usage Examples:

import { loadYaml, loadAllYaml, dumpYaml } from '@kubernetes/client-node';
import * as fs from 'fs';

// Load single YAML document
const loadManifest = () => {
  const yamlContent = `
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  namespace: default
spec:
  containers:
  - name: app
    image: nginx:latest
    ports:
    - containerPort: 80
`;

  try {
    const pod = loadYaml(yamlContent);
    console.log('Loaded pod:', pod.metadata?.name);
    return pod;
  } catch (error) {
    console.error('YAML parsing error:', error);
  }
};

// Load multiple YAML documents
const loadMultipleManifests = () => {
  const yamlContent = `
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  app.conf: |
    server_name = my-app
    port = 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: app
        image: my-app:latest
`;

  try {
    const manifests = loadAllYaml(yamlContent);
    console.log(`Loaded ${manifests.length} manifests`);
    
    manifests.forEach((manifest, index) => {
      console.log(`${index + 1}. ${manifest.kind}: ${manifest.metadata?.name}`);
    });
    
    return manifests;
  } catch (error) {
    console.error('Multi-YAML parsing error:', error);
  }
};

// Load YAML from file
const loadManifestFromFile = async (filePath: string) => {
  try {
    const yamlContent = fs.readFileSync(filePath, 'utf8');
    const manifest = loadYaml(yamlContent);
    console.log('Loaded from file:', manifest.metadata?.name);
    return manifest;
  } catch (error) {
    console.error('File loading error:', error);
  }
};

// Convert objects to YAML
const exportToYaml = () => {
  const deployment = {
    apiVersion: 'apps/v1',
    kind: 'Deployment',
    metadata: {
      name: 'web-server',
      namespace: 'production',
      labels: {
        app: 'web-server',
        version: 'v1.0'
      }
    },
    spec: {
      replicas: 3,
      selector: {
        matchLabels: {
          app: 'web-server'
        }
      },
      template: {
        metadata: {
          labels: {
            app: 'web-server',
            version: 'v1.0'
          }
        },
        spec: {
          containers: [{
            name: 'web',
            image: 'nginx:1.20',
            ports: [{
              containerPort: 80
            }],
            env: [{
              name: 'ENVIRONMENT',
              value: 'production'
            }]
          }]
        }
      }
    }
  };

  try {
    const yamlString = dumpYaml(deployment, {
      indent: 2,
      quotingType: '"',
      forceQuotes: false
    });
    
    console.log('Generated YAML:');
    console.log(yamlString);
    
    // Save to file
    fs.writeFileSync('./deployment.yaml', yamlString);
    console.log('Saved to deployment.yaml');
    
  } catch (error) {
    console.error('YAML serialization error:', error);
  }
};

// Process multiple manifest files
const processManifestDirectory = (dirPath: string) => {
  const files = fs.readdirSync(dirPath)
    .filter(file => file.endsWith('.yaml') || file.endsWith('.yml'));
  
  const allManifests = [];
  
  files.forEach(file => {
    const filePath = `${dirPath}/${file}`;
    const content = fs.readFileSync(filePath, 'utf8');
    
    try {
      const manifests = loadAllYaml(content);
      allManifests.push(...manifests);
      console.log(`Loaded ${manifests.length} manifests from ${file}`);
    } catch (error) {
      console.error(`Error processing ${file}:`, error);
    }
  });
  
  return allManifests;
};

// Validate YAML structure
const validateKubernetesYaml = (yamlContent: string) => {
  try {
    const manifest = loadYaml(yamlContent);
    
    // Basic validation
    if (!manifest.apiVersion) {
      throw new Error('Missing apiVersion');
    }
    if (!manifest.kind) {
      throw new Error('Missing kind');
    }
    if (!manifest.metadata?.name) {
      throw new Error('Missing metadata.name');
    }
    
    console.log('YAML validation passed');
    return true;
  } catch (error) {
    console.error('YAML validation failed:', error.message);
    return false;
  }
};

Patch Strategies

Constants and utilities for different Kubernetes patch strategies.

/**
 * Kubernetes patch strategy constants
 */
const PatchStrategy = {
  /** JSON Patch (RFC 6902) */
  JsonPatch: 'application/json-patch+json',
  /** JSON Merge Patch (RFC 7396) */
  MergePatch: 'application/merge-patch+json',
  /** Strategic Merge Patch (Kubernetes-specific) */
  StrategicMergePatch: 'application/strategic-merge-patch+json',
  /** Server-Side Apply */
  ServerSideApply: 'application/apply-patch+yaml'
} as const;

type PatchStrategy = typeof PatchStrategy[keyof typeof PatchStrategy];

Usage Examples:

import { KubeConfig, CoreV1Api, PatchStrategy } from '@kubernetes/client-node';

const kc = new KubeConfig();
kc.loadFromDefault();
const k8sApi = kc.makeApiClient(CoreV1Api);

// JSON Patch (RFC 6902)
const jsonPatch = async () => {
  const patch = [
    {
      op: 'replace',
      path: '/spec/replicas',
      value: 5
    },
    {
      op: 'add',
      path: '/metadata/labels/environment',
      value: 'production'
    }
  ];

  try {
    await k8sApi.patchNamespacedDeployment(
      'my-deployment',
      'default',
      patch,
      undefined, // pretty
      undefined, // dryRun
      undefined, // fieldManager
      undefined, // fieldValidation
      undefined, // force
      {
        headers: {
          'Content-Type': PatchStrategy.JsonPatch
        }
      }
    );
    console.log('JSON Patch applied');
  } catch (error) {
    console.error('JSON Patch failed:', error);
  }
};

// Strategic Merge Patch
const strategicMergePatch = async () => {
  const patch = {
    spec: {
      template: {
        spec: {
          containers: [{
            name: 'app',
            env: [{
              name: 'DEBUG',
              value: 'true'
            }]
          }]
        }
      }
    }
  };

  try {
    await k8sApi.patchNamespacedDeployment(
      'my-deployment',
      'default',
      patch,
      undefined,
      undefined,
      undefined,
      undefined,
      undefined,
      {
        headers: {
          'Content-Type': PatchStrategy.StrategicMergePatch
        }
      }
    );
    console.log('Strategic Merge Patch applied');
  } catch (error) {
    console.error('Strategic Merge Patch failed:', error);
  }
};

// Merge Patch
const mergePatch = async () => {
  const patch = {
    metadata: {
      labels: {
        version: 'v2.0',
        environment: 'staging'
      }
    }
  };

  try {
    await k8sApi.patchNamespacedPod(
      'my-pod',
      'default',
      patch,
      undefined,
      undefined,
      undefined,
      undefined,
      undefined,
      {
        headers: {
          'Content-Type': PatchStrategy.MergePatch
        }
      }
    );
    console.log('Merge Patch applied');
  } catch (error) {
    console.error('Merge Patch failed:', error);
  }
};

// Server-Side Apply
const serverSideApply = async () => {
  const manifest = {
    apiVersion: 'v1',
    kind: 'ConfigMap',
    metadata: {
      name: 'app-config',
      namespace: 'default'
    },
    data: {
      'app.properties': 'debug=true\nport=8080'
    }
  };

  try {
    await k8sApi.patchNamespacedConfigMap(
      'app-config',
      'default',
      manifest,
      undefined,
      undefined,
      'my-controller', // fieldManager is required
      undefined,
      true, // force
      {
        headers: {
          'Content-Type': PatchStrategy.ServerSideApply
        }
      }
    );
    console.log('Server-Side Apply completed');
  } catch (error) {
    console.error('Server-Side Apply failed:', error);
  }
};

Health Checking

Health checking utilities for monitoring Kubernetes cluster readiness and liveness.

/**
 * Kubernetes cluster health checking
 */
class Health {
  constructor(config: KubeConfig);
  
  /**
   * Check cluster readiness endpoint
   * @param opts - Request options
   * @returns Promise that resolves to readiness status
   */
  readyz(opts: RequestOptions): Promise<boolean>;
  
  /**
   * Check cluster liveness endpoint
   * @param opts - Request options
   * @returns Promise that resolves to liveness status
   */
  livez(opts: RequestOptions): Promise<boolean>;
}

interface RequestOptions {
  /** Request timeout in milliseconds */
  timeout?: number;
  /** Additional headers */
  headers?: Record<string, string>;
}

Usage Examples:

import { KubeConfig, Health } from '@kubernetes/client-node';

const kc = new KubeConfig();
kc.loadFromDefault();

const health = new Health(kc);

// Check cluster readiness
const checkReadiness = async () => {
  try {
    const isReady = await health.readyz({ timeout: 5000 });
    console.log('Cluster ready:', isReady);
    return isReady;
  } catch (error) {
    console.error('Readiness check failed:', error);
    return false;
  }
};

// Check cluster liveness
const checkLiveness = async () => {
  try {
    const isLive = await health.livez({ timeout: 5000 });
    console.log('Cluster live:', isLive);
    return isLive;
  } catch (error) {
    console.error('Liveness check failed:', error);
    return false;
  }
};

// Continuous health monitoring
const monitorClusterHealth = () => {
  const interval = setInterval(async () => {
    try {
      const [ready, live] = await Promise.all([
        health.readyz({ timeout: 3000 }),
        health.livez({ timeout: 3000 })
      ]);
      
      const status = ready && live ? '✅ HEALTHY' : '❌ UNHEALTHY';
      console.log(`Cluster status: ${status} (ready: ${ready}, live: ${live})`);
      
      if (!ready || !live) {
        console.warn('Cluster health issues detected');
      }
      
    } catch (error) {
      console.error('Health check error:', error);
    }
  }, 30000); // Check every 30 seconds
  
  // Stop monitoring on process exit
  process.on('SIGINT', () => {
    clearInterval(interval);
    console.log('Health monitoring stopped');
    process.exit(0);
  });
};

// Health check with retries
const checkHealthWithRetry = async (maxRetries = 3) => {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const [ready, live] = await Promise.all([
        health.readyz({ timeout: 2000 }),
        health.livez({ timeout: 2000 })
      ]);
      
      if (ready && live) {
        console.log(`Cluster healthy (attempt ${attempt})`);
        return true;
      }
      
      console.warn(`Cluster unhealthy (attempt ${attempt}/${maxRetries})`);
      
    } catch (error) {
      console.error(`Health check attempt ${attempt} failed:`, error.message);
    }
    
    if (attempt < maxRetries) {
      await new Promise(resolve => setTimeout(resolve, 1000));
    }
  }
  
  console.error('Cluster health check failed after all retries');
  return false;
};

HTTP Middleware

HTTP request/response middleware utilities for customizing API client behavior.

/**
 * Create header middleware for HTTP requests
 * @param key - Header name
 * @param value - Header value
 * @returns Observable middleware
 */
function setHeaderMiddleware(key: string, value: string): ObservableMiddleware;

/**
 * Create header options for configuration
 * @param key - Header name
 * @param value - Header value
 * @param opt - Optional existing configuration options
 * @returns Configuration options with header middleware
 */
function setHeaderOptions(
  key: string,
  value: string,
  opt?: ConfigurationOptions
): ConfigurationOptions;

Usage Examples:

import { 
  KubeConfig, 
  CoreV1Api, 
  createConfiguration,
  setHeaderMiddleware,
  setHeaderOptions 
} from '@kubernetes/client-node';

const kc = new KubeConfig();
kc.loadFromDefault();

// Add custom headers to all requests
const setupCustomHeaders = () => {
  const headerOptions = setHeaderOptions('X-Custom-Header', 'my-value');
  const config = createConfiguration(headerOptions);
  
  // Use configuration with custom headers
  const k8sApi = new CoreV1Api(config);
  return k8sApi;
};

// Add multiple custom headers
const setupMultipleHeaders = () => {
  let options = setHeaderOptions('X-Client-Version', '1.0.0');
  options = setHeaderOptions('X-Environment', 'production', options);
  options = setHeaderOptions('X-User-Agent', 'my-app/1.0', options);
  
  const config = createConfiguration(options);
  const k8sApi = new CoreV1Api(config);
  return k8sApi;
};

// Custom middleware for request logging
const setupLoggingMiddleware = () => {
  const loggingMiddleware = {
    pre: (context) => {
      console.log(`Making request to: ${context.url}`);
      console.log(`Method: ${context.init.method || 'GET'}`);
      return Promise.resolve(context);
    },
    post: (context) => {
      console.log(`Response status: ${context.response.status}`);
      return Promise.resolve(context);
    }
  };
  
  const config = createConfiguration({
    middleware: [loggingMiddleware]
  });
  
  const k8sApi = new CoreV1Api(config);
  return k8sApi;
};

// Authentication middleware
const setupAuthMiddleware = (token: string) => {
  const authMiddleware = {
    pre: (context) => {
      context.init.headers = {
        ...context.init.headers,
        'Authorization': `Bearer ${token}`
      };
      return Promise.resolve(context);
    }
  };
  
  const config = createConfiguration({
    middleware: [authMiddleware]
  });
  
  return new CoreV1Api(config);
};

Resource Utilities

Utility functions for working with Kubernetes resources, quantities, and common operations.

/**
 * Get all pods running on a specific node
 * @param api - CoreV1Api instance
 * @param nodeName - Name of the node
 * @returns Promise that resolves to array of pods
 */
function podsForNode(api: CoreV1Api, nodeName: string): Promise<V1Pod[]>;

/**
 * Convert Kubernetes quantity to scalar number
 * @param quantity - Kubernetes quantity string (e.g., "100m", "1Gi")
 * @returns Numeric value
 */
function quantityToScalar(quantity: string): number | bigint;

/**
 * Extract unit suffix from quantity string
 * @param quantity - Kubernetes quantity string
 * @returns Unit suffix
 */
function findSuffix(quantity: string): string;

/**
 * Utility function to add log options to URL search parameters
 * @param options - Log streaming options
 * @param searchParams - URLSearchParams object to modify
 */
function AddOptionsToSearchParams(options: LogOptions, searchParams: URLSearchParams): void;

Usage Examples:

import { 
  KubeConfig, 
  CoreV1Api, 
  podsForNode,
  quantityToScalar,
  findSuffix 
} from '@kubernetes/client-node';

const kc = new KubeConfig();
kc.loadFromDefault();
const k8sApi = kc.makeApiClient(CoreV1Api);

// Get pods on specific node
const getNodePods = async (nodeName: string) => {
  try {
    const pods = await podsForNode(k8sApi, nodeName);
    console.log(`Found ${pods.length} pods on node ${nodeName}`);
    
    pods.forEach(pod => {
      console.log(`- ${pod.metadata?.name} (${pod.status?.phase})`);
    });
    
    return pods;
  } catch (error) {
    console.error('Failed to get node pods:', error);
  }
};

// Convert resource quantities
const convertQuantities = () => {
  const quantities = ['100m', '1Gi', '500Mi', '2', '1.5'];
  
  quantities.forEach(quantity => {
    const scalar = quantityToScalar(quantity);
    const suffix = findSuffix(quantity);
    
    console.log(`${quantity}: ${scalar} (suffix: ${suffix})`);
  });
};

// Analyze resource usage
const analyzeResourceUsage = async () => {
  try {
    const nodes = await k8sApi.listNode();
    
    for (const node of nodes.body.items) {
      const nodeName = node.metadata?.name;
      if (!nodeName) continue;
      
      console.log(`\nNode: ${nodeName}`);
      
      // Get node capacity
      const cpuCapacity = node.status?.capacity?.cpu;
      const memoryCapacity = node.status?.capacity?.memory;
      
      if (cpuCapacity) {
        const cpuScalar = quantityToScalar(cpuCapacity);
        console.log(`CPU Capacity: ${cpuCapacity} (${cpuScalar} cores)`);
      }
      
      if (memoryCapacity) {
        const memoryScalar = quantityToScalar(memoryCapacity);
        console.log(`Memory Capacity: ${memoryCapacity} (${memoryScalar} bytes)`);
      }
      
      // Get pods on this node
      const pods = await podsForNode(k8sApi, nodeName);
      console.log(`Running Pods: ${pods.length}`);
      
      // Calculate total requests/limits
      let totalCpuRequests = 0;
      let totalMemoryRequests = 0;
      
      pods.forEach(pod => {
        pod.spec?.containers?.forEach(container => {
          const cpuRequest = container.resources?.requests?.cpu;
          const memoryRequest = container.resources?.requests?.memory;
          
          if (cpuRequest) {
            totalCpuRequests += quantityToScalar(cpuRequest) as number;
          }
          if (memoryRequest) {
            totalMemoryRequests += quantityToScalar(memoryRequest) as number;
          }
        });
      });
      
      console.log(`Total CPU Requests: ${totalCpuRequests}`);
      console.log(`Total Memory Requests: ${totalMemoryRequests}`);
    }
  } catch (error) {
    console.error('Resource analysis failed:', error);
  }
};

// Utility for resource comparison
const compareResources = (resource1: string, resource2: string) => {
  const scalar1 = quantityToScalar(resource1);
  const scalar2 = quantityToScalar(resource2);
  
  if (scalar1 > scalar2) {
    return `${resource1} > ${resource2}`;
  } else if (scalar1 < scalar2) {
    return `${resource1} < ${resource2}`;
  } else {
    return `${resource1} = ${resource2}`;
  }
};

// Example usage
console.log(compareResources('1Gi', '1024Mi')); // Should be equal
console.log(compareResources('500m', '1')); // 500m < 1

docs

api-clients.md

configuration.md

index.md

monitoring.md

pod-operations.md

utilities.md

tile.json