aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornotgne22020-10-10 10:31:58 -0700
committernotgne22020-10-10 10:31:58 -0700
commit4a2b677e892845b121d353864d54aec92a411e48 (patch)
tree39de25748b17ee9d2236a74e297b9bd7c33f6e28
parentdb8301a45796cd919cbfa085f85ac6288e73a8db (diff)
parent219d55e99e792a093c12dbc045bed88a4bfe1916 (diff)
Merge branch 'master' of github.com:notgne2/deploy-rs into master
-rw-r--r--README.md90
-rw-r--r--default.nix13
-rw-r--r--flake.lock37
-rw-r--r--flake.nix50
-rw-r--r--interface/README.md4
-rw-r--r--src/main.rs14
-rw-r--r--src/utils/mod.rs25
7 files changed, 149 insertions, 84 deletions
diff --git a/README.md b/README.md
index 15877d1..2710183 100644
--- a/README.md
+++ b/README.md
@@ -6,32 +6,108 @@ SPDX-License-Identifier: MPL-2.0
# deploy-rs
-A Simple multi-profile Nix-flake deploy tool.
+A Simple, multi-profile Nix-flake deploy tool.
-**This is very early development software, you should expect to find issues**
+**This is very early development software, you should expect to find issues, and things will change**
## Usage
+Basic usage: `deploy [options] <flake>`.
-- `nix run github:serokell/deploy-rs your-flake#node.profile`
-- `nix run github:serokell/deploy-rs your-flake#node`
+The given flake can be just a source `my-flake`, or optionally specify the node to deploy `my-flake#my-node`, or specify a profile too `my-flake#my-node.my-profile`.
+
+You can try out this tool easily with `nix run`:
- `nix run github:serokell/deploy-rs your-flake`
+If you require a signing key to push closures to your server, specify the path to it in the `LOCAL_KEY` environment variable.
+
+Check out `deploy --help` for CLI flags! Remember to check there before making one-time changes to things like hostnames.
+
## API
-Example Nix expressions/configurations are in the [examples folder](./examples).
+### Profile
+
+This is the core of how `deploy-rs` was designed, any number of these can run on a node, as any user (see further down for specifying user information). If you want to mimick the behaviour of traditional tools like NixOps or Morph, try just defining one `profile` called `system`, as root, containing a nixosSystem, and you can even similarly use [home-manager](https://github.com/nix-community/home-manager) on any non-privileged user.
+
+```nix
+{
+ # The command to bootstrap your profile, this is optional
+ bootstrap = "mkdir xyz";
+
+ # A derivation containing your required software, and a script to activate it in `${path}/activate`
+ # For ease of use, `deploy-rs` provides a function to easy all this required activation script to any derivation
+ path = deploy-rs.lib.x86_64-linux.setActivate pkgs.hello "./bin/hello";
+
+ # ...generic options... (see lower section)
+}
+```
+
+### Node
+
+This defines a single node/server, and the profiles you intend it to run.
+
+```nix
+{
+ # The hostname of your server, don't worry, this can be overridden at runtime if needed
+ hostname = "my.server.gov";
+
+ # An optional list containing the order you want profiles to be deployed.
+ profilesOrder = [ "something" "system" ];
+
+ profiles = {
+ system = {}; # Definition shown above
+ something = {}; # Definition shown above
+ };
+
+ # ...generic options... (see lower section)
+}
+```
+
+### Deploy
+
+This is the top level attribute containing all of the options for this tool
+
+```nix
+{
+ nodes = {
+ my-node = {}; # Definition shown above
+ another-node = {}; # Definition shown above
+ };
+
+ # ...generic options... (see lower section)
+}
+```
+
+### Generic options
+
+This is a set of options that can be put in any of the above definitions, with the priority being `profile > node > deploy`
+
+```nix
+{
+ sshUser = "admin"; # This is the user that deploy-rs will use when connecting
+ user = "root"; # This is the user that the profile will be deployed to (will use sudo if not the same as above)
+ sshOpts = [ "-p" "2121" ]; # These are arguments that will be passed to SSH
+ fastConnection = false; # Fast connection to the node. If this is true, copy the whole closure instead of letting the node substitute
+ autoRollback = true; # If the previous profile should be re-activated if activation fails
+}
+```
+
+A stronger definition of the schema is in the [interface directory](./interface), and full working examples Nix expressions/configurations are in the [examples folder](./examples).
## Idea
-`deploy-rs` is a simple Rust program that will take a Nix flake and use it to deploy any of your defined profiles to your nodes. This is _strongly_ based off of [serokell/deploy](https://github.com/serokell/deploy), with the intention of eventually replacing it.
+`deploy-rs` is a simple Rust program that will take a Nix flake and use it to deploy any of your defined profiles to your nodes. This is _strongly_ based off of [serokell/deploy](https://github.com/serokell/deploy), designed to replace it and expand upon it.
This type of design (as opposed to more traditional tools like NixOps or morph) allows for lesser-privileged deployments, and the ability to update different things independently of eachother.
## Things to work on
- ~~Ordered profiles~~
-- Automatic rollbacks if one profile on node failed to deploy (partially implemented)
+- ~~Automatic rollbacks~~
- UI (?)
+- automatic kexec lustration of servers (maybe)
+- Remote health checks
+- Rollback on reconnection failure (technically, rollback if not reconnected to)
## About Serokell
diff --git a/default.nix b/default.nix
new file mode 100644
index 0000000..873ece4
--- /dev/null
+++ b/default.nix
@@ -0,0 +1,13 @@
+(import
+ (
+ let
+ lock = builtins.fromJSON (builtins.readFile ./flake.lock);
+ in
+ fetchTarball {
+ url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
+ sha256 = lock.nodes.flake-compat.locked.narHash;
+ }
+ )
+ {
+ src = ./.;
+ }).defaultNix
diff --git a/flake.lock b/flake.lock
index 0a41d47..cbcd1bc 100644
--- a/flake.lock
+++ b/flake.lock
@@ -1,8 +1,26 @@
{
"nodes": {
+ "flake-compat": {
+ "flake": false,
+ "locked": {
+ "lastModified": 1600853454,
+ "narHash": "sha256-EgsgbcJNZ9AQLVhjhfiegGjLbO+StBY9hfKsCwc8Hw8=",
+ "owner": "edolstra",
+ "repo": "flake-compat",
+ "rev": "94cf59784c73ecec461eaa291918eff0bfb538ac",
+ "type": "github"
+ },
+ "original": {
+ "owner": "edolstra",
+ "repo": "flake-compat",
+ "type": "github"
+ }
+ },
"naersk": {
"inputs": {
- "nixpkgs": "nixpkgs"
+ "nixpkgs": [
+ "nixpkgs"
+ ]
},
"locked": {
"lastModified": 1597138680,
@@ -21,20 +39,6 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1601091160,
- "narHash": "sha256-26UI9LGjRO8Sv253zJZkoapP260QkJPQ2+vRyC1i+kI=",
- "owner": "NixOS",
- "repo": "nixpkgs",
- "rev": "2768436826543af2b1540e4fe6b5afa15850e155",
- "type": "github"
- },
- "original": {
- "id": "nixpkgs",
- "type": "indirect"
- }
- },
- "nixpkgs_2": {
- "locked": {
"lastModified": 1600387253,
"narHash": "sha256-WtdpHuiunPF9QMlcXrWJkESuIjSSjP9WMOKvYQS/D7M=",
"owner": "NixOS",
@@ -51,8 +55,9 @@
},
"root": {
"inputs": {
+ "flake-compat": "flake-compat",
"naersk": "naersk",
- "nixpkgs": "nixpkgs_2",
+ "nixpkgs": "nixpkgs",
"utils": "utils"
}
},
diff --git a/flake.nix b/flake.nix
index 9cfaa49..81603e4 100644
--- a/flake.nix
+++ b/flake.nix
@@ -3,43 +3,53 @@
# SPDX-License-Identifier: MPL-2.0
{
+ description = "A Simple multi-profile Nix-flake deploy tool.";
+
inputs = {
- naersk.url = "github:nmattia/naersk/master";
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
+ naersk = {
+ url = "github:nmattia/naersk/master";
+ inputs.nixpkgs.follows = "nixpkgs";
+ };
utils.url = "github:numtide/flake-utils";
+ flake-compat = {
+ url = "github:edolstra/flake-compat";
+ flake = false;
+ };
};
- outputs = { self, nixpkgs, utils, naersk }:
+ outputs = { self, nixpkgs, utils, naersk, ... }:
utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; };
naersk-lib = pkgs.callPackage naersk { };
- setActivate = base: activate: pkgs.symlinkJoin {
- name = ("activatable-" + base.name);
- paths = [
- base
- (pkgs.writeTextFile {
- name = base.name + "-activate-path";
- text = ''
- #!${pkgs.runtimeShell}
- ${activate}
- '';
- executable = true;
- destination = "/activate";
- })
- ];
- };
in
{
- defaultPackage = naersk-lib.buildPackage ./.;
+ defaultPackage = self.packages."${system}".deploy-rs;
+ packages.deploy-rs = naersk-lib.buildPackage ./.;
- defaultApp = {
+ defaultApp = self.apps."${system}".deploy-rs;
+ apps.deploy-rs = {
type = "app";
program = "${self.defaultPackage."${system}"}/bin/deploy";
};
lib = {
- inherit setActivate;
+ setActivate = base: activate: pkgs.symlinkJoin {
+ name = ("activatable-" + base.name);
+ paths = [
+ base
+ (pkgs.writeTextFile {
+ name = base.name + "-activate-path";
+ text = ''
+ #!${pkgs.runtimeShell}
+ ${activate}
+ '';
+ executable = true;
+ destination = "/activate";
+ })
+ ];
+ };
checkSchema = deploy: pkgs.runCommandNoCC "jsonschema-deploy-system" { }
"${pkgs.python3.pkgs.jsonschema}/bin/jsonschema -i ${pkgs.writeText "deploy.json" (builtins.toJSON deploy)} ${./interface/deploy.json} && touch $out";
diff --git a/interface/README.md b/interface/README.md
index c6b52bd..bfca01e 100644
--- a/interface/README.md
+++ b/interface/README.md
@@ -7,6 +7,7 @@ deploy
├── <NODE>
│   ├── <generic args>
│   ├── hostname
+ │   ├── profilesOrder
│   └── profiles
│   ├── <PROFILE>
│   │   ├── <generic args>
@@ -14,7 +15,6 @@ deploy
│   │   └── path
│   └── <PROFILE>...
└── <NODE>...
-
```
Where `<generic args>` are all optional and can be one or multiple of:
@@ -29,4 +29,4 @@ A formal definition for the structure can be found in [the JSON schema](./deploy
For every profile of every node, arguments are merged with `<PROFILE>` taking precedence over `<NODE>` and `<NODE>` taking precedence over top-level.
-Values can be overridden for all the profiles deployed by setting environment variables with the same names as the profile, for example `sshUser=foobar nix run github:serokell/deploy .` will connect to all nodes as `foobar@<NODE>.hostname`.
+Certain read values can be overridden by supplying flags to the deploy binary, for example `deploy --auto-rollback true .` will enable automatic rollback for all nodes being deployed to, regardless of settings. \ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
index 04d7868..b28a520 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -349,20 +349,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
hostname: opts.hostname,
};
- match (cmd_overrides.purity(), deploy_flake.node, deploy_flake.profile) {
- (utils::OverridePurity::ErrorProfile, _, None) => good_panic!(
- "You have specified an override not suitible for deploying to multiple profiles, please specify your target profile explicitly"
- ),
- (utils::OverridePurity::Error, None, _) => good_panic!(
- "You have specified an override not suitible for deploying to multiple nodes, please specify your target node explicitly"
- ),
-
- (utils::OverridePurity::Warn, None, _) => warn!(
- "Certain overrides you have provided might be dangerous when used on multiple nodes or profiles, be cautious"
- ),
- _ => (),
- };
-
let supports_flakes = test_flake_support().await?;
let data =
diff --git a/src/utils/mod.rs b/src/utils/mod.rs
index 51f977f..672a9ba 100644
--- a/src/utils/mod.rs
+++ b/src/utils/mod.rs
@@ -28,31 +28,6 @@ pub struct CmdOverrides {
pub hostname: Option<String>,
}
-pub enum OverridePurity {
- ErrorProfile,
- Error,
- Warn,
- Pure,
-}
-
-impl CmdOverrides {
- pub fn purity(&self) -> OverridePurity {
- if self.profile_user.is_some() {
- return OverridePurity::ErrorProfile;
- }
-
- if self.hostname.is_some() || self.ssh_user.is_some() {
- return OverridePurity::Error;
- }
-
- if self.ssh_opts.is_some() || self.fast_connection.is_some() {
- return OverridePurity::Warn;
- }
-
- OverridePurity::Pure
- }
-}
-
#[derive(PartialEq, Debug)]
pub struct DeployFlake<'a> {
pub repo: &'a str,