aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--examples/simple/flake.lock85
-rw-r--r--examples/simple/flake.nix16
-rw-r--r--examples/system/flake.lock85
-rw-r--r--examples/system/flake.nix87
-rw-r--r--flake.nix25
-rw-r--r--interface/README.md32
-rw-r--r--interface/deploy.json103
-rw-r--r--src/main.rs9
8 files changed, 371 insertions, 71 deletions
diff --git a/examples/simple/flake.lock b/examples/simple/flake.lock
index a57ff9d..7791c84 100644
--- a/examples/simple/flake.lock
+++ b/examples/simple/flake.lock
@@ -1,7 +1,74 @@
{
"nodes": {
+ "deploy-rs": {
+ "inputs": {
+ "naersk": "naersk",
+ "nixpkgs": "nixpkgs_2",
+ "utils": "utils"
+ },
+ "locked": {
+ "lastModified": 1601668691,
+ "narHash": "sha256-1mWf71DPRNgTIUKJ4Dy+CjoyZo4JkPdrwjYJy2UzqZE=",
+ "type": "git",
+ "url": "file:///home/notgne2/Dev/Serokell/deploy-rs"
+ },
+ "original": {
+ "owner": "serokell",
+ "repo": "deploy-rs",
+ "type": "github"
+ }
+ },
+ "naersk": {
+ "inputs": {
+ "nixpkgs": "nixpkgs"
+ },
+ "locked": {
+ "lastModified": 1597138680,
+ "narHash": "sha256-3pDN/W17wjVDbrkgo60xQSb24+QAPQ7ulsUq5atNni0=",
+ "owner": "nmattia",
+ "repo": "naersk",
+ "rev": "529e910a3f423a8211f8739290014b754b2555b6",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nmattia",
+ "ref": "master",
+ "repo": "naersk",
+ "type": "github"
+ }
+ },
"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",
+ "repo": "nixpkgs",
+ "rev": "72b9660dc18ba347f7cd41a9504fc181a6d87dc3",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixpkgs-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "nixpkgs_3": {
+ "locked": {
"lastModified": 1592491430,
"narHash": "sha256-7WNpr16iUyjG4caad137nCqxXNTdct202jy05lslZXA=",
"owner": "NixOS",
@@ -16,7 +83,23 @@
},
"root": {
"inputs": {
- "nixpkgs": "nixpkgs"
+ "deploy-rs": "deploy-rs",
+ "nixpkgs": "nixpkgs_3"
+ }
+ },
+ "utils": {
+ "locked": {
+ "lastModified": 1600209923,
+ "narHash": "sha256-zoOWauTliFEjI++esk6Jzk7QO5EKpddWXQm9yQK24iM=",
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "rev": "3cd06d3c1df6879c9e41cb2c33113df10566c760",
+ "type": "github"
+ },
+ "original": {
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "type": "github"
}
}
},
diff --git a/examples/simple/flake.nix b/examples/simple/flake.nix
index f53352b..d44b888 100644
--- a/examples/simple/flake.nix
+++ b/examples/simple/flake.nix
@@ -5,7 +5,9 @@
{
description = "Deploy GNU hello to localhost";
- outputs = { self, nixpkgs }:
+ inputs.deploy-rs.url = "github:serokell/deploy-rs";
+
+ outputs = { self, nixpkgs, deploy-rs }:
let
setActivate = base: activate: nixpkgs.legacyPackages.x86_64-linux.symlinkJoin {
name = ("activatable-" + base.name);
@@ -29,16 +31,10 @@
hostname = "localhost";
profiles.hello = {
user = "balsoft";
- path = setActivate nixpkgs.legacyPackages.x86_64-linux.hello "./bin/hello";
+ path = deploy-rs.lib.x86_64-linux.setActivate nixpkgs.legacyPackages.x86_64-linux.hello "./bin/hello";
};
};
- checks = builtins.mapAttrs
- (_: pkgs: {
- jsonschema = pkgs.runCommandNoCC "jsonschema-deploy-simple" { }
- "${pkgs.python3.pkgs.jsonschema}/bin/jsonschema -i ${
- pkgs.writeText "deploy.json" (builtins.toJSON self.deploy)
- } ${../../interface/deploy.json} && touch $out";
- })
- nixpkgs.legacyPackages;
+
+ checks = { "x86_64-linux" = { jsonSchema = deploy-rs.lib.x86_64-linux.checkSchema self.deploy; }; };
};
}
diff --git a/examples/system/flake.lock b/examples/system/flake.lock
index a57ff9d..d3e489a 100644
--- a/examples/system/flake.lock
+++ b/examples/system/flake.lock
@@ -1,7 +1,74 @@
{
"nodes": {
+ "deploy-rs": {
+ "inputs": {
+ "naersk": "naersk",
+ "nixpkgs": "nixpkgs_2",
+ "utils": "utils"
+ },
+ "locked": {
+ "lastModified": 1601668691,
+ "narHash": "sha256-HvzPMsgSOQfCRoPtkwLRv09CkNjOsLHjcZtyHF+8Zbs=",
+ "type": "git",
+ "url": "file:///home/notgne2/Dev/Serokell/deploy-rs"
+ },
+ "original": {
+ "owner": "serokell",
+ "repo": "deploy-rs",
+ "type": "github"
+ }
+ },
+ "naersk": {
+ "inputs": {
+ "nixpkgs": "nixpkgs"
+ },
+ "locked": {
+ "lastModified": 1597138680,
+ "narHash": "sha256-3pDN/W17wjVDbrkgo60xQSb24+QAPQ7ulsUq5atNni0=",
+ "owner": "nmattia",
+ "repo": "naersk",
+ "rev": "529e910a3f423a8211f8739290014b754b2555b6",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nmattia",
+ "ref": "master",
+ "repo": "naersk",
+ "type": "github"
+ }
+ },
"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",
+ "repo": "nixpkgs",
+ "rev": "72b9660dc18ba347f7cd41a9504fc181a6d87dc3",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixpkgs-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "nixpkgs_3": {
+ "locked": {
"lastModified": 1592491430,
"narHash": "sha256-7WNpr16iUyjG4caad137nCqxXNTdct202jy05lslZXA=",
"owner": "NixOS",
@@ -16,7 +83,23 @@
},
"root": {
"inputs": {
- "nixpkgs": "nixpkgs"
+ "deploy-rs": "deploy-rs",
+ "nixpkgs": "nixpkgs_3"
+ }
+ },
+ "utils": {
+ "locked": {
+ "lastModified": 1600209923,
+ "narHash": "sha256-zoOWauTliFEjI++esk6Jzk7QO5EKpddWXQm9yQK24iM=",
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "rev": "3cd06d3c1df6879c9e41cb2c33113df10566c760",
+ "type": "github"
+ },
+ "original": {
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "type": "github"
}
}
},
diff --git a/examples/system/flake.nix b/examples/system/flake.nix
index 68cf3ce..32fefa1 100644
--- a/examples/system/flake.nix
+++ b/examples/system/flake.nix
@@ -5,65 +5,42 @@
{
description = "Deploy a full system with hello service as a separate profile";
- outputs = { self, nixpkgs }:
- let
- setActivate = base: activate: nixpkgs.legacyPackages.x86_64-linux.symlinkJoin {
- name = ("activatable-" + base.name);
- paths = [
- base
- (nixpkgs.legacyPackages.x86_64-linux.writeTextFile {
- name = base.name + "-activate-path";
- text = ''
- #!${nixpkgs.legacyPackages.x86_64-linux.runtimeShell}
- ${activate}
- '';
- executable = true;
- destination = "/activate";
- })
- ];
- };
- in
- {
- nixosConfigurations.example-nixos-system = nixpkgs.lib.nixosSystem {
- system = "x86_64-linux";
- modules = [ ./configuration.nix ];
- };
+ inputs.deploy-rs.url = "github:serokell/deploy-rs";
- nixosConfigurations.bare = nixpkgs.lib.nixosSystem {
- system = "x86_64-linux";
- modules =
- [ ./bare.nix "${nixpkgs}/nixos/modules/virtualisation/qemu-vm.nix" ];
- };
+ outputs = { self, nixpkgs, deploy-rs }: {
+ nixosConfigurations.example-nixos-system = nixpkgs.lib.nixosSystem {
+ system = "x86_64-linux";
+ modules = [ ./configuration.nix ];
+ };
- # This is the application we actually want to run
- defaultPackage.x86_64-linux = import ./hello.nix nixpkgs;
+ nixosConfigurations.bare = nixpkgs.lib.nixosSystem {
+ system = "x86_64-linux";
+ modules =
+ [ ./bare.nix "${nixpkgs}/nixos/modules/virtualisation/qemu-vm.nix" ];
+ };
- deploy.nodes.example = {
- sshOpts = [ "-p" "2221" ];
- hostname = "localhost";
- fastConnection = true;
- profiles = {
- system = {
- sshUser = "admin";
- path =
- setActivate self.nixosConfigurations.example-nixos-system.config.system.build.toplevel "./bin/switch-to-configuration switch";
- user = "root";
- };
- hello = {
- sshUser = "hello";
- path = setActivate self.defaultPackage.x86_64-linux "./bin/activate";
- user = "hello";
- };
+ # This is the application we actually want to run
+ defaultPackage.x86_64-linux = import ./hello.nix nixpkgs;
+
+ deploy.nodes.example = {
+ sshOpts = [ "-p" "2221" ];
+ hostname = "localhost";
+ fastConnection = true;
+ profiles = {
+ system = {
+ sshUser = "admin";
+ path =
+ deploy-rs.lib.x86_64-linux.setActivate self.nixosConfigurations.example-nixos-system.config.system.build.toplevel "./bin/switch-to-configuration switch";
+ user = "root";
+ };
+ hello = {
+ sshUser = "hello";
+ path = deploy-rs.lib.x86_64-linux.setActivate self.defaultPackage.x86_64-linux "./bin/activate";
+ user = "hello";
};
};
-
- checks = builtins.mapAttrs
- (_: pkgs: {
- jsonschema = pkgs.runCommandNoCC "jsonschema-deploy-system" { }
- "${pkgs.python3.pkgs.jsonschema}/bin/jsonschema -i ${
- pkgs.writeText "deploy.json" (builtins.toJSON self.deploy)
- } ${../../interface/deploy.json} && touch $out";
- })
- nixpkgs.legacyPackages;
};
+
+ checks = { "x86_64-linux" = { jsonSchema = deploy-rs.lib.x86_64-linux.checkSchema self.deploy; }; };
+ };
}
diff --git a/flake.nix b/flake.nix
index d3d1817..9cfaa49 100644
--- a/flake.nix
+++ b/flake.nix
@@ -14,12 +14,35 @@
let
pkgs = import nixpkgs { inherit system; };
naersk-lib = pkgs.callPackage naersk { };
- in {
+ 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 ./.;
defaultApp = {
type = "app";
program = "${self.defaultPackage."${system}"}/bin/deploy";
};
+
+ lib = {
+ inherit setActivate;
+
+ 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
new file mode 100644
index 0000000..c6b52bd
--- /dev/null
+++ b/interface/README.md
@@ -0,0 +1,32 @@
+A flake must have a `deploy` output with the following structure:
+
+```
+deploy
+├── <generic args>
+└── nodes
+ ├── <NODE>
+ │   ├── <generic args>
+ │   ├── hostname
+ │   └── profiles
+ │   ├── <PROFILE>
+ │   │   ├── <generic args>
+ │   │   ├── bootstrap
+ │   │   └── path
+ │   └── <PROFILE>...
+ └── <NODE>...
+
+```
+
+Where `<generic args>` are all optional and can be one or multiple of:
+
+- `sshUser` -- user to connect as
+- `user` -- user to install and activate profiles with
+- `sshOpts` -- options passed to `nix copy` and `ssh`
+- `fastConnection` -- whether the connection from this host to the target one is fast (if it is, don't substitute on target and copy the entire closure) [default: `false`]
+- `autoRollback` -- whether to roll back when the deployment fails [default: `false`]
+
+A formal definition for the structure can be found in [the JSON schema](./deploy.json)
+
+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`.
diff --git a/interface/deploy.json b/interface/deploy.json
new file mode 100644
index 0000000..aaa6534
--- /dev/null
+++ b/interface/deploy.json
@@ -0,0 +1,103 @@
+{
+ "$schema": "http://json-schema.org/draft/2019-09/schema#",
+ "title": "Deploy",
+ "description": "Matches a correct deploy attribute of a flake",
+ "definitions": {
+ "generic_settings": {
+ "type": "object",
+ "properties": {
+ "sshUser": {
+ "type": "string"
+ },
+ "user": {
+ "type": "string"
+ },
+ "sshOpts": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "fastConnection": {
+ "type": "boolean"
+ },
+ "autoRollback": {
+ "type": "boolean"
+ }
+ }
+ },
+ "node_settings": {
+ "type": "object",
+ "properties": {
+ "hostname": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "hostname"
+ ]
+ },
+ "profile_settings": {
+ "type": "object",
+ "properties": {
+ "path": {
+ "type": "string"
+ },
+ "bootstrap": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "path"
+ ]
+ }
+ },
+ "type": "object",
+ "allOf": [
+ {
+ "$ref": "#/definitions/generic_settings"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "nodes": {
+ "type": "object",
+ "patternProperties": {
+ "[A-z][A-z0-9_-]*": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/generic_settings"
+ },
+ {
+ "$ref": "#/definitions/node_settings"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "profiles": {
+ "type": "object",
+ "patternProperties": {
+ "[A-z][A-z0-9_-]*": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/generic_settings"
+ },
+ {
+ "$ref": "#/definitions/profile_settings"
+ }
+ ]
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ }
+ ]
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ }
+ ]
+} \ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
index 0d80e42..219c3e5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -10,6 +10,7 @@ use tokio::process::Command;
use merge::Merge;
extern crate pretty_env_logger;
+
#[macro_use]
extern crate log;
@@ -177,12 +178,14 @@ async fn get_deployment_data(
let mut c = match supports_flakes {
true => Command::new("nix"),
- false => Command::new("nix-instanciate"),
+ false => Command::new("nix-instantiate"),
};
let mut build_command = match supports_flakes {
true => {
- c.arg("eval").arg("--json").arg(format!("{}#deploy", repo))
+ c.arg("eval")
+ .arg("--json")
+ .arg(format!("{}#deploy", repo))
}
false => {
c
@@ -190,7 +193,7 @@ async fn get_deployment_data(
.arg("--read-write-mode")
.arg("--json")
.arg("--eval")
- .arg("--E")
+ .arg("-E")
.arg(format!("let r = import {}/.; in if builtins.isFunction r then (r {{}}).deploy else r.deploy", repo))
}
};