From 8a1705988e548ba040cdb6e3884034b78916641c Mon Sep 17 00:00:00 2001 From: Dmitry Ukov Date: Fri, 25 Nov 2016 00:04:21 +0300 Subject: [PATCH 01/11] Fixed spec file Change-Id: I546db287a8e55e169878f7c5b9c203989c5e4368 --- specs/fuel-nailgun-extension-iac.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/fuel-nailgun-extension-iac.spec b/specs/fuel-nailgun-extension-iac.spec index 46bce03..15ac466 100644 --- a/specs/fuel-nailgun-extension-iac.spec +++ b/specs/fuel-nailgun-extension-iac.spec @@ -20,7 +20,7 @@ Nailgun extension that generates deployment data based on configuration files published in external git repository %prep -%setup -q -n %{name}-%{version} +%setup -q -c -n %{name}-%{version} %build %py2_build From 663a12d1c00c27ad477bf2cf7b6a2bc0c3980530 Mon Sep 17 00:00:00 2001 From: Dmitry Ukov Date: Fri, 25 Nov 2016 22:08:24 +0300 Subject: [PATCH 02/11] Added OSLO_PACKAGE_VERSION env variable Python pbr module requires .git directory to determine package version. Perestroika creates sources tarball using git archive command which removes .git folder Change-Id: I74f2b6c62f9c388507d3e8ea6fe853906ee20859 --- specs/fuel-nailgun-extension-iac.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/fuel-nailgun-extension-iac.spec b/specs/fuel-nailgun-extension-iac.spec index 15ac466..ec447b1 100644 --- a/specs/fuel-nailgun-extension-iac.spec +++ b/specs/fuel-nailgun-extension-iac.spec @@ -23,10 +23,10 @@ published in external git repository %setup -q -c -n %{name}-%{version} %build -%py2_build +export OSLO_PACKAGE_VERSION=%{version} %py2_build %install -%py2_install +export OSLO_PACKAGE_VERSION=%{version} %py2_install %files %license LICENSE From c6ab6b5be8ce65720ed905cf3594f8360941ced0 Mon Sep 17 00:00:00 2001 From: Dmitry Ukov Date: Thu, 24 Nov 2016 17:58:25 +0300 Subject: [PATCH 03/11] Fixed issues with --key parameter Added logic for gitrepo object to handle repositories without keys Change-Id: Icef48dc98a8166ee1f21c0be64b61cad8eab9123 --- fuel_external_git/objects.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/fuel_external_git/objects.py b/fuel_external_git/objects.py index c03237f..e9c82c0 100644 --- a/fuel_external_git/objects.py +++ b/fuel_external_git/objects.py @@ -66,8 +66,9 @@ class GitRepo(NailgunObject): except exc.NoSuchPathError: logger.debug("Repo folder does not exist. Cloning repo") self._create_key_file(instance.repo_name, instance.user_key) - os.environ['GIT_SSH'] = \ - self._get_ssh_cmd(instance.repo_name) + if instance.user_key: + os.environ['GIT_SSH'] = \ + self._get_ssh_cmd(instance.repo_name) repo_path = os.path.join(const.REPOS_DIR, instance.repo_name) repo = Repo.clone_from(instance.git_url, repo_path) @@ -83,8 +84,10 @@ class GitRepo(NailgunObject): logger.debug('Repo directory exists. Removing...') shutil.rmtree(repo_path) - self._create_key_file(data['repo_name'], data['user_key']) - os.environ['GIT_SSH'] = self._get_ssh_cmd(data['repo_name']) + user_key = data.get('user_key', '') + if user_key: + self._create_key_file(data['repo_name'], user_key) + os.environ['GIT_SSH'] = self._get_ssh_cmd(data['repo_name']) repo = Repo.clone_from(data['git_url'], repo_path) instance = super(GitRepo, self).create(data) @@ -114,13 +117,18 @@ class GitRepo(NailgunObject): return logger.debug("Repo TTL exceeded. Fetching code...") - ssh_cmd = self._get_ssh_cmd(instance.repo_name) + git_shell_env = {} + if instance.user_key: + ssh_cmd = self._get_ssh_cmd(instance.repo_name) - if not os.path.exists(self._get_key_path(instance.repo_name)): - logger.debug('Key file does not exist. Creating...') - self._create_key_file(instance.repo_name) + if not os.path.exists(self._get_key_path(instance.repo_name)): + logger.debug('Key file does not exist. Creating...') + self._create_key_file(instance.repo_name) - with instance.repo.git.custom_environment(GIT_SSH=ssh_cmd): + logger.debug("Updating ENV with ssh command") + git_shell_env['GIT_SSH'] = ssh_cmd + + with instance.repo.git.custom_environment(**git_shell_env): commit = instance.repo.remotes.origin.fetch(refspec=instance.ref) commit = commit[0].commit instance.repo.head.reference = commit From e2c4e9193083f1566e0ec8560b92023ebf0a6b27 Mon Sep 17 00:00:00 2001 From: Dmitry Ukov Date: Thu, 24 Nov 2016 15:31:47 +0300 Subject: [PATCH 04/11] Added support global and cluster overrides Change-Id: I0188d8f0b1e095d1de20a12b5f9279c9b66d8ff5 --- fuel_external_git/extension.py | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/fuel_external_git/extension.py b/fuel_external_git/extension.py index 8bd9271..7e54b77 100644 --- a/fuel_external_git/extension.py +++ b/fuel_external_git/extension.py @@ -115,7 +115,7 @@ class OpenStackConfigPipeline(BasePipeline): Genereate OpenStack configuration hash based on configuration files stored in git repository associated with a particular environment """ - logger.info("Started serialisation for node {}".format(node.id)) + logger.info("Started serialization for node {}".format(node.id)) repo = GitRepo.get_by_cluster_id(node.cluster_id) if not repo: return node_data @@ -130,19 +130,21 @@ class OpenStackConfigPipeline(BasePipeline): data = cls.lcm_v2(repo_path, node_data) utils.deep_merge(node_data, data) - logger.info("Finished serialisation for node {}".format(node.id)) + logger.info("Finished serialization for node {}".format(node.id)) return node_data @classmethod def process_deployment_for_cluster(self, cluster, data): - logger.info("Started serialisation for cluster {}".format(cluster.id)) + logger.info("Started serialization for cluster {}".format(cluster.id)) repo = GitRepo.get_by_cluster_id(cluster.id) if not repo: return data + repo_path = os.path.join(const.REPOS_DIR, repo.repo_name) + yaml_drv = 'fuel_external_git.drivers.yaml_driver.YamlConfig' + if repo.manage_master: GitRepo.checkout(repo) - repo_path = os.path.join(const.REPOS_DIR, repo.repo_name) resource_mapping = ExternalGit.ext_settings['master_mapping'] master_config = utils.get_config_hash( repo_path, @@ -152,7 +154,21 @@ class OpenStackConfigPipeline(BasePipeline): data['master_config'] = master_config - logger.info("Finished serialisation for cluster {}".format(cluster.id)) + overrides = {} + for override in ('global.yaml', 'cluster.yaml'): + res_mapping = { + override: { + 'driver': yaml_drv, + 'resource': 'yaml' + } + } + override_data = utils.get_config_hash(repo_path, + res_mapping, + exts=['yaml']) + utils.deep_merge(overrides, override_data) + + utils.deep_merge(data, overrides) + logger.info("Finished serialization for cluster {}".format(cluster.id)) return data From a7bc4d88b1a21cf3988323c00497145e1bcb3bb4 Mon Sep 17 00:00:00 2001 From: Dmitry Ukov Date: Mon, 28 Nov 2016 12:17:35 +0300 Subject: [PATCH 05/11] Whitelist rules bulk deletion User should be able to specify list of rule IDs to delete Change-Id: I500aa50af377947e3d59b3dff179ebe3734cf988 --- README.md | 2 +- doc/cli.md | 4 ++-- fuel_external_git/fuelclient_audit.py | 10 ++++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 07f9b4e..6ca2bfd 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,7 @@ fuel2 audit whitelist show These rules can be managed by following commands: ``` fuel2 audit whitelist add --task --rule -fuel2 audit whitelist delete +fuel2 audit whitelist delete [ ...] fuel2 audit whitelist load fromfile ``` diff --git a/doc/cli.md b/doc/cli.md index 7770926..9b12c9f 100644 --- a/doc/cli.md +++ b/doc/cli.md @@ -70,9 +70,9 @@ To add a rule: fuel2 audit whitelist add --task --rule ``` -To delete a rule: +To delete a rule or set of rules: ``` -fuel2 audit whitelist delete +fuel2 audit whitelist delete [ ... ] ``` To add rules from YAML file: diff --git a/fuel_external_git/fuelclient_audit.py b/fuel_external_git/fuelclient_audit.py index fd17553..0a3eea7 100644 --- a/fuel_external_git/fuelclient_audit.py +++ b/fuel_external_git/fuelclient_audit.py @@ -309,15 +309,17 @@ class WhitelistRuleDelete(command.Command): parser = super(WhitelistRuleDelete, self).get_parser(prog_name) parser.add_argument('rule_id', type=int, + nargs='+', help='Rule ID to delete') return parser def take_action(self, parsed_args): - rule_id = parsed_args.rule_id + rule_ids = parsed_args.rule_id - fc_client.delete_request( - '/clusters/changes-whitelist/{rule}'.format(rule=rule_id) - ) + for rule in rule_ids: + fc_client.delete_request( + '/clusters/changes-whitelist/{rule}'.format(rule=rule) + ) return ((), {}) From 99d1bc311046d69733a5629859a573ae139f4ef6 Mon Sep 17 00:00:00 2001 From: Dmitry Ukov Date: Mon, 28 Nov 2016 16:05:36 +0300 Subject: [PATCH 06/11] Adjusted README file Documented new git repository structure Change-Id: Ie40441ba8be0c8177bb14b09598e099f55f1e141 --- README.md | 63 ++++++++++++++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 6ca2bfd..67f389a 100644 --- a/README.md +++ b/README.md @@ -63,51 +63,48 @@ fuel2 gitrepo get configs --env 1 Here is the example repo structure ``` . -|-- controller_configs -| `-- glance-api.conf -|-- node_1_configs -| `-- nova.conf -|-- nova.conf -|-- overrides.yaml -`-- tools - `-- show-config-for.py +|-- cluster.yaml +|-- nodes +| `-- node-1.domain.local.yaml +`-- roles + |-- compute.yaml + |-- controller.yaml + `-- primary-controller.yaml ``` -There are three levels of configuration: Global, Role, Node. Each level has higher priority in terms +There are three levels of configuration: Cluster, Role, Node. Each level has higher priority in terms of configuration parameters. -* Global - configuration parameters from all configs from this level will be applied to all nodes +* Cluster - configuration parameters from all configs from this level will be applied to all nodes in environment. * Role - configuration parameters from all configs from this level will be applied to nodes with a particular role. Parameters from this level will override parameters from Global level * Node - configuration parameters from all configs from this level will be applied to node with a particular id. Parameters from this level will override parameters from Global and Role levels -For example we have ```nova.conf``` file with ```debug = True``` in Global level and ```nova.conf``` -with ```debug = False``` in Role level. Resulting configuration will be: +For example we have following contents of the files ``` -[DEFAULT] -debug = False +# cat cluster.yaml +configuration: + nova_config: + 'DEFAULT/nova_test': + value: cluster_param + 'DEFAULT/another_param': + value: another_param_value + +# cat roles/primary-controller.yaml +configuration: + nova_config: + 'DEFAULT/nova_test': + value: controller_param ``` -Configuration files for Global level should be placed in repo root. Role and Node levels should be -described in overrides.yaml placed in repo root directory using following format +Resulting configuration Hash will be: ``` -nodes: - '': '' -roles: - '': '' +configuration: + nova_config: + 'DEFAULT/nova_test': + value: controller_param + 'DEFAULT/another_param': + value: another_param_value ``` -Example overrides.yaml -``` -nodes: - '1': node_1_configs - '2': node_2_configs -roles: - 'cinder': 'cinder_configs' - 'compute': 'compute_configs' - 'controller': 'controller_configs' - 'primary-controller': 'controller_configs' -``` -Configuration files for Role and Node levels should be placed in corresponding directory described -in overrides.yaml ### Audit and enforcement This feature enables the operator to audit the changes made to the environment as well as enforce From bb14dd87f5e51ef6c82ad0ed3d852e2a1b984952 Mon Sep 17 00:00:00 2001 From: Dmitry Ukov Date: Fri, 2 Dec 2016 11:35:21 +0300 Subject: [PATCH 07/11] Migrations should be added to rpm package Change-Id: Iba2ffcf8d54d6b532733c367961f52071e47a114 --- fuel_external_git/migrations/__init__.py | 0 .../migrations/versions/__init__.py | 0 .../gitrepo/tools/show-config-for.py | 103 ------------------ 3 files changed, 103 deletions(-) create mode 100644 fuel_external_git/migrations/__init__.py create mode 100644 fuel_external_git/migrations/versions/__init__.py delete mode 100644 fuel_external_git/templates/gitrepo/tools/show-config-for.py diff --git a/fuel_external_git/migrations/__init__.py b/fuel_external_git/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fuel_external_git/migrations/versions/__init__.py b/fuel_external_git/migrations/versions/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fuel_external_git/templates/gitrepo/tools/show-config-for.py b/fuel_external_git/templates/gitrepo/tools/show-config-for.py deleted file mode 100644 index 9804ea4..0000000 --- a/fuel_external_git/templates/gitrepo/tools/show-config-for.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/bin/env python -# 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 ConfigParser -import os -import sys -import yaml - - -def deep_merge(dct, merge_dct): - for k, v in merge_dct.iteritems(): - if (k in dct and isinstance(dct[k], dict)): - deep_merge(dct[k], merge_dct[k]) - else: - dct[k] = merge_dct[k] - - -def read_config_files(from_dir): - confs = {} - for config_file in os.listdir(from_dir): - if config_file.endswith('conf'): - cfg = ConfigParser.ConfigParser() - cfg.read(os.path.join(from_dir, config_file)) - confs[config_file] = cfg - - return confs - - -def update_configs(orig, new): - for file_name, cfg in new.items(): - global_cfg = orig.get(file_name, None) - if global_cfg: - deep_merge(global_cfg.__dict__, cfg.__dict__) - else: - orig[file_name] = cfg - - -def main(repo_path, dest_dir, role=None, node=None): - overrides_file = os.path.join(repo_path, 'overrides.yaml') - if not (os.path.exists(overrides_file) or role and node): - print("There is no overrides.yaml file. But role or node specified") - sys.exit(1) - else: - overrides = yaml.load(open(overrides_file)) - - configs = read_config_files(repo_path) - if role and overrides['roles'].get(role, None): - cfg_path = os.path.join(repo_path, overrides['roles'][role]) - role_configs = read_config_files(cfg_path) - update_configs(configs, role_configs) - if node and overrides['nodes'].get(node, None): - cfg_path = os.path.join(repo_path, overrides['nodes'][node]) - node_configs = read_config_files(cfg_path) - update_configs(configs, node_configs) - - for file_name, cfg in configs.items(): - with open(os.path.join(dest_dir, file_name), 'w') as fd: - cfg.write(fd) - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Generate Configs') - parser.add_argument('-s', '--src', dest='src', action='store', - help='Config Source dir', required=True) - parser.add_argument('-d', '--dst', dest='dst', action='store', - help='Config Destination dir', required=True) - parser.add_argument('-r', '--role', dest='role', action='store', - help='Generate configs for role') - parser.add_argument('-n', '--node', dest='node', action='store', - help='Generate configs for node') - parser.add_argument('-f', '--force', dest='force', action='store_true', - help='Force generate configs') - - args = parser.parse_args() - - if not args.force and args.node and not args.role: - print(("You have to specify role for node to get full config file." - " Use --force parameter to ignore this")) - sys.exit(1) - - src = os.path.abspath(args.src) - dst = os.path.abspath(args.dst) - if not os.path.isdir(src): - print("Source dir {} does not exists".format(args.src)) - sys.exit(1) - if os.path.isdir(dst): - print("Destination dir {} exists.".format(args.dst)) - print("Remove it to proceed or specify different path") - sys.exit(1) - else: - os.mkdir(dst) - - main(src, dst, role=args.role, node=args.node) From c626c76d41551665b9bc119906ac2c959483e12b Mon Sep 17 00:00:00 2001 From: Dmitry Ukov Date: Fri, 2 Dec 2016 13:45:48 +0300 Subject: [PATCH 08/11] Include all file from fuel_external_git dir Change-Id: I2dea68625853cb970a2626ce894ac79b25650986 --- MANIFEST.in | 1 + 1 file changed, 1 insertion(+) diff --git a/MANIFEST.in b/MANIFEST.in index c978a52..a6e4a82 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,5 +2,6 @@ include AUTHORS include ChangeLog exclude .gitignore exclude .gitreview +recursive-include fuel_external_git * global-exclude *.pyc From 75019a58dcc78a929471840f09dcdfdee65262e9 Mon Sep 17 00:00:00 2001 From: Dmitry Ukov Date: Fri, 2 Dec 2016 14:56:24 +0300 Subject: [PATCH 09/11] Make lcmv2 default Change-Id: Icfe3d74c7b886b354dd7546501b599e72150d4f6 --- fuel_external_git/extension.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fuel_external_git/extension.py b/fuel_external_git/extension.py index 7e54b77..ef930fe 100644 --- a/fuel_external_git/extension.py +++ b/fuel_external_git/extension.py @@ -123,7 +123,7 @@ class OpenStackConfigPipeline(BasePipeline): GitRepo.checkout(repo) repo_path = os.path.join(const.REPOS_DIR, repo.repo_name) - lcm_version = ExternalGit.ext_settings.get('lcm_version', 'v1') + lcm_version = ExternalGit.ext_settings.get('lcm_version', 'v2') if lcm_version == 'v1': data = cls.lcm_v1(node, node_data, repo_path) else: From a3171ef317f6816004327bc4b6583fd5b9eaf337 Mon Sep 17 00:00:00 2001 From: Dmitry Ukov Date: Tue, 24 Jan 2017 13:29:43 +0400 Subject: [PATCH 10/11] User can add all outofsync tasks to whitelist Change-Id: Ic73913d72ed5eaecb8a44fad47413ad47d94287d --- fuel_external_git/fuelclient_audit.py | 41 +++++++++++++++++++++++++++ setup.cfg | 1 + 2 files changed, 42 insertions(+) diff --git a/fuel_external_git/fuelclient_audit.py b/fuel_external_git/fuelclient_audit.py index 0a3eea7..5998c9e 100644 --- a/fuel_external_git/fuelclient_audit.py +++ b/fuel_external_git/fuelclient_audit.py @@ -355,3 +355,44 @@ class WhitelistRuleAddFromFile(lister.Lister, command.Command): ret = data_utils.get_display_data_multi(self.columns, ret) return (self.columns, ret) + + +class WhitelistRuleAddAll(OutOfSyncResources): + columns = ( + 'id', + 'fuel_task', + 'rule' + ) + + def take_action(self, parsed_args): + task_id = parsed_args.task + if not task_id: + all_tasks = Task.get_all() + env_tasks = filter( + lambda t: t.data['cluster'] == parsed_args.env and + t.data['name'] == 'dry_run_deployment', + all_tasks) + env_tasks.sort(key=lambda t: t.data['time_start']) + fuel_task = env_tasks[-1] + else: + fuel_task = Task(task_id) + + env_id = fuel_task.data['cluster'] + + changes = Audit.get_outofsync(fuel_task) + + remap = lambda x: { + 'fuel_task': x['task_id'], + 'rule': x['resource'][:254] + } + remap_changes = map(remap, changes) + uniq_data = set(map(lambda x: tuple(x.items()), remap_changes)) + data = map(lambda x: dict(x), uniq_data) + + ret = fc_client.post_request( + '/clusters/{env}/changes-whitelist/'.format(env=env_id), + data + ) + ret = data_utils.get_display_data_multi(self.columns, ret) + + return (self.columns, ret) diff --git a/setup.cfg b/setup.cfg index deecffe..c010d77 100644 --- a/setup.cfg +++ b/setup.cfg @@ -35,3 +35,4 @@ fuelclient: audit_whitelist_add = fuel_external_git.fuelclient_audit:WhitelistRuleAdd audit_whitelist_load_fromfile = fuel_external_git.fuelclient_audit:WhitelistRuleAddFromFile audit_whitelist_delete = fuel_external_git.fuelclient_audit:WhitelistRuleDelete + audit_whitelist_load_all = fuel_external_git.fuelclient_audit:WhitelistRuleAddAll From 705b10f68ad4f50cda2b8cd690775e7ac14d364f Mon Sep 17 00:00:00 2001 From: Andreas Jaeger Date: Thu, 2 Feb 2017 20:03:57 +0100 Subject: [PATCH 11/11] Prepare for using standard python tests Add simple script to setup mysql and postgresql databases, this script can be run by users during testing and will be run by CI systems for specific setup before running unit tests. This is exactly what is currently done by OpenStack CI in project-config. This allows to change in project-config the python-db jobs to python-jobs since python-jobs will call this script initially. See also http://lists.openstack.org/pipermail/openstack-dev/2016-November/107784.html Change-Id: Ie6febef4afcb62571a0619c7f31c2fb1bd3e4fe4 (cherry picked from commit 8e0957c7763d637218e1bf908070cd40ef7697c8) --- tools/test-setup.sh | 57 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100755 tools/test-setup.sh diff --git a/tools/test-setup.sh b/tools/test-setup.sh new file mode 100755 index 0000000..07a0785 --- /dev/null +++ b/tools/test-setup.sh @@ -0,0 +1,57 @@ +#!/bin/bash -xe + +# This script will be run by OpenStack CI before unit tests are run, +# it sets up the test system as needed. +# Developers should setup their test systems in a similar way. + +# This setup needs to be run as a user that can run sudo. + +# The root password for the MySQL database; pass it in via +# MYSQL_ROOT_PW. +DB_ROOT_PW=${MYSQL_ROOT_PW:-insecure_slave} + +# This user and its password are used by the tests, if you change it, +# your tests might fail. +DB_USER=openstack_citest +DB_PW=openstack_citest + +sudo -H mysqladmin -u root password $DB_ROOT_PW + +# It's best practice to remove anonymous users from the database. If +# a anonymous user exists, then it matches first for connections and +# other connections from that host will not work. +sudo -H mysql -u root -p$DB_ROOT_PW -h localhost -e " + DELETE FROM mysql.user WHERE User=''; + FLUSH PRIVILEGES; + GRANT ALL PRIVILEGES ON *.* + TO '$DB_USER'@'%' identified by '$DB_PW' WITH GRANT OPTION;" + +# Now create our database. +mysql -u $DB_USER -p$DB_PW -h 127.0.0.1 -e " + SET default_storage_engine=MYISAM; + DROP DATABASE IF EXISTS openstack_citest; + CREATE DATABASE openstack_citest CHARACTER SET utf8;" + +# Same for PostgreSQL +# The root password for the PostgreSQL database; pass it in via +# POSTGRES_ROOT_PW. +DB_ROOT_PW=${POSTGRES_ROOT_PW:-insecure_slave} + +# Setup user +root_roles=$(sudo -H -u postgres psql -t -c " + SELECT 'HERE' from pg_roles where rolname='$DB_USER'") +if [[ ${root_roles} == *HERE ]];then + sudo -H -u postgres psql -c "ALTER ROLE $DB_USER WITH SUPERUSER LOGIN PASSWORD '$DB_PW'" +else + sudo -H -u postgres psql -c "CREATE ROLE $DB_USER WITH SUPERUSER LOGIN PASSWORD '$DB_PW'" +fi + +# Store password for tests +cat << EOF > $HOME/.pgpass +*:*:*:$DB_USER:$DB_PW +EOF +chmod 0600 $HOME/.pgpass + +# Now create our database +psql -h 127.0.0.1 -U $DB_USER -d template1 -c "DROP DATABASE IF EXISTS openstack_citest" +createdb -h 127.0.0.1 -U $DB_USER -l C -T template0 -E utf8 openstack_citest