<commit_before>#!/usr/bin/python

# Copyright 2014 IBM Corporation
# <NAME>(<EMAIL>)

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.

# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


import getopt
import sys
import zipfile
import tempfile
import os.path
import logging
import shutil
# from jujutranslator.nodetype2charm import Nodetype2Charm
from translator.toscalib.tosca_template import ToscaTemplate
from pprint import pprint
from inspect import currentframe, getframeinfo

try:
    from yaml import CSafeLoader as Loader
except ImportError:
    from yaml import SafeLoader as Loader


def usage():
    print 'juju-tosca-import.py [--help] [--description] <CSAR zip file>'


def description():
    print """Juju plugin to import a orchestration specification from
    a CSAR file containing YAML files"""


def unpack_zip(zipfn):
    # zip file needs to be in the TOSCA CSAR format
    try:
        zip = zipfile.ZipFile(zipfn, 'r')
    except:
        print "Unable to open zip file", zipfn
        usage()
        sys.exit(2)

    logger.debug(zip.namelist())
    tmpdir = tempfile.mkdtemp(prefix="CSAR_", dir="./")
    zip.extractall(tmpdir)
    return tmpdir


def parse_metafile(tmpdir):
    if not os.path.isfile(tmpdir+"/TOSCA-Metadata/TOSCA.meta"):
        print "TOSCA.meta not found in CSAR file"
        sys.exit(1)
    try:
        tfile = open(tmpdir+'/TOSCA-Metadata/TOSCA.meta', 'r')
    except:
        print "Couldn't open Tosca metafile"
        sys.exit(2)
    tlines = tfile.readlines()
    for line in tlines:
        if (line.startswith("Name")):
            attr, value = line.split(":", 2)
            # if it's a yaml file pointer, need to find it here, and parse it?
            logger.debug("Found yaml file: " + tmpdir + "/" + value.strip())
            # TODO Need to handle multiple yaml files
            tosca_tpl = os.path.join(tmpdir + "/" + value.strip())
            yamlcontent = ToscaTemplate(tosca_tpl)

            return yamlcontent


def create_charms(yaml, tmpdir, bundledir):
    # create charms based on yaml file
    # tmpdir holds the contents of the CSAR file and may need
    # artifacts pulled from it.
    # bundledir is the output directory for the bundle file and
    # file artifacts should be placed there.
    cyaml = "\tservices:\n"
    for nodetmp in yaml.nodetemplates:
        logger.debug("Found node type:" + nodetmp.name + nodetmp.type)
        cyaml += "\t\t" + nodetmp.name + ":\n"
        print "Props:" + str(sorted([p.name for p in nodetmp.properties]))
        print "Caps:" + str(sorted([p.name for p in nodetmp.capabilities]))
        print
        cyaml += "\t\t\tOptions:\n"
        for prop in nodetmp.properties:
            pprint(prop.value)
            # TODO figure out proper mapping to bundle
            # TODO how to handle props that have get_input values?
            cyaml += "\t\t\t\t" + prop.name + ":" + "\n"

        # TODO not sure these classes are warranted with toscalib
        # doing the heavy lifting on the parser.
        # translator = Nodetype2Charm(nodetmp, bundledir)
        # translator.execute()
        print

    return(cyaml)


def create_relations(yaml, tmpdir, bundledir):
    ryaml = "\trelations:\n"
    # create relations based on yaml file
    for nodetmp in yaml.nodetemplates:
        logger.debug("Found rel node:" + nodetmp.name + " " + nodetmp.type)
        for relation, node in nodetmp.relationship.items():
            ryaml += "\t\t" + nodetmp.name + ":" + node.name + "\n"

    return(ryaml)


def create_bundle(cyaml, ryaml, bundledir):
    logger.debug(bundledir)
    bfn = bundledir + "/tosca.yaml"
    try:
        bfile = open(bfn, 'w')
    except:
        print ("Couldn't open bundlefile")
        sys.exit(2)
    bfile.write("toscaImport:\n")
    bfile.write(cyaml + "\n")
    bfile.write(ryaml + "\n")
    bfile.close()
    return(bfn)


# Main
def main():
    # setup debug logging
    global logger
    logger = logging.getLogger('root')
    # FORMAT = "[%(filename)s:%(lineno)s-%(funcName)s()]%(message)s"
    FORMAT = "[%(lineno)s-%(funcName)s] %(message)s"
    logging.basicConfig(format=FORMAT)
    logger.setLevel(logging.DEBUG)

    # input params
    zipfn = ''
    try:
        opts, args = getopt.getopt(sys.argv[1:], "hd", ["help", "description"])
    except getopt.GetoptError as err:
        print str(err)
        usage()
        sys.exit(2)

    for opt, arg in opts:
        if opt in ("-h", "--help"):
            usage()
            sys.exit()
        elif opt in ("-d", "--description"):
            description()
            sys.exit()
        else:
            assert False, "unhandled option"

    if not (len(args) == 1):
        usage()
        sys.exit(2)

    # Unpack the zip file into a temp directory
    zipfn = sys.argv[1]
    tmpdir = unpack_zip(zipfn)

    # Read the TOSCA.meta file
    yaml = parse_metafile(tmpdir)

    # TODO should use this to mkdir, but its annoying right now
    # bundledir = tempfile.mkdtemp(prefix="BUNDLE_", dir="./")
    bundledir = "./BUNDLE"
    cbundle = create_charms(yaml, tmpdir, bundledir)
    rbundle = create_relations(yaml, tmpdir, bundledir)
    bundlefile = create_bundle(str(cbundle), str(rbundle), bundledir)<commit_msg>Make sure bundledir exists<commit_after>#!/usr/bin/python

# Copyright 2014 IBM Corporation
# <NAME>(<EMAIL>)

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.

# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


import getopt
import sys
import zipfile
import tempfile
import os.path
import logging
import shutil
# from jujutranslator.nodetype2charm import Nodetype2Charm
from translator.toscalib.tosca_template import ToscaTemplate
from pprint import pprint
from inspect import currentframe, getframeinfo

try:
    from yaml import CSafeLoader as Loader
except ImportError:
    from yaml import SafeLoader as Loader


def usage():
    print 'juju-tosca-import.py [--help] [--description] <CSAR zip file>'


def description():
    print """Juju plugin to import a orchestration specification from
    a CSAR file containing YAML files"""


def unpack_zip(zipfn):
    # zip file needs to be in the TOSCA CSAR format
    try:
        zip = zipfile.ZipFile(zipfn, 'r')
    except:
        print "Unable to open zip file", zipfn
        usage()
        sys.exit(2)

    logger.debug(zip.namelist())
    tmpdir = tempfile.mkdtemp(prefix="CSAR_", dir="./")
    zip.extractall(tmpdir)
    return tmpdir


def parse_metafile(tmpdir):
    if not os.path.isfile(tmpdir+"/TOSCA-Metadata/TOSCA.meta"):
        print "TOSCA.meta not found in CSAR file"
        sys.exit(1)
    try:
        tfile = open(tmpdir+'/TOSCA-Metadata/TOSCA.meta', 'r')
    except:
        print "Couldn't open Tosca metafile"
        sys.exit(2)
    tlines = tfile.readlines()
    for line in tlines:
        if (line.startswith("Name")):
            attr, value = line.split(":", 2)
            # if it's a yaml file pointer, need to find it here, and parse it?
            logger.debug("Found yaml file: " + tmpdir + "/" + value.strip())
            # TODO Need to handle multiple yaml files
            tosca_tpl = os.path.join(tmpdir + "/" + value.strip())
            yamlcontent = ToscaTemplate(tosca_tpl)

            return yamlcontent


def create_charms(yaml, tmpdir, bundledir):
    # create charms based on yaml file
    # tmpdir holds the contents of the CSAR file and may need
    # artifacts pulled from it.
    # bundledir is the output directory for the bundle file and
    # file artifacts should be placed there.
    cyaml = "\tservices:\n"
    for nodetmp in yaml.nodetemplates:
        logger.debug("Found node type:" + nodetmp.name + nodetmp.type)
        cyaml += "\t\t" + nodetmp.name + ":\n"
        print "Props:" + str(sorted([p.name for p in nodetmp.properties]))
        print "Caps:" + str(sorted([p.name for p in nodetmp.capabilities]))
        print
        cyaml += "\t\t\tOptions:\n"
        for prop in nodetmp.properties:
            pprint(prop.value)
            # TODO figure out proper mapping to bundle
            # TODO how to handle props that have get_input values?
            cyaml += "\t\t\t\t" + prop.name + ":" + "\n"

        # TODO not sure these classes are warranted with toscalib
        # doing the heavy lifting on the parser.
        # translator = Nodetype2Charm(nodetmp, bundledir)
        # translator.execute()
        print

    return(cyaml)


def create_relations(yaml, tmpdir, bundledir):
    ryaml = "\trelations:\n"
    # create relations based on yaml file
    for nodetmp in yaml.nodetemplates:
        logger.debug("Found rel node:" + nodetmp.name + " " + nodetmp.type)
        for relation, node in nodetmp.relationship.items():
            ryaml += "\t\t" + nodetmp.name + ":" + node.name + "\n"

    return(ryaml)


def create_bundle(cyaml, ryaml, bundledir):
    logger.debug(bundledir)
    bfn = bundledir + "/tosca.yaml"
    try:
        bfile = open(bfn, 'w')
    except:
        print ("Couldn't open bundlefile")
        sys.exit(2)
    bfile.write("toscaImport:\n")
    bfile.write(cyaml + "\n")
    bfile.write(ryaml + "\n")
    bfile.close()
    return(bfn)


# Main
def main():
    # setup debug logging
    global logger
    logger = logging.getLogger('root')
    # FORMAT = "[%(filename)s:%(lineno)s-%(funcName)s()]%(message)s"
    FORMAT = "[%(lineno)s-%(funcName)s] %(message)s"
    logging.basicConfig(format=FORMAT)
    logger.setLevel(logging.DEBUG)

    # input params
    zipfn = ''
    try:
        opts, args = getopt.getopt(sys.argv[1:], "hd", ["help", "description"])
    except getopt.GetoptError as err:
        print str(err)
        usage()
        sys.exit(2)

    for opt, arg in opts:
        if opt in ("-h", "--help"):
            usage()
            sys.exit()
        elif opt in ("-d", "--description"):
            description()
            sys.exit()
        else:
            assert False, "unhandled option"

    if not (len(args) == 1):
        usage()
        sys.exit(2)

    # Unpack the zip file into a temp directory
    zipfn = sys.argv[1]
    tmpdir = unpack_zip(zipfn)

    # Read the TOSCA.meta file
    yaml = parse_metafile(tmpdir)

    # TODO should use this to mkdir, but its annoying right now
    # bundledir = tempfile.mkdtemp(prefix="BUNDLE_", dir="./")
    bundledir = "./BUNDLE"
    if not os.path.exists(bundledir):
        os.mkdir(bundledir)
    cbundle = create_charms(yaml, tmpdir, bundledir)
    rbundle = create_relations(yaml, tmpdir, bundledir)
    bundlefile = create_bundle(str(cbundle), str(rbundle), bundledir)
{'fraction_non_alphanumeric': 0.11144449207029576, 'fraction_numerical': 0.003086155165023575, 'mean_word_length': 2.665095821551995, 'pattern_counts': {'":': 8, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2316943', 'n_tokens_mistral': 3743, 'n_tokens_neox': 3613, 'n_words': 1146}