Code Monkey home page Code Monkey logo

nulecule's Introduction

Composite Container-based Application Specification

\ˈnü-li-ˌkyül\ (n.) a made-up word meaning "the mother of all atomic particles".

Your installer for container-based applications. Replace your shell script and deployment instructions with some metadata.

Change runtime parameters for different environments. No need to edit files before deployment. Users can choose interactive or unattended deployment. Guide web interface users with parameter metadata to validate user input and provide descriptive help.

Bridge between Enterprise IT and PaaS With pluggable orchestration providers you can package your application to run on OpenShift, Kubernetes, Docker Compose, Helios, Panamax, Docker Machine, etc. and allow the user to choose the target when deployed.

Compose applications from a catalog. No need to re-package common services. Create composite applications by referencing other Nulecule-compliant apps. For example, adding a well-designed, orchestrated database is simply a reference to another container image.

Problem Statement

Currently there is no standard way of defining a multi-container application's configuration without distributing instructions and files to the end-user. Additionally, these files must be managed and distributed via different systems than the containers themselves.

Containers in the OCI (Open Container Initiative) format derived from Docker offers a new approach for application packaging. OCI enables application-centric aggregate packaging, optimized for deployment into containers. However most applications will consist of multiple containers, which surfaces two issues: the relationships between containers need to be expressed in order to manage dependencies and orchestrate the deployment (e.g. set up network connections) with consideration of environmental factors, and this application-level meta-data needs to be distributed. OCI itself, however, stops at the individual container. Orchestration tools such as Kubernetes offer a generic description model for multi-container applications, however they do not define a transport model, nor a standard way to parameterize a generic template. The mindset of most, if not all, current container orchestration systems is to treat the aggregate, multi-container application as state of the cluster rather than an entity in it's own right and therefore they regress beyond the portability that OCI introduced. This means that it's very easy to put a individual service into a Docker-style Registry, however there is no way to represent a full application at the distribution level - I can create a single MariaDB container, but not a MariaDB/Galera cluster or even a full application such as Kolab. So what is missing? A standard way to describe and package a multi-container application.

What is Nulecule?

Nulecule defines a pattern and model for packaging complex multi-container applications and services, referencing all their dependencies, including orchestration metadata in a container image for building, deploying, monitoring, and active management.

The Nulecule specification enables complex applications to be defined, packaged and distributed using standard container technologies. The resulting container includes dependencies, supports multiple orchestration providers, and has the ability to specify resource requirements. The Nulecule specification also supports the aggregation of multiple composite applications. The Nulecule specification is container and orchestration agnostic, enabling the use of any container and orchestration technology.

Glossary of terms

Nulecule Specification Highlights

  • Application description and context maintained in a single container through extensible metadata
  • Composable definition of complex applications through inheritance and composition of containers into a single, standards-based, portable description.
  • Simplified dependency management for the most complex applications through a directed graph to reflect relationships.
  • Container and orchestration engine agnostic, enabling the use of any container technology and/or orchestration technology

“The Big Picture”

Alt Nulecule specification high-level story.

Deployment User Experience

The Nulecule specification has been implemented in the Atomic App reference implementation. Atomic App currently supports docker containers and kubernetes and docker orchestration providers. The atomic command is used to run the container that contains the Nulecule specification and the Atomic App implementation.

This example is a single container application based on the centos/httpd image, but you can use your own.

You may wish to run the Nulecule from an empty directory as it will copy the Nulecule files to the working directory for inspection every time it is run.

Option 1: Non-interactive defaults

Run the image. It will automatically use kubernetes as the orchestration provider. This will become interactive and prompt for defaults if the Nulecule file doesn't provide defaults for all of the parameters.

[sudo] atomic run projectatomic/helloapache

Option 2: Unattended

  1. Create the file answers.conf with these contents:

    This sets up the values for the two configurable parameters (image and hostport) and indicates that kubernetes should be the orchestration provider.

     [general]
     provider = kubernetes
    
     [helloapache-app]
     image = centos/httpd # optional: choose a different image
     hostport = 80        # optional: choose a different port to expose
    
  2. Run the application from the current working directory

     $ [sudo] atomic run projectatomic/helloapache
     ...
     helloapache
    
  3. As an additional experiment, remove the kubernetes pod and change the provider to 'docker' and re-run the application to see it get deployed on native docker.

Option 3: Install and Run

You may want to download the application, review the configuration and parameters as specified in the Nulecule file, and edit the answerfile before running the application.

  1. Download the application files using atomic install

     [sudo] atomic install projectatomic/helloapache
    
  2. Rename answers.conf.sample

     mv answers.conf.sample answers.conf
    
  3. Edit answers.conf, review files if desired and then run

     $ [sudo] atomic run projectatomic/helloapache
     ...
     helloapache
    

Test

Any of these approaches should create a kubernetes pod or a running docker container.

With a kubernetes pod, once its state is "Running" curl the minion it's running on.

$ kubectl get pod helloapache
POD                IP                  CONTAINER(S)       IMAGE(S)           HOST                LABELS              STATUS
helloapache        172.17.0.8          helloapache        centos/httpd       10.3.9.216/         name=helloapache   Running
$ curl 10.3.9.216
<bunches_of_html_goodness>

If you test the docker provider, once the container is running, curl the port on your localhost.

$ curl localhost
<bunches_of_html_goodness>

Additional examples are available in the examples directory.

Developer User Experience

See the Getting Started with Nulecule guide.

Implementations

This is only a specification. Implementations may be written in any language. See implementation guide for more details.

Reference implementation https://github.com/projectatomic/atomicapp

Examples / Library

For a library of examples conforming to the current reference implementation atomicapp please visit github.com/projectatomic/nulecule-library

Developer tooling

Developer tooling is TBD. There is some work planned for DevAssistant.

Contributing

Please review the contributing guidelines before submitting pull requests.

###Communication channels

Copyright

Copyright (C) 2016 Red Hat Inc.

This program is free software: you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details.

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

The GNU General Public License is provided within the file LICENSING.

nulecule's People

Contributors

aweiteka avatar cdrage avatar dustymabe avatar ggallen avatar goern avatar jankaluza avatar jasonbrooks avatar johnmark avatar jzb avatar kadel avatar kanarip avatar kwk avatar lalatendumohanty avatar langdon avatar miabbott avatar michaelvirgil avatar mscherer avatar navidshaikh avatar nzwulfin avatar rtnpro avatar sallyom avatar tradej avatar veillard avatar vlajos avatar vpavlin avatar wking avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nulecule's Issues

Terminology for different types of images

Since I've started working with Nulecule, I've been hitting this problem - there are basically 2 types of images one needs to speak of:

  • "meta images" - the images that contain the orchestration info
  • "binary images" - the images that contain the actual services that make up the application

Since these two types are not distinguished by Nulecule docs, it's kind of necessary to agree on these prior to every discussion and people sometimes call them differently, which is confusing.
I'd like to propose that the names of these two image types are standardized, so that it's clear what people talk about (not sure if "meta images" and "binary images" are a good candidates, but so far most people I talked to have been using these).

Make json spec valid

default impl uses invalid json...

 "replicas": REPLICAS 

so, to fix this ... we need to do 3 things:

  1. define the json schema to be valid
  2. add the json files into this repo (right now theyre empty). invalid json is impossible to format using std json tools.
  3. update the impl projectatomic/atomicapp#4, to implement that spec.

Including information on how to build all images for application

Background

I'm working on a tool called atomicapp-builder [1], that should be able to rebuild a whole Nulecule app based on a given Nulecule file and cccp-index [2].

Terminology

While working on atomicapp-builder, I realized that Nulecule operates with two types of images, that don't really have names in Nulecule documentation (at least I didn't find the names :)). I'll call them meta images and binary images throughout this proposal:

  • meta image is an image created from repo that contains a Nulecule file and perhaps some provider files (like k8s config etc); meta image doesn't contain any actual source code of the application
  • binary image is an image that contains services needed to actually run the application, e.g. a database, a web server with application logic etc.

Problem statement

While current Nulecule specification, combined with a cccp-index, allows resolving what meta images need to be built for an application to work, there is no general way to tell what binary images need to be built and how. This is problematic for my use case, since atomicapp-builder should be able to build all images from scratch.

Proposal

I'd like to propose an addition of optional field called images for graph items. This field, if used, would provide information required to build binary images for the application. An example follows:

graph:
  - name: foobar
    params:
      - name: image
        description: The frontend part
        default: foobar:sometag
      - name: hostport
        description: The host TCP port as the external endpoint
        default: 80
      - name: publicip
        description: The IP address or addresses at which your app can be reached
    artifacts:
      kubernetes:
        - file://artifacts/k8s/foobar-controller.json
        - file://artifacts/k8s/foobar-service.json
    images:
      - name: foobar:sometag
        source: https://github.com/foo/bar/
        scm_type: git
        build_configs:
          stable:
            tag: v1.2.3
          latest:
            branch: master
        image_type: docker
        image_buildfile: some/dir/Dockerfile

I think the example is quite self-explanatory, so I'll just comment very briefly:

  • images is a list of json objects with following properties:
    • name (required) - name of the image to build
    • source (required) - SCM repository URL
    • scm_type (optional) - type of SCM to use, defaults to git
    • build_configs (optional) - a json object containing named build configurations; only 2 configs are allowed - stable and master
      • every build config can contain either branch or tag; the default is branch: master
      • by default, both configs point to master branch, e.g.
latest:
  branch: master
stable:
  branch: master
  • branch or tag (optional) - branch or tag to build from
  • image_type (optional) - type of containerization engine to build image for, defaults to docker
  • image_buildfile (optional) - path of build file of the image inside the repo, defaults to Dockerfile

Things to consider / Q&A

  • Q: What if user doesn't provide any/all instructions on how to build images?
    A: Since the field is optional, this is not a problem. Some tooling may however require providing list of all images that will be needed for the application; if an incomplete list is provided, this tooling may be unable to work with the application.
  • Q: Why have multiple build configs?
    A: So that there is a builtin way to specify how to build various versions of this application, e.g. the latest development version, the latest stable version, a specific released version, etc... The tooling used for building Nulecule apps shall expose options to select one of the build configs.
  • Q: Why not provide arbitrary number of configs?
    A: This crossed my mind, but I'm not sure how to sanely implement this in the build tooling. The problem is that the set of images to build is unknown prior to invoking the build, so a defined set of configurations makes sense (I can't specify configs for images that I don't know will be built). OTOH the problem is, that I may want to be building my app with latest config, but all its dependencies in stable config... I'm a bit torn here, another opinion would be appreciated!
  • Q: Isn't this too complicated?
    A: I don't know, you tell me :) If someone can think of a nicer/more concise way, I'll be happy to see it!

CC @arrfab @vpavlin @kbsingh

[1] https://github.com/bkabrda/atomicapp-builder/
[2] https://github.com/kbsingh/cccp-index/

Support provider-specific params

This is just a placeholder to consider yet another parameter scope: those params that are only related to a specific provider. We expect some providers to have many more parameters than others. For example, typically the docker provider will have fewer params than the kubernetes provider.

mariadb example feels outdated

But it carries a good idea that shows how to integrate src for a nulecule and just package what the atomicapp really needs...

I vote for removing the example and transforming it to a blog entry.

How to define providers and extensions

How much do we need to define for specific providers and extensions? Are these defined externally to the spec or does it need to be consolidated here?

Expand artifacts source methods

We want to be able to use remote provider artifacts for several reasons:

  • there are typically external sources for provider files (for example, docker compose, kubernetes)
  • if remote sources exist we don't want to clone and maintain them separately
  • remote source must be version controlled

Proposal by way of example:

  1. Local file (current specification)

     artifacts:
      - file://path/to/local/file.json
    
  2. Version control (support branch and tag)

    artifacts:
      - source: https://github.com/GoogleCloudPlatform/kubernetes.git
        type: git
        branch: release-0.9
        path: examples/guestbook
    
  3. Single remote file

    artifacts:
      - https://raw.githubusercontent.com/projectatomic/nulecule/master/examples/helloapache/artifacts/k8s/hello-apache-pod.json
    

[epic] Rework params to support xpath-like replacing and non-scalar values

Problem statement

Currently params work with simple substitution. You need to specify the param name prefixed with $ in the artifact and it's then replaced with the value given either by default, answers file or by the user in case of interactive mode. This is a problem because a developer of nulecule application has to modify (upstream) kube files and replace real values with something like $image. This brings debuging problems right now (you cannot use artifacts shipped in nulecule app directly) and will bring a lot of maintainance problems in the future (you need to mirror all changes in upstream artifacts in your modified files).

Based on the description in previous paragraph it is obvious (almost) all artifacts has to be modified from upstream and thus maintained directly in the nulecule app repo - i.e. it does not make much sense to reference artifacts by remote URL (https://...) and deffer their download to the point of installation.

Also there already were some discussions about supporting non-scalar types, thus part of this proposal is addition of type key to the params definition.

Proposal

JSON Pointer

Based on an idea of @markllama we came to the conclusion we need to be able to replace param values in artifacts not based on the placeholder, but based on the position in the json/yaml object. This will enable developers of nulecule applications to exactly specify what should be replaced without a need to modify the artifacts.

This concept is described in a JSON Pointer (https://tools.ietf.org/html/rfc6901)

For this kubernetes pod definition

{
    "apiVersion": "v1beta3",
    "kind": "Pod",
    "metadata": {
        "labels": {
            "app": "helloapache"
        },
        "name": "helloapache"
    },
    "spec": {
        "containers": [
            {
                "image": "centos/httpd",
                "name": "helloapache",
                "ports": [
                    {
                        "containerPort": 80,
                        "hostPort": 8080,
                        "protocol": "TCP"
                    }
                ]
            }
        ]
    }
}

The param image should look like

params:
  - name: image
    pointer: [/spec/containers/0/image]
    description: The webserver image
    default: centos/httpd

As you can see, pointer is defined as an array which means you can specify more places in an artifact(s) where the param should be used. Also the default is optional and if not specified (i.e. if the key default is omitted) the actual value in artifact can be used. Existing key default set to null means that a user needs to provide the value in answers.

Although using the pointer will be strongly recommended, current substitution of $ prefixed variables will continue to work as there might be some use cases for it.

To preserve the simplicity of answers file, params will be refferenced by name there. On the other hand extension to support JSON Pointer notaition as keys in answers file should be simple (and would potentially enable user to replace not only the given params, but, for debugging purposes, any value in any artifact)

Problems

  • Same JSON Pointer path might exist in multiple artifacts although user might want to change the value only in a single specific artifact

    • This might trigger a discussion about adding artifacts specific params again.
  • Exact location specified by JSON Pointer might lead to failing runs in case of unexpected changes in artifact.
    f.e. value of environment variable PASS specified in kubernetes pod definition:

    ...
        "containers": [
          {
            "name": "mariadb",
            "image": "$image",
            "env": [
              {"name": "USER", "value": "$db_user"},
              {"name": "PASS", "value": "$db_pass"},
              {"name": "NAME", "value": "$db_name"}
            ],
            "cpu": 1,
    ...
    

    would have path .../containers/env/1/value. If upstream decides to add environment variable FOO above the PASS variable, the path to PASS changes to .../containers/env/2/value (note the change 1 -> 2).

    • This is probably a smaller issue then current state of mirroring all artifacts as a part of the app

Allow URL and git description for artifacts

Although specification does not block anybody from specifying remote location, current implementation and the way how we substitute params basically supports only artifacts stored locally. As a part of this proposal we should document ability of the spec to accept remote locations for artifacts - i.e.

artifacts:
  - kubernetes:
     - https://raw.githubusercontent.com/projectatomic/nulecule/master/examples/skydns-atomicapp/artifacts/kubernetes/skydns-replicationcontroller.yaml
     - ftp://example.com/nulecule/my-app/artifact.json
     - file:artifacts/artifact2.json
     - ...

I'd also like to propose a special type of artifact which would be specified by object in a format similar to:

artifacts:
  - kubernetes:
     - git_url: https://github.com/projectatomic/nulecule/
       checkout: fda3fb8c48a7f8e6b73f70f55035c21fa22d7941
       path: examples/skydns-atomicapp/

Where

  • git_url: is mandatory and represents a string which can be used in git clone command
  • checkout: is optional and represents a string which can be used in git checkout command
  • path: is optional and represent a string which is
    1. a directory and can be used in cd command (all files found in that directory are then expected to be artifacts)
    2. a file and can be read

Artifacts can be then specified by a combination by URL like strings and above specified objects describing contents of git repository.

Problems

The only problem I can think of regarding this change is potentially conflicting file names. This is not really a spec problem, but mostly an implementation problem thus at least some naming suggestions might be provided to developers.

Add type to the params definition

Currently we use INI format to store answers.conf(.sample). Although this is nice from user experience point of view, it blocks us from using non-scalar values for params as is.

Let's assume we have an application which expects a list of IP addresses as a parameter. With current params structure and INI file it's not possible to parse and pass such value to the Nulecule app without assumptions being done about the param - i.e. mathing the value to some regular expressions or something similar. In case of adding a type key to params definition we would be able to recognize the value type easily and by parsing it also validate it against the given type.

For yaml and json types are implicit, for INI we would need to introduce some conventions - f.e.:

nulecule:
params:
  - name: public_ips
    pointer: /spec/containers/0/public_ip
    type: array
    default:
      - 10.0.0.3
      - 10.0.0.4

-----

answers.conf:
[my-app]
public_ips = '["192.168.1.2", "192.168.1.3"]'

The type key might be optional and default to current behaviour - i.e. type string.

Problems

This would obviously bring more complexity to both implementation of the spec and creation of nulecule apps.

tag name of releases use v-notation

vx.y.z is only used for the release tags and archives, but not anywhere else in the spec. We should normalize that and retag without the v

Proposal: Mechanism for binding unbound variables in Kubernetes templates

Nulecule needs a standardized mechanism for replacing unbound variables in the Kubernetes data structure templates which define a complex application in Kuberentes.

This proposal offers a suggestion for both the mechanics of inserting variables into the Kubernetes templates and for a way for Nulecule developers to indicate to application consumers what variables remain unbound and must be resolved to run a Nulecule.

Discussion points

  • Re-usable container images generally require some inputs (variables) which can be unique to each instance.
  • Kubernetes Container and Container Template data structures can provide these through environment variables and other means.
  • Kubernetes and Nulecule service developers will provide values for these variables in the Kubernetes YAML/JSON data structures when creating Kubernetes services, pods, replication controllers.

Suggestion

JSON and YAML components can be described and accessed using an XPATH formed string. When creating a Kubernetes template, any unresolved variables will be specified in a separate section in the Nulecule file. Each variable specification will consist of an ID or key and a llst of XPATH strings for the placement of the needed value in the matching JSON/YAML templates.

This offers two benefits:

  • The consumer of the Nulecule as a single location to look for the set of unbound variables which must be satisfied for the application to deploy and run.
  • The implementation can use a standard notation and mechanism for resolving and binding the variables when the application is instantiated.

Additional Discussion

What remains is to define the specification for how the variable/path sets will be provided in the Nulecule files and how they will be mechanically resolved at run-time.

Additional comments encouraged.

Use list of apps instead of magic key naming

Looking at a Kubernetes API issue they point out the potential for confusion when using arbitrary names for keys. Consider A vs B:

A, current spec:

graph:
  mariadb-app:
    params:
      ...
    artifacts:
      ...

B, proposed

graph:
  - name: mariadb-app
    params:
      ...
    artifacts:
      ...

I think B is clearer that we're not doing something magic with the keys; They're just arbitrary names. Note we would have to bump the spec version with this change.

expand source definition of an application

We had a brief chat with @vpavlin and @kbsingh today.
It could be great if application source could be specified by:

  • git url
  • git branch
  • path to source within git repo

Then the application could be built straight from sources (and e.g. fed into build system).

Graph including "docker username" during dev

While I am developing my sub-apps for my overall-app, I want to be able to use the "name that will appear in the registry" without having done a push to the registry yet in the graph.

e.g.
"graph": [ "my-user/redis-app", "my-app" ]

but, on disk, it is graph/my-user-redis-app? or graph/my-user.redis-app? or graph/my-user/redis-app ? because I haven't pushed it to the registry yet.

projectatomic/helloapache example is failing

I tried to run the helloapache example from dockerhub on latest CentOS7 box, it failed to run. CC @ggallen

Here are the steps I followed

  • Get a single node k8s setup
[vagrant@localhost ~]$ kubectl get nodes
NAME        LABELS                             STATUS
127.0.0.1   kubernetes.io/hostname=127.0.0.1   Ready
  • Run the helloapache example
[vagrant@localhost ~]$ atomic run projectatomic/helloapache
/usr/bin/docker pull projectatomic/helloapache
latest: Pulling from docker.io/projectatomic/helloapache
f1b10cd84249: Pull complete
c852f6d61e65: Pull complete
7322fbe74aa5: Pull complete
00b732e9ad70: Pull complete
54fa122efced: Pull complete
b6c62bd7b7bb: Pull complete
c2c2d3f8fe0a: Pull complete
01b6c9c5d908: Pull complete
a2fe7177d65a: Pull complete
616b6e613571: Pull complete
0b6b10d60c35: Pull complete
ae71f37e66d3: Pull complete
5cd578686f9d: Pull complete
f6c7e1e80ccd: Pull complete
d0abd9728a48: Pull complete
72930c585f3e: Pull complete
aa99af784907: Pull complete
a7b22197203f: Already exists
Digest: sha256:98bcea47bea3cfa3057b824716f02b94fd133c1d0062b4f18cf59706177ef92c
Status: Downloaded newer image for docker.io/projectatomic/helloapache:latest
docker run -it --rm  --privileged -v /home/vagrant:/atomicapp -v /run:/run -v /:/host --net=host --name helloapache -e NAME=helloapache -e IMAGE=projectatomic/helloapache projectatomic/helloapache -v  run  /atom
icapp
2015-08-21 11:30:51,447 - atomicapp.install - INFO - App name is projectatomic/helloapache, will be populated to /atomicapp
2015-08-21 11:30:51,447 - atomicapp.utils - INFO - atomicapp.status.info.message=Loading app projectatomic/helloapache .
2015-08-21 11:30:51,447 - atomicapp.utils - INFO - atomicapp.status.answer.message={"general": {"namespace": "default", "provider": "kubernetes"}}
2015-08-21 11:30:51,447 - atomicapp.nulecule_base - DEBUG - {'namespace': 'default', 'provider': 'kubernetes'}
2015-08-21 11:30:51,499 - atomicapp.nulecule_base - DEBUG - Output of docker images cmd:
2015-08-21 11:30:51,499 - atomicapp.utils - INFO - atomicapp.status.info.message=Pulling image projectatomic/helloapache ...
latest: Pulling from docker.io/projectatomic/helloapache
f1b10cd84249: Already exists
c852f6d61e65: Already exists
7322fbe74aa5: Already exists
00b732e9ad70: Already exists
54fa122efced: Already exists
b6c62bd7b7bb: Already exists
c2c2d3f8fe0a: Already exists
01b6c9c5d908: Already exists
a2fe7177d65a: Already exists
616b6e613571: Already exists
0b6b10d60c35: Already exists
ae71f37e66d3: Already exists
5cd578686f9d: Already exists
f6c7e1e80ccd: Already exists
d0abd9728a48: Already exists
72930c585f3e: Already exists
aa99af784907: Already exists
a7b22197203f: Already exists
Digest: sha256:98bcea47bea3cfa3057b824716f02b94fd133c1d0062b4f18cf59706177ef92c
Status: Image is up to date for docker.io/projectatomic/helloapache:latest
2015-08-21 11:30:52,291 - atomicapp.nulecule_base - DEBUG - {'namespace': 'default', 'provider': 'kubernetes'}
2015-08-21 11:30:52,292 - atomicapp.install - DEBUG - Creating a container with name helloapache-WJiMlh
2015-08-21 11:30:52,292 - atomicapp.install - DEBUG - /usr/bin/docker run --name helloapache-WJiMlh --entrypoint /bin/true projectatomic/helloapache
2015-08-21 11:30:53,120 - atomicapp.utils - INFO - Using temporary directory /tmp/nulecule-cjiCCa
2015-08-21 11:30:53,120 - atomicapp.install - DEBUG - ['/usr/bin/docker', 'cp', 'helloapache-WJiMlh:/application-entity', '/tmp/nulecule-cjiCCa']
2015-08-21 11:30:53,247 - atomicapp.install - DEBUG - Application entity data copied to /tmp/nulecule-cjiCCa
2015-08-21 11:30:53,248 - atomicapp.utils - INFO - atomicapp.status.info.message=Copied app successfully.
helloapache-WJiMlh
2015-08-21 11:30:53,300 - atomicapp.install - INFO - Copying app helloapache
2015-08-21 11:30:53,311 - atomicapp.nulecule_base - DEBUG - Setting app id to helloapache-app
2015-08-21 11:30:53,312 - atomicapp.install - DEBUG - App ID: helloapache-app
2015-08-21 11:30:53,312 - atomicapp.nulecule_base - DEBUG - Version check successful: specversion == 0.0.2
2015-08-21 11:30:53,312 - atomicapp.utils - INFO - atomicapp.status.info.message=Checking all artifacts
2015-08-21 11:30:53,312 - atomicapp.nulecule_base - DEBUG - Provider: docker
2015-08-21 11:30:53,312 - atomicapp.utils - INFO - atomicapp.status.info.message=Artifact file://artifacts/docker/hello-apache-pod_run: OK.
2015-08-21 11:30:53,312 - atomicapp.nulecule_base - DEBUG - Provider: kubernetes
2015-08-21 11:30:53,312 - atomicapp.utils - INFO - atomicapp.status.info.message=Artifact file://artifacts/kubernetes/hello-apache-pod.json: OK.
2015-08-21 11:30:53,312 - atomicapp.utils - INFO - atomicapp.status.info.message=All artifacts OK.
2015-08-21 11:30:53,312 - atomicapp.nulecule_base - INFO - Artifacts for helloapache-app present for these providers: docker, kubernetes
2015-08-21 11:30:53,312 - atomicapp.utils - INFO - atomicapp.status.info.message=Loading Nulecule file.
2015-08-21 11:30:53,312 - atomicapp.install - INFO - Installing dependencies for helloapache-app
2015-08-21 11:30:53,312 - atomicapp.utils - DEBUG - {u'artifacts': {u'docker': [u'file://artifacts/docker/hello-apache-pod_run'], u'kubernetes': [u'file://artifacts/kubernetes/hello-apache-pod.json']}, u'params': [{u'default': u'centos/httpd', u'name': u'image', u'description': u'The webserver image'}, {u'default': 80, u'name': u'hostport', u'description': u'The host TCP port as the external endpoint'}], u'name': u'helloapache-app'}
2015-08-21 11:30:53,313 - atomicapp.install - DEBUG - Component helloapache-app is part of the app
2015-08-21 11:30:53,313 - atomicapp.install - DEBUG - Values: {u'helloapache-app': {u'image': u'centos/httpd', u'hostport': 80}}
2015-08-21 11:30:53,313 - atomicapp.utils - INFO - atomicapp.status.info.message=All dependencies installed successfully.
2015-08-21 11:30:53,313 - atomicapp.install - DEBUG - {u'helloapache-app': {u'image': u'centos/httpd', u'hostport': 80}}
2015-08-21 11:30:53,313 - atomicapp.nulecule_base - DEBUG - Data given {u'helloapache-app': {u'image': u'centos/httpd', u'hostport': 80}}
2015-08-21 11:30:53,313 - atomicapp.install - DEBUG - {u'helloapache-app': {u'image': u'centos/httpd', u'hostport': 80}, 'general': {'namespace': 'default', 'provider': 'kubernetes'}}
2015-08-21 11:30:53,313 - atomicapp.nulecule_base - INFO - Writing answers file template to /atomicapp/answers.conf.sample
2015-08-21 11:30:53,313 - atomicapp.nulecule_base - DEBUG - writing {u'helloapache-app': {u'image': u'centos/httpd', u'hostport': 80}, 'general': {'namespace': 'default', 'provider': 'kubernetes'}} to /atomicapp/answers.conf.sample with format ini
2015-08-21 11:30:53,314 - atomicapp.utils - INFO - atomicapp.status.answer.message={"helloapache-app": {"image": "centos/httpd", "hostport": 80}, "general": {"namespace": "default", "provider": "kubernetes"}}
2015-08-21 11:30:53,314 - atomicapp.utils - INFO - atomicapp.status.info.message=Install Successful.
2015-08-21 11:30:53,314 - atomicapp.utils - INFO - atomicapp.status.info.message=Install Successful.
2015-08-21 11:30:53,314 - atomicapp.utils - DEBUG - Using working directory /atomicapp/.workdir
2015-08-21 11:30:53,314 - atomicapp.plugin - DEBUG - Loading providers from /usr/lib/python2.7/site-packages/atomicapp-0.1.9-py2.7.egg/atomicapp/providers
2015-08-21 11:30:53,322 - atomicapp.nulecule_base - DEBUG - Setting app id to helloapache-app
2015-08-21 11:30:53,322 - atomicapp.nulecule_base - DEBUG - Version check successful: specversion == 0.0.2
2015-08-21 11:30:53,322 - atomicapp.nulecule_base - DEBUG - Provider: docker
2015-08-21 11:30:53,322 - atomicapp.utils - INFO - atomicapp.status.info.message=Artifact file://artifacts/docker/hello-apache-pod_run: OK.
2015-08-21 11:30:53,322 - atomicapp.nulecule_base - DEBUG - Provider: kubernetes
2015-08-21 11:30:53,323 - atomicapp.utils - INFO - atomicapp.status.info.message=Artifact file://artifacts/kubernetes/hello-apache-pod.json: OK.
2015-08-21 11:30:53,323 - atomicapp.utils - INFO - atomicapp.status.info.message=All artifacts OK.
2015-08-21 11:30:53,323 - atomicapp.nulecule_base - INFO - Artifacts for helloapache-app present for these providers: docker, kubernetes
2015-08-21 11:30:53,323 - atomicapp.utils - DEBUG - {u'artifacts': {u'docker': [u'file://artifacts/docker/hello-apache-pod_run'], u'kubernetes': [u'file://artifacts/kubernetes/hello-apache-pod.json']}, u'params': [{u'default': u'centos/httpd', u'name': u'image', u'description': u'The webserver image'}, {u'default': 80, u'name': u'hostport', u'description': u'The host TCP port as the external endpoint'}], u'name': u'helloapache-app'}
2015-08-21 11:30:53,323 - atomicapp.run - DEBUG - Processing component 'helloapache-app' and graph item '{u'artifacts': {u'docker': [u'file://artifacts/docker/hello-apache-pod_run'], u'kubernetes': [u'file://artifacts/kubernetes/hello-apache-pod.json']}, u'params': [{u'default': u'centos/httpd', u'name': u'image', u'description': u'The webserver image'}, {u'default': 80, u'name': u'hostport', u'description': u'The host TCP port as the external endpoint'}], u'name': u'helloapache-app'}'
2015-08-21 11:30:53,323 - atomicapp.plugin - DEBUG - Found provider <class 'kubernetes.KubernetesProvider'>
2015-08-21 11:30:53,323 - atomicapp.nulecule_base - DEBUG - Param provider already in general with value kubernetes
2015-08-21 11:30:53,323 - atomicapp.nulecule_base - DEBUG - Param namespace already in general with value default
2015-08-21 11:30:53,323 - atomicapp.utils - INFO - atomicapp.status.info.message=Deploying component helloapache-app ...
2015-08-21 11:30:53,323 - atomicapp.run - INFO - Using provider kubernetes for component helloapache-app
2015-08-21 11:30:53,323 - atomicapp.run - DEBUG - Templating artifact /atomicapp/artifacts/kubernetes/hello-apache-pod.json
2015-08-21 11:30:53,324 - atomicapp.nulecule_base - DEBUG - Param provider already in general with value kubernetes
2015-08-21 11:30:53,324 - atomicapp.nulecule_base - DEBUG - Param namespace already in general with value default
2015-08-21 11:30:53,324 - atomicapp.run - DEBUG - Config: {u'image': u'centos/httpd', 'provider': 'kubernetes', 'namespace': 'default', u'hostport': 80}
2015-08-21 11:30:53,324 - atomicapp.run - DEBUG - {u'image': u'centos/httpd', 'provider': 'kubernetes', 'namespace': 'default', u'hostport': 80}
2015-08-21 11:30:53,324 - atomicapp.plugin - DEBUG - Writing artifact to /atomicapp/.workdir/helloapache-app/artifacts/kubernetes/hello-apache-pod.json
2015-08-21 11:30:53,324 - kubernetes - DEBUG - Given config: {u'image': u'centos/httpd', 'provider': 'kubernetes', 'namespace': 'default', u'hostport': 80}
2015-08-21 11:30:53,324 - kubernetes - INFO - Using namespace default
2015-08-21 11:30:53,324 - kubernetes - INFO - trying kubectl at /host/usr/bin/kubectl
2015-08-21 11:30:53,325 - kubernetes - INFO - found kubectl at /host/usr/bin/kubectl
2015-08-21 11:30:53,325 - kubernetes - INFO - Deploying to Kubernetes
2015-08-21 11:30:53,325 - kubernetes - DEBUG - /atomicapp/.workdir/helloapache-app/artifacts/kubernetes/hello-apache-pod.json
2015-08-21 11:30:53,341 - kubernetes - DEBUG - stdout =
2015-08-21 11:30:53,341 - kubernetes - DEBUG - stderr = error: could not read an encoded object from /atomicapp/.workdir/helloapache-app/artifacts/kubernetes/hello-apache-pod.json: API version "v1beta3" in "/atomicapp/.workdir/helloapache-app/artifacts/kubernetes/hello-apache-pod.json" isn't supported, only supports API versions ["v1"]
error: no objects passed to create


2015-08-21 11:30:53,341 - atomicapp.utils - INFO - atomicapp.status.error.message=cmd failed: /host/usr/bin/kubectl create -f /atomicapp/.workdir/helloapache-app/artifacts/kubernetes/hello-apache-pod.json --namespace=default
Traceback (most recent call last):
  File "/usr/bin/atomicapp", line 9, in <module>
    load_entry_point('atomicapp==0.1.9', 'console_scripts', 'atomicapp')()
  File "/usr/lib/python2.7/site-packages/atomicapp-0.1.9-py2.7.egg/atomicapp/cli/main.py", line 227, in main
    cli.run()
  File "/usr/lib/python2.7/site-packages/atomicapp-0.1.9-py2.7.egg/atomicapp/cli/main.py", line 203, in run
    args.func(args)
  File "/usr/lib/python2.7/site-packages/atomicapp-0.1.9-py2.7.egg/atomicapp/cli/main.py", line 54, in cli_run
    if ae.run() is not None:
  File "/usr/lib/python2.7/site-packages/atomicapp-0.1.9-py2.7.egg/atomicapp/run.py", line 230, in run
    self._dispatchGraph()
  File "/usr/lib/python2.7/site-packages/atomicapp-0.1.9-py2.7.egg/atomicapp/run.py", line 125, in _dispatchGraph
    self._processComponent(component, graph_item)
  File "/usr/lib/python2.7/site-packages/atomicapp-0.1.9-py2.7.egg/atomicapp/run.py", line 213, in _processComponent
    provider.deploy()  
  File "/usr/lib/python2.7/site-packages/atomicapp-0.1.9-py2.7.egg/atomicapp/providers/kubernetes.py", line 137, in deploy
    self._callK8s(k8s_file)
  File "/usr/lib/python2.7/site-packages/atomicapp-0.1.9-py2.7.egg/atomicapp/providers/kubernetes.py", line 101, in _callK8s
    raise Exception(str(stderr))
Exception: error: could not read an encoded object from /atomicapp/.workdir/helloapache-app/artifacts/kubernetes/hello-apache-pod.json: API version "v1beta3" in "/atomicapp/.workdir/helloapache-app/artifacts/kubernetes/hello-apache-pod.json" isn't supported, only supports API versions ["v1"]
error: no objects passed to create

[1] https://hub.docker.com/r/projectatomic/helloapache/

Get back the definition of files the nulecule app consists of

With the move to the JSON Schema we lost the definition of files/dirs and it's content which was previously specified in the schema.json. I think it was useful - for example generation of Dockerfile was very easy that with it. Can we think about where/how to specify it again?

specify a method to inject environment variables into the deployed applications environment

user story

As a deployment guy
I want to inject/set an environment variable
so that it is accessible from within the application

Rational

Most applications that require a API_KEY or TOKEN do read this information from env vars, so that the secrets must not be stored in any file. We need to find a specification that will inject env vars into the application context/environment.

PROPOSAL: Single directory for spec, use tagged releases

I cannot maintain the spec in its current form. Adding to the spec requires us to guess the next version number, create a directory with that number, copy over the files from the previous version and start updating. This prevents us from using diff as we need to among other issues.

Proposal

  1. Use release tags like everyone else. We have none.
  2. Create a branch with each release for any bugfixes required after release. This allows us to fix something in version n.0 (typo, etc) and create a new release tagged n.1.
  3. Host the current spec on an external site like readthedocs.org or projectatomic.io. We will direct users there.
  4. Master is latest. Any changes are pushed to master.

Implementation

  1. Create a 0.0.1 release branch from the last 0.0.1 commit.
  2. Tag a 0.0.1 release from the last 0.0.1 commit.
  3. Create a 0.0.2 release branch from the last 0.0.2 commit.
  4. Tag a 0.0.2 release from the last 0.0.2 commit.
  5. Commit a change to master that compresses directory into a single directory. Proposed new layout:
├── docs
├── examples
└── spec
    ├── constraint.json
    ├── examples
    │   └── template
    │       ├── artifacts
    │       │   ├── provider1
    │       │   │   ├── pod.json
    │       │   │   └── service.json
    │       │   └── provider2
    │       │       └── file.json
    │       ├── Dockerfile
    │       └── Nulecule
    ├── files
    ├── graph.json
    ├── license.json
    ├── metadata.json
    ├── param.json
    ├── provider.json
    ├── README.md
    ├── requirement.json
    ├── requirements
    │   └── persistentvolume.json
    └── schema.json

ACK?

wordpress-centos7-atomicapp errors out on fedora atomic 22

On fedora-atomic 22.87 (kubernetes-1.0.0-0.9.git2d88675 & docker-1.7.1-4.gitcc60fc3 ), running sudo atomic run projectatomic/wordpress-centos7-atomicapp errors out:

2015-08-06 21:21:35,844 - atomicapp.install - DEBUG - ['docker', 'cp', 'wordpress-centos7-atomicapp-TcVrjq:/application-entity', '/tmp/nulecule-kUdMCL']
FATA[0000] Error response from daemon: Could not find the file /application-entity in container wordpress-centos7-atomicapp-TcVrjq 
wordpress-centos7-atomicapp-TcVrjq
2015-08-06 21:21:36,040 - atomicapp.install - DEBUG - Nulecule path for pulled image: /tmp/nulecule-kUdMCL/application-entity/Nulecule
Traceback (most recent call last):
  File "/usr/bin/atomicapp", line 9, in <module>
    load_entry_point('atomicapp==0.1', 'console_scripts', 'atomicapp')()
  File "/usr/lib/python2.7/site-packages/atomicapp/cli/main.py", line 89, in main
    cli.run()
  File "/usr/lib/python2.7/site-packages/atomicapp/cli/main.py", line 70, in run
    args.func(args)
  File "/usr/lib/python2.7/site-packages/atomicapp/cli/main.py", line 20, in cli_run
    ae = Run(**vars(args))
  File "/usr/lib/python2.7/site-packages/atomicapp/run.py", line 64, in __init__
    install.install()
  File "/usr/lib/python2.7/site-packages/atomicapp/install.py", line 98, in install
    self.nulecule_base.loadMainfile(mainfile_path)
  File "/usr/lib/python2.7/site-packages/atomicapp/nulecule_base.py", line 88, in loadMainfile
    raise Exception("%s not found: %s" % (MAIN_FILE, path))
Exception: Nulecule not found: /tmp/nulecule-kUdMCL/application-entity/Nulecule

Define service dependencies

My app depends on a service (e.g. SkyDNS). I want to define it as a dependency and deploy if not available on my cluster. If the service is active on my cluster, do nothing.

Questions

  • How does openshift deal with this?
  • Is there any upstream kubernetes work in this area?

RFE: specifiy how to integrate external services

As as developer I want to write applications and package them up as a Nulecule, and would like to address external services, so that we can use for example public cloud SaaS offerings.

By 'external' I mean something that is available via TCP/IP at a given Port. To address these Kubernetes has the concept of 'service'... OpenShift too has this... how to formalize this inside of Nulecule Spec?

Determine provider layout

For v1 we need to flesh out how providers are specified.

  • Should providers be specified as a magically named directory?
  • Should the provider type be part of a data structure?

Package ELK stack example using atomicapp

Since ELK stack seems to be common use-case, we could add it as an example under nulecule/examples/. I'm willing to become a secondary owner for this under guidance from a primary one, since I don't have much knowledge of atomicapp.

remove skydns example

Any objections? It does not show something in addition to the other examples and I cant figure out if it was used by any other example.

Maintain single spec file

Currently we have both a human-readable README and a machine-readable JSON file to describe the specification. With some extension we could put all of the additional data from the README into the JSON and create a parser script to render it.

Rename Atomicfile

Atomicfile is an interesting name but too specific to project atomic. As a specification we need another filename.

It is not clear what the prescribed format of license name is

In the License Object, there is a name field that says:

The license name used for the API.

However, it is not clear what format of the name should be used. Such as, for example:

  • GNU GPL, Version 3
  • GNU GPL version 3
  • GNU GPL 3
  • GNU General Public License, version 3 or later

In example GNU GPL, Version 3 is used. Is the format required? Optional? What about other licenses?

atomicapp message flow to cockpit broken

if you look at the output of atomic run projectatomic/atomicapp on issue #152 you see that it fails, but the last message sent to Cockpit it 2015-08-20 15:51:56,319 - atomicapp.utils - INFO - atomicapp.status.info.message=Copied app successfully. atomicapp-ScBViM

Examples are not valid Nulecule 0.0.2

Results of running the validator on the Nulecule files of the examples:

examples/guestbook-go/Nulecule
graph > 0 > params: {'hostport': {'description': 'The host TCP port as the external endpoint', 'default': 80}, 'publicip': {'description': 'The IP address or addresses at which your app can be reached'}, 'image': {'description': 'The frontend part', 'default': 'kubernetes/guestbook:v2'}} is not of type 'array'

examples/helloapache/Nulecule
graph > 0 > params: {'image': {'default': 'centos/httpd', 'description': 'The webserver image'}, 'hostport': {'default': 80, 'description': 'The host TCP port as the external endpoint'}} is not of type 'array'

examples/mariadb-app/Nulecule
graph > 0 > params: {'db_user': {'description': 'database user'}, 'db_pass': {'description': 'Database password'}, 'db_name': {'description': 'database name'}, 'image': {'description': 'which mariadb image to use (including registry if not docker hub)', 'default': 'fedora/mariadb'}} is not of type 'array'

examples/redis-centos7-atomicapp/Nulecule
graph > 0 > params: {'hostport': {'description': 'The host TCP port as the external endpoint', 'default': 6379}, 'image': {'description': 'The redis master part', 'default': 'jasonbrooks/redis'}} is not of type 'array'
graph > 1 > params: {'hostport': {'description': 'The host TCP port as the external endpoint', 'default': 6379}, 'image': {'description': 'The redis slave part', 'default': 'jasonbrooks/redis'}} is not of type 'array'

Maintainers and PR review

We need to ensure changes to the spec are reviewed carefully and consider impact to implementations.

@goern would you be able to review pull requests?
@vpavlin would you be able to review pull requests?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.