summaryrefslogtreecommitdiff
path: root/config
diff options
context:
space:
mode:
authorDan Duvall <dduvall@wikimedia.org>2017-10-24 18:04:47 -0700
committerDan Duvall <dduvall@wikimedia.org>2017-11-06 13:25:20 -0800
commit515d9f26eb616a9c3a0b70ba6eca88570a15b0ef (patch)
tree0f8d3b0a6381f4ea2c43ce063f6af9990a2abb2f /config
parent5d4cc80edf4fdba60069a7ef1e450117195fb987 (diff)
downloadblubber-515d9f26eb616a9c3a0b70ba6eca88570a15b0ef.tar.gz
Documented all exported types, functions, and interfaces
Summary: Wrote inline documentation for all the things. Fixes T168000 Test Plan: Execute `godoc -http=:6060` and proofread all the things. Reviewers: thcipriani, hashar, #release-engineering-team, demon Reviewed By: thcipriani, #release-engineering-team, demon Tags: #release-engineering-team Maniphest Tasks: T168000 Differential Revision: https://phabricator.wikimedia.org/D841
Diffstat (limited to 'config')
-rw-r--r--config/apt.go13
-rw-r--r--config/artifacts.go24
-rw-r--r--config/common.go24
-rw-r--r--config/config.go6
-rw-r--r--config/flag.go9
-rw-r--r--config/node.go31
-rw-r--r--config/reader.go6
-rw-r--r--config/runs.go37
-rw-r--r--config/variant.go24
9 files changed, 155 insertions, 19 deletions
diff --git a/config/apt.go b/config/apt.go
index e1f8f53..3a7a688 100644
--- a/config/apt.go
+++ b/config/apt.go
@@ -4,14 +4,27 @@ import (
"phabricator.wikimedia.org/source/blubber/build"
)
+// AptConfig represents configuration pertaining to package installation from
+// existing APT sources.
+//
type AptConfig struct {
Packages []string `yaml:"packages"`
}
+// Merge takes another AptConfig and combines the packages declared within
+// with the packages of this AptConfig.
+//
func (apt *AptConfig) Merge(apt2 AptConfig) {
apt.Packages = append(apt.Packages, apt2.Packages...)
}
+// InstructionsForPhase injects build instructions that will install the
+// declared packages during the privileged phase.
+//
+// PhasePrivileged
+//
+// Updates the APT cache, installs configured packages, and cleans up.
+//
func (apt AptConfig) InstructionsForPhase(phase build.Phase) []build.Instruction {
if len(apt.Packages) > 0 {
switch phase {
diff --git a/config/artifacts.go b/config/artifacts.go
index 654f10f..bd1bdeb 100644
--- a/config/artifacts.go
+++ b/config/artifacts.go
@@ -4,12 +4,30 @@ import (
"phabricator.wikimedia.org/source/blubber/build"
)
+// ArtifactsConfig declares files and directories to be copied from one
+// variant's container to another during the build.
+//
+// The most common use of such "multi-stage" builds is to compile and test
+// software using one variant image that contains a comprehensive set of
+// development dependencies, and copy the software binaries or production only
+// source files over into a smaller image that contains only production
+// dependencies. For a shorthand configuration of this precise pattern, use
+// VariantConfig.Copies.
+//
type ArtifactsConfig struct {
- From string `yaml:"from"`
- Source string `yaml:"source"`
- Destination string `yaml:"destination"`
+ From string `yaml:"from"` // source variant from which to copy
+ Source string `yaml:"source"` // source path within variant from which to copy
+ Destination string `yaml:"destination"` // destination path within current variant
}
+// InstructionsForPhase injects instructions into the given build phase that
+// copy configured artifacts.
+//
+// PhasePostInstall
+//
+// Injects build.CopyFrom instructions for the configured source and
+// destination paths.
+//
func (ac ArtifactsConfig) InstructionsForPhase(phase build.Phase) []build.Instruction {
switch phase {
case build.PhasePostInstall:
diff --git a/config/common.go b/config/common.go
index dae0013..11357d8 100644
--- a/config/common.go
+++ b/config/common.go
@@ -4,15 +4,20 @@ import (
"phabricator.wikimedia.org/source/blubber/build"
)
+// CommonConfig holds the configuration fields common to both the root config
+// and each configured variant.
+//
type CommonConfig struct {
- Base string `yaml:"base"`
- Apt AptConfig `yaml:"apt"`
- Node NodeConfig `yaml:"node"`
- Runs RunsConfig `yaml:"runs"`
- SharedVolume Flag `yaml:"sharedvolume"`
- EntryPoint []string `yaml:"entrypoint"`
+ Base string `yaml:"base"` // name/path to base image
+ Apt AptConfig `yaml:"apt"` // APT related configuration
+ Node NodeConfig `yaml:"node"` // Node related configuration
+ Runs RunsConfig `yaml:"runs"` // runtime environment configuration
+ SharedVolume Flag `yaml:"sharedvolume"` // define a volume instead of copying in source files
+ EntryPoint []string `yaml:"entrypoint"` // entry-point executable
}
+// Merge takes another CommonConfig and merges its fields this one's.
+//
func (cc1 *CommonConfig) Merge(cc2 CommonConfig) {
if cc2.Base != "" {
cc1.Base = cc2.Base
@@ -28,10 +33,17 @@ func (cc1 *CommonConfig) Merge(cc2 CommonConfig) {
}
}
+// PhaseCompileableConfig returns all fields that implement
+// build.PhaseCompileable in the order that their instructions should be
+// injected.
+//
func (cc *CommonConfig) PhaseCompileableConfig() []build.PhaseCompileable {
return []build.PhaseCompileable{cc.Apt, cc.Node, cc.Runs}
}
+// InstructionsForPhase injects instructions into the given build phase for
+// each member field that supports it.
+//
func (cc *CommonConfig) InstructionsForPhase(phase build.Phase) []build.Instruction {
instructions := []build.Instruction{}
diff --git a/config/config.go b/config/config.go
index 6f4283f..3360012 100644
--- a/config/config.go
+++ b/config/config.go
@@ -1,5 +1,11 @@
+// Package config provides the internal representation of Blubber
+// configuration parsed from YAML. Each configuration type may implement
+// its own hooks for injecting build instructions into the compiler.
+//
package config
+// Config holds the root fields of a Blubber configuration.
+//
type Config struct {
CommonConfig `yaml:",inline"`
Variants map[string]VariantConfig `yaml:"variants"`
diff --git a/config/flag.go b/config/flag.go
index b841819..6fb9e72 100644
--- a/config/flag.go
+++ b/config/flag.go
@@ -1,10 +1,16 @@
package config
+// Flag represents a nullable boolean value that is considered null until
+// either parsed from YAML or merged in from another Flag value.
+//
type Flag struct {
True bool
set bool
}
+// UnmarshalYAML implements yaml.Unmarshaler to parse the underlying boolean
+// value and detect that the Flag should no longer be considered null.
+//
func (flag *Flag) UnmarshalYAML(unmarshal func(interface{}) error) error {
if err := unmarshal(&flag.True); err != nil {
return err
@@ -15,6 +21,9 @@ func (flag *Flag) UnmarshalYAML(unmarshal func(interface{}) error) error {
return nil
}
+// Merge takes another flag and, if set, merged its boolean value into this
+// one.
+//
func (flag *Flag) Merge(flag2 Flag) {
if flag2.set {
flag.True = flag2.True
diff --git a/config/node.go b/config/node.go
index 90859e8..561c915 100644
--- a/config/node.go
+++ b/config/node.go
@@ -5,11 +5,17 @@ import (
"phabricator.wikimedia.org/source/blubber/build"
)
+// NodeConfig holds configuration fields related to the Node environment and
+// whether/how to install NPM packages.
+//
type NodeConfig struct {
- Dependencies Flag `yaml:"dependencies"`
- Env string `yaml:"env"`
+ Dependencies Flag `yaml:"dependencies"` // install dependencies declared in package.json
+ Env string `yaml:"env"` // environment name ("production" install)
}
+// Merge takes another NodeConfig and merges its fields into this one's,
+// overwriting both the environment and dependencies flag.
+//
func (nc *NodeConfig) Merge(nc2 NodeConfig) {
nc.Dependencies.Merge(nc2.Dependencies)
@@ -18,6 +24,27 @@ func (nc *NodeConfig) Merge(nc2 NodeConfig) {
}
}
+// InstructionsForPhase injects instructions into the build related to Node
+// dependency installation and setting of the NODE_ENV, NODE_PATH, and PATH
+// environment variables.
+//
+// PhasePreInstall
+//
+// Installs Node package dependencies declared in package.json into the shared
+// library directory (/opt/lib). Only production related packages are install
+// if NodeConfig.Env is set to "production" in which case `npm dedupe` is also
+// run. Installing dependencies during the build.PhasePreInstall phase allows
+// a compiler implementation (e.g. Docker) to produce cache-efficient output
+// so only changes to package.json will invalidate these steps of the image
+// build.
+//
+// PhasePostInstall
+//
+// Injects build.Env instructions for NODE_ENV, NODE_PATH, and PATH, setting
+// the environment according to the configuration, ensuring that packages
+// installed during build.PhasePreInstall are found by Node, and that any
+// installed binaries are found by shells.
+//
func (nc NodeConfig) InstructionsForPhase(phase build.Phase) []build.Instruction {
switch phase {
case build.PhasePreInstall:
diff --git a/config/reader.go b/config/reader.go
index 0f4cc12..7aa060d 100644
--- a/config/reader.go
+++ b/config/reader.go
@@ -35,6 +35,7 @@ func expandIncludes(config *Config, name string, included map[string]bool) ([]st
// ExpandVariant merges a named variant with a config. It also attempts to
// recursively expand any included variants in the expanded variant.
+//
func ExpandVariant(config *Config, name string) (*VariantConfig, error) {
expanded := new(VariantConfig)
expanded.CommonConfig.Merge(config.CommonConfig)
@@ -53,6 +54,8 @@ func ExpandVariant(config *Config, name string) (*VariantConfig, error) {
return expanded, nil
}
+// ReadConfig unmarshals the given YAML bytes into a Config struct.
+//
func ReadConfig(data []byte) (*Config, error) {
var config Config
@@ -61,6 +64,9 @@ func ReadConfig(data []byte) (*Config, error) {
return &config, err
}
+// ReadConfigFile unmarshals the given YAML file contents into a Config
+// struct.
+//
func ReadConfigFile(path string) (*Config, error) {
data, err := ioutil.ReadFile(path)
diff --git a/config/runs.go b/config/runs.go
index 6a176c3..ef9f4ea 100644
--- a/config/runs.go
+++ b/config/runs.go
@@ -6,16 +6,26 @@ import (
"phabricator.wikimedia.org/source/blubber/build"
)
+// LocalLibPrefix declares the shared directory into which application level
+// dependencies will be installed.
+//
const LocalLibPrefix = "/opt/lib"
+// RunsConfig holds configuration fields related to the application's
+// runtime environment.
+//
type RunsConfig struct {
- In string `yaml:"in"`
- As string `yaml:"as"`
- Uid int `yaml:"uid"`
- Gid int `yaml:"gid"`
- Environment map[string]string `yaml:"environment"`
+ In string `yaml:"in"` // working directory
+ As string `yaml:"as"` // unprivileged user
+ Uid int `yaml:"uid"` // unprivileged UID
+ Gid int `yaml:"gid"` // unprivileged GID
+ Environment map[string]string `yaml:"environment"` // environment variables
}
+// Merge takes another RunsConfig and overwrites this struct's fields. All
+// fields except Environment are overwritten if set. The latter is an additive
+// merge.
+//
func (run *RunsConfig) Merge(run2 RunsConfig) {
if run2.In != "" {
run.In = run2.In
@@ -39,6 +49,9 @@ func (run *RunsConfig) Merge(run2 RunsConfig) {
}
}
+// Home returns the home directory for the configured user, or /root if no
+// user is set.
+//
func (run RunsConfig) Home() string {
if run.As == "" {
return "/root"
@@ -47,6 +60,20 @@ func (run RunsConfig) Home() string {
}
}
+// InstructionsForPhase injects build instructions related to the runtime
+// configuration.
+//
+// PhasePrivileged
+//
+// Creates LocalLibPrefix directory and unprivileged user home directory,
+// creates the unprivileged user and its group, and sets up directory
+// permissions.
+//
+// PhasePrivilegeDropped
+//
+// Injects build.Env instructions for the user home directory and all
+// names/values defined by RunsConfig.Environment.
+//
func (run RunsConfig) InstructionsForPhase(phase build.Phase) []build.Instruction {
ins := []build.Instruction{}
diff --git a/config/variant.go b/config/variant.go
index 8e53b70..60fa325 100644
--- a/config/variant.go
+++ b/config/variant.go
@@ -4,19 +4,34 @@ import (
"phabricator.wikimedia.org/source/blubber/build"
)
+// VariantConfig holds configuration fields for each defined build variant.
+//
type VariantConfig struct {
- Includes []string `yaml:"includes"`
- Copies string `yaml:"copies"`
- Artifacts []ArtifactsConfig `yaml:"artifacts"`
+ Includes []string `yaml:"includes"` // references to one or more
+ Copies string `yaml:"copies"` // copy standard artifacts from another variant
+ Artifacts []ArtifactsConfig `yaml:"artifacts"` // non-standard artifact configuration
CommonConfig `yaml:",inline"`
}
+// Merge takes another VariantConfig and overwrites this struct's fields.
+// Artifacts are merged additively.
+//
func (vc *VariantConfig) Merge(vc2 VariantConfig) {
vc.Copies = vc2.Copies
vc.Artifacts = append(vc.Artifacts, vc2.Artifacts...)
vc.CommonConfig.Merge(vc2.CommonConfig)
}
+// InstructionsForPhase injects build instructions related to artifact
+// copying, volume definition or copying of application files, and all common
+// configuration.
+//
+// PhaseInstall
+//
+// If VariantConfig.Copies is not set, either copy in application files or
+// define a shared volume. Otherwise, delegate to
+// ArtifactsConfig.InstructionsForPhase.
+//
func (vc *VariantConfig) InstructionsForPhase(phase build.Phase) []build.Instruction {
instructions := vc.CommonConfig.InstructionsForPhase(phase)
ainstructions := []build.Instruction{}
@@ -41,6 +56,9 @@ func (vc *VariantConfig) InstructionsForPhase(phase build.Phase) []build.Instruc
return instructions
}
+// VariantDependencies returns all unique names of other variants that are
+// referenced in the VariantConfig.Artifacts configuration.
+//
func (vc *VariantConfig) VariantDependencies() []string {
// get unique set of variant dependencies based on artifacts
existing := map[string]bool{}