summaryrefslogtreecommitdiffstats
path: root/ci/test.sh
blob: 4f8a04219c75a10bcef80d54c6a68bd1d20ee2fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/bin/sh
##############################################################################
# Copyright (c) 2016 Dan Radez (Red Hat)
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Apache License, Version 2.0
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################

set -e

# Make sure python dependencies are installed
for pkg in epel-release python34-devel python34-nose python-pep8; do
  if ! rpm -q ${pkg} > /dev/null; then
    if ! sudo yum install -y ${pkg}; then
      echo "Failed to install ${pkg} package..."
      exit 1
    fi
  fi
done

# Make sure coverage is installed
if ! python3 -c "import coverage" &> /dev/null; then sudo easy_install-3.4 coverage; fi

pushd ../build/ > /dev/null
make python-tests
make python-pep8-check
popd > /dev/null
light .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
#!/usr/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 collections
import copy
import os
import sys
import traceback
import yaml
import six
import re


#convert comments into 'comments<num>: ...' YAML
def to_commented_yaml(filename):
    out_str = ''
    last_non_comment_spaces = ''
    with open(filename, 'r') as f:
        comment_count = 0
        for line in f:
            char_count = 0
            spaces = ''
            for char in line:
                char_count += 1
                if char == ' ':
                    spaces+=' '
                    next;
                elif char == '#':
                    comment_count += 1
                    comment = line[char_count:-1]
                    out_str += "%scomment%i_%i: '%s'\n" % (last_non_comment_spaces, comment_count, len(spaces), comment)
                    break;
                else:
                    last_non_comment_spaces = spaces
                    out_str += line

                    #inline comments check
                    m = re.match(".*:.*#(.*)", line)
                    if m:
                        comment_count += 1
                        out_str += "%s  inline_comment%i: '%s'\n" % (last_non_comment_spaces, comment_count, m.group(1))
                    break;

    with open(filename, 'w') as f:
        f.write(out_str)

    return out_str

#convert back to normal #commented YAML
def to_normal_yaml(filename):

    with open(filename, 'r') as f:
        data = f.read()

    out_str = ''
    next_line_break = False
    for line in data.split('\n'):
        m = re.match(" +comment[0-9]+_([0-9]+): '(.*)'.*", line) #normal comments
        i = re.match(" +inline_comment[0-9]+: '(.*)'.*", line) #inline comments
        if m:
            if next_line_break:
                out_str += '\n'
                next_line_break = False
            for x in range(0, int(m.group(1))):
                out_str += " "
            out_str += "#%s\n" % m.group(2)
        elif i:
            out_str += " #%s\n" % i.group(1)
            next_line_break = False
        else:
            if next_line_break:
                out_str += '\n'
            out_str += line
            next_line_break = True

    if next_line_break:
        out_str += '\n'

    with open(filename, 'w') as f:
        f.write(out_str)

    return out_str


class description(six.text_type):
    pass

# FIXME: Some of this duplicates code from build_endpoint_map.py, we should
# refactor to share the common code
class TemplateDumper(yaml.SafeDumper):
    def represent_ordered_dict(self, data):
        return self.represent_dict(data.items())

    def description_presenter(self, data):
        if '\n' in data:
            style = '>'
        else:
            style = ''
        return self.represent_scalar(
            yaml.resolver.BaseResolver.DEFAULT_SCALAR_TAG, data, style=style)


# We load mappings into OrderedDict to preserve their order
class TemplateLoader(yaml.SafeLoader):
    def construct_mapping(self, node):
        self.flatten_mapping(node)
        return collections.OrderedDict(self.construct_pairs(node))


TemplateDumper.add_representer(description,
                               TemplateDumper.description_presenter)

TemplateDumper.add_representer(collections.OrderedDict,
                               TemplateDumper.represent_ordered_dict)


TemplateLoader.add_constructor(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
                               TemplateLoader.construct_mapping)

def write_template(template, filename=None):
    with open(filename, 'w') as f:
        yaml.dump(template, f, TemplateDumper, width=120, default_flow_style=False)

def exit_usage():
    print('Usage %s <yaml file>' % sys.argv[0])
    sys.exit(1)

def convert(filename):
    print('Converting %s' % filename)
    try:
        tpl = yaml.load(open(filename).read(), Loader=TemplateLoader)
    except Exception:
        print(traceback.format_exc())
        return 0

    # Check which path we need for run-os-net-config.sh because we have
    # nic config templates in the top-level and network/config
    script_paths = ['network/scripts/run-os-net-config.sh',
                    '../../scripts/run-os-net-config.sh']
    script_path = None
    for p in script_paths:
        check_path = os.path.join(os.path.dirname(filename), p)
        if os.path.isfile(check_path):
            print("Found %s, using %s" % (check_path, p))
            script_path = p
    if script_path is None:
        print("Error couldn't find run-os-net-config.sh relative to filename")
        exit_usage()

    for r in six.iteritems(tpl.get('resources', {})):
        if (r[1].get('type') == 'OS::Heat::StructuredConfig' and
            r[1].get('properties', {}).get('group') == 'os-apply-config' and
            r[1].get('properties', {}).get('config', {}).get('os_net_config')):
            #print("match %s" % r[0])
            new_r = collections.OrderedDict()
            new_r['type'] = 'OS::Heat::SoftwareConfig'
            new_r['properties'] = collections.OrderedDict()
            new_r['properties']['group'] = 'script'
            old_net_config = r[1].get(
                'properties', {}).get('config', {}).get('os_net_config')
            new_config = {'str_replace': collections.OrderedDict()}
            new_config['str_replace']['template'] = {'get_file': script_path}
            new_config['str_replace']['params'] = {'$network_config': old_net_config}
            new_r['properties']['config'] = new_config
            tpl['resources'][r[0]] = new_r
        else:
            print("No match %s" % r[0])
            return 0

    # Preserve typical HOT template key ordering
    od_result = collections.OrderedDict()
    # Need to bump the HOT version so str_replace supports serializing to json
    od_result['heat_template_version'] = "2016-10-14"
    if tpl.get('description'):
        od_result['description'] = description(tpl['description'])
    od_result['parameters'] = tpl['parameters']
    od_result['resources'] = tpl['resources']
    od_result['outputs'] = tpl['outputs']
    #print('Result:')
    #print('%s' % yaml.dump(od_result, Dumper=TemplateDumper, width=120, default_flow_style=False))
    #print('---')
    #replace = raw_input(
        #"Replace file %s?  Answer y/n" % filename).lower() == 'y'
    #if replace:
    #print("Replace %s" % filename)
    write_template(od_result, filename)
    #else:
    #    print("NOT replacing %s" % filename)
    #    return 0
    return 1

if len(sys.argv) < 2:
    exit_usage()

path_args = sys.argv[1:]
exit_val = 0
num_converted = 0

for base_path in path_args:
    if os.path.isfile(base_path) and base_path.endswith('.yaml'):
        to_commented_yaml(base_path)
        num_converted += convert(base_path)
        to_normal_yaml(base_path)
    else:
        print('Unexpected argument %s' % base_path)
        exit_usage()
if num_converted == 0:
  exit_val = 1
sys.exit(exit_val)