Skip to content

Commit

Permalink
Add deploy without creating a state file
Browse files Browse the repository at this point in the history
  • Loading branch information
adisbladis authored and grahamc committed Mar 22, 2020
1 parent 7a8a4ee commit 1398e9b
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 9 deletions.
1 change: 1 addition & 0 deletions nixops/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@
help="activate unchanged configurations as well",
)
add_common_deployment_options(subparser)
add_common_modify_options(subparser)

subparser = add_subparser(subparsers, "send-keys", help="send encryption keys")
subparser.set_defaults(op=op_send_keys)
Expand Down
44 changes: 44 additions & 0 deletions nixops/evaluation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from dataclasses import dataclass
import subprocess
import typing
import json


@dataclass
class NetworkEval:

description: str = "Unnamed NixOps network"
enableRollback: bool = False
enableState: bool = True


def _eval_attr(
attr, nix_exprs: typing.List[str]
) -> typing.Dict[typing.Any, typing.Any]:
p = subprocess.run(
[
"nix-instantiate",
"--eval-only",
"--json",
"--strict",
# Arg
"--arg",
"checkConfigurationOptions",
"false",
# Attr
"-A",
attr,
]
+ nix_exprs,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
if p.returncode != 0:
raise RuntimeError(p.stderr.decode())

return json.loads(p.stdout)


def eval_network(nix_exprs: typing.List[str]) -> NetworkEval:
result = _eval_attr("network", nix_exprs)
return NetworkEval(**result)
41 changes: 33 additions & 8 deletions nixops/script_defs.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@
from datetime import datetime
from pprint import pprint
import importlib
from functools import lru_cache

from nixops.plugins import get_plugin_manager
from nixops.evaluation import eval_network


pm = get_plugin_manager()
Expand All @@ -37,6 +39,11 @@
]


@lru_cache()
def _create_state(state_file: str) -> nixops.statefile.StateFile:
return nixops.statefile.StateFile(state_file)


def op_list_plugins(args):
if args.verbose:
tbl = create_table([("Installed Plugins", "c"), ("Plugin Reference", "c")])
Expand Down Expand Up @@ -68,14 +75,14 @@ def sort_deployments(
# $NIXOPS_DEPLOYMENT.
def one_or_all(args: argparse.Namespace) -> List[nixops.deployment.Deployment]:
if args.all:
sf = nixops.statefile.StateFile(args.state_file)
sf = _create_state(args.state_file)
return sf.get_all_deployments()
else:
return [open_deployment(args)]


def op_list_deployments(args):
sf = nixops.statefile.StateFile(args.state_file)
sf = _create_state(args.state_file)
tbl = create_table(
[
("UUID", "l"),
Expand All @@ -99,7 +106,7 @@ def op_list_deployments(args):


def open_deployment(args):
sf = nixops.statefile.StateFile(args.state_file)
sf = _create_state(args.state_file)
depl = sf.open_deployment(uuid=args.deployment)

depl.extra_nix_path = sum(args.nix_path or [], [])
Expand Down Expand Up @@ -145,12 +152,19 @@ def modify_deployment(args, depl: nixops.deployment.Deployment):


def op_create(args):
sf = nixops.statefile.StateFile(args.state_file)
sf = _create_state(args.state_file)
depl = sf.create_deployment()
sys.stderr.write("created deployment ‘{0}’\n".format(depl.uuid))
modify_deployment(args, depl)
if args.name or args.deployment:
set_name(depl, args.name or args.deployment)

# When deployment is created without state "name" does not exist
name = args.deployment
if "name" in args:
name = args.name or args.deployment

if name:
set_name(depl, name)

sys.stdout.write(depl.uuid + "\n")


Expand Down Expand Up @@ -284,7 +298,7 @@ def name_to_key(name: str) -> Tuple[str, str, List[object]]:
)

if args.all:
sf = nixops.statefile.StateFile(args.state_file)
sf = _create_state(args.state_file)
if not args.plain:
tbl = create_table([("Deployment", "l")] + table_headers)
for depl in sort_deployments(sf.get_all_deployments()):
Expand Down Expand Up @@ -553,7 +567,18 @@ def op_restore(args):


def op_deploy(args):

# If nix expressions are passed evaluate the network first so we can figure
# out if we need to create state or not
if args.nix_exprs:
network = eval_network(args.nix_exprs)
# If state is not enabled we need to create the deployment first in the in-memory sqlite db
if not network.enableState:
args.state_file = ":memory:"
op_create(args)

depl = open_deployment(args)

if args.confirm:
depl.logger.set_autoresponse("y")
if args.evaluate_only:
Expand Down Expand Up @@ -710,7 +735,7 @@ def op_export(args):


def op_import(args):
sf = nixops.statefile.StateFile(args.state_file)
sf = _create_state(args.state_file)
existing = set(sf.query_deployments())

dump = json.loads(sys.stdin.read())
Expand Down
5 changes: 4 additions & 1 deletion nixops/statefile.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ class StateFile(object):
def __init__(self, db_file: str) -> None:
self.db_file: str = db_file

if os.path.splitext(db_file)[1] not in [".nixops", ".charon"]:
if db_file != ":memory:" and os.path.splitext(db_file)[1] not in [
".nixops",
".charon",
]:
raise Exception(
"state file ‘{0}’ should have extension ‘.nixops’".format(db_file)
)
Expand Down

0 comments on commit 1398e9b

Please sign in to comment.