diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..90815ae --- /dev/null +++ b/Pipfile @@ -0,0 +1,19 @@ +[[source]] +url = "https://pypi.python.org/simple" +verify_ssl = true +name = "pypi" + + +[packages] +"e1839a8" = {path = ".", editable = true} + + +[dev-packages] +awscli = "*" +tox = "*" +twine = "*" +wheel = "*" + +pytest = ">=3.5" +pytest-cov = "*" +pytest-flake8 = "*" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..958447c --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,539 @@ +{ + "_meta": { + "hash": { + "sha256": "eca89cd6130e115a8d0bb30f7015773c33708bf0c7214775dd7e9a074e4e7d7d" + }, + "pipfile-spec": 6, + "requires": {}, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.python.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "backports.ssl-match-hostname": { + "hashes": [ + "sha256:502ad98707319f4a51fa2ca1c677bd659008d27ded9f6380c79e8932e38dcdf2" + ], + "markers": "python_version < '3.5'", + "version": "==3.5.0.1" + }, + "boto3": { + "hashes": [ + "sha256:a2d5c0a007ff50b4a08f402925495e18e41e336d22767a2b4fa21913fa875b2f", + "sha256:f303b0feaabbe98b36ab12be1c641799104c935c9e0c9315b6fe53a39d668d79" + ], + "version": "==1.7.14" + }, + "botocore": { + "hashes": [ + "sha256:2d83993e60ba56ca3ddb48a0d4da86c1cfa1f687993abe760eeb0059d10e52f6", + "sha256:5e61efeb68688149fb8220f0bca6c8a89bc998dffb99673d0bf24cfe2f2e47a9" + ], + "version": "==1.10.14" + }, + "certifi": { + "hashes": [ + "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", + "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0" + ], + "version": "==2018.4.16" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "click": { + "hashes": [ + "sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d", + "sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b" + ], + "version": "==6.7" + }, + "docker": { + "hashes": [ + "sha256:43b45b92bed372161a5d4f3c7137e16b30d93845e99a00bc727938e52850694e", + "sha256:dc5cc0971a0d36fe94c5ce89bd4adb6c892713500af7b0818708229c3199911a" + ], + "version": "==3.3.0" + }, + "docker-pycreds": { + "hashes": [ + "sha256:764a7ea2f6484bc5de5bf0c060f08b41a1118cf1acb987626b3ff45f3cc40dac", + "sha256:e3732a03610a00461a716997670c7010bf1c214a3edc440f7d6a2a3a830ecd9d" + ], + "version": "==0.2.3" + }, + "docutils": { + "hashes": [ + "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", + "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", + "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6" + ], + "version": "==0.14" + }, + "e1839a8": { + "editable": true, + "path": "." + }, + "future": { + "hashes": [ + "sha256:e39ced1ab767b5936646cedba8bcce582398233d6a627067d4c6a454c90cfedb" + ], + "version": "==0.16.0" + }, + "futures": { + "hashes": [ + "sha256:9ec02aa7d674acb8618afb127e27fde7fc68994c0437ad759fa094a574adb265", + "sha256:ec0a6cb848cc212002b9828c3e34c675e0c9ff6741dc445cab6fdd4e1085d1f1" + ], + "markers": "python_version == '2.6' or python_version == '2.7'", + "version": "==3.2.0" + }, + "idna": { + "hashes": [ + "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f", + "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4" + ], + "version": "==2.6" + }, + "ipaddress": { + "hashes": [ + "sha256:64b28eec5e78e7510698f6d4da08800a5c575caa4a286c93d651c5d3ff7b6794", + "sha256:b146c751ea45cad6188dd6cf2d9b757f6f4f8d6ffb96a023e6f2e26eea02a72c" + ], + "markers": "python_version < '3.3'", + "version": "==1.0.22" + }, + "jmespath": { + "hashes": [ + "sha256:6a81d4c9aa62caf061cb517b4d9ad1dd300374cd4706997aff9cd6aedd61fc64", + "sha256:f11b4461f425740a1d908e9a3f7365c3d2e569f6ca68a2ff8bc5bcd9676edd63" + ], + "version": "==0.9.3" + }, + "python-dateutil": { + "hashes": [ + "sha256:3220490fb9741e2342e1cf29a503394fdac874bc39568288717ee67047ff29df", + "sha256:9d8074be4c993fbe4947878ce593052f71dac82932a677d49194d8ce9778002e" + ], + "markers": "python_version >= '2.7'", + "version": "==2.7.2" + }, + "pyyaml": { + "hashes": [ + "sha256:0c507b7f74b3d2dd4d1322ec8a94794927305ab4cebbe89cc47fe5e81541e6e8", + "sha256:16b20e970597e051997d90dc2cddc713a2876c47e3d92d59ee198700c5427736", + "sha256:3262c96a1ca437e7e4763e2843746588a965426550f3797a79fca9c6199c431f", + "sha256:326420cbb492172dec84b0f65c80942de6cedb5233c413dd824483989c000608", + "sha256:4474f8ea030b5127225b8894d626bb66c01cda098d47a2b0d3429b6700af9fd8", + "sha256:592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab", + "sha256:5ac82e411044fb129bae5cfbeb3ba626acb2af31a8d17d175004b70862a741a7", + "sha256:5f84523c076ad14ff5e6c037fe1c89a7f73a3e04cf0377cb4d017014976433f3", + "sha256:827dc04b8fa7d07c44de11fabbc888e627fa8293b695e0f99cb544fdfa1bf0d1", + "sha256:b4c423ab23291d3945ac61346feeb9a0dc4184999ede5e7c43e1ffb975130ae6", + "sha256:bc6bced57f826ca7cb5125a10b23fd0f2fff3b7c4701d64c439a300ce665fff8", + "sha256:c01b880ec30b5a6e6aa67b09a2fe3fb30473008c85cd6a67359a1b15ed6d83a4", + "sha256:ca233c64c6e40eaa6c66ef97058cdc80e8d0157a443655baa1b2966e812807ca", + "sha256:e863072cdf4c72eebf179342c94e6989c67185842d9997960b3e69290b2fa269" + ], + "version": "==3.12" + }, + "requests": { + "hashes": [ + "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", + "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e" + ], + "version": "==2.18.4" + }, + "s3transfer": { + "hashes": [ + "sha256:90dc18e028989c609146e241ea153250be451e05ecc0c2832565231dacdf59c1", + "sha256:c7a9ec356982d5e9ab2d4b46391a7d6a950e2b04c472419f5fdec70cc0ada72f" + ], + "version": "==0.1.13" + }, + "six": { + "hashes": [ + "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", + "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" + ], + "version": "==1.11.0" + }, + "tqdm": { + "hashes": [ + "sha256:139b1672ab75ca6cb670d215ab0b408bec214ca3bed918de50ff265e0ee77617", + "sha256:75efcd98827971f96aa9b270e73ccedf1d275b781a9149a0846a7728010d045e" + ], + "version": "==4.23.2" + }, + "urllib3": { + "hashes": [ + "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", + "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f" + ], + "version": "==1.22" + }, + "websocket-client": { + "hashes": [ + "sha256:188b68b14fdb2d8eb1a111f21b9ffd2dbf1dbc4e4c1d28cf2c37cdbf1dd1cae6", + "sha256:a453dc4dfa6e0db3d8fd7738a308a88effe6240c59f3226eb93e8f020c216149" + ], + "version": "==0.47.0" + } + }, + "develop": { + "attrs": { + "hashes": [ + "sha256:4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265", + "sha256:e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b" + ], + "version": "==18.1.0" + }, + "awscli": { + "hashes": [ + "sha256:84b0788681bcfbd7d2b23eede1b0cb17307fb55511adbed1358efc90fbe158eb", + "sha256:be3f7407e5409bcc8eae49c1691765fbe26fcb5e64bee12239d39b2f6d0026cd" + ], + "index": "pypi", + "version": "==1.15.14" + }, + "botocore": { + "hashes": [ + "sha256:2d83993e60ba56ca3ddb48a0d4da86c1cfa1f687993abe760eeb0059d10e52f6", + "sha256:5e61efeb68688149fb8220f0bca6c8a89bc998dffb99673d0bf24cfe2f2e47a9" + ], + "version": "==1.10.14" + }, + "certifi": { + "hashes": [ + "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", + "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0" + ], + "version": "==2018.4.16" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "colorama": { + "hashes": [ + "sha256:a4c0f5bc358a62849653471e309dcc991223cf86abafbec17cd8f41327279e89", + "sha256:e043c8d32527607223652021ff648fbb394d5e19cba9f1a698670b338c9d782b", + "sha256:f4945bf52ae49da0728fe730a33c18744803752fc948f154f29dc0c4f9f2f9cc" + ], + "version": "==0.3.7" + }, + "configparser": { + "hashes": [ + "sha256:5308b47021bc2340965c371f0f058cc6971a04502638d4244225c49d80db273a" + ], + "markers": "python_version < '3.2'", + "version": "==3.5.0" + }, + "coverage": { + "hashes": [ + "sha256:03481e81d558d30d230bc12999e3edffe392d244349a90f4ef9b88425fac74ba", + "sha256:0b136648de27201056c1869a6c0d4e23f464750fd9a9ba9750b8336a244429ed", + "sha256:104ab3934abaf5be871a583541e8829d6c19ce7bde2923b2751e0d3ca44db60a", + "sha256:15b111b6a0f46ee1a485414a52a7ad1d703bdf984e9ed3c288a4414d3871dcbd", + "sha256:198626739a79b09fa0a2f06e083ffd12eb55449b5f8bfdbeed1df4910b2ca640", + "sha256:1c383d2ef13ade2acc636556fd544dba6e14fa30755f26812f54300e401f98f2", + "sha256:28b2191e7283f4f3568962e373b47ef7f0392993bb6660d079c62bd50fe9d162", + "sha256:2eb564bbf7816a9d68dd3369a510be3327f1c618d2357fa6b1216994c2e3d508", + "sha256:337ded681dd2ef9ca04ef5d93cfc87e52e09db2594c296b4a0a3662cb1b41249", + "sha256:3a2184c6d797a125dca8367878d3b9a178b6fdd05fdc2d35d758c3006a1cd694", + "sha256:3c79a6f7b95751cdebcd9037e4d06f8d5a9b60e4ed0cd231342aa8ad7124882a", + "sha256:3d72c20bd105022d29b14a7d628462ebdc61de2f303322c0212a054352f3b287", + "sha256:3eb42bf89a6be7deb64116dd1cc4b08171734d721e7a7e57ad64cc4ef29ed2f1", + "sha256:4635a184d0bbe537aa185a34193898eee409332a8ccb27eea36f262566585000", + "sha256:56e448f051a201c5ebbaa86a5efd0ca90d327204d8b059ab25ad0f35fbfd79f1", + "sha256:5a13ea7911ff5e1796b6d5e4fbbf6952381a611209b736d48e675c2756f3f74e", + "sha256:69bf008a06b76619d3c3f3b1983f5145c75a305a0fea513aca094cae5c40a8f5", + "sha256:6bc583dc18d5979dc0f6cec26a8603129de0304d5ae1f17e57a12834e7235062", + "sha256:701cd6093d63e6b8ad7009d8a92425428bc4d6e7ab8d75efbb665c806c1d79ba", + "sha256:7608a3dd5d73cb06c531b8925e0ef8d3de31fed2544a7de6c63960a1e73ea4bc", + "sha256:76ecd006d1d8f739430ec50cc872889af1f9c1b6b8f48e29941814b09b0fd3cc", + "sha256:7aa36d2b844a3e4a4b356708d79fd2c260281a7390d678a10b91ca595ddc9e99", + "sha256:7d3f553904b0c5c016d1dad058a7554c7ac4c91a789fca496e7d8347ad040653", + "sha256:7e1fe19bd6dce69d9fd159d8e4a80a8f52101380d5d3a4d374b6d3eae0e5de9c", + "sha256:8c3cb8c35ec4d9506979b4cf90ee9918bc2e49f84189d9bf5c36c0c1119c6558", + "sha256:9d6dd10d49e01571bf6e147d3b505141ffc093a06756c60b053a859cb2128b1f", + "sha256:9e112fcbe0148a6fa4f0a02e8d58e94470fc6cb82a5481618fea901699bf34c4", + "sha256:ac4fef68da01116a5c117eba4dd46f2e06847a497de5ed1d64bb99a5fda1ef91", + "sha256:b8815995e050764c8610dbc82641807d196927c3dbed207f0a079833ffcf588d", + "sha256:be6cfcd8053d13f5f5eeb284aa8a814220c3da1b0078fa859011c7fffd86dab9", + "sha256:c1bb572fab8208c400adaf06a8133ac0712179a334c09224fb11393e920abcdd", + "sha256:de4418dadaa1c01d497e539210cb6baa015965526ff5afc078c57ca69160108d", + "sha256:e05cb4d9aad6233d67e0541caa7e511fa4047ed7750ec2510d466e806e0255d6", + "sha256:e4d96c07229f58cb686120f168276e434660e4358cc9cf3b0464210b04913e77", + "sha256:f3f501f345f24383c0000395b26b726e46758b71393267aeae0bd36f8b3ade80", + "sha256:f8a923a85cb099422ad5a2e345fe877bbc89a8a8b23235824a93488150e45f6e" + ], + "version": "==4.5.1" + }, + "docutils": { + "hashes": [ + "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", + "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", + "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6" + ], + "version": "==0.14" + }, + "enum34": { + "hashes": [ + "sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850", + "sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a", + "sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79", + "sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1" + ], + "markers": "python_version < '3.4'", + "version": "==1.1.6" + }, + "flake8": { + "hashes": [ + "sha256:7253265f7abd8b313e3892944044a365e3f4ac3fcdcfb4298f55ee9ddf188ba0", + "sha256:c7841163e2b576d435799169b78703ad6ac1bbb0f199994fc05f700b2a90ea37" + ], + "version": "==3.5.0" + }, + "funcsigs": { + "hashes": [ + "sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca", + "sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50" + ], + "markers": "python_version < '3.0'", + "version": "==1.0.2" + }, + "futures": { + "hashes": [ + "sha256:9ec02aa7d674acb8618afb127e27fde7fc68994c0437ad759fa094a574adb265", + "sha256:ec0a6cb848cc212002b9828c3e34c675e0c9ff6741dc445cab6fdd4e1085d1f1" + ], + "markers": "python_version == '2.6' or python_version == '2.7'", + "version": "==3.2.0" + }, + "idna": { + "hashes": [ + "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f", + "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4" + ], + "version": "==2.6" + }, + "jmespath": { + "hashes": [ + "sha256:6a81d4c9aa62caf061cb517b4d9ad1dd300374cd4706997aff9cd6aedd61fc64", + "sha256:f11b4461f425740a1d908e9a3f7365c3d2e569f6ca68a2ff8bc5bcd9676edd63" + ], + "version": "==0.9.3" + }, + "mccabe": { + "hashes": [ + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + ], + "version": "==0.6.1" + }, + "more-itertools": { + "hashes": [ + "sha256:0dd8f72eeab0d2c3bd489025bb2f6a1b8342f9b198f6fc37b52d15cfa4531fea", + "sha256:11a625025954c20145b37ff6309cd54e39ca94f72f6bb9576d1195db6fa2442e", + "sha256:c9ce7eccdcb901a2c75d326ea134e0886abfbea5f93e91cc95de9507c0816c44" + ], + "version": "==4.1.0" + }, + "pkginfo": { + "hashes": [ + "sha256:5878d542a4b3f237e359926384f1dde4e099c9f5525d236b1840cf704fa8d474", + "sha256:a39076cb3eb34c333a0dd390b568e9e1e881c7bf2cc0aee12120636816f55aee" + ], + "version": "==1.4.2" + }, + "pluggy": { + "hashes": [ + "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff", + "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c", + "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5" + ], + "version": "==0.6.0" + }, + "py": { + "hashes": [ + "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881", + "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a" + ], + "version": "==1.5.3" + }, + "pyasn1": { + "hashes": [ + "sha256:0d7f6e959fe53f3960a23d73f35e1fce61348b30915b6664309ca756de7c1f89", + "sha256:5a0db897b311d265cde49615cf783f1c78613138605cdd0f907ecfa5b2aba3ee", + "sha256:758cb50abddc03e4563fd9e7f03db56e3e87b58c0bd01247360326e5c0c7ffa5", + "sha256:7d626683e3d792cccc608da02498aff37ab4f3dafd8905d6bf755d11f9b26b43", + "sha256:a7efe807c4b83a859e2735c692b92ed7b567cfddc4163763412920041d876c2b", + "sha256:b5a9ca48055b9a20f6d1b3d68e38692e5431c86a0f99ea602e61294e891fee5b", + "sha256:c07d6e587b2f928366b1f67c09bda026a3e6fcc99e80a744dc67f8fca3895626", + "sha256:d258b0a71994f7770599835249cece1caef3c70def868c4915e6e5ca49b67d15", + "sha256:d5cd6ed995dba16fad0c521cfe31cd2d68400b53fcc2bce93326829be73ab6d1", + "sha256:d84c2aea3cf43780e9e6a19f4e4dddee9f6976519020e64e47c57e5c7a8c3dd2", + "sha256:e85895087905c65b5b594eb91f7522664c85545b147d5f4d4e7b1b07da8dcbdc", + "sha256:f81c96761fca60d64b1c9b79ec2e40cf9495a745cf570613079ef324aeb9672b" + ], + "version": "==0.4.2" + }, + "pycodestyle": { + "hashes": [ + "sha256:682256a5b318149ca0d2a9185d365d8864a768a28db66a84a2ea946bcc426766", + "sha256:6c4245ade1edfad79c3446fadfc96b0de2759662dc29d07d80a6f27ad1ca6ba9" + ], + "version": "==2.3.1" + }, + "pyflakes": { + "hashes": [ + "sha256:08bd6a50edf8cffa9fa09a463063c425ecaaf10d1eb0335a7e8b1401aef89e6f", + "sha256:8d616a382f243dbf19b54743f280b80198be0bca3a5396f1d2e1fca6223e8805" + ], + "version": "==1.6.0" + }, + "pytest": { + "hashes": [ + "sha256:54713b26c97538db6ff0703a12b19aeaeb60b5e599de542e7fca0ec83b9038e8", + "sha256:829230122facf05a5f81a6d4dfe6454a04978ea3746853b2b84567ecf8e5c526" + ], + "index": "pypi", + "version": "==3.5.1" + }, + "pytest-cov": { + "hashes": [ + "sha256:03aa752cf11db41d281ea1d807d954c4eda35cfa1b21d6971966cc041bbf6e2d", + "sha256:890fe5565400902b0c78b5357004aab1c814115894f4f21370e2433256a3eeec" + ], + "index": "pypi", + "version": "==2.5.1" + }, + "pytest-flake8": { + "hashes": [ + "sha256:e5cdc4f459c9436ac6c649e428a014bb5988605858549397374ec29a776cae68", + "sha256:ec248d4a215d6c7cd9d3ca48f365ece0e3892b46d626c22a95ccc80188ff35ed" + ], + "index": "pypi", + "version": "==1.0.1" + }, + "python-dateutil": { + "hashes": [ + "sha256:3220490fb9741e2342e1cf29a503394fdac874bc39568288717ee67047ff29df", + "sha256:9d8074be4c993fbe4947878ce593052f71dac82932a677d49194d8ce9778002e" + ], + "markers": "python_version >= '2.7'", + "version": "==2.7.2" + }, + "pyyaml": { + "hashes": [ + "sha256:0c507b7f74b3d2dd4d1322ec8a94794927305ab4cebbe89cc47fe5e81541e6e8", + "sha256:16b20e970597e051997d90dc2cddc713a2876c47e3d92d59ee198700c5427736", + "sha256:3262c96a1ca437e7e4763e2843746588a965426550f3797a79fca9c6199c431f", + "sha256:326420cbb492172dec84b0f65c80942de6cedb5233c413dd824483989c000608", + "sha256:4474f8ea030b5127225b8894d626bb66c01cda098d47a2b0d3429b6700af9fd8", + "sha256:592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab", + "sha256:5ac82e411044fb129bae5cfbeb3ba626acb2af31a8d17d175004b70862a741a7", + "sha256:5f84523c076ad14ff5e6c037fe1c89a7f73a3e04cf0377cb4d017014976433f3", + "sha256:827dc04b8fa7d07c44de11fabbc888e627fa8293b695e0f99cb544fdfa1bf0d1", + "sha256:b4c423ab23291d3945ac61346feeb9a0dc4184999ede5e7c43e1ffb975130ae6", + "sha256:bc6bced57f826ca7cb5125a10b23fd0f2fff3b7c4701d64c439a300ce665fff8", + "sha256:c01b880ec30b5a6e6aa67b09a2fe3fb30473008c85cd6a67359a1b15ed6d83a4", + "sha256:ca233c64c6e40eaa6c66ef97058cdc80e8d0157a443655baa1b2966e812807ca", + "sha256:e863072cdf4c72eebf179342c94e6989c67185842d9997960b3e69290b2fa269" + ], + "version": "==3.12" + }, + "requests": { + "hashes": [ + "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", + "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e" + ], + "version": "==2.18.4" + }, + "requests-toolbelt": { + "hashes": [ + "sha256:42c9c170abc2cacb78b8ab23ac957945c7716249206f90874651971a4acff237", + "sha256:f6a531936c6fa4c6cfce1b9c10d5c4f498d16528d2a54a22ca00011205a187b5" + ], + "version": "==0.8.0" + }, + "rsa": { + "hashes": [ + "sha256:25df4e10c263fb88b5ace923dd84bf9aa7f5019687b5e55382ffcdb8bede9db5", + "sha256:43f682fea81c452c98d09fc316aae12de6d30c4b5c84226642cf8f8fd1c93abd" + ], + "version": "==3.4.2" + }, + "s3transfer": { + "hashes": [ + "sha256:90dc18e028989c609146e241ea153250be451e05ecc0c2832565231dacdf59c1", + "sha256:c7a9ec356982d5e9ab2d4b46391a7d6a950e2b04c472419f5fdec70cc0ada72f" + ], + "version": "==0.1.13" + }, + "six": { + "hashes": [ + "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", + "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" + ], + "version": "==1.11.0" + }, + "tox": { + "hashes": [ + "sha256:96efa09710a3daeeb845561ebbe1497641d9cef2ee0aea30db6969058b2bda2f", + "sha256:9ee7de958a43806402a38c0d2aa07fa8553f4d2c20a15b140e9f771c2afeade0" + ], + "index": "pypi", + "version": "==3.0.0" + }, + "tqdm": { + "hashes": [ + "sha256:139b1672ab75ca6cb670d215ab0b408bec214ca3bed918de50ff265e0ee77617", + "sha256:75efcd98827971f96aa9b270e73ccedf1d275b781a9149a0846a7728010d045e" + ], + "version": "==4.23.2" + }, + "twine": { + "hashes": [ + "sha256:08eb132bbaec40c6d25b358f546ec1dc96ebd2638a86eea68769d9e67fe2b129", + "sha256:2fd9a4d9ff0bcacf41fdc40c8cb0cfaef1f1859457c9653fd1b92237cc4e9f25" + ], + "index": "pypi", + "version": "==1.11.0" + }, + "urllib3": { + "hashes": [ + "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", + "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f" + ], + "version": "==1.22" + }, + "virtualenv": { + "hashes": [ + "sha256:1d7e241b431e7afce47e77f8843a276f652699d1fa4f93b9d8ce0076fd7b0b54", + "sha256:e8e05d4714a1c51a2f5921e62f547fcb0f713ebbe959e0a7f585cc8bef71d11f" + ], + "version": "==15.2.0" + }, + "wheel": { + "hashes": [ + "sha256:1ae8153bed701cb062913b72429bcf854ba824f973735427681882a688cb55ce", + "sha256:9cdc8ab2cc9c3c2e2727a4b67c22881dbb0e1c503d592992594c5e131c867107" + ], + "index": "pypi", + "version": "==0.31.0" + } + } +} diff --git a/README.rst b/README.rst index 6175883..98e8f2b 100644 --- a/README.rst +++ b/README.rst @@ -36,8 +36,8 @@ Installation $ pip install ecr-cli -Configuration file ------------------- +ECR Configuration file +---------------------- If you place a file in `YAML format`_ with the filename ``.ecr.yml`` in the same directory as ``Dockerfile``, profile name, region name, registry ID and tag can be set. @@ -98,15 +98,17 @@ Build Build an image from a Dockerfile. Options: - -t, --tag TEXT - --dockerfile PATH Name of the Dockerfile (Default is ‘PATH/Dockerfile’). + -t, --tag TEXT Name and optionally a tag in the `name:tag` format. + --dockerfile PATH Name of the Dockerfile (Default is `PATH/Dockerfile`). + --configfile PATH Name of the ECR configuration file (Default is `PATH/.ecr.yml`). --cache / --no-cache Use cache when building the image. --rm / --no-rm Remove intermediate containers after a successful build. --force-rm / --no-force-rm Always remove intermediate containers. --pull / --no-pull Always attempt to pull a newer version of the image. --squash / --no-squash Squash newly built layers into a single new layer. --push / --no-push Push an image or a repository to a Amazon ECR registry after a successful build. - --quiet / --no-quiet Suppress the build output and print image ID on success. + --quiet / --no-quiet Suppress the standard output. + --no-profile Forcibly disable the ECR configuration file profile. -h, --help Show this message and exit. Push @@ -119,6 +121,7 @@ Push Push an image or a repository to a Amazon ECR registry. Options: + --quiet / --no-quiet Suppress the standard output. -h, --help Show this message and exit. Pull @@ -131,6 +134,7 @@ Pull Pull an image or a repository from a Amazon ECR registry Options: + --quiet / --no-quiet Suppress the standard output. -h, --help Show this message and exit. Authentication diff --git a/ecr_cli/__init__.py b/ecr_cli/__init__.py index 4d0ca19..adabb1e 100644 --- a/ecr_cli/__init__.py +++ b/ecr_cli/__init__.py @@ -1,9 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import - -__version__ = '0.0.1' - +__version__ = '0.0.8' CONTEXT_SETTINGS = dict( help_option_names=['-h', '--help'], diff --git a/ecr_cli/action.py b/ecr_cli/action.py index 51f2639..aff3a2e 100644 --- a/ecr_cli/action.py +++ b/ecr_cli/action.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import + +import itertools import logging import sys import click import docker -import itertools - from docker.errors import DockerException from docker.utils.json_stream import json_stream from future.utils import string_types @@ -14,7 +14,6 @@ from ecr_cli.client import EcrClient - _logger = logging.getLogger(__name__) _logger.addHandler(logging.StreamHandler(sys.stdout)) _logger.setLevel(logging.INFO) @@ -36,13 +35,14 @@ def __init__(self, profile_name=None, region_name=None, registry_id=None, def login(self, reauth=True): username, password, registry = self._ecr_client.get_authorization_token( self._registry_id) - self._docker_client.login(username=username, password=password, - registry=registry, reauth=reauth) - _logger.debug(registry) self._registry = registry.replace('https://', '') - return registry + self._docker_client.login(username=username, password=password, + registry=self._registry, reauth=reauth) + _logger.debug(self._registry) + return self._registry def _process_stream(self, stream): + # TODO Safe dictionary key access result_stream, internal_stream = itertools.tee(json_stream(stream)) image_ids = set() progress_bars = {} @@ -111,7 +111,11 @@ def build(self, tags, path=None, dockerfile=None, cache=True, rm=False, if isinstance(resp, string_types): image_id = resp else: - image_id = self._process_stream(resp)[0] + image_ids = self._process_stream(resp) + if not image_ids: + image_id = tag + else: + image_id = image_ids[0] image = self._docker_client.images.get(image_id) if tags and len(tags) > 1: for t in tags[1:]: @@ -119,13 +123,14 @@ def build(self, tags, path=None, dockerfile=None, cache=True, rm=False, image.tag('{0}/{1}'.format(self._registry, name), tag, force=True) return image - def push(self, name, tag=None): + def push(self, name, tag=None, quiet=False): resp = self._docker_client.images.push( - '{0}/{1}'.format(self._registry, name), tag, stream=True) - image_ids = self._process_stream(resp) - return tuple(image_ids) + '{0}/{1}'.format(self._registry, name), tag, stream=not quiet) + if not quiet: + self._process_stream(resp) - def pull(self, name, tag=None): + def pull(self, name, tag=None, quiet=False): resp = self._docker_client.images.client.api.pull( - '{0}/{1}'.format(self._registry, name), tag, stream=True) - self._process_stream(resp) + '{0}/{1}'.format(self._registry, name), tag, stream=not quiet) + if not quiet: + self._process_stream(resp) diff --git a/ecr_cli/cli.py b/ecr_cli/cli.py old mode 100644 new mode 100755 index 973c24a..03cfa1a --- a/ecr_cli/cli.py +++ b/ecr_cli/cli.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- from __future__ import absolute_import + import os import click @@ -8,7 +9,7 @@ import ecr_cli.message as msg from ecr_cli import CONTEXT_SETTINGS from ecr_cli.action import EcrAction -from ecr_cli.util import load_config +from ecr_cli.util import load_ecr_config @click.group(context_settings=CONTEXT_SETTINGS) @@ -31,9 +32,12 @@ def cli(ctx, profile, region, registry_id, debug): @cli.command(help=msg.HELP_COMMAND_BUILD) @click.argument('path', type=click.Path(exists=True, dir_okay=True), nargs=1, required=True) -@click.option('--tag', '-t', type=str, multiple=True, required=False) +@click.option('--tag', '-t', type=str, multiple=True, required=False, + help=msg.HELP_OPTION_TAG) @click.option('--dockerfile', type=click.Path(exists=True, file_okay=True), required=False, help=msg.HELP_OPTION_DOCKERFILE) +@click.option('--configfile', type=click.Path(exists=True, file_okay=True), required=False, + help=msg.HELP_OPTION_CONFIGFILE) @click.option('--cache/--no-cache', default=True, required=False, help=msg.HELP_OPTION_CACHE) @click.option('--rm/--no-rm', default=False, required=False, @@ -48,14 +52,21 @@ def cli(ctx, profile, region, registry_id, debug): help=msg.HELP_OPTION_PUSH) @click.option('--quiet/--no-quiet', default=False, required=False, help=msg.HELP_OPTION_QUIET) +@click.option('--no-profile', is_flag=True, default=False, required=False, + help=msg.HELP_OPTION_NO_PROFILE) @click.pass_context -def build(ctx, path, tag, dockerfile, cache, rm, force_rm, pull, squash, push, quiet): - config = load_config(os.path.dirname(dockerfile) if dockerfile else path) +def build(ctx, path, tag, dockerfile, configfile, cache, rm, force_rm, + pull, squash, push, quiet, no_profile): + if not configfile: + configfile = os.path.join(os.path.dirname(dockerfile) if dockerfile else path, + '.ecr.yml') + config = load_ecr_config(configfile) if not config and not tag: raise RuntimeError('Missing argument `tag`.') action = EcrAction( - profile_name=ctx.obj['profile'] if ctx.obj['profile'] else config.profile_name, + profile_name=None if no_profile else + ctx.obj['profile'] if ctx.obj['profile'] else config.profile_name, region_name=ctx.obj['region'] if ctx.obj['region'] else config.region_name, registry_id=ctx.obj['registry_id'] if ctx.obj['registry_id'] else config.registry_id, debug=ctx.obj['debug']) @@ -64,31 +75,35 @@ def build(ctx, path, tag, dockerfile, cache, rm, force_rm, pull, squash, push, q pull=pull, squash=squash, quiet=quiet) if push: for t in config.tags: - action.push(t) + action.push(t, quiet=quiet) @cli.command(help=msg.HELP_COMMAND_PUSH) @click.argument('name', type=str, nargs=-1, required=True) +@click.option('--quiet/--no-quiet', default=False, required=False, + help=msg.HELP_OPTION_QUIET) @click.pass_context -def push(ctx, name): +def push(ctx, name, quiet): action = EcrAction(profile_name=ctx.obj['profile'], region_name=ctx.obj['region'], registry_id=ctx.obj['registry_id'], debug=ctx.obj['debug']) for n in name: - action.push(n) + action.push(n, quiet=quiet) @cli.command(help=msg.HELP_COMMAND_PULL) @click.argument('name', type=str, nargs=-1, required=True) +@click.option('--quiet/--no-quiet', default=False, required=False, + help=msg.HELP_OPTION_QUIET) @click.pass_context -def pull(ctx, name): +def pull(ctx, name, quiet): action = EcrAction(profile_name=ctx.obj['profile'], region_name=ctx.obj['region'], registry_id=ctx.obj['registry_id'], debug=ctx.obj['debug']) for n in name: - action.pull(n) + action.pull(n, quiet=quiet) if __name__ == '__main__': diff --git a/ecr_cli/client.py b/ecr_cli/client.py index 82d5934..f449f61 100644 --- a/ecr_cli/client.py +++ b/ecr_cli/client.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import + import base64 import logging import sys from boto3.session import Session - _logger = logging.getLogger(__name__) _logger.addHandler(logging.StreamHandler(sys.stdout)) _logger.setLevel(logging.INFO) diff --git a/ecr_cli/message.py b/ecr_cli/message.py index 6241589..3603b53 100644 --- a/ecr_cli/message.py +++ b/ecr_cli/message.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import - HELP_COMMAND_BUILD = 'Build an image from a Dockerfile.' HELP_COMMAND_PUSH = 'Push an image or a repository to a Amazon ECR registry.' HELP_COMMAND_PULL = 'Pull an image or a repository from a Amazon ECR registry' @@ -11,8 +10,9 @@ HELP_OPTION_DEBUG = 'Turn on debug logging.' HELP_OPTION_REGISTRY_ID = 'AWS account ID that correspond to a Amazon ECR registry ' \ 'that you want to log in to.' -HELP_OPTION_TAG = 'Name and optionally a tag in the ‘name:tag’ format.' -HELP_OPTION_DOCKERFILE = 'Name of the Dockerfile (Default is ‘PATH/Dockerfile’).' +HELP_OPTION_TAG = 'Name and optionally a tag in the `name:tag` format.' +HELP_OPTION_DOCKERFILE = 'Name of the Dockerfile (Default is `PATH/Dockerfile`).' +HELP_OPTION_CONFIGFILE = 'Name of the ECR configuration file (Default is `PATH/.ecr.yml`).' HELP_OPTION_CACHE = 'Use cache when building the image.' HELP_OPTION_RM = 'Remove intermediate containers after a successful build.' HELP_OPTION_FORCE_RM = 'Always remove intermediate containers.' @@ -20,4 +20,5 @@ HELP_OPTION_SQUASH = 'Squash newly built layers into a single new layer.' HELP_OPTION_PUSH = 'Push an image or a repository to a Amazon ECR registry ' \ 'after a successful build.' -HELP_OPTION_QUIET = 'Suppress the build output and print image ID on success.' +HELP_OPTION_QUIET = 'Suppress the standard output.' +HELP_OPTION_NO_PROFILE = 'Forcibly disable the ECR configuration file profile.' diff --git a/ecr_cli/model.py b/ecr_cli/model.py index 5301957..c540d4b 100644 --- a/ecr_cli/model.py +++ b/ecr_cli/model.py @@ -14,11 +14,12 @@ def __init__(self, tags, profile_name=None, region_name=None, registry_id=None): def from_dict(value): tags = value.get('tags', None) assert tags, 'Missing sequence `tags`.' + registry_id = value.get('registry_id', None) return EcrConfig( tags, value.get('profile_name', None), value.get('region_name', None), - value.get('registry_id', None),) + str(registry_id) if registry_id else registry_id,) def _key(self): return (self.tags, diff --git a/ecr_cli/util.py b/ecr_cli/util.py index d832d93..d9475c7 100644 --- a/ecr_cli/util.py +++ b/ecr_cli/util.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import + import codecs import os @@ -8,10 +9,9 @@ from ecr_cli.model import EcrConfig -def load_config(path): - conf = os.path.join(path, '.ecr.yml') +def load_ecr_config(file_): config = None - if os.path.exists(conf): - with codecs.open(conf, 'rb', 'utf-8') as f: + if os.path.exists(file_): + with codecs.open(file_, 'rb', 'utf-8') as f: config = EcrConfig.from_dict(yaml.load(f)) return config diff --git a/setup.py b/setup.py index 98a6d24..687cff8 100755 --- a/setup.py +++ b/setup.py @@ -1,13 +1,13 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- from __future__ import print_function + import codecs -from setuptools import setup +from setuptools import find_packages, setup import ecr_cli - with codecs.open('README.rst', 'rb', 'utf-8') as readme: long_description = readme.read() @@ -21,7 +21,7 @@ author='laughingman7743', author_email='laughingman7743@gmail.com', license='MIT License', - packages=['ecr_cli'], + packages=find_packages(), package_data={ '': ['*.rst'], }, @@ -34,7 +34,7 @@ 'tqdm>=4.19.0' ], tests_require=[ - 'pytest', + 'pytest>=3.5', 'pytest-cov', 'pytest-flake8', ],