{ "info": { "author": "Shaun Verch", "author_email": "shaun@getcloudless.com", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy" ], "description": "\n# Cloudless\n\nCloudless makes it easier to interact with cloud resources by doing most of the\nwork that a human doesn't need to care about for you, and by being transparent\nabout what it's doing.\n\n- [Homepage](https://getcloudless.com)\n- [Documentation](https://docs.getcloudless.com)\n- [Github](https://github.com/getcloudless/cloudless)\n\n## Installation\n\nThis project depends on [Python\n3.6.0](https://www.python.org/downloads/release/python-360/) or greater. To\ninstall, run:\n\n```shell\npip3 install cloudless\n```\n\n## Quick Start\n\nThese examples show how to quickly create a simple service that is accessible on\nport 80 in Google Compute Engine and in Amazon Web Services. Run any command\nwith `--help` for more usage.\n\n### Google Compute Engine Credentials\n\nTo set up the Google Compute Engine client, you must first create your Google\nCompute Engine account and navigate to\n[https://console.cloud.google.com/iam-admin/serviceaccounts](https://console.cloud.google.com/iam-admin/serviceaccounts).\nThere you can select your project and create a service account. Remember the\nservice account email and create a key for this service account. Download and\nsave this key on your local machine, remembering the path.\n\nYou will also need the project ID (not the project name). Go to\n[https://console.cloud.google.com/iam-admin/settings/project](https://console.cloud.google.com/iam-admin/settings/project)\nand select your project to find your project ID. When you think you have\neverything, run:\n\n```shell\ncldls init --provider gce\ncldls network list\n```\n\nThis will set the \"default\" profile to use the \"gce\" backend. You can change\nthe profile by passing `--profile` to cloudless or setting the\n`CLOUDLESS_PROFILE` environment variable. See [Profiles](#profiles) for more information.\n\n### Amazon Web Services Credentials\n\nTo set up the Amazon Web Services client, follow the steps at\n[https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html)\nto configure the aws cli. Currently, cloudless only uses the \"default\" aws\nprofile that is configured in this way. After you set up a default profile that\nworks with the AWS cli, everything in cloudless should work. When you think you\nhave this working, run:\n\n```\ncldls init --provider aws\ncldls network list\n```\n\nThis will set the \"default\" profile to use the \"aws\" backend. You can change\nthe profile by passing `--profile` to cloudless or setting the\n`CLOUDLESS_PROFILE` environment variable. See [Profiles](#profiles) for more information.\n\n### Simple Service\n\nThe next steps are identical regardless of which cloud provider you're using.\nThey do assume you have an image named \"cloudless-example-base-image-v0\" with\nUbuntu 16.04 installed on it in your provider. See the [Image\nBuilder](#image-builder) section for how to build an image like this using\nCloudless.\n\nOnce you have the prerequisites, you can create your service with:\n\n```shell\ncldls network create mynet examples/network/blueprint.yml\ncldls service create mynet myservice examples/apache/blueprint.yml\ncldls paths allow_network_block mynet myservice 0.0.0.0/0 80\ncldls service get mynet myservice\n# Navigate to the \"public_ip\" of each instance in a browser to see the service.\n```\n\n### Command Line Autocomplete\n\nSince this project uses [click](https://click.palletsprojects.com/en/7.x/),\nautocomplete is built in. Just follow\n[https://click.palletsprojects.com/en/5.x/bashcomplete/](https://click.palletsprojects.com/en/5.x/bashcomplete/)\nif you use bash or\n[https://github.com/click-contrib/click-completion](https://github.com/click-contrib/click-completion)\nfor other shells.\n\nFor example, for bash puth this in your .bashrc:\n\n```shell\neval \"$(_CLDLS_COMPLETE=source cldls)\"\n```\n\n## Profiles\n\nBoth the API and the command line support using profiles that are created with `cldls init`. The\norder of priority for loading profiles is:\n\n1. Explicitly set via the `profile` argument to `cloudless.Client` in the python api, or via the\n `--profile` option to the `cldls` command line.\n2. Set in the `CLOUDLESS_PROFILE` environment variable.\n3. `\"default\"`\n\n## Client Setup In Python API\n\nIn the Python API, you must create a client object to connect to the cloud\nplatform that you'll be working with. The client handles authentication with\nthe cloud provider, so you must pass it the name of the provider and the\nauthentication credentials.\n\nIf you are trying this project for the first time, it's recommended that you use\nthe \"mock-aws\" client.\n\n### Google Compute Engine Client\n\nTo use the Google Compute Engine client, you must create a service account and\ndownload the credentials locally. Because this provider is implemented using\n[Apache Libcloud](https://libcloud.apache.org/), you can refer to the [Google\nCompute Engine Driver\nSetup](https://libcloud.readthedocs.io/en/latest/compute/drivers/gce.html#getting-driver-with-service-account-authentication)\ndocumentation in that project for more details.\n\nWhen you have the credentials, you can do something like this, preferably in a\ndotfile you don't commit to version control. Note the credentials file is in\nJSON format:\n\n```shell\nexport CLOUDLESS_GCE_USER_ID=\"sverch-cloudless@cloudless-000000.iam.gserviceaccount.com\"\nexport CLOUDLESS_GCE_CREDENTIALS_PATH=\"/home/sverch/.gce/credentials.json\"\nexport CLOUDLESS_GCE_PROJECT_NAME=\"cloudless-000000\"\n```\n\nThen, you can run these commands in a python shell to create a GCE client:\n\n```python\nimport cloudless\nimport os\nclient = cloudless.Client(\"gce\", credentials={\n \"user_id\": os.environ['CLOUDLESS_GCE_USER_ID'],\n \"key\": os.environ['CLOUDLESS_GCE_CREDENTIALS_PATH'],\n \"project\": os.environ['CLOUDLESS_GCE_PROJECT_NAME']})\n```\n\nIf you want to avoid having to pass all this configuration explicitly to the client object, you can\nuse a [Cloudless Profile](#profiles).\n\n### Amazon Web Services Client\n\nCurrently no credentials can be passed in as arguments for the AWS provider\n(they are ignored). However this provider is implemented with\n[Boto](http://docs.pythonboto.org/en/latest/), which looks in many other places\nfor the credentials, so you can configure them in other ways. See the [boto3\ncredential setup\ndocumentation](https://boto3.readthedocs.io/en/latest/guide/configuration.html)\nfor more details.\n\nOnce you have set up your credentials, you can run the following to create an AWS client that uses\nthe \"default\" aws profile (if you pass an empty credentials object, this cloudless profile will use\nwhatever the `AWS_PROFILE` environment variable is set to, which might be confusing):\n\n```python\nimport cloudless\nclient = cloudless.Client(\"aws\", credentials={\"profile\": \"default\"})\n```\n\nIf you want to avoid having to pass all this configuration explicitly to the client object, you can\nuse a [Cloudless Profile](#profiles).\n\n### Mock Amazon Web Services Client\n\nThe Mock AWS client is for demonstration and testing. Since it is all running\nlocally, you don't need any credentials. Simply run:\n\n```python\nimport cloudless\nclient = cloudless.Client(\"mock-aws\", credentials={})\n```\n\n## Architecture\n\nThere are only three objects in Cloudless: A Network, a Service, and a Path. This\nis an example that shows a Network `dev`, a `public_load_balancer` Service, an\n`internal_service` Service, a Path from the internet to `public_load_balancer`\non port 443, and a Path from `public_load_balancer` to `internal_service` on\nport 80. See the [visualization](#visualization) section for how to generate\nthis graph.\n\n![Cloudless Simple Service Example](docs/images/example.svg)\n\n### Network\n\nA Network is the top level container for everything else. To create a new\nnetwork, run:\n\n```python\ndev_network = client.network.create(\"dev\")\n```\n\nThis will return the \"Network\" object that describes the network that was\ncreated. You can retrieve an existing network or list all existing networks by\nrunning:\n\n```python\ndev_network = client.network.get(\"dev\")\nall_networks = client.network.list()\n```\n\nFinally, to destroy a network:\n\n```python\nclient.network.destroy(dev_network)\n```\n\nCreate should use sane defaults, but if you need to do something special see\n[docs/network-configuration.md](docs/network-configuration.md).\n\nIn [ipython](https://ipython.org/), you can run `?` to [get help on any\nobject](https://ipython.readthedocs.io/en/stable/interactive/python-ipython-diff.html#accessing-help),\nfor example `client.network.create?`.\n\n### Service\n\nA Service a logical group of instances and whatever resources are needed to\nsupport them (subnetworks, firewalls, etc.).\n\nTo create a Service, you must first define a configuration file called a\n\"blueprint\" that specifies how the service should be configured. This is an\nexample of what a Service blueprint might look like:\n\n```yaml\n---\nnetwork:\n subnetwork_max_instance_count: 768\n\nplacement:\n availability_zones: 3\n\ninstance:\n public_ip: True\n memory: 4GB\n cpus: 1\n gpu: false\n disks:\n - size: 8GB\n type: standard\n device_name: /dev/sda1\n\nimage:\n name: \"ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-*\"\n\ninitialization:\n - path: \"haproxy-cloud-config.yml\"\n vars:\n PrivateIps:\n required: true\n```\n\nThe \"network\" section tells Cloudless to create subnetworks for this service big\nenough for 768 instances.\n\nThe \"placement\" section tells Cloudless to ensure instances in this service are\nprovisioned across three availaibility zones (which most cloud providers\nguarantee are meaningfully isolated from each other for resilience).\n\nThe \"instance\" section describes the resource reqirements of each instance.\nCloudless will automatically choose a instance type that meets these requirements.\n\nThe \"image\" section represents the name of the image you want your instances to\nhave. In this case, we are using an image name only found in AWS by default, so\nthis example will only work there. See `examples/apache` for a blueprint that\nworks cross cloud because it uses a custom image.\n\nThe \"initialization\" section describes startup scripts that you want to run when\nthe instance boots. You may also pass in variables, which will get passed to\nthe given file as [jinja2](http://jinja.pocoo.org/) template arguments. This is\na good place to specify environment specific configuration, so your base image\ncan stay the same across environments.\n\nOnce you have the blueprint, the example below shows how you could use it.\nThese examples create a group of private instances and then create some HAProxy\ninstances in front of those instances to balance load. Note that many commands\ntake `dev_network` as the first argument. That's the same network object\nreturned by the network commands shown above. These assume you have created the\nbase image in `examples/base-image` on the provider you are using.\n\n```python\ninternal_service = client.service.create(dev_network, \"private\",\n blueprint=\"examples/nginx/blueprint.yml\")\nprivate_ips = [instance.private_ip for instance in client.service.get_instances(internal_service)]\nload_balancer_service = client.service.create(dev_network, \"public\",\n blueprint=\"examples/haproxy/blueprint.yml\",\n template_vars={\"PrivateIps\": private_ips})\ninternal_service = client.service.get(dev_network, \"public\")\nload_balancer_service client.service.get(dev_network, \"private\")\nclient.service.list()\nclient.service.destroy(internal_service)\nclient.service.destroy(load_balancer_service)\n```\n\n### Path\n\nThe Path is how you tell Cloudless that two services should be able to communicate.\nNo blueprint is needed for this, but you need to have the service objects you\ncreated earlier. This example adds a path from the load balancer to the\ninternal service on port 80 and makes the load balancer internet accessible on\nport 443:\n\n```python\nfrom cloudless.types.networking import CidrBlock\ninternet = CidrBlock(\"0.0.0.0/0\")\nclient.paths.add(load_balancer_service, internal_service, 80)\nclient.paths.add(internet, load_balancer_service, 443)\n```\n\nYou can check whether things have access to other things or print out all paths\nwith the following functions:\n\n```python\nclient.paths.has_access(load_balancer_service, internal_service, 80)\nclient.paths.internet_accessible(load_balancer_service, 443)\nclient.paths.internet_accessible(internal_service, 443)\nclient.paths.list()\nprint(client.graph())\n```\n\n## Visualization\n\nGet a summary in the form of a graphviz compatible dot file by running:\n\n```python\nclient.graph()\n```\n\nTo generate the vizualizations, run:\n\n```shell\ncd ui && env PROVIDER= bash graph.sh\n```\n\nAnd open `ui/graph.html` in a browser. Note this won't work for the `mock-aws`\nprovider since it will be running in a different process.\n\n## Image Builder\n\nThis project provides a cross cloud image builder that depends on the core\ncloudless APIs. this means that for the most part it is completely cloud\nindependent, mod differences in the image that you start with (so it's\ncompletely independent if you're building your own custom image from scratch).\n\nFor this example, we use the Ubuntu image provided by the cloud provider, so we\nhave different blueprints for AWS and GCE (because the standard Ubuntu images\nthey provide have different names).\n\nFirst, to deploy a service running a single instance:\n\n```shell\n$ cldls --profile gce image-build deploy examples/base-image/gce_image_build_configuration.yml\n```\n\nNext, to run the configure script. This is a shellscript that cloudless will\npass the login credentials to as arguments, and where you can run your\nconfiguration as code scripts:\n\n```shell\n$ cldls --profile gce image-build configure examples/base-image/gce_image_build_configuration.yml\n```\n\nNext, to run the check script. This is another shellscript that cloudless will\npass the login credentials to as arguments, and where you can run your\nvalidation to make sure the configuration step worked as expected:\n\n```shell\n$ cldls --profile gce image-build check examples/base-image/gce_image_build_configuration.yml\n```\n\nFinally, when you have your scripts working as you want them to, run a cleanup\nin preparation for a full build. Saving images without a full build is not\nsupported to discourage modifications that are made on the machine and not\nrecorded in scripts anywhere making it into the image:\n\n```shell\n$ cldls --profile gce image-build cleanup examples/base-image/gce_image_build_configuration.yml\n```\n\nNow, run the full build end to end, and you have your new image!\n\n```shell\n$ cldls --profile gce image-build run examples/base-image/gce_image_build_configuration.yml\n```\n\nWe can list the image with:\n\n```shell\n$ cldls --profile gce image list\nImage Name: cloudless-example-base-image-v0\nImage Id: ami-0d7366265fcccbe46\nImage Created At: 2018-09-20T16:51:03.000Z\n```\n\nGet it by name with:\n\n```shell\n$ cldls --profile gce image get cloudless-example-base-image-v0\nImage Name: cloudless-example-base-image-v0\nImage Id: ami-0d7366265fcccbe46\nImage Created At: 2018-09-20T16:51:03.000Z\n```\n\nAnd finally, delete the image. You might want to wait on this step because the\n[Service Tester](#service-tester) step below uses this image:\n\n```shell\n$ cldls --profile gce image delete cloudless-example-base-image-v0\nDeleted image: cloudless-example-base-image-v0\n```\n\nSee [examples/base-image](examples/base-image) for examples of how to create a\ncross cloud base image using this framework.\n\n## Service Tester\n\nThis project also provides a framework to help test that blueprint files work as\nexpected. The framework will create, verify, and clean up the service under\ntest. It also spins up all dependent services so you can test services \"in\ncontext\". It's sort of a hybrid between a unit test and an integration test.\n\nThese examples assume the profile you have configured has an image that was\nbuilt using the [Image Builder](#image-builder) step above. If you've followed\nthose steps, these instructions are completely identical regardless of whether\nyou're using AWS or GCE.\n\nFirst, to create the service:\n\n```shell\n$ cldls service-test deploy examples/apache/service_test_configuration.yml\nCreation complete!\nTo log in, run:\nssh -i examples/apache/id_rsa_test cloudless_service_test@35.237.12.140\n$ ssh -i examples/apache/id_rsa_test cloudless_service_test@35.237.12.140\n...\n...\n\nUbuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by\napplicable law.\n\ncloudless@test-network-jmeiwknbsg-test-service-hswonxmeda-0:~$ \n```\n\nThis will create a temporary network to sandbox the test. Now, to verify that\nthe service is behaving as expected:\n\n```shell\n$ cldls service-test check examples/apache/service_test_configuration.yml\nINFO:cloudless.providers.gce:Discovering subnetwork test-network-jmeiwknbsg, test-service-hswonxmeda\nINFO:cloudless.util:Attempt number: 1\nINFO:cloudless.util:Check successful!\nCheck complete!\nTo log in, run:\nssh -i examples/apache/id_rsa_test cloudless@35.237.12.140\n```\n\nFinally, to clean up everything:\n\n```shell\n$ cldls service-test cleanup examples/apache/service_test_configuration.yml\n```\n\nIf you want to run all the previous steps all together, you can run:\n\n```shell\n$ cldls service-test run examples/apache/service_test_configuration.yml\n```\n\nSee [examples](examples) for examples of how to set up a blueprint to be\ntestable with this framework.\n\n## Testing\n\nTo run the local tests run:\n\n```shell\npipenv install --dev\ntox\n```\n\nTo run tests against GCE and AWS, run:\n\n```shell\ntox -e gce\ntox -e aws\n```\n\nThese will use the `gce-cloudless-test` and `aws-cloudless-test` cloudless\nprofiles respectively. See [Profiles](#profiles) for more information.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/sverch/cloudless", "keywords": "", "license": "Apache 2.0", "maintainer": "", "maintainer_email": "", "name": "cloudless", "package_url": "https://pypi.org/project/cloudless/", "platform": "", "project_url": "https://pypi.org/project/cloudless/", "project_urls": { "Homepage": "https://github.com/sverch/cloudless" }, "release_url": "https://pypi.org/project/cloudless/0.0.10/", "requires_dist": [ "boto3 (==1.9.202)", "botocore (==1.12.202)", "PyYAML (==5.1.2)", "Jinja2 (==2.10.1)", "pytest (==5.0.1)", "attr (==0.3.1)", "Click (==7.0)", "click-repl (==0.1.6)", "apache-libcloud (==2.5.0)", "pycryptodome (==3.8.2)", "jsonschema (==3.0.2)", "jsonref (==0.2)", "cattrs (==0.9.0)", "moto (==1.3.13)", "lazy-import (==0.2.2)", "retrying (==1.3.3)", "paramiko (==2.6.0)", "pytest (==5.0.1) ; extra == 'testing'", "pytest-xdist (==1.29.0) ; extra == 'testing'", "tox (==3.13.2) ; extra == 'testing'", "pylint (==2.3.1) ; extra == 'testing'" ], "requires_python": ">=3.6.0", "summary": "The cloudless infrastructure project.", "version": "0.0.10" }, "last_serial": 5658239, "releases": { "0.0.0": [ { "comment_text": "", "digests": { "md5": "0ca3762c9db91b7bbcbb1b8966486a90", "sha256": "fac6c194ae1e1a2633b243e180e35bbb0b6b34345b4804aa9533b2e25d2b4302" }, "downloads": -1, "filename": "cloudless-0.0.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "0ca3762c9db91b7bbcbb1b8966486a90", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 58657, "upload_time": "2018-09-10T01:43:34", "url": "https://files.pythonhosted.org/packages/35/8d/c7869712fa1845af5a4afc87696135344239e693271b5a5cd9e1f51a63ac/cloudless-0.0.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d4f39dfecf22c4e867fe1a88c6f33d3f", "sha256": "f28c0a8e671d0d682316bd30d56e7bec66ed7192237386b11d00bf68b3d843de" }, "downloads": -1, "filename": "cloudless-0.0.0.tar.gz", "has_sig": false, "md5_digest": "d4f39dfecf22c4e867fe1a88c6f33d3f", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 42157, "upload_time": "2018-09-10T01:43:36", "url": "https://files.pythonhosted.org/packages/7c/31/9f837560c057192e5224e4b59222123101a6d84268e40d99048343aee5f2/cloudless-0.0.0.tar.gz" } ], "0.0.1": [ { "comment_text": "", "digests": { "md5": "85405959d6756ff03fb460fb6828b339", "sha256": "39cbc569132e749dcd8890ec1582635a91e4effa0234babb6321872585d41e63" }, "downloads": -1, "filename": "cloudless-0.0.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "85405959d6756ff03fb460fb6828b339", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 60134, "upload_time": "2018-09-10T17:53:22", "url": "https://files.pythonhosted.org/packages/8f/32/d7bd724aa043a519018b9b1228839384aa6c4d95138e75d49f3c4fcb25ac/cloudless-0.0.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "66d7f7f092a20ac9184f855bc2e7acad", "sha256": "415dfda25fca289b7443ebb318c305213456f0684c3acaba862a6a0c58ab6e2c" }, "downloads": -1, "filename": "cloudless-0.0.1.tar.gz", "has_sig": false, "md5_digest": "66d7f7f092a20ac9184f855bc2e7acad", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 43637, "upload_time": "2018-09-10T17:53:24", "url": "https://files.pythonhosted.org/packages/59/da/b74738ad57f5bc0e7240bfa948114536e7d0c97dfb941bb0005c00b16f76/cloudless-0.0.1.tar.gz" } ], "0.0.10": [ { "comment_text": "", "digests": { "md5": "3d35e35d31b364e275696255a4186b52", "sha256": "44c138c2bee75fe4bde5846689e438bc057378a2a453afb6c6a89f971ccbbdb5" }, "downloads": -1, "filename": "cloudless-0.0.10-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "3d35e35d31b364e275696255a4186b52", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 105800, "upload_time": "2019-08-10T00:44:05", "url": "https://files.pythonhosted.org/packages/1e/87/c2afb093326e6c5cd36aee58f8a060135b1ac5084d67ad4d7e23938dadcc/cloudless-0.0.10-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "cc8ef8381d6e0306efd1347546475133", "sha256": "e635c4a4d71bc5d3141d5764149b4e2a98faeab31cece6af8d9c7a66affd0cea" }, "downloads": -1, "filename": "cloudless-0.0.10.tar.gz", "has_sig": false, "md5_digest": "cc8ef8381d6e0306efd1347546475133", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 72292, "upload_time": "2019-08-10T00:44:07", "url": "https://files.pythonhosted.org/packages/96/a1/1506247066a20d13f346d406f654798512140be1e624cf272fb3e0238861/cloudless-0.0.10.tar.gz" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "66bfa44b765a90397f1cfc5207314cd5", "sha256": "36601c2b132ab1320d91cbf7f469df9b70c6dcc0361798d29ff39839187d2eef" }, "downloads": -1, "filename": "cloudless-0.0.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "66bfa44b765a90397f1cfc5207314cd5", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 69824, "upload_time": "2018-09-15T05:05:07", "url": "https://files.pythonhosted.org/packages/32/ed/75afe25da8ec5efe99ed813e06fbc0adb0b311d1210b4bd476ea72c8cde8/cloudless-0.0.2-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "65281357d42f5f68f71e75b42d36f225", "sha256": "ef3ec47709faf4f3a6bea090089ab66b862860a25a12ef8d04edd48383247663" }, "downloads": -1, "filename": "cloudless-0.0.2.tar.gz", "has_sig": false, "md5_digest": "65281357d42f5f68f71e75b42d36f225", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 50823, "upload_time": "2018-09-15T05:05:08", "url": "https://files.pythonhosted.org/packages/06/d1/1911ed580b20774e35405bae775226c20e3ae0e049d6830aa32e0b35148e/cloudless-0.0.2.tar.gz" } ], "0.0.3": [ { "comment_text": "", "digests": { "md5": "0db345785f1228096f34a1e64d2c8dc8", "sha256": "4acaf43daf54b3f0d43bef7a4f48a99e29d50290e6ac1dbd73ea8fbd8b0426a8" }, "downloads": -1, "filename": "cloudless-0.0.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "0db345785f1228096f34a1e64d2c8dc8", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 86381, "upload_time": "2018-09-25T03:09:31", "url": "https://files.pythonhosted.org/packages/cd/5d/f06b63a6129d3c49ac8868ae275bdfd71672fd9d4517ce3e40c6f4dae291/cloudless-0.0.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "1137e383fa51b22c315490d32a8269b4", "sha256": "c801b27032d061bf7c89cfdcd08b85e92a2b7e3ed13152626b4f38d7335e9858" }, "downloads": -1, "filename": "cloudless-0.0.3.tar.gz", "has_sig": false, "md5_digest": "1137e383fa51b22c315490d32a8269b4", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 61133, "upload_time": "2018-09-25T03:09:33", "url": "https://files.pythonhosted.org/packages/d6/55/af94e7045bda1095143db6da27f93d1abddf9ff3ccc90f4db045b9a3a9b9/cloudless-0.0.3.tar.gz" } ], "0.0.4": [ { "comment_text": "", "digests": { "md5": "4cfff5aa1838df42b5ed8cf50cd12269", "sha256": "dc460f4b18422324687a291547c41073e72a29353eda8db11b3d4064ac85645e" }, "downloads": -1, "filename": "cloudless-0.0.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "4cfff5aa1838df42b5ed8cf50cd12269", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 86381, "upload_time": "2018-09-25T03:24:28", "url": "https://files.pythonhosted.org/packages/fc/de/202bc81a05a022a1cb60c3d09e0089973f58a72fcd24c60676148b5d8852/cloudless-0.0.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "57fc1f37bf44dd5ab5d175f3fadf4a8b", "sha256": "16f3245d0fe1f5e2767c41b4d6ba9d9df479a56ddf72eaeafc20b670965016f0" }, "downloads": -1, "filename": "cloudless-0.0.4.tar.gz", "has_sig": false, "md5_digest": "57fc1f37bf44dd5ab5d175f3fadf4a8b", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 61141, "upload_time": "2018-09-25T03:24:30", "url": "https://files.pythonhosted.org/packages/22/fe/f3d26fa67cba1a8cd3631a13f139c2ad4e42fcba9d85a6facc7bb5ca8f51/cloudless-0.0.4.tar.gz" } ], "0.0.5": [ { "comment_text": "", "digests": { "md5": "6e25331dd7660bc316007851971354f9", "sha256": "4178baba857d77195c5200f2cf4230d7e94922d50b4938311c407b0e6664423b" }, "downloads": -1, "filename": "cloudless-0.0.5-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "6e25331dd7660bc316007851971354f9", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 86840, "upload_time": "2018-10-16T03:37:27", "url": "https://files.pythonhosted.org/packages/f4/28/ca97c4d810f393ee6eac1ed099728d52f7a9540a91ae8679aa0cb598fb32/cloudless-0.0.5-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e845ec09a309f76252920df987d06a7f", "sha256": "83180a706716bff45e031a682dba72f5407b63c32770d17204b3213a2684e4dc" }, "downloads": -1, "filename": "cloudless-0.0.5.tar.gz", "has_sig": false, "md5_digest": "e845ec09a309f76252920df987d06a7f", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 64061, "upload_time": "2018-10-16T03:37:28", "url": "https://files.pythonhosted.org/packages/47/a5/4ea8a2ce696c42c2193d391430942c1053e6dd86ad5056931733d5f3cbbf/cloudless-0.0.5.tar.gz" } ], "0.0.6": [ { "comment_text": "", "digests": { "md5": "c5e4c890523ffc83bd713cb7750b801d", "sha256": "a9af3fcf7d4190e445adebd026bec2532f0b528d243fe96a4ebfb1fc7ad4bb27" }, "downloads": -1, "filename": "cloudless-0.0.6-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "c5e4c890523ffc83bd713cb7750b801d", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 87002, "upload_time": "2018-11-15T16:18:48", "url": "https://files.pythonhosted.org/packages/75/00/9374cccb49381a493656b83921356fff7263aa5c32103a6ec1453a042eb8/cloudless-0.0.6-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8a2c53994f0f758860f8735525cc71d6", "sha256": "1fc3421228448f59283ce5c3cf86ac933247fa132fcc394b904be1fd474cf598" }, "downloads": -1, "filename": "cloudless-0.0.6.tar.gz", "has_sig": false, "md5_digest": "8a2c53994f0f758860f8735525cc71d6", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 64191, "upload_time": "2018-11-15T16:18:50", "url": "https://files.pythonhosted.org/packages/f6/c1/1ad71cd6fa15cc8333578e3fee5136ce7507a8e180af4a7b8cd9031ddfbf/cloudless-0.0.6.tar.gz" } ], "0.0.7": [ { "comment_text": "", "digests": { "md5": "10999c0ce0b32194120703adfa53dec9", "sha256": "4344622376d19a69ad2e6e88d87bdd07b5368ffd4fa58e45eff9f291e5e41828" }, "downloads": -1, "filename": "cloudless-0.0.7-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "10999c0ce0b32194120703adfa53dec9", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 87263, "upload_time": "2018-11-15T16:49:15", "url": "https://files.pythonhosted.org/packages/cc/df/a95efbbc2e8dde3952704d25968f7127ff6a0ad993fb030e3317c8dffd7b/cloudless-0.0.7-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "71c9e5bd15fc61e87fc3a1c2242ff751", "sha256": "c56f6776d94c3a1db5ddbb2a7416dbbaf85935d3792268f4068d46ffd1145e63" }, "downloads": -1, "filename": "cloudless-0.0.7.tar.gz", "has_sig": false, "md5_digest": "71c9e5bd15fc61e87fc3a1c2242ff751", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 64311, "upload_time": "2018-11-15T16:49:17", "url": "https://files.pythonhosted.org/packages/37/f0/c656bff11a38798e4806b09c30748ae03f52030da34231c1071fac60e35a/cloudless-0.0.7.tar.gz" } ], "0.0.8": [ { "comment_text": "", "digests": { "md5": "fd3238a0a55e478dc9c142f5b908e112", "sha256": "311e51b14582dd6af5e530be750de23f47f0044c01c8b83f27fab15e81cdbadf" }, "downloads": -1, "filename": "cloudless-0.0.8-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "fd3238a0a55e478dc9c142f5b908e112", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 88215, "upload_time": "2019-03-01T23:31:21", "url": "https://files.pythonhosted.org/packages/8b/a9/6300458214bf73db37b26adacf8c68dc5fcc18e4c2fd1afed2fa31ece406/cloudless-0.0.8-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "7f6b084c1bbbf7868e76ad9300ff94de", "sha256": "84155a1b03e1c4a86c6d3848a70c3b6339dbe9512aa1b1955cdafa4a34eca72d" }, "downloads": -1, "filename": "cloudless-0.0.8.tar.gz", "has_sig": false, "md5_digest": "7f6b084c1bbbf7868e76ad9300ff94de", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 63313, "upload_time": "2019-03-01T23:31:23", "url": "https://files.pythonhosted.org/packages/4f/e4/198478dbf9c95484e32471866d62f324ad2393479fd66054692efb542726/cloudless-0.0.8.tar.gz" } ], "0.0.9": [ { "comment_text": "", "digests": { "md5": "8ab7dd31dd9c6d37a7cc047c4d14617c", "sha256": "acbd586ff9ded4b0834c9b8c117454b8f868bbcbb309f9845d085576ce7b58bc" }, "downloads": -1, "filename": "cloudless-0.0.9-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "8ab7dd31dd9c6d37a7cc047c4d14617c", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 88225, "upload_time": "2019-03-02T21:40:26", "url": "https://files.pythonhosted.org/packages/fb/ab/d84c903a553cdb96ab3e9eb640f3233b3351214e95a1542ad933377c40df/cloudless-0.0.9-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "9bb9c4fb5b2c8ea9f6c2927e615c3fcb", "sha256": "fd7d86c3047139d370dbf5e3b61f6371ddf466edfd16a1d4ac39c1ea96963824" }, "downloads": -1, "filename": "cloudless-0.0.9.tar.gz", "has_sig": false, "md5_digest": "9bb9c4fb5b2c8ea9f6c2927e615c3fcb", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 63645, "upload_time": "2019-03-02T21:40:28", "url": "https://files.pythonhosted.org/packages/8f/8e/db3c9dbeaa34057bb5454d39fc89e54c6e3f16cfdc4b641ba3581c111f69/cloudless-0.0.9.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "3d35e35d31b364e275696255a4186b52", "sha256": "44c138c2bee75fe4bde5846689e438bc057378a2a453afb6c6a89f971ccbbdb5" }, "downloads": -1, "filename": "cloudless-0.0.10-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "3d35e35d31b364e275696255a4186b52", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 105800, "upload_time": "2019-08-10T00:44:05", "url": "https://files.pythonhosted.org/packages/1e/87/c2afb093326e6c5cd36aee58f8a060135b1ac5084d67ad4d7e23938dadcc/cloudless-0.0.10-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "cc8ef8381d6e0306efd1347546475133", "sha256": "e635c4a4d71bc5d3141d5764149b4e2a98faeab31cece6af8d9c7a66affd0cea" }, "downloads": -1, "filename": "cloudless-0.0.10.tar.gz", "has_sig": false, "md5_digest": "cc8ef8381d6e0306efd1347546475133", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 72292, "upload_time": "2019-08-10T00:44:07", "url": "https://files.pythonhosted.org/packages/96/a1/1506247066a20d13f346d406f654798512140be1e624cf272fb3e0238861/cloudless-0.0.10.tar.gz" } ] }