{ "info": { "author": "Fernando Sure", "author_email": "fernandosure@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Environment :: Console", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: MacOS", "Operating System :: POSIX", "Operating System :: Unix", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 3", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "ECS Compose\n----------\n\ndocker-compose like deployments for AWS Elastic Container Service\n\nKey Features\n------------\n- easy to read / maintain deployment scripts\n- deploy multiple services with a single command\n- creates services with private (service-discovery) and internet-facing Application Load Balancers\n- route53 integration when combining an ALB\n- cluster specific or service customizable environment variables\n\n\nTL;DR\n-----\nDeploy a complete ECS cluster with a single command:\n\n $ ecs-compose cluster deploy my-cluster -f my-services.yml\n\n\nYou just need to specify the services that will be deployed within the cluster in a YAML file like the following\n\n\nYAML Configuration\n-----------\n\nYou can form as well a YAML configuration file for use it when creating or updating a cluster definition (eg. POST / PUT /api/clusters).\nBasically the YAML stackfile is similar in form to a docker-compose yaml file with the following structure\n\n```\nvpc:\n id: vpc-xxx\n subnets:\n public: [\"subnet-xxx\", \"subnet-xxx\"]\n private: [\"subnet-xxx\", \"subnet-xxx\"]\n\n security_groups:\n public: [\"sg-xxx\"]\n private: [\"sg-xxx\"]\n\nlogging:\n log_driver: awslogs\n options:\n awslogs-group: /ecs/staging\n awslogs-region: us-east-1\n awslogs-stream-prefix: svc\n\nservice_discovery:\n namespace: example.sd\n\ndefaults:\n memory: 930\n environment:\n - JAVA_OPTS: -Duser.timezone=\"UTC\" -Xms256m -Xmx640m -XX:MaxMetaspaceSize=256m\n - SPRING_PROFILES_ACTIVE: staging\n - LOGGING_LEVEL_ROOT: INFO\n - SERVER_PORT: 80\n\nservices:\n\n - edge-service:\n image: xxx.dkr.ecr.us-east-1.amazonaws.com/edge-service:latest\n ports:\n - \"8080:8080\"\n environment:\n - SERVER_PORT: 8080\n desired_count: 1\n elb:\n type: public\n protocol: HTTPS\n ports:\n public: 443\n container: 8080\n certificates:\n - arn:aws:acm:us-east-1:xxx:certificate/xxx-xxx-xxx-xxx-xxx\n dns:\n hosted_zone_id: xxxx\n record_name: staging.example.com\n healthcheck:\n protocol: HTTP\n port: 8080\n path: /health\n deployment_configuration:\n maximum_percent: 100\n minimum_healthy_percent: 0\n placement_constraints:\n - expression: \"attribute:ecs.instance-type =~ p3.*\"\n type: \"memberOf\"\n - expression: \"attribute:ecs.availability-zone == us-east-1a\"\n type: \"memberOf\"\n\n - user-service:\n image: xxx.dkr.ecr.us-east-1.amazonaws.com/user-service:latest\n ports:\n - \"80:80\"\n desired_count: 1\n dns_discovery:\n name: user.staging\n\n - deeplearning:\n image: xxx.dkr.ecr.us-east-1.amazonaws.com/deep-learning:latest\n ports:\n - \"8080:8080\"\n desired_count: 1\n gpus: 1\n dns_discovery:\n name: deeplearning.staging\n \n # WORKERS NO PORTS EXPOSED\n - email-worker:\n image: xxx.dkr.ecr.us-east-1.amazonaws.com/email-worker:xxx\n\n```\n\n\n# VPC Section\n```\nvpc:\n id: vpc-xxx\n subnets:\n public: [\"subnet-xxx\", \"subnet-xxx\"]\n private: [\"subnet-xxx\", \"subnet-xxx\"]\n\n security_groups:\n public: [\"sg-xxx\"]\n private: [\"sg-xxx\"]\n```\nvpc\n- id: the VPC id where the ECS cluster is located\n\nvpc.subnets\n- public: subnet-id where the public load balancers (if any) will be placed on\n- private: subnet.id where the private load balancers (if any) will be placed on\n\nvpc.security_groups\n- public: the security group that will be attached to a public load balancer\n- private: the security group that will be attached to private load balancer o service discovery service\n\n\n# Logging Section\n```\nlogging:\n log_driver: awslogs\n options:\n awslogs-group: /ecs/staging\n awslogs-region: us-east-1\n awslogs-stream-prefix: svc\n```\nIn this section you specify the logging driver and (optional) the parameters to that specific driver. You can use gelf, awslogs, syslog, etc.\n\n\n# Service Discovery Section\n```\nservice_discovery:\n namespace: example.sd\n```\n\nIn this section you specify the desired private namespace that will be used for registering the services using DNS based Service Discovery. You can't assign multilevel domains here, only top level domains are allowed e.g. example.local\n\n# Defaults Section\n```\ndefaults:\n memory: 930\n environment:\n - JAVA_OPTS: -Duser.timezone=\"UTC\" -Xms256m -Xmx640m -XX:MaxMetaspaceSize=256m\n - SPRING_PROFILES_ACTIVE: staging\n - LOGGING_LEVEL_ROOT: INFO\n - SERVER_PORT: 80\n```\nIn this section you need to specify the hard limit (in MiB) of memory to present to the container and the default environment variables that will be applied to all services within the stackfile. The reason behind the global environment section is preventing from copy and paste all over the place instead, if you need to overwrite a specific envvar you can declare that within the service definition and that envvar will have greater precedence over the global one.\n\n\n\n# Service Section\n## When a service needs to be publicly exposed in a public subnet.\n```\nservices:\n - edge-service:\n image: xxx.dkr.ecr.us-east-1.amazonaws.com/edge-service:latest\n ports:\n - \"8080:8080\"\n environment:\n - SERVER_PORT: 8080\n desired_count: 1\n elb:\n type: public\n protocol: HTTPS\n ports:\n public: 443\n container: 8080\n certificates:\n - arn:aws:acm:us-east-1:xxx:certificate/xxx-xxx-xxx-xxx-xxx\n dns:\n hosted_zone_id: xxxx\n record_name: staging.example.com\n healthcheck:\n protocol: HTTP\n port: 8080\n path: /health\n\n```\nIn this section you define an array of services that will be deployed in the cluster.\nEach array item corresponds to a different service and you will need to specify the name of the service and then its properties.\n\n- image: Specify the image to start the container from\n- ports: if the service will expose ports to the outside then you need to specify those in short syntax (HOST:CONTAINER).\n- environment: the environment variable declared in this section have greater precedence over the global definition and will overwrite the global one.\n- desired_count: the number of desired instances for the service\n- gpus: the number of gpu's assigned (when using gpu instances)\n- placement_constraints: rules that are considered during task placement.\n - expression: A cluster query language expression to apply to the constraint. You cannot specify an expression if the constraint type is distinctInstance.\n - type: The type of constraint. Use distinctInstance to ensure that each task in a particular group is running on a different container instance. Use memberOf to restrict the selection to a group of valid candidates.\n- deployment_configuration:\n - maximum_percent: represents an upper limit on the number of your service's tasks that are allowed in the RUNNING or PENDING state during a deployment, as a percentage of the desired number of tasks (rounded down to the nearest integer).\n - minimum_healthy_percent: represents a lower limit on the number of your service's tasks that must remain in the RUNNING state during a deployment, as a percentage of the desired number of tasks (rounded up to the nearest integer).\n- elb: the application load balancer definition.\n - type: whether if the load balancer will be public (will be placed in the public subnet and a public security group assigned) or private (will be place in the private subnet and a private security group assigned)\n - protocol: The protocol for connections from clients to the load balancer (HTTP/HTTPS)\n - ports:\n - public: The port on which the load balancer is listening\n - container: The port on which the target container will receive traffic (this will need to match the public exposed port of the container)\n - certificates: a single item array of the AWS ACM (certificate manager) arn of the certificate to be applied to the ALB\n - dns:\n - hosted_zone_id: route53 hosted_zone_id for updating the CNAME record that the load balancer will listen requests from.\n - record_name: the route53 recordset of from which the ALB will listen requests from (if isnt already created it will create it automatically otherwise will update the recordset)\n - healthcheck: the configurations the load balancer uses when performing health checks on targets.\n - protocol: The protocol the load balancer uses when performing health checks on the container target.\n - port: The port the load balancer uses when performing health checks on the container target.\n - path: The ping path that is the destination on the targets for health checks. The default is /.\n\n## When a service only needs to be reachable by other services that are part of the same cluster.\n```\nservices:\n - user-service:\n image: xxx.dkr.ecr.us-east-1.amazonaws.com/user-service:latest\n ports:\n - \"80:80\"\n desired_count: 1\n dns_discovery:\n name: user.staging\n```\n\n\n- dns_discovery: When using this feature make sure that you already declared the service discovery namespace that will be used to register the services.\n - name: the name of the route53 recordset to be used by other services to reach this service (it will create an 'A' record) if you want to use the same namespace for different clusters make sure to split the name of the service into a multilevel domain (e.g. `..`)\n\n## When a service doesn't need to be exposed (worker services)\n```\n - email-worker:\n image: xxx.dkr.ecr.us-east-1.amazonaws.com/email-worker:xxx\n```\nThere aren't any exposed ports and no load balancer / service discovery configuration. Only the container image definition and if required (desired_count)\n\n\n\nInstallation\n------------\n\nThe project is available on PyPI. Simply run::\n\n $ pip install ecs-compose\n\n\nConfiguration\n-------------\nThe mechanism in which **ecs-compose** looks for credentials is to search through a list of possible locations and stop as soon as it finds credentials.\n\n- Environment variables\n- Shared credential file (~/.aws/credentials)\n- AWS config file (~/.aws/config)\n- Assume Role provider\n- Boto2 config file (/etc/boto.cfg and ~/.boto)\n- Instance metadata service on an Amazon EC2 instance that has an IAM role configured.\n\nPlease read the boto3 documentation for more details\n(http://boto3.readthedocs.org/en/latest/guide/configuration.html#configuration).\n\nOr just run::\n\n $ aws configure\n\n\nActions\n-------\nCurrently the following actions are supported:\n\n**Cluster related operations**\n\ndeploy\n======\ndeploy / redeploys a single or multiple services at once defined in the YAML stackfile\n\ndestroy\n=====\nDestroy the entire AWS ECS Cluster with all services and attached load balancers associated with it.\n\ndescribe\n=====\nList all deployed services within the specified cluster as YAML stackfile\n\n**Individual service related operations**\n\ndestroy\n=====\nDestroy an individual service within the specified cluster with its load balancer associated with it.\n\n\nUsage\n-----\n\nFor detailed information about the available actions, arguments and options, run::\n\n $ ecs-compose --help\n $ ecs-compose cluster --help\n $ ecs-compose service --help", "description_content_type": "text/markdown", "docs_url": null, "download_url": "https://github.com/fernandosure/ecs-compose/archive/0.9.89.tar.gz", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/fernandosure/ecs-compose", "keywords": "ECS,AWS", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "ecs-compose", "package_url": "https://pypi.org/project/ecs-compose/", "platform": "any", "project_url": "https://pypi.org/project/ecs-compose/", "project_urls": { "Download": "https://github.com/fernandosure/ecs-compose/archive/0.9.89.tar.gz", "Homepage": "https://github.com/fernandosure/ecs-compose" }, "release_url": "https://pypi.org/project/ecs-compose/0.9.89/", "requires_dist": null, "requires_python": "", "summary": "Amazon ECS cli for docker-compose like deployments", "version": "0.9.89" }, "last_serial": 5175592, "releases": { "0.9.72": [ { "comment_text": "", "digests": { "md5": "0499b64f8cefa3fed7f9fce0a94d6e13", "sha256": "45aed36427216d3dad1777e1d380e0202f89878c1cf48d442a92210586672cf5" }, "downloads": -1, "filename": "ecs-compose-0.9.72.tar.gz", "has_sig": false, "md5_digest": "0499b64f8cefa3fed7f9fce0a94d6e13", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13679, "upload_time": "2018-06-22T16:54:02", "url": "https://files.pythonhosted.org/packages/e7/84/15967c8ea91169f750acd8c031843f26584400fed4f9f617f02b1b14cdf3/ecs-compose-0.9.72.tar.gz" } ], "0.9.73": [ { "comment_text": "", "digests": { "md5": "091c31c8aebf48be67cd2cca2fedf9df", "sha256": "8a22a71c5afa1681eb020e81cb0e060788aa90ffcb39f07a8826e5fa4250defc" }, "downloads": -1, "filename": "ecs-compose-0.9.73.tar.gz", "has_sig": false, "md5_digest": "091c31c8aebf48be67cd2cca2fedf9df", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12053, "upload_time": "2018-06-25T16:04:44", "url": "https://files.pythonhosted.org/packages/30/ef/ea1493ac3b3c85e387f4a377b05e98814dc78fa61a5d8a0c697aed49db6f/ecs-compose-0.9.73.tar.gz" } ], "0.9.74": [ { "comment_text": "", "digests": { "md5": "f768e3983043ab2ed494329fd812bc36", "sha256": "fcfe7fe69e34cc85337385c867f75acead8a8e9b7714bed9906dade9b37f7f87" }, "downloads": -1, "filename": "ecs-compose-0.9.74.tar.gz", "has_sig": false, "md5_digest": "f768e3983043ab2ed494329fd812bc36", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14067, "upload_time": "2018-07-17T23:46:28", "url": "https://files.pythonhosted.org/packages/fb/42/78ffd5616d739a0adb4f32c7dcc3ce60d1c9aab99287923112b286ac30ef/ecs-compose-0.9.74.tar.gz" } ], "0.9.75": [ { "comment_text": "", "digests": { "md5": "fce07c20789dab20840bd4e32c36f657", "sha256": "0dffc7ebfc7a35bc2d4a390e3dd66c845cd103344f1a67ea4ffc0b20fdea8823" }, "downloads": -1, "filename": "ecs-compose-0.9.75.tar.gz", "has_sig": false, "md5_digest": "fce07c20789dab20840bd4e32c36f657", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17116, "upload_time": "2018-07-19T19:50:50", "url": "https://files.pythonhosted.org/packages/37/fb/af2f73b544049e4ebeac18fe0fcd0b864b0dac0410509d33aef76c5e7285/ecs-compose-0.9.75.tar.gz" } ], "0.9.76": [ { "comment_text": "", "digests": { "md5": "2bcba9bddae20f0aecd21186a9cd0834", "sha256": "63223711f962b66e87010b6b553e8c3b92c8fa5a79aa0258b1d9101efe3d978a" }, "downloads": -1, "filename": "ecs-compose-0.9.76.tar.gz", "has_sig": false, "md5_digest": "2bcba9bddae20f0aecd21186a9cd0834", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17257, "upload_time": "2018-07-26T23:49:46", "url": "https://files.pythonhosted.org/packages/9e/b8/8dc2434fdeca5a164e94259294d568cd13029f1ab5ae27ba5551d40df90b/ecs-compose-0.9.76.tar.gz" } ], "0.9.77": [ { "comment_text": "", "digests": { "md5": "b185eebb73385e7bb57daaf9b2953198", "sha256": "77d81e80a77cdbe6c23b2d5acf4f867c2a95f7a3012516b76bbbbdddd0cf1b4f" }, "downloads": -1, "filename": "ecs-compose-0.9.77.tar.gz", "has_sig": false, "md5_digest": "b185eebb73385e7bb57daaf9b2953198", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17241, "upload_time": "2018-07-27T15:59:34", "url": "https://files.pythonhosted.org/packages/26/53/180a9cac00931a9ffef9a79eeaec68b6618cc5783ddda6ebf249d51ff846/ecs-compose-0.9.77.tar.gz" } ], "0.9.78": [ { "comment_text": "", "digests": { "md5": "8d56e1391373b3c667d7695ee21ca9c6", "sha256": "52dfb6eccf77071a1ca32f45ae8cf4cdd08ebba57e99fad2eeb9ebdb060ac369" }, "downloads": -1, "filename": "ecs-compose-0.9.78.tar.gz", "has_sig": false, "md5_digest": "8d56e1391373b3c667d7695ee21ca9c6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14077, "upload_time": "2018-08-01T16:53:15", "url": "https://files.pythonhosted.org/packages/23/fc/d1352f06471aa42d3de688a3f8d78412a28f3dad2ad9776d1412351db8cf/ecs-compose-0.9.78.tar.gz" } ], "0.9.79": [ { "comment_text": "", "digests": { "md5": "a5016560101c791a3bac64adfa24d594", "sha256": "3c3dcf20d4579106c8bc6d8886b24828adb62cf495822d0bcda5a1e982cd8d35" }, "downloads": -1, "filename": "ecs-compose-0.9.79.tar.gz", "has_sig": false, "md5_digest": "a5016560101c791a3bac64adfa24d594", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14235, "upload_time": "2018-08-27T18:44:50", "url": "https://files.pythonhosted.org/packages/da/b4/f41dea115595c433f8ea5288dc9ce87d9eb551f1f20a7e29c5ab9a96da49/ecs-compose-0.9.79.tar.gz" } ], "0.9.80": [ { "comment_text": "", "digests": { "md5": "981cf68932570bd838097c48d585ae9b", "sha256": "e541247b54e82ce8141adcf89f80861ce557c69f6633d382e631505025d5b531" }, "downloads": -1, "filename": "ecs-compose-0.9.80.tar.gz", "has_sig": false, "md5_digest": "981cf68932570bd838097c48d585ae9b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17355, "upload_time": "2018-08-29T17:04:31", "url": "https://files.pythonhosted.org/packages/c9/53/0258d4a594716195cd77590a93f4730a9911a77203f05694b2819c4561fd/ecs-compose-0.9.80.tar.gz" } ], "0.9.82": [ { "comment_text": "", "digests": { "md5": "3d81e72c02cbc6ba5d28fed45921f01a", "sha256": "1429c420c68d57b14dfbe4544d3f2b4ba3c6ad3de5c3af493ba10356f43e1bc5" }, "downloads": -1, "filename": "ecs-compose-0.9.82.tar.gz", "has_sig": false, "md5_digest": "3d81e72c02cbc6ba5d28fed45921f01a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14787, "upload_time": "2019-03-13T05:56:25", "url": "https://files.pythonhosted.org/packages/08/3d/c9361308c52553bb3ded3ff8e9d8f701536d6f2b89572382f714ba077d7c/ecs-compose-0.9.82.tar.gz" } ], "0.9.83": [ { "comment_text": "", "digests": { "md5": "60108039a65f3d2be2b53ce01caed56f", "sha256": "6ac76fb2d8b8e23f9f408dd5f333e457ffe4dd030075abcc4196a6ac6a460cf4" }, "downloads": -1, "filename": "ecs-compose-0.9.83.tar.gz", "has_sig": false, "md5_digest": "60108039a65f3d2be2b53ce01caed56f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19331, "upload_time": "2019-03-14T06:11:12", "url": "https://files.pythonhosted.org/packages/75/08/44fd14de2382b705c5d7d914198db00b8bbe7f813f2bd7f6639cd4e2a9cd/ecs-compose-0.9.83.tar.gz" } ], "0.9.84": [ { "comment_text": "", "digests": { "md5": "98d2b25fa1845b2eaf054d955db14b9d", "sha256": "6978b4e5a74654e9008f3491fe18acd651ac4bb6dee1ab904dfc9687bb98e055" }, "downloads": -1, "filename": "ecs-compose-0.9.84.tar.gz", "has_sig": false, "md5_digest": "98d2b25fa1845b2eaf054d955db14b9d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15532, "upload_time": "2019-03-22T11:58:32", "url": "https://files.pythonhosted.org/packages/18/e0/f849aa25d70d64cd35d25775e81ae03ec866c3df69f137a003f865e20bc9/ecs-compose-0.9.84.tar.gz" } ], "0.9.85": [ { "comment_text": "", "digests": { "md5": "1a2843016b7041abdcdc07dbe8fe587e", "sha256": "18da29d771ea30e2f42eccb4aa672af00f942e3d0a08614ff0fb9a231ca9324e" }, "downloads": -1, "filename": "ecs-compose-0.9.85.tar.gz", "has_sig": false, "md5_digest": "1a2843016b7041abdcdc07dbe8fe587e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19253, "upload_time": "2019-03-22T15:00:03", "url": "https://files.pythonhosted.org/packages/7a/40/9c8795bc912097890db28d5fda0e551feee5a69e540702c17326d99d2000/ecs-compose-0.9.85.tar.gz" } ], "0.9.86": [ { "comment_text": "", "digests": { "md5": "6091a51c48aaa1002eb0c1ddf1add0d6", "sha256": "4f2b9eee7be0ab8319cc23ae19db54595600db02b2a5aab2bace586a7b7da7db" }, "downloads": -1, "filename": "ecs-compose-0.9.86.tar.gz", "has_sig": false, "md5_digest": "6091a51c48aaa1002eb0c1ddf1add0d6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15824, "upload_time": "2019-04-02T04:05:11", "url": "https://files.pythonhosted.org/packages/c6/cc/8212c8a7dba10a7255ea3165dea2159e11de1483cbb36939764770acb56f/ecs-compose-0.9.86.tar.gz" } ], "0.9.88": [ { "comment_text": "", "digests": { "md5": "ba2570a78f163654ce64ec436f48ce92", "sha256": "b720af0fe20992b9552c21e01023d59730b095a66b9bf20dab56ee9071dcc2e6" }, "downloads": -1, "filename": "ecs-compose-0.9.88.tar.gz", "has_sig": false, "md5_digest": "ba2570a78f163654ce64ec436f48ce92", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15726, "upload_time": "2019-04-10T21:12:14", "url": "https://files.pythonhosted.org/packages/d3/53/f52f4c8a619a69f9c8d7043b144fca8d7c859afd15d2af434372756e5cbc/ecs-compose-0.9.88.tar.gz" } ], "0.9.89": [ { "comment_text": "", "digests": { "md5": "92d7527638a7ee0f9ff00ca0806eb788", "sha256": "fdf39a98a27b88139932a2d3e6967c60a82b67f70eb98bc2af768c715203b74a" }, "downloads": -1, "filename": "ecs-compose-0.9.89.tar.gz", "has_sig": false, "md5_digest": "92d7527638a7ee0f9ff00ca0806eb788", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19100, "upload_time": "2019-04-23T05:04:25", "url": "https://files.pythonhosted.org/packages/12/8c/ed5858f73ffdfe36ffca77ad59cdecd24827a887a457a0a379d0a823208c/ecs-compose-0.9.89.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "92d7527638a7ee0f9ff00ca0806eb788", "sha256": "fdf39a98a27b88139932a2d3e6967c60a82b67f70eb98bc2af768c715203b74a" }, "downloads": -1, "filename": "ecs-compose-0.9.89.tar.gz", "has_sig": false, "md5_digest": "92d7527638a7ee0f9ff00ca0806eb788", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19100, "upload_time": "2019-04-23T05:04:25", "url": "https://files.pythonhosted.org/packages/12/8c/ed5858f73ffdfe36ffca77ad59cdecd24827a887a457a0a379d0a823208c/ecs-compose-0.9.89.tar.gz" } ] }