Ejemplo n.º 1
0
class RequirementSpecification(solum_plan.Requirement):
    """CAMP v1.1 RequirementSpecification."""

    fulfillment = api_types.MultiType(wtypes.text, ServiceSpecification)
    """Either a ServiceSpecification or a reference to a
    ServiceSpecification."""
    def __init__(self, **kwargs):
        if 'fulfillment' in kwargs:
            fulfill = kwargs.get('fulfillment')
            if type(fulfill) is not str:
                kwargs['fulfillment'] = ServiceSpecification(**fulfill)

        super(RequirementSpecification, self).__init__(**kwargs)
Ejemplo n.º 2
0
class Artifact(wtypes.Base):
    """Artifact."""

    name = wtypes.text
    "Name of the artifact."

    artifact_type = wtypes.text
    "Type of artifact."

    content = {wtypes.text: api_types.MultiType(wtypes.text, bool)}
    "Type specific content as a flat dict."

    ports = api_types.MultiType(api_types.PortType, [api_types.PortType],
                                {wtypes.text: api_types.PortType})
    "Type of ports which an app listens on"

    language_pack = wtypes.text
    "The Language pack required for this artifact."

    requirements = [Requirement]
    "List of requirements for the artifact."

    unittest_cmd = wtypes.text
    "Optional unit test command for the artifact."

    run_cmd = wtypes.text
    "The command for starting up user code when a DU is deployed."

    repo_token = wtypes.text
    "The OAuth token to access repository"

    def __init__(self, **kwargs):
        if 'requirements' in kwargs:
            kwargs['requirements'] = [
                Requirement(**re) for re in kwargs.get('requirements', [])
            ]
        super(Artifact, self).__init__(**kwargs)
Ejemplo n.º 3
0
class Plan(api_types.Base):
    """Representation of an Plan file.

    The Plan resource is a representation of a Plan file. Plans are used to
    create Assembly resources. A Plan resource may be used to create an
    arbitrary number of Assembly instances. They use artifacts and services
    to indicate what will be used to generate the plan, and what services
    Solum can use to satisfy them. Note: Plan files are YAML and Plan resources
    are the REST representation of the Plan file after services have been
    matched to ones offered by Solum.
    """

    artifacts = [Artifact]
    """List of artifacts defining the plan."""

    services = [ServiceReference]
    """List of services needed by the plan."""

    trigger_uri = wtypes.text
    """The trigger uri used to trigger the build of the plan"""

    parameters = {
        wtypes.text:
        api_types.MultiType(wtypes.text, six.integer_types, bool, float)
    }
    """User defined parameters"""
    def __init__(self, **kwargs):
        if 'artifacts' in kwargs:
            kwargs['artifacts'] = [
                Artifact(**art) for art in kwargs.get('artifacts', [])
            ]
        if 'services' in kwargs:
            kwargs['services'] = [
                ServiceReference(**sr) for sr in kwargs.get('services', [])
            ]
        super(Plan, self).__init__(**kwargs)

    @classmethod
    def sample(cls):
        return cls(uri='http://example.com/v1/plans/x1',
                   name='Example-plan',
                   type='plan',
                   tags=['small'],
                   artifacts=[{
                       'name':
                       'My-python-app',
                       'artifact_type':
                       'git_pull',
                       'content': {
                           'href': 'git://example.com/project.git',
                           'private': False
                       },
                       'language_pack':
                       uuidutils.generate_uuid(),
                       'requirements': [{
                           'requirement_type': 'git_pull',
                           'fulfillment': 'id:build'
                       }]
                   }],
                   services=[{
                       'name': 'Build-Service',
                       'id': 'build',
                       'characteristics': ['python_build_service']
                   }],
                   project_id='1dae5a09ef2b4d8cbf3594b0eb4f6b94',
                   user_id='55f41cf46df74320b9486a35f5d28a11',
                   trigger_uri='http://example.com/v1/triggers/1abc234',
                   description='A plan with no services or artifacts shown')

    @classmethod
    def from_db_model(cls, m, host_url):
        json = m.as_dict()
        json['type'] = m.__tablename__
        json['uri'] = '%s/v1/%s/%s' % (host_url, m.__resource__, m.uuid)
        if m.raw_content is not None:
            json.update(m.raw_content)
        del json['id']
        return cls(**(json))

    def as_dict(self, db_model):
        base = super(Plan, self).as_dict(db_model)
        if self.artifacts is not wsme.Unset:
            base.update({
                'artifacts':
                [wjson.tojson(Artifact, art) for art in self.artifacts]
            })
        if self.services is not wsme.Unset:
            base.update({
                'services':
                [wjson.tojson(ServiceReference, ref) for ref in self.services]
            })
        if self.parameters is not wsme.Unset:
            base.update({'parameters': self.parameters})
        return base
Ejemplo n.º 4
0
 def test_invalid_values(self):
     vt = api_types.MultiType(wtypes.text, bool)
     self.assertRaises(ValueError, vt.validate, 10)
     self.assertRaises(ValueError, vt.validate, 0.10)
     self.assertRaises(ValueError, vt.validate, object())
Ejemplo n.º 5
0
 def test_valid_values(self):
     vt = api_types.MultiType(wtypes.text, bool)
     value = vt.validate("somestring")
     self.assertEqual("somestring", value)
     value = vt.validate(True)
     self.assertEqual(True, value)
Ejemplo n.º 6
0
 def test_multitype_tostring(self):
     vt = api_types.MultiType(wtypes.text, bool)
     vts = str(vt)
     self.assertIn(str(wtypes.text), vts)
     self.assertIn(str(bool), vts)
     self.assertNotIn(str(six.integer_types[0]), vts)
Ejemplo n.º 7
0
class LanguagePack(api_types.Base):
    """Representation of a language pack.

    When a user creates an application, he specifies the language pack
    to be used. The language pack is responsible for building the application
    and producing an artifact for deployment.

    For a complete list of language pack attributes please
    refer: https://etherpad.openstack.org/p/Solum-Language-pack-json-format
    """
    def __init__(self, **kwds):
        self.__name = wsme.Unset
        super(LanguagePack, self).__init__(**kwds)

    def get_name(self):
        return self.__name

    def set_name(self, value):
        if len(value) > 100:
            raise ValueError(
                _('Names must not be longer than 100 '
                  'characters'))
        allowed_chars = string.ascii_lowercase + string.digits + '-_'
        for ch in value:
            if ch not in allowed_chars:
                raise ValueError(_('Names must only contain a-z,0-9,-,_'))
        self.__name = value

    name = wtypes.wsproperty(str, get_name, set_name, mandatory=True)

    language_pack_type = wtypes.text
    """Type of the language pack. Identifies the language supported by the
    language pack. This attribute value will use the
    org.openstack.solum namespace.
    """

    compiler_versions = [wtypes.text]
    """List of all the compiler versions supported by the language pack.
    Example: For a java language pack supporting Java versions 1.4 to 1.7,
    version = ['1.4', '1.6', '1.7']
    """

    runtime_versions = [wtypes.text]
    """List of all runtime versions supported by the language pack.
    Runtime version can be different than compiler version.
    Example: An application can be compiled with java 1.7 but it should
    run in java 1.6 as it is backward compatible.
    """

    language_implementation = wtypes.text
    """Actual language implementation supported by the language pack.
    Example: In case of java it might be 'Sun' or 'openJava'
    In case of C++ it can be 'gcc' or 'icc' or 'microsoft'.
    """

    build_tool_chain = [BuildTool]
    """Toolchain available in the language pack.
    Example: For a java language pack which supports Ant and Maven,
    build_tool_chain = ["{type:ant,version:1.7}","{type:maven,version:1.2}"]
    """

    os_platform = {str: wtypes.text}
    """OS and its version used by the language pack.
    This attribute identifies the base image of the language pack.
    """

    attributes = {str: wtypes.text}
    """Additional section attributes will be used to expose custom
    attributes designed by language pack creator.
    """

    source_uri = wtypes.text
    """The URI of the app/element."""

    source_format = SOURCE_KIND
    """The source repository format."""

    status = STATE_KIND
    """The state of the image. """

    base_image_id = wtypes.text
    """The id (in glance) of the image to customize."""

    image_format = IMAGE_KIND
    """The image format."""

    created_image_id = wtypes.text
    """The id of the created image in glance."""

    lp_metadata = wtypes.text
    """The languagepack meta data."""
    """Parameters that can be used as part of lp building process."""
    lp_params = wtypes.DictType(
        wtypes.text,
        wtypes.DictType(
            wtypes.text,
            api_types.MultiType(wtypes.text, six.integer_types, bool, float)))

    @classmethod
    def from_image(cls, image, host_url):
        as_dict = {}
        image_id = image['id']
        as_dict['uuid'] = image_id
        as_dict['name'] = image['name']
        as_dict['type'] = 'language_pack'
        as_dict['uri'] = '%s/v1/%s/%s' % (host_url, 'language_packs', image_id)
        image_tags = image['tags']
        comp_versions = []
        run_versions = []
        build_tools = []
        attrs = {}
        for tag in image_tags:
            if tag.startswith(DESCRIPTION):
                as_dict['description'] = tag[len(DESCRIPTION):]
            if tag.startswith(TYPE):
                as_dict['language_pack_type'] = tag[len(TYPE):]
            if tag.startswith(COMPILER_VERSION):
                comp_versions.append(tag[len(COMPILER_VERSION):])
            if tag.startswith(RUNTIME_VERSION):
                run_versions.append(tag[len(RUNTIME_VERSION):])
            if tag.startswith(IMPLEMENTATION):
                as_dict['language_implementation'] = tag[len(IMPLEMENTATION):]
            if tag.startswith(BUILD_TOOL):
                bt_type, bt_version = tag[len(BUILD_TOOL):].split('::')
                build_tool = BuildTool(type=bt_type, version=bt_version)
                build_tools.append(build_tool)
            if tag.startswith(OS_PLATFORM):
                osp_type, osp_version = tag[len(OS_PLATFORM):].split('::')
                os_platform = {'OS': osp_type, 'version': osp_version}
                as_dict['os_platform'] = os_platform
            if tag.startswith(ATTRIBUTE):
                key, value = tag[len(ATTRIBUTE):].split('::')
                attrs[key] = value
        as_dict['attributes'] = attrs
        as_dict['compiler_versions'] = comp_versions
        as_dict['runtime_versions'] = run_versions
        as_dict['build_tool_chain'] = build_tools
        return cls(**(as_dict))

    def as_image_dict(self):
        tags = ['solum::lp']
        if self.description is not wsme.Unset:
            tags.append(DESCRIPTION + self.description)
        if self.language_pack_type is not wsme.Unset:
            tags.append(TYPE + self.language_pack_type)
        if self.compiler_versions is not wsme.Unset:
            for cv in self.compiler_versions:
                tags.append(COMPILER_VERSION + cv)
        if self.runtime_versions is not wsme.Unset:
            for rv in self.runtime_versions:
                tags.append(RUNTIME_VERSION + rv)
        if self.language_implementation is not wsme.Unset:
            tags.append(IMPLEMENTATION + self.language_implementation)
        if self.build_tool_chain is not wsme.Unset:
            for bt in self.build_tool_chain:
                tags.append(BUILD_TOOL + bt.type + '::' + bt.version)
        ptfm = self.os_platform
        if ptfm is not wsme.Unset and 'OS' in ptfm and 'version' in ptfm:
            tags.append(OS_PLATFORM + ptfm['OS'] + '::' + ptfm['version'])
        if self.build_tool_chain is not wsme.Unset:
            for key, value in self.attributes.items():
                tags.append(ATTRIBUTE + key + '::' + value)
        # TODO(julienvey) parse specific attributes for image creation from
        # self.attributes, such as image_format...
        return {'name': self.name, 'tags': tags}

    @classmethod
    def sample(cls):
        return cls(
            uri='http://example.com/v1/images/b3e0d79',
            source_uri='git://example.com/project/app.git',
            source_format='heroku',
            name='php-web-app',
            type='languagepack',
            description='A php web application',
            tags=['group_xyz'],
            project_id='1dae5a09ef2b4d8cbf3594b0eb4f6b94',
            user_id='55f41cf46df74320b9486a35f5d28a11',
            base_image_id='4dae5a09ef2b4d8cbf3594b0eb4f6b94',
            created_image_id='4afasa09ef2b4d8cbf3594b0ec4f6b94',
            image_format='docker',
            language_pack_name='java-1.4-1.7',
            language_pack_type='org.openstack.solum.Java',
            language_pack_id='123456789abcdef',
            compiler_versions=['1.4', '1.6', '1.7'],
            runtime_versions=['1.4', '1.6', '1.7'],
            language_implementation='Sun',
            build_tool_chain=[
                BuildTool(type='ant', version='1.7'),
                BuildTool(type='maven', version='1.2')
            ],
            os_platform={
                'OS': 'Ubuntu',
                'version': '12.04'
            },
            attributes={
                'optional_attr1': 'value',
                'admin_email': '*****@*****.**'
            },
        )
Ejemplo n.º 8
0
class App(api_types.Base):
    """Representation of an App.

    The App is the primary resource managed by Solum.
    """
    # Inherited fields:
    # uri
    # uuid
    # name is overridden.
    # type
    # description
    # tags
    # project_id
    # user_id

    version = wtypes.wsattr(int)
    id = wtypes.text
    name = wtypes.text
    deleted = bool
    languagepack = wtypes.text
    stack_id = wtypes.text
    ports = api_types.MultiType(api_types.PortType, [api_types.PortType],
                                {wtypes.text: api_types.PortType})
    source = {wtypes.text: wtypes.text}
    workflow_config = {wtypes.text: wtypes.text}
    trigger_uuid = wtypes.text
    trigger_actions = [wtypes.text]
    trigger_uri = wtypes.text
    trust_id = wtypes.text
    trust_user = wtypes.text
    app_url = wtypes.text
    status = wtypes.text
    repo_token = wtypes.text
    created_at = datetime.datetime

    parameters = {
        wtypes.text:
        api_types.MultiType(wtypes.text, six.integer_types, bool, float)
    }
    """User defined parameters"""
    def __init__(self, *args, **kwargs):
        super(App, self).__init__(*args, **kwargs)

    @classmethod
    def sample(cls):
        return cls(
            name="sampleapp",
            description="sample app",
        )

    @classmethod
    def from_db_model(cls, m, host_url):
        json = m.as_dict()
        json['type'] = m.__tablename__
        json['uri'] = '%s/v1/apps/%s' % (host_url, m.id)
        json['trigger_uri'] = ('%s/v1/triggers/%s' %
                               (host_url, m.trigger_uuid))
        return cls(**(json))

    def as_dict(self, db_model):
        attrs = [
            'name',
            'id',
            'description',
            'languagepack',
            'project_id',
            'user_id',
            'deleted',
            'source',
            'ports',
            'trigger_actions',
            'workflow_config',
            'stack_id',
        ]
        base = super(App, self).as_dict(db_model)

        if self.parameters is not wsme.Unset:
            base.update({'parameters': self.parameters})

        for a in attrs:
            if getattr(self, a) is wsme.Unset:
                continue
            if getattr(self, a) is None:
                continue
            base[a] = getattr(self, a)
        return base
Ejemplo n.º 9
0
class Workflow(wtypes.Base):
    """Representation of a Workflow.

    A workflow maintains a living creation and deployment of an App.
    """

    # (devkulkarni) Added base_url to get around strict validation
    # checking of WSME 0.8.0
    # https://bugs.launchpad.net/solum/+bug/1491504
    # https://bugs.launchpad.net/solum/+bug/1491499
    base_url = common_types.Uri
    "URI of the base resource."

    uri = common_types.Uri
    "URI to the resource."

    uuid = wtypes.text
    "Unique Identifier of the resource"

    type = wtypes.text
    "The resource type."

    id = wtypes.text
    updated_at = datetime.datetime
    created_at = datetime.datetime
    app_id = wtypes.text
    wf_id = int
    source = wtypes.DictType(
        wtypes.text,
        api_types.MultiType(wtypes.text, six.integer_types, bool, float))
    config = {wtypes.text: wtypes.text}
    actions = [wtypes.text]
    du_id = wtypes.text
    status = wtypes.text
    result = wtypes.text
    scale_target = int

    def __init__(self, *args, **kwargs):
        super(Workflow, self).__init__(*args, **kwargs)

    @classmethod
    def sample(cls):
        return cls(wf_id=1, config={}, actions={}, source={}, status='')

    @classmethod
    def from_db_model(cls, m, host_url):
        json = m.as_dict()
        json['type'] = m.__tablename__
        json['uri'] = ''
        json['uri'] = ('%s/v1/apps/%s/workflows/%s' %
                       (host_url, m.app_id, m.wf_id))
        return cls(**(json))

    def as_dict_from_keys(self, keys):
        return dict((k, getattr(self, k)) for k in keys
                    if hasattr(self, k) and getattr(self, k) != wsme.Unset)

    def as_dict(self, db_model):
        valid_keys = [
            attr for attr in db_model.__dict__.keys()
            if attr[:2] != '__' and attr != 'as_dict'
        ]
        base = self.as_dict_from_keys(valid_keys)
        attrs = [
            'id', 'app_id', 'wf_id', 'source', 'config', 'actions', 'status',
            'result', 'scale_target'
        ]
        for a in attrs:
            if getattr(self, a) is wsme.Unset:
                continue
            if getattr(self, a) is None:
                continue
            base[a] = getattr(self, a)
        return base