Add a command to create a new Kayobe environment
Change-Id: I2f33bda5f2f84bbbb0f40240d2575a0b69ddceea Story: 2002009 Task: 40038
This commit is contained in:
parent
1419636930
commit
2bc568debb
@ -21,6 +21,7 @@ from cliff.command import Command
|
||||
from cliff.hooks import CommandHook
|
||||
|
||||
from kayobe import ansible
|
||||
from kayobe import environment
|
||||
from kayobe import kolla_ansible
|
||||
from kayobe import utils
|
||||
from kayobe import vault
|
||||
@ -1687,3 +1688,34 @@ class BaremetalComputeUpdateDeploymentImage(KayobeAnsibleMixin, VaultMixin,
|
||||
)
|
||||
self.run_kayobe_playbooks(parsed_args, playbooks,
|
||||
extra_vars=extra_vars)
|
||||
|
||||
|
||||
class EnvironmentCreate(KayobeAnsibleMixin, VaultMixin, Command):
|
||||
"""Create a new Kayobe environment."""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(EnvironmentCreate, self).get_parser(prog_name)
|
||||
group = parser.add_argument_group("Kayobe Environments")
|
||||
environment.add_args(group)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.app.LOG.debug("Creating new Kayobe environment")
|
||||
if not parsed_args.environment:
|
||||
self.app.LOG.error("An environment must be specified")
|
||||
sys.exit(1)
|
||||
|
||||
source_config_path = parsed_args.source_config_path
|
||||
if source_config_path:
|
||||
result = utils.is_readable_dir(source_config_path)
|
||||
if not result["result"]:
|
||||
self.app.LOG.error("Kayobe configuration %s is invalid: %s",
|
||||
source_config_path, result["message"])
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
environment.create_kayobe_environment(parsed_args)
|
||||
except Exception as e:
|
||||
self.app.LOG.error("Failed to create environment %s: %s",
|
||||
parsed_args.environment, repr(e))
|
||||
sys.exit(1)
|
||||
|
64
kayobe/environment.py
Normal file
64
kayobe/environment.py
Normal file
@ -0,0 +1,64 @@
|
||||
# Copyright (c) 2021 StackHPC Ltd.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
from kayobe import utils
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def add_args(parser):
|
||||
"""Add arguments required for managing Kayobe environments to a parser."""
|
||||
parser.add_argument("--source-config-path",
|
||||
help="Kayobe configuration to import")
|
||||
|
||||
|
||||
def create_kayobe_environment(parsed_args):
|
||||
"""Create a new Kayobe environment."""
|
||||
if not parsed_args.environment:
|
||||
LOG.error("You must specify an environment to create")
|
||||
sys.exit(1)
|
||||
|
||||
# Ensure environments directory exists and is readable inside config path
|
||||
kc_environments = os.path.join(parsed_args.config_path, "environments")
|
||||
result = utils.is_readable_dir(kc_environments)
|
||||
if not result["result"]:
|
||||
if result["message"] == "Path does not exist":
|
||||
os.mkdir(kc_environments)
|
||||
else:
|
||||
LOG.error("Kayobe global environments directory %s is invalid: %s",
|
||||
kc_environments, result["message"])
|
||||
sys.exit(1)
|
||||
|
||||
env_path = os.path.join(kc_environments, parsed_args.environment)
|
||||
result = utils.is_readable_dir(env_path)
|
||||
if result["result"]:
|
||||
LOG.error("Kayobe environment directory %s already exists", env_path)
|
||||
sys.exit(1)
|
||||
else:
|
||||
if result["message"] == "Path does not exist":
|
||||
os.mkdir(env_path)
|
||||
else:
|
||||
LOG.error("Kayobe environment directory %s is invalid: %s",
|
||||
env_path, result["message"])
|
||||
sys.exit(1)
|
||||
|
||||
source_config_path = parsed_args.source_config_path
|
||||
if source_config_path:
|
||||
utils.copy_dir(source_config_path, env_path)
|
83
kayobe/tests/unit/test_environment.py
Normal file
83
kayobe/tests/unit/test_environment.py
Normal file
@ -0,0 +1,83 @@
|
||||
# Copyright (c) 2021 StackHPC Ltd.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
from kayobe import ansible
|
||||
from kayobe import environment
|
||||
from kayobe import utils
|
||||
|
||||
|
||||
class TestCase(unittest.TestCase):
|
||||
|
||||
@mock.patch.object(utils, "is_readable_dir")
|
||||
def test_unreadable_environments_directory(self, mock_readable_dir):
|
||||
mock_readable_dir.return_value = {
|
||||
"result": False,
|
||||
"message": "Directory is not readable"
|
||||
}
|
||||
parser = argparse.ArgumentParser()
|
||||
args = [
|
||||
"--config-path", "/path/to/config",
|
||||
"--environment", "foo",
|
||||
]
|
||||
ansible.add_args(parser)
|
||||
environment.add_args(parser)
|
||||
parsed_args = parser.parse_args(args)
|
||||
self.assertRaises(SystemExit,
|
||||
environment.create_kayobe_environment, parsed_args)
|
||||
|
||||
@mock.patch.object(utils, "is_readable_dir")
|
||||
def test_environment_exists(self, mock_readable_dir):
|
||||
mock_readable_dir.side_effect = [{"result": True}, {"result": True}]
|
||||
parser = argparse.ArgumentParser()
|
||||
args = [
|
||||
"--config-path", "/path/to/config",
|
||||
"--environment", "foo",
|
||||
]
|
||||
ansible.add_args(parser)
|
||||
environment.add_args(parser)
|
||||
parsed_args = parser.parse_args(args)
|
||||
self.assertRaises(SystemExit,
|
||||
environment.create_kayobe_environment, parsed_args)
|
||||
|
||||
@mock.patch.object(utils, "copy_dir")
|
||||
@mock.patch.object(os, "mkdir")
|
||||
@mock.patch.object(utils, "is_readable_dir")
|
||||
def test_create_kayobe_environment(self, mock_readable_dir, mock_mkdir,
|
||||
mock_copy_dir):
|
||||
mock_readable_dir.return_value = {
|
||||
"result": False,
|
||||
"message": "Path does not exist"
|
||||
}
|
||||
parser = argparse.ArgumentParser()
|
||||
args = [
|
||||
"--config-path", "/path/to/config",
|
||||
"--source-config-path", "/path/to/foo",
|
||||
"--environment", "foo",
|
||||
]
|
||||
ansible.add_args(parser)
|
||||
environment.add_args(parser)
|
||||
parsed_args = parser.parse_args(args)
|
||||
environment.create_kayobe_environment(parsed_args)
|
||||
expected_calls = [
|
||||
mock.call("/path/to/config/environments"),
|
||||
mock.call("/path/to/config/environments/foo"),
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_mkdir.call_args_list)
|
||||
mock_copy_dir.assert_called_once_with(
|
||||
"/path/to/foo", "/path/to/config/environments/foo")
|
@ -17,6 +17,7 @@ import glob
|
||||
import itertools
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
@ -222,3 +223,16 @@ def intersect_limits(args_limit, cli_limit):
|
||||
separator = ':&'
|
||||
limits = [l for l in [args_limit, cli_limit] if l]
|
||||
return separator.join(limits)
|
||||
|
||||
|
||||
def copy_dir(src, dest):
|
||||
if not os.path.isdir(dest):
|
||||
shutil.copytree(src, dest)
|
||||
else:
|
||||
for file in os.listdir(src):
|
||||
src_path = os.path.join(src, file)
|
||||
dest_path = os.path.join(dest, file)
|
||||
if os.path.isdir(src_path):
|
||||
copy_dir(src_path, dest_path)
|
||||
else:
|
||||
shutil.copy2(src_path, dest_path)
|
||||
|
@ -48,6 +48,7 @@ kayobe.cli=
|
||||
control_host_bootstrap = kayobe.cli.commands:ControlHostBootstrap
|
||||
control_host_upgrade = kayobe.cli.commands:ControlHostUpgrade
|
||||
configuration_dump = kayobe.cli.commands:ConfigurationDump
|
||||
environment_create = kayobe.cli.commands:EnvironmentCreate
|
||||
kolla_ansible_run = kayobe.cli.commands:KollaAnsibleRun
|
||||
network_connectivity_check = kayobe.cli.commands:NetworkConnectivityCheck
|
||||
overcloud_bios_raid_configure = kayobe.cli.commands:OvercloudBIOSRAIDConfigure
|
||||
|
Loading…
Reference in New Issue
Block a user