cloudless

Cloudless is a python library to provide a basic set of easy to use primitive operations that can work with many different cloud providers.

These primitives are:

  • Create a "Network" (also known as VPC, Network, Environment). e.g. "dev".
  • Create a "Service" within that network. e.g. "apache-public".
  • Easily control network connections and firewalls using "Paths".

The goal is to provide an intuitive abstraction that is powerful enough to build on, so that building other layers on top is easy and anything built on it is automatically cross cloud.

The main entry point to this module is through the cloudless.Client object, and all calls that interact with a backing cloud provider go through this object.

Client

Client(self, profile=None, provider=None, credentials=None)

Top Level Cloudless Client.

This is the object through which all calls to the backing service provider are made.

Most functionality is stored in the subclasses that are attached to this client. Currently they are cloudless.NetworkClient, cloudless.ServiceClient, and cloudless.PathsClient. See the documentation on those sub-components for more usage details.

To use:

import cloudless
client = cloudless.Client(provider, credentials)
client.network?
client.service?
client.paths?

Where "provider" is the backing service provider, and "credentials" is a hash containing whatever credentials are required by the chosen provider. See the supported providers list for details.

graph

Client.graph(self)

Return a DOT formatted graph string containing all resources on the current provider.

This string can be passed to a program like graphviz to generate a graph visualization.

NetworkClient

NetworkClient(self, provider, credentials)

Cloudless Network Client.

This is the object through which all network related calls are made. The objects returned by these commands are of type cloudless.types.common.Network.

Usage:

import cloudless
client = cloudless.Client(provider, credentials)
client.network.create("network", blueprint="tests/blueprints/network.yml")
client.network.get("network")
client.network.list()
client.network.destroy(client.network.get("network"))

The above commands will create and destroy a network named "network".

create

NetworkClient.create(self, name, blueprint=None)

Create new network named "name" with blueprint file at "blueprint".

Example:

client.network.create("mynetwork", "network-blueprint.yml")

get

NetworkClient.get(self, name)

Get a network named "name" and return some data about it.

Example:

client.network.get("mynetwork")

destroy

NetworkClient.destroy(self, network)

Destroy the given network.

Example:

client.network.destroy(client.network.get("mynetwork"))

list

NetworkClient.list(self)

List all networks.

Example:

client.network.list()

ServiceClient

ServiceClient(self, provider, credentials)

Cloudless Service Client.

This is the object through which all service related calls are made. The objects returned by these commands are of type cloudless.types.common.Service which contain objects of type cloudless.types.common.Subnetwork, which themselves contain lists of cloudless.types.common.Instance. This is because the service is the logical grouping, but behind the scenes they are groups of instances deployed in private subnetworks.

Usage:

import cloudless
client = cloudless.Client(provider, credentials)
network = client.network.create("network", blueprint="tests/blueprints/network.yml")
client.service.create(network, "public", blueprint="tests/blueprints/service.yml")
myservice = client.service.get(mynetwork, "public")
client.service.list()
client.service.destroy(myservice)

The above commands will create and destroy a service named "public" in the network "network".

create

ServiceClient.create(self, network, service_name, blueprint, template_vars=None, count=None)

Create a service in "network" named "service_name" with blueprint file at "blueprint".

"template_vars" are passed to the initialization scripts as jinja2 variables.

Example:

example_network = client.network.create("example")
example_service = client.service.create(network=example_network,
                                        name="example_service",
                                        blueprint="example-blueprint.yml")

get

ServiceClient.get(self, network, service_name)

Get a service in "network" named "service_name".

Example:

example_service = client.service.get(network=client.network.get("example"),
                                     name="example_service")

get_instances

ServiceClient.get_instances(self, service)

Helper to return the list of instances given a service object.

Example:

example_service = client.service.get(network=client.network.get("example"),
                                     name="example_service")
instances = client.service.get_instances(example_service)

destroy

ServiceClient.destroy(self, service)

Destroy a service described by the "service" object.

Example:

example_service = client.service.get(network=client.network.get("example"),
                                     name="example_service")
client.service.destroy(example_service)

list

ServiceClient.list(self)

List all services.

Example:

client.service.list()

node_types

ServiceClient.node_types(self)

Get mapping of node types to the resources.

Example:

client.service.node_types()

PathsClient

PathsClient(self, provider, credentials)

Cloudless Paths Client.

This is the object through which all path related calls are made. The objects returned by these commands are of type cloudless.types.common.Path which contain objects of type cloudless.types.common.Service and cloudless.types.networking.CidrBlock depending on whether the path is internally or externally facing.

Usage:

import cloudless
client = cloudless.Client(provider, credentials)
internal_service = client.service.get(network, "internal_service")
load_balancer = client.service.get(network, "load_balancer")
internet = cloudless.types.networking.CidrBlock("0.0.0.0/0")
client.paths.add(load_balancer, internal_service, 80)
client.paths.add(internet, load_balancer, 443)
client.paths.list()
client.graph()

The above commands will result in the public internet having access to "load_balancer" on port 443 and "load_balancer" having access to "internal_service" on port 80.

add

PathsClient.add(self, source, destination, port)

Make the service or cidr block described by "destination" accessible from the service or cidr block described by "source" on the given port.

Either "source" or "destination" must be a service object.

Example:

service1 = client.service.get(network=client.network.get("example"), name="service1")
service2 = client.service.get(network=client.network.get("example"), name="service2")
internet = cloudless.types.networking.CidrBlock("0.0.0.0/0")
client.paths.add(service1, service2, 443)
client.paths.add(internet, service1, 80)

remove

PathsClient.remove(self, source, destination, port)

Ensure the service or cidr block described by "destination" is not accessible from the service or cidr block described by "source" on the given port.

Either "source" or "destination" must be a service object.

Example:

service1 = client.service.get(network=client.network.get("example"), name="service1")
service2 = client.service.get(network=client.network.get("example"), name="service2")
internet = cloudless.types.networking.CidrBlock("0.0.0.0/0")
client.paths.remove(service1, service2, 443)
client.paths.remove(internet, service1, 80)

list

PathsClient.list(self)

List all paths and return a dictionary structure representing a graph.

Example:

client.paths.list()

internet_accessible

PathsClient.internet_accessible(self, service, port)

Returns true if the service described by "service" is internet accessible on the given port.

Example:

service1 = client.service.get(network=client.network.get("example"), name="service1")
client.paths.internet_accessible(service1, 443)

has_access

PathsClient.has_access(self, source, destination, port)

Returns true if the service or cidr block described by "destination" is accessible from the service or cidr block described by "source" on the given port.

Either "source" or "destination" must be a service object.

Example:

service1 = client.service.get(network=client.network.get("example"), name="service1")
service2 = client.service.get(network=client.network.get("example"), name="service2")
internet = cloudless.types.networking.CidrBlock("0.0.0.0/0")
client.paths.has_access(service1, service2, 443)
client.paths.has_access(internet, service1, 80)