Workspace and Packages
Namespace brings a modern package management approach to infrastructure development. All the user code is organized into modules that define the versioning boundary. Modules in turn, are further split into packages that represent individual servers and/or collect tests, definitions of secrets, resources and volumes.
Workspace
A workspace defines a set of environments and their configurations. ns-workspace.cue
contains configuration bits that need to be shared between developers, for example:
// See below for more details about environments.
environment: {
dev: {
runtime: "kubernetes"
purpose: "DEVELOPMENT"
}
prod: {
runtime: "kubernetes"
purpose: "PRODUCTION"
}
}
Workstation-specific configuration bits are generated by ns
and stored in devhost.textpb
. Add
this file to .gitignore
.
Environment
An environment encapsulates configurations used within a particular use-case.
By default, Namespace assumes three environments (dev
, staging
, prod
) but you can define
an arbitrary number of environments for each workspace.
Infrastructure associated with an environment:
- Kubernetes cluster (with each environment being deployed to a separate Kubernetes namespace).
- Environment purpose: DEVELOPMENT, PRODUCTION
By default, ns
used the dev
environment that is automatically configured by ns prepare local
(but you can configure dev
for your own cluster with ns prepare existing
).
Namespace optimizes builds and deployments per environment (e.g. strips symbols for production).
Module
A module is a source code directory that defines a project root. A single git repository may
contain multiple modules. Modules group multiple packages together, all packages within a module
have the same version and configuration of dependent modules. As most users only need a single
module per workspace, we recommend defining modules alongside the workspace in ns-workspace.cue
.
Module name
A module name must correspond to a valid repository path, as ns
uses the module name to fetch and
manage modules as needed.
module_name: "github.com/username/repo"
Dependencies
Modules can depend on other modules, which allows applications to use servers, resources, etc., from
packages that live in a dependency. ns
automatically downloads dependencies into a local cache as
needed.
Dependencies are managed via ns mod
but can also be edited manually in the module definition
(ns-workspace.cue
).
dependency: {
"namespacelabs.dev/foundation": {
version: "f8ad005f1e92ceb88118d2296840703b0ddcbbe8"
}
}
When performing changes over multiple repositories in parallel, it's often useful to be able to use
the local changes made to a dependent repository without pushing those changes to HEAD. That can be
achieved using replace
.
replace: {
"namespacelabs.dev/foundation": "../path/to/local/foundation"
}
Requirements
A module can express requirements. For example, it can declare which Namespace CLI versions it is compatible with by requiring a minimum API version.
module: "github.com/username/reponame"
requirements: {
api: 37
}
You can determine the API version of your ns
installation with ns version
.
Since namespacelabs.dev/foundation
sets requirements and all modules depend on it, setting
requirements in your module is usually superfluous.
Package
A package is the unit in Namespace's package management. Packages are
defined using standard CUE, over one or more files (with
an extension .cue
). Packages can declare a set of different types of
primitives like servers, tests, etc.
Refer to the syntax reference for more details.
Example of a package that defines a server and an end-to-end test:
server: {
name: "server"
// Build the Go code from the package root
integration: "go"
// The server exposes port 4000 as a public endpoint
services: webapi: {
port: 4000
kind: "http"
ingress: true
}
}
tests: {
putAndGet: {
// Builds the Go binary from the "test" subpackage
integration: go: pkg: "./test"
}
}