importplan

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 16, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package importplan classifies an import input (repo URL, docker run command, image reference, compose file or Dockerfile) and builds a side-effect free deployment plan preview from it.

Index

Constants

View Source
const (
	EnvMaxFileBytes = "APP_IMPORT_MAX_FILE_BYTES"
	EnvMaxFiles     = "APP_IMPORT_MAX_FILES"
	EnvFetchTimeout = "APP_IMPORT_FETCH_TIMEOUT"
)

Env vars bounding repository inspection.

View Source
const MaxInputBytes = 512 * 1024

MaxInputBytes caps Input.Text, compose files and Dockerfiles included.

Variables

View Source
var EnvExampleFiles = []string{".env.example", ".env.sample", ".env.template", "env.example", ".env.dist"}

EnvExampleFiles are the repo files scanned for env variable declarations.

View Source
var ErrEmptyInput = errors.New("importplan: input is empty")

ErrEmptyInput is returned for blank input.

View Source
var ErrFileLimit = errors.New("importplan: repository file limit reached")

ErrFileLimit is returned once a plan has read its allowed number of files.

View Source
var ErrNoImage = errors.New("importplan: docker run command has no image")

ErrNoImage is returned when a docker run command names no image.

View Source
var ErrNotDockerRun = errors.New("importplan: not a docker run command")

ErrNotDockerRun is returned when the text is not a `docker run` command.

View Source
var ErrUnclassified = errors.New("importplan: could not tell what this input is")

ErrUnclassified is returned when the input matches no known source shape.

View Source
var ErrUnterminatedQuote = errors.New("importplan: unterminated quote")

ErrUnterminatedQuote is returned by Tokenize for an unbalanced quote.

Functions

func KeyLooksSecret

func KeyLooksSecret(key string) bool

KeyLooksSecret reports whether an env variable name suggests a secret.

func Tokenize

func Tokenize(s string) ([]string, error)

Tokenize splits a shell-style command line into words. It handles single and double quotes, backslash escapes and backslash-newline continuations. Nothing is expanded or executed: $VAR and $(...) stay literal text.

Types

type BuildMethod

type BuildMethod string

BuildMethod is how the plan's app gets its image.

const (
	BuildImage      BuildMethod = "image"
	BuildDockerfile BuildMethod = "dockerfile"
	BuildRailpack   BuildMethod = "railpack"
	BuildStatic     BuildMethod = "static"
	BuildCompose    BuildMethod = "compose"
	BuildUnknown    BuildMethod = "unknown"
)

Build methods a plan can use.

type DeployKind

type DeployKind string

DeployKind names which existing create/deploy endpoint a plan feeds.

const (
	// DeployApp is POST /api/v1/apps with a prebuilt image.
	DeployApp DeployKind = "app"
	// DeployBuild is POST /api/v1/apps then POST /api/v1/apps/{name}/builds.
	DeployBuild DeployKind = "build"
	// DeployCompose is POST /api/v1/apps/{name}/compose.
	DeployCompose DeployKind = "compose"
	// DeployNone means the input alone cannot be deployed (for example a bare Dockerfile snippet).
	DeployNone DeployKind = "none"
)

type DeploymentPlan

type DeploymentPlan struct {
	Source        SourceKind `json:"source"`
	SuggestedName string     `json:"suggested_name"`
	Deploy        DeployKind `json:"deploy"`
	// RepoURL and Ref are set for repo sources.
	RepoURL string `json:"repo_url,omitempty"`
	Ref     string `json:"ref,omitempty"`
	// ComposeYAML is the compose document to POST for DeployCompose,
	// generated from a docker run command or supplied by the caller.
	ComposeYAML string        `json:"compose_yaml,omitempty"`
	Services    []ServicePlan `json:"services"`
	// DomainSuggestion is a hint only; nothing is configured from it.
	DomainSuggestion string    `json:"domain_suggestion,omitempty"`
	Warnings         []Warning `json:"warnings"`
	// MissingRequiredEnv lists required variables with no value; deploy is blocked until each has one.
	MissingRequiredEnv []string `json:"missing_required_env"`
}

DeploymentPlan is the full preview returned before anything is created.

func Plan

func Plan(ctx context.Context, in Input, deps Deps) (*DeploymentPlan, error)

Plan builds the deployment plan preview. It performs no writes.

type Deps

type Deps struct {
	// Files reads repository files; nil disables repo inspection.
	Files FileSource
	// Detect returns a Railpack provider id for a repo; nil skips the fallback.
	Detect func(ctx context.Context, repoURL, ref string) (string, error)
}

Deps are the outside effects Plan may use; every field is optional.

type EnvVar

type EnvVar struct {
	Key        string `json:"key"`
	Value      string `json:"value,omitempty"`
	Required   bool   `json:"required"`
	HasDefault bool   `json:"has_default"`
	Secret     bool   `json:"secret"`
	Source     string `json:"source,omitempty"`
}

EnvVar is one discovered environment variable. Value is empty for a secret-looking variable; the plan never echoes such defaults back.

func ParseDockerfile

func ParseDockerfile(text string) (ports []int, env []EnvVar)

ParseDockerfile extracts the EXPOSE ports and ENV entries of a Dockerfile.

func ParseEnvFile

func ParseEnvFile(text, source string) []EnvVar

ParseEnvFile parses KEY=VALUE lines (comments, `export`, quotes handled). Values are treated as data only and are never interpolated.

type FileSource

type FileSource interface {
	ReadFile(ctx context.Context, repoURL, ref, path string) (data []byte, ok bool, err error)
}

FileSource reads single files from a repository. ok is false for a missing file.

type HTTPFiles

type HTTPFiles struct {
	Client   *http.Client
	MaxBytes int64
	MaxFiles int
	// contains filtered or unexported fields
}

HTTPFiles reads raw files from a git host over http(s) through the SSRF-guarded client, so nothing is cloned or written to disk.

func NewHTTPFiles

func NewHTTPFiles() *HTTPFiles

NewHTTPFiles builds a FileSource with limits taken from the environment.

func (*HTTPFiles) ReadFile

func (h *HTTPFiles) ReadFile(ctx context.Context, repoURL, ref, path string) ([]byte, bool, error)

ReadFile fetches one file, capped at MaxBytes.

type Input

type Input struct {
	// Text is a URL, image reference, docker run command, compose YAML or Dockerfile.
	Text string `json:"text"`
	// Kind overrides classification when set.
	Kind SourceKind `json:"kind,omitempty"`
	// Ref selects a branch for repo sources.
	Ref string `json:"ref,omitempty"`
	// Name overrides the suggested app name.
	Name string `json:"name,omitempty"`
	// Port overrides the detected container port.
	Port int `json:"port,omitempty"`
	// Env carries operator-supplied values, keyed by variable name. They
	// satisfy required variables and are injected into a generated compose file.
	Env map[string]string `json:"env,omitempty"`
}

Input is the raw request to Classify and Plan.

type PortMapping

type PortMapping struct {
	Host      int `json:"host,omitempty"`
	Container int `json:"container"`
}

PortMapping is one published or exposed port.

type ServicePlan

type ServicePlan struct {
	Name        string        `json:"name"`
	Image       string        `json:"image,omitempty"`
	Build       BuildMethod   `json:"build"`
	BuildReason string        `json:"build_reason,omitempty"`
	Port        int           `json:"port,omitempty"`
	Ports       []PortMapping `json:"ports,omitempty"`
	Command     []string      `json:"command,omitempty"`
	Entrypoint  []string      `json:"entrypoint,omitempty"`
	HealthPath  string        `json:"health_path,omitempty"`
	Env         []EnvVar      `json:"env,omitempty"`
	Volumes     []VolumeMount `json:"volumes,omitempty"`
	Restart     string        `json:"restart,omitempty"`
	MemoryBytes int64         `json:"memory_bytes,omitempty"`
	NanoCPUs    int64         `json:"nano_cpus,omitempty"`
}

ServicePlan is the plan for one service (compose files carry several).

type SourceKind

type SourceKind string

SourceKind is what Classify decided the input is.

const (
	SourceRepo       SourceKind = "repo"
	SourceDockerRun  SourceKind = "docker_run"
	SourceImage      SourceKind = "image"
	SourceCompose    SourceKind = "compose"
	SourceDockerfile SourceKind = "dockerfile"
)

Source kinds Classify can return.

func Classify

func Classify(in Input) (SourceKind, error)

Classify decides what kind of input text is.

type StackGuess

type StackGuess struct {
	Name   string
	Method BuildMethod
	Port   int
	Health string
	Start  string
	Why    string
}

StackGuess is a stack detected from manifest files alone.

func GuessStack

func GuessStack(read func(string) (string, bool, error)) (StackGuess, bool)

GuessStack inspects manifest files through read, in a fixed order, to pick a stack.

type VolumeMount

type VolumeMount struct {
	Name          string `json:"name,omitempty"`
	HostPath      string `json:"host_path,omitempty"`
	ContainerPath string `json:"container_path"`
	ReadOnly      bool   `json:"read_only,omitempty"`
	// NeedsApproval flags a host bind mount, which only root may create.
	NeedsApproval bool `json:"needs_approval,omitempty"`
}

VolumeMount is one volume or bind mount.

type Warning

type Warning struct {
	// Code is stable and machine readable, for example "unsupported_flag".
	Code    string `json:"code"`
	Message string `json:"message"`
}

Warning is a note the operator should read before deploying.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL