python-designateclient-1.0.0/0000775000175300017540000000000012234460017017325 5ustar jenkinsjenkins00000000000000python-designateclient-1.0.0/ChangeLog0000664000175300017540000005321612234460017021106 0ustar jenkinsjenkins00000000000000commit 12c57f2809820aec1344ff43ebfb688dc782b2fd Author: Kiall Mac Innes Date: Wed Oct 30 15:22:34 2013 +0000 Keyring is not actually used Change-Id: I583ac67b10d51e95fefd8bb1ea2c6fa13a79caa9 commit 4f65c151cf8c0a2b04e771fc1e25bef95bf00077 Author: Kiall Mac Innes Date: Wed Oct 30 15:02:53 2013 +0000 Remove outdated version value from setup.cfg Change-Id: Ic99a31efce6e6baa6e9fe6de7bb83a1537a83ea5 commit 4fef192f674534cb1c7f616fdf84c5876f38a527 Merge: 45046bb e2d7dc2 Author: Jenkins Date: Thu Oct 31 11:49:54 2013 +0000 Merge "Added domain and record description editing" commit e2d7dc2c5cd0c7e2e2a87f9742f9456968b705c9 Author: Graham Hayes Date: Wed Oct 30 18:22:54 2013 +0000 Added domain and record description editing Change-Id: I8cdf3b9fa986255a9c1787f4ed8375bded8ee062 Closes-Bug: 1213889 commit 45046bb552a3aeeba9ad60d3077627d303024083 Author: Kiall Mac Innes Date: Wed Oct 30 13:33:29 2013 +0000 Sync requirements with stable/havana requirements Change-Id: I5ca0a8ddcf89fe816d47dfd4d720410780444d60 commit 67147265207435a58748e13e0565967781cc5c61 Author: Kiall Mac Innes Date: Sun Oct 27 14:52:28 2013 +0000 Ensure TTL is treated as an int in the CLI Change-Id: Icd6e56adb416946af98bcc1dd1fbbe16c2aef8c8 commit d22d1afa590704a2cc70b35f1298e74ccf848c33 Author: Brian DeHamer Date: Thu Oct 24 12:24:15 2013 -0700 Update dependency versions Bring dependency versions in-line with the global OpenStack requirements Change-Id: Ifa0f30a2dc335b69c96fade95e3ef1b92db7927e Closes-bug: #1239428 commit e405cb3f447dffbcd6665de93334274d7149f3b2 Author: Kiall Mac Innes Date: Mon Oct 14 12:45:19 2013 +0100 Ensure Invalid JSON and errors during deletes are displayed correctly Change-Id: Iccd4ee10611cfa58a98618f29545d5b194edafa3 commit d1e24a90c59df320bbba8c28e298147bd94a1a5f Author: Kiall Mac Innes Date: Wed Sep 25 15:16:35 2013 +0100 Correct two Record examples in the binding docs Change-Id: I73df92ab161a3f6dacb196d827130de8f7ae8252 commit 1416ffa87ee43f28fbec9676079d7eaaa0a1c0cf Author: Kiall Mac Innes Date: Wed Sep 25 13:54:13 2013 +0100 Add Python bindings docs Change-Id: I95a098190917017b010a323403ca43108f078958 commit 472ec278d48988c0e6c603edfbdfff116ef7ab0c Author: Simon McCartney Date: Thu Sep 19 16:17:12 2013 +0100 first drop of python-designateclient docs Change-Id: Iecad349608bdc391b1c8613bac55b37f2719be19 commit 76a37fa37c89cd0754bee5302d64e84a23f3dcf8 Author: Kiall Mac Innes Date: Wed Sep 18 16:55:29 2013 +0100 Ensure beta versions are not downloaded from pypi Change-Id: I636040826af81b6df4c8631e65876316fa10c081 commit 5fe58dac71a42fbfd4e6fcc78b8aaa328303ab73 Author: Kiall Mac Innes Date: Wed Sep 18 12:55:40 2013 +0100 Add a --insecure arg to ignore invalid SSL certs Change-Id: I7350c2f9d8f857300784955b2b776f3f1dc69933 commit b2e1033e9ecbe5b68c5633e65f71941e0fe8f74c Author: Kiall Mac Innes Date: Wed Sep 18 11:16:05 2013 +0100 Ensure we only list sphinx as a dep once Change-Id: If863d8e7a7eda78c721b5e83e9053ec5b70fcee2 commit f7bc95a871abd6af6bfec062feefe851c1ad2a4e Author: Dirk Mueller Date: Wed Sep 4 14:40:46 2013 +0200 Use Python 3.x compatible except construct. Python 3.x deprecated the form "except x,y:". Switch usage to "except x as y:", which works with any Python version >= 2.6 Change-Id: Id276fdaee9e8753568227e638408e5bccff28e67 commit bd8023493a153780260c8f40f9dcc133c829cd37 Author: Kiall Mac Innes Date: Thu Aug 8 01:02:11 2013 +0100 Allow auth using a pre-fetched token Change-Id: I6ed13d969410be83ebfce443d5758a7d0b98386b commit 7d142020d82a3a6641ebf72f152cc7fd51e904d5 Author: Kiall Mac Innes Date: Thu Aug 8 11:38:35 2013 +0100 Update to PBR 0.5.21+ Change-Id: Icb0754f9d64ea2b4d561866c8c5f614316217a1b commit 8b8d07eb542b0c0c21fb5976a702778dbcc6191b Author: Kiall Mac Innes Date: Tue Jul 9 13:06:13 2013 +0100 doc/requirements.txt should be a proxy Change-Id: I48efc2a988018b67668ab609ea02cf5a1105a772 commit 80f8ca7506dae9e897fc1f7872ddc2b52b9c3422 Author: Kiall Mac Innes Date: Tue Jul 9 12:38:01 2013 +0100 Remove comments from *requirements.txt (workaround pbr bug) Workaround for pbr bug #1191923 Change-Id: Iba7c09090011073b50084dd0efa269d713ea7de2 commit 479c70fadd0273893ed9106eb0bf973120d638e8 Author: Kiall Mac Innes Date: Tue Jun 25 13:01:08 2013 +0100 Sync with openstack/requirements Change-Id: Id92c17cf2cd11bf653afabd2e283519f94a5dc50 commit d37eeaf7fc79f5c008cb236661a031bdc0fe1c32 Author: Monty Taylor Date: Fri Jun 14 18:33:00 2013 -0400 Rename to designate in .gitreview. Change-Id: I48d8e3bd6846c9f8809204e8a2190e9d7e0c964b commit 67c14f0573f15f6fbe6c71e8323828af27e1203a Author: Kiall Mac Innes Date: Sun Jun 9 21:18:36 2013 +0100 Rename Moniker -> Designate Change-Id: Idf7153aa287adc874a2878dc829950fda52a4879 commit dbd861712228c0e5cb8b959c0b75b76cca66c156 Author: Kiall Mac Innes Date: Sun Jun 9 15:06:11 2013 +0100 Add Hacking checks Change-Id: I5435e83a8dbe3c3273b59ecb3c5f1be26c9bec96 commit 72bc53b67cb3d8829247d1e631bdf7b198a4206e Author: Kiall Mac Innes Date: Sat May 25 13:07:04 2013 +0100 Migrate to PBR Change-Id: I4f32b7c3ca7831becdd49f75a7fa48bfcfa7fe76 commit e8f7306112fd1029a5f701b72bf4b3dfd670b689 Merge: d038db8 02835b0 Author: Jenkins Date: Sat May 25 12:00:50 2013 +0000 Merge "Always allow overriding the endpoint" commit 02835b085608ba1fa88dd70e1fcf03c9b1801f29 Author: Kiall Mac Innes Date: Sat May 25 12:57:52 2013 +0100 Always allow overriding the endpoint Change-Id: Iff4d152e8e59f895a42adf6927e559ca73472888 commit d038db8a505aa31a1c78072d382ed3b3cda738a0 Author: Endre Karlson Date: Thu May 23 23:23:57 2013 +0200 Switch to flake8 and testr Change-Id: Ia25ef86786895f376be410f74b9a30e3e8ff4243 commit e853efb11d06be74dc7a7bb43bdd2cf7f55e239e Author: Patrick Galbraith Date: Fri May 3 18:40:18 2013 -0300 Added reporting functionality to Moniker client Change-Id: I12687d678a1b7c22bfbfd0480c53912152d8d7eb commit 9bfedc76f928aaa603f2f386e81de6bddf6eb806 Author: Kiall Mac Innes Date: Fri May 3 14:31:42 2013 +0100 Correct diagnostics URI Change-Id: Ibe2723617268a4df7a7de7d0b46d7aa621a8d4ab commit 8b33e3248f53ba810204ba39f9e50048849fd8fe Author: Kiall Mac Innes Date: Sat Apr 13 18:11:28 2013 +0100 Include type when listing records. Change-Id: I09b1ed71f593173ea6661165c9b16bbe64e1ca27 commit d9188704f4b1cdb015a45f70de5bb8b642917c6f Author: Kiall Mac Innes Date: Fri Apr 12 13:33:13 2013 +0100 Support loading resources from 3rd party packages. E.g. client extensions Change-Id: I919c915802632d0c72fbec8bcb28085661334b34 commit 84d326920fc9e6592b8fe9a56adaf6be0d9358c3 Author: Kiall Mac Innes Date: Fri Apr 12 13:11:46 2013 +0100 Allow for controllers to be loaded dynamically. Change-Id: If85de4c02406e8ffd49da3c04c23db58ad2df119 commit 63c3a1a7853ca60c28394ff419c708dcabdc4f38 Author: Kiall Mac Innes Date: Thu Apr 11 12:50:48 2013 +0100 Add a command to list the nameservers for a domain Change-Id: Id44b9f8cfc0a79a7514ff338aab42f39067e1226 commit 48bcdae017049922f53c4b0a48b7f0c73739181d Author: Kiall Mac Innes Date: Thu Apr 11 12:50:28 2013 +0100 List commands should show a reduced set of columns Change-Id: I8c56e5a9366e9e7b6569b7e001f069fc0a812470 commit 41fde43dabe5bc2405942879451166474e369cef Author: Kiall Mac Innes Date: Fri Mar 29 23:53:46 2013 +0000 Add keyring to pip-requires Change-Id: I25a54badf2f33d2f25257793b227c80e86e69894 commit 2b97f4560cd521acd33bb22a12ba4523f7e673a3 Author: Kiall Mac Innes Date: Tue Mar 26 17:16:07 2013 +0000 Clean error message display :) Change-Id: Ie74e590c7d9c9de0b5a22ca5185c3cd5438a50cb commit 1e47b5a369d9cdf4b79122b470cc411aa98e6308 Author: Kiall Mac Innes Date: Tue Mar 26 12:54:15 2013 +0000 Cleanup optional and obsolete CLI params. Change-Id: Ief9e5cba48f0a5462688f01b469cd39c689356d7 commit 487502e9f2ea28956f17fd8dbde6f9851f4a8306 Author: Kiall Mac Innes Date: Tue Mar 26 12:41:18 2013 +0000 Rename OS_SERVICE_ENDPOINT env var to OS_DNS_ENDPOINT Change-Id: I8ed89a819449d5a286c10fe79ac400fcc6af5db8 commit 3dd76600c2d8deafcef669a439b0594fc3e7254a Author: Kiall Mac Innes Date: Tue Mar 26 12:37:55 2013 +0000 Sync JSONSchemas Change-Id: I25609bd75751f64da7d28856dbeddb320741f87e commit fba78c044cce8108888f72ef4bb6ae8756955ebd Author: Kiall Mac Innes Date: Wed Mar 13 20:34:36 2013 +0000 Rename OS_SERVICE_TYPE env var to OS_DNS_SERVICE_TYPE Change-Id: I8b602491ed2cf41cd1807505af2f6970d419fee2 commit fbf8714df61d38f2606609d78bab663b04f323ca Author: Kiall Mac Innes Date: Mon Mar 4 13:29:36 2013 +0000 Sync JSONSchemas Change-Id: Ia9a67ce8d777fb5cc8bb711049174d707b79b407 commit af9ea73030a38a560d3756ad78a9a62377ef1b38 Author: Kiall Mac Innes Date: Mon Mar 4 12:49:31 2013 +0000 Have tox.ini actually run nosetests Change-Id: I3c93a6614ff71bfe2405257e2684fbc0fa05e76c commit f8e1f46839be89b15a312080bc33ef22ab0e3484 Author: Kiall Mac Innes Date: Wed Feb 27 16:35:42 2013 +0000 Pin to jsonschema less than 1.0 Change-Id: I9c4b804a5dd476c69976aed841f804283ecf8996 commit c6a1f56ed6b6befc77967ba40e751a6a80238ae8 Author: Davide Guerri Date: Sun Feb 24 16:47:50 2013 +0100 Add support for administrative access (via X-Moniker-Sudo-Tenant-ID header) Change-Id: Ia92f9c33cebb529333de72765371189ea11b72bc commit e824b5b470581252173af4076a913f4c81ea7766 Author: Kiall Mac Innes Date: Mon Feb 18 12:50:40 2013 +0000 Ensure resources and tools/* are included in sdist Change-Id: I9185187cdaa20f2142c44f474f74acdde47888a6 commit 67fec06719b073f48dd3aa7144f8f537780a304a Author: Kiall Mac Innes Date: Thu Feb 7 17:45:03 2013 +0000 Add diagnostics to Python API and CLI Change-Id: Ib26adada4a5610f7eb6a3458caa4ca4b18d804ca commit d9737b5b2aa25fa424aaa699c3335881ecb2aa4a Author: Kiall Mac Innes Date: Thu Jan 31 10:27:20 2013 +0000 Bump JSONSchema version to 0.8, tracking the server component. Change-Id: I95afdfd1e426cb2d924586f260154ff62d1498d2 commit a7d61bc8aa70eb96e9fc30f54802262da84e44d9 Author: Kiall Mac Innes Date: Wed Jan 30 22:16:21 2013 +0000 Attempt to support both cliff 1.2 and 1.3. Change-Id: I5a5787867af09086c9945ace6f12153b17396bf7 commit 045cd76af3dde212c1eec9dad851cabdcd114274 Author: Kiall Mac Innes Date: Tue Jan 29 18:27:08 2013 +0000 Re-add version.py Change-Id: I585bb80c0dcbbae0809f4ec05255c96216dddbed commit 2d296646cf69fb4763e6762de17d03b9f982c307 Author: Kiall Mac Innes Date: Mon Jan 28 23:44:07 2013 +0000 Sync with Oslo 30a50c8a Change-Id: I12a39aaa506d0938e742285d97c4bf28e21dcb2c commit a3235ccec23e490452a6c460d450f6098b190803 Author: Kiall Mac Innes Date: Thu Jan 24 09:33:58 2013 +0000 Sync Schemas Change-Id: I813a2e39bc46ceef7d53b2ccfcee561b315c11b9 commit 6574e7d2a22a73e030767e970c8ee1670dafb279 Author: Kiall Mac Innes Date: Thu Jan 24 09:27:47 2013 +0000 Add support for supplying custom service type. Change-Id: I1fc317b7235b54ceea0228dfd71b933f8bbb8855 commit 62a0163caa11d1c268707716472d83253e12d4a9 Author: Kiall Mac Innes Date: Wed Jan 9 17:17:56 2013 +0000 Fixup MANIFEST.in Change-Id: Ia41cfb4472388b02fd47c75085e7445137c99ef8 commit a13844144b46863c1e32830696f97ccee248032d Author: Kiall Mac Innes Date: Wed Jan 9 17:16:23 2013 +0000 Ensure we supply Oslo Version with the correct `python_package` name Change-Id: Iae20135b6c5c6d80e6b62bbb59be6c9f4c94dee7 commit 9a9e075b4863597b01de165ad807381b2a465129 Author: Kiall Mac Innes Date: Wed Jan 9 17:07:12 2013 +0000 Sync with oslo a8973c52 Change-Id: Iacf59007d63a24df3973353d275b4113334e2d46 commit d7e35140b58f01c54204f110cb310642fd522c0e Author: Kiall Mac Innes Date: Tue Jan 8 12:46:46 2013 +0000 Ensure `moniker --version` reports the correct version number. Change-Id: I15466dbc60e161ce6d5a21fd1ddcc59f4a10e525 commit 574fa9c7b8d11e291cf4f6fab2a23a2411819166 Author: Kiall Mac Innes Date: Tue Jan 8 12:44:27 2013 +0000 Sync with oslo-incubator ad93e4e3 Change-Id: Id85b0862e3813cf93fbf49c06df04ae34835bfc2 commit 1258c120b9cdeb5935e1eb12e05a87bfe23d99d6 Author: Kiall Mac Innes Date: Sun Dec 30 02:35:39 2012 +0000 Actually use the *correct* version of requests. Follow up to I17ca5e80 - I misread and assumed a < was a >. Change-Id: I77d5d73d01d0b5129e963a2d8670002fc457ff57 commit 13c601cc9c9ae0bd71e449eef77e95e1a7a15f16 Author: Kiall Mac Innes Date: Sun Dec 30 00:01:03 2012 +0000 Depend on and update for requests>1.0 (Matching {keystone,cinder,nova}client) Change-Id: I17ca5e802108fcf6dc906ff23b6b61f53a25eac1 commit 4e9729e0667f40e99eed031357727a29cecc2a4a Author: Kiall Mac Innes Date: Sat Dec 29 23:58:53 2012 +0000 Depend on cliff>=1.2.1 Change-Id: Ida38a944fe5dd875db12c2826b8d3a4168e54f79 commit ec6137590f4dac912312fced8da08d4f8f6f5a12 Author: Kiall Mac Innes Date: Sat Dec 29 19:21:25 2012 +0000 Support record priority in the CLI Change-Id: I772029632f8fa349621fc8f9e600d452cce0ad86 commit 145a7275f351d6399c4642b453cfb773f35a1d6e Author: Kiall Mac Innes Date: Fri Dec 14 13:04:30 2012 -0800 Support CLI updating of domains/records/servers. Updates to all resource types should now be functional. Change-Id: I9057ebd4ebffdeeb70c0c9b962c49b3dcb68d8f4 commit f4537b64c5252c562dd6bdd5327856b9d1422620 Author: Kiall Mac Innes Date: Fri Dec 14 12:57:52 2012 -0800 Ensure Update Records and Servers works correctly in the Python API Change-Id: I2bff6d0c7e7e580776aa34bf434778c823b8ebc2 commit 388dfa4e9da82b4d93402b85fdb33927317a6288 Author: Kiall Mac Innes Date: Fri Dec 14 12:56:54 2012 -0800 Sync JSON-Schemas Change-Id: I6a6b7510bcff14376f9275feb19dfdabeed96bd7 commit d21546becab576d890d60968d203342012d356ac Author: Kiall Mac Innes Date: Tue Dec 11 16:41:50 2012 -0800 Provide a sane error message when --os-auth-url or --os-endpoint have not been supplied. Change-Id: I930ea853cec00db87c87115ab3e3a94b7fe3c703 commit f99f313672073f9d657912ca27e89844f47d371e Author: Kiall Mac Innes Date: Tue Dec 11 06:24:48 2012 -0800 Handle HTTP 400 errors somewhat more sanely. Change-Id: I49c4225adfd552f0dd01c80cc3053ff2599eb47f commit 47c85147a5341717db88c2bbcd02ddccaa8898f9 Author: Kiall Mac Innes Date: Tue Dec 11 06:23:45 2012 -0800 Ensure Warlock passes the approperiate error message along with it's exceptions. Change-Id: I966555181ab63ae50cadfd61ac38abda51f46350 commit a17d9391b7c6deb5007c21f6aac0850e67841785 Merge: af690af 7cc1c85 Author: Jenkins Date: Tue Dec 11 14:13:07 2012 +0000 Merge "Include setup-requires in tox.ini" commit af690af0803bcab4b781382eb5089c4dfefc5800 Merge: 186cab8 0aa39f6 Author: Jenkins Date: Tue Dec 11 14:13:01 2012 +0000 Merge "Sync with Oslo e6c576d9" commit 7cc1c856027208801fb5375a736d29ccd86e1072 Author: Kiall Mac Innes Date: Tue Dec 11 06:10:37 2012 -0800 Include setup-requires in tox.ini Change-Id: Ie5e7b7b12e8ddcf82e41f747c25de84f4ccc4743 commit 186cab8f795bd214dd3c20a62a001feef84334e3 Author: Endre Karlson Date: Tue Dec 11 13:05:54 2012 +0100 Positionals don't need require=Bool Change-Id: Id2e4910547e7a9672fee71939ee5ab6255dd5865 commit 0aa39f69b6b7f98e18293c3fbfb2d3852e763859 Author: Kiall Mac Innes Date: Sun Dec 9 20:22:03 2012 +0000 Sync with Oslo e6c576d9 Change-Id: Ic6b6c8fe9797fcc72761bb05fd6d38beb6326be5 commit 8ab7de1d14fda8a8f8bc59bc26d1848b3dc5d968 Author: Kiall Mac Innes Date: Tue Dec 4 17:19:45 2012 +0000 Remove unused code Change-Id: I3c2068fd315d1acaa3a93a740f1603a117f14cf5 commit 9bdc8dda5347616402dcd3322847da4f8bbbfd23 Author: Kiall Mac Innes Date: Tue Dec 4 16:29:53 2012 +0000 Ensure Servers CLI args are defined correctly Change-Id: I4a5b861768f6e379f12d5d07e91367df68a9f501 commit cd5017cc9c679c8dc158ba5c7b96de7f5947635f Author: Kiall Mac Innes Date: Tue Dec 4 16:06:48 2012 +0000 Sync Server JSONSchema Change-Id: Ia088f5d45058f0933b6b429a4433da699fc19c60 commit 4dd4ed773b874e6f44964c3f4d36e78dc2fb3218 Author: Kiall Mac Innes Date: Mon Dec 3 15:25:50 2012 +0000 Fixup pyflakes issue Change-Id: I23df6c5ab0ce55e4511cadcca3476f1fc008f382 commit 18cae5e5eebf75b3d7ef11d33aacb56ece183748 Author: Kiall Mac Innes Date: Wed Nov 28 13:28:14 2012 +0000 Add Records and Servers CLI commands Change-Id: I61249dc1d9d70b35255a1cad7080cba306a85d42 commit 68319c6e89cf24c84d163940ddd65aa68942fc1d Author: Endre Karlson Date: Wed Nov 28 01:58:08 2012 +0100 Add ID as a positional argument to GetCommand Change-Id: I07871ba5a072080f473310d9613efd555a85cb3b commit d636818d2acf9e87afe8945703b30cf6756f0fe8 Author: Endre Karlson Date: Tue Nov 27 23:34:52 2012 +0100 More helpers in the base Controller Change-Id: I0b80cdb5d71d03200e3a106d2a71cecaa9e4fed3 commit 168b7d736a9974251edaea3e67b25e98d7f2f217 Author: Endre Karlson Date: Tue Nov 27 14:49:47 2012 +0100 Fix actual != expected row count for items Fixes bug #1083591 Change-Id: I162705a622c24090ce54eb7f12a65d96874611a7 commit 6f280a8693c2039ce4353cf65046858cf28fcff6 Author: Kiall Mac Innes Date: Mon Nov 19 23:08:35 2012 +0000 Initial Python client bindings and CLI Change-Id: Iac4a73acfb515c1e213a1dd0865a62bc39e3ed0f commit fd06cdfad06caa7a46ea848178b945c86cb428d1 Merge: a1598f0 bf49d45 Author: Jenkins Date: Sun Nov 18 03:33:54 2012 +0000 Merge "Add JSONSchemas" commit a1598f05f37733679603bb1c9d9472de46ea6fed Author: Kiall Mac Innes Date: Wed Nov 14 23:58:06 2012 +0000 Initial Domain/Record/Server model skeletons Change-Id: Ie9b834cb2b9616273db004fd56cfec5c343b1551 commit 0faa442fb3b5f571ee1eaec83df7c25f9106677c Author: Kiall Mac Innes Date: Sun Nov 18 03:14:48 2012 +0000 Sync tox.ini with moniker repo Change-Id: I11e972f82648052d48b305685b406af5671844a6 commit d7976fdb7cf9e17d77375e587309feb535f41dc5 Author: Kiall Mac Innes Date: Sun Nov 18 03:02:18 2012 +0000 Add PyFlakes tox env Change-Id: I91af105b2b8427b71257c492f2b2830c5602aee2 commit bf49d45324ca477c9a368036cec257829399089c Author: Kiall Mac Innes Date: Wed Nov 14 22:35:35 2012 +0000 Add JSONSchemas Change-Id: Ic776f94224e3ebacf0b1c672fe47152d447f8a82 commit 77409845403b51945b52e25550bbc599d4cd71af Author: Kiall Mac Innes Date: Thu Nov 1 15:25:56 2012 +0000 Sync with OS-Common 3d6c2368 + Use OS-C's Version Module Change-Id: I5208d2955f477973cff713713989a9ae8b74f80b commit fbce3d38bf139f96506ecf3c710937661018d882 Author: Monty Taylor Date: Thu Nov 1 02:35:52 2012 +0100 Rename package to python-monikerclient. Change-Id: Ie0221b83c857b11e21f5f223966f47afdaec252e commit 935b0392cf548840fcd9934a240d1fe31e00d6b8 Author: Kiall Mac Innes Date: Thu Nov 1 15:07:35 2012 +0000 Add pypi trove classifiers Change-Id: I62009fdb221680fe884a22e60162f0a7eb0abb14 commit 9fef6dee41aee22f5196aeb8c15ce85a3d1f1c5f Author: Kiall Mac Innes Date: Thu Nov 1 03:20:47 2012 +0000 Cache pip downloads on Jenkins Change-Id: Ic144b83423034adcc75bbc360527e2e1f3cbdd95 commit 21c4b1ddfe44536f8411afdbb32ff7873f893968 Author: Kiall Mac Innes Date: Thu Nov 1 03:08:06 2012 +0000 Fixup tox.ini for Stackforge+Gerrit Change-Id: Ib2b07140c4dc6891b60f878880c165bb0758819f commit b7bee717b21c007f6581a063605fb93c89a43cf9 Author: Kiall Mac Innes Date: Sun Oct 28 18:08:42 2012 +0000 Exit with the correct return code commit 7c64019e45cb8d161f0b68fd1a8128a4de6259af Author: Kiall Mac Innes Date: Fri Oct 26 18:03:25 2012 +0100 Initial Commit - CLI Skeletonpython-designateclient-1.0.0/.testr.conf0000664000175300017540000000032512234457733021426 0ustar jenkinsjenkins00000000000000[DEFAULT] test_command=OS_STDOUT_CAPTURE=1 OS_STDERR_CAPTURE=1 ${PYTHON:-python} -m subunit.run discover -t ./ ./designateclient/tests $LISTOPT $IDOPTION test_id_option=--load-list $IDFILE test_list_option=--list python-designateclient-1.0.0/test-requirements.txt0000664000175300017540000000021312234457733023575 0ustar jenkinsjenkins00000000000000coverage>=3.6 discover flake8==2.0 hacking>=0.5.6,<0.8 mox>=0.5.3 pep8==1.4.5 pyflakes>=0.7.2,<0.7.4 python-subunit testrepository>=0.0.17 python-designateclient-1.0.0/setup.py0000775000175300017540000000141512234457733021056 0ustar jenkinsjenkins00000000000000#!/usr/bin/env python # Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. # THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT import setuptools setuptools.setup( setup_requires=['pbr'], pbr=True) python-designateclient-1.0.0/README.rst0000664000175300017540000000000012234457733021015 0ustar jenkinsjenkins00000000000000python-designateclient-1.0.0/requirements.txt0000664000175300017540000000016312234457733022624 0ustar jenkinsjenkins00000000000000cliff>=1.4.3 jsonschema>=1.3.0,!=1.4.0 pbr>=0.5.21,<1.0 python-keystoneclient>=0.3.2 requests>=1.1 stevedore>=0.10 python-designateclient-1.0.0/tox.ini0000664000175300017540000000142312234457733020653 0ustar jenkinsjenkins00000000000000[tox] envlist = py26,py27,flake8 minversion = 1.6 [testenv] sitepackages = False install_command = pip install {opts} {packages} setenv = VIRTUAL_ENV={envdir} LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=C deps = -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt commands = python setup.py testr --testr-args='{posargs}' [tox:jenkins] downloadcache = ~/cache/pip [testenv:flake8] commands = flake8 [testenv:pep8] commands = flake8 [testenv:pyflakes] commands = flake8 [testenv:cover] commands = python setup.py testr --coverage --testr-args='{posargs}' [testenv:venv] commands = {posargs} [flake8] ignore = H302,H306,H401,H402,H404 builtins = _ exclude = .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,tools python-designateclient-1.0.0/PKG-INFO0000664000175300017540000000142412234460017020423 0ustar jenkinsjenkins00000000000000Metadata-Version: 1.1 Name: python-designateclient Version: 1.0.0 Summary: DNS as a Service - Client Home-page: https://launchpad.net/python-designateclientclient Author: Kiall Mac Innes Author-email: kiall@managedit.ie License: UNKNOWN Description: Platform: UNKNOWN Classifier: Environment :: OpenStack Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 2.6 Classifier: Topic :: Internet :: Name Service (DNS) python-designateclient-1.0.0/bin/0000775000175300017540000000000012234460017020075 5ustar jenkinsjenkins00000000000000python-designateclient-1.0.0/bin/designate0000775000175300017540000000140012234457733021774 0ustar jenkinsjenkins00000000000000#!/usr/bin/env python # Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import sys from designateclient.shell import DesignateShell shell = DesignateShell() sys.exit(shell.run(sys.argv[1:])) python-designateclient-1.0.0/doc/0000775000175300017540000000000012234460017020072 5ustar jenkinsjenkins00000000000000python-designateclient-1.0.0/doc/requirements.txt0000664000175300017540000000010112234457733023361 0ustar jenkinsjenkins00000000000000sphinx>=1.1.2 -r ../requirements.txt -r ../test-requirements.txt python-designateclient-1.0.0/doc/source/0000775000175300017540000000000012234460017021372 5ustar jenkinsjenkins00000000000000python-designateclient-1.0.0/doc/source/shell-examples.rst0000664000175300017540000000405112234457733025062 0ustar jenkinsjenkins00000000000000====================================== designate command line tool - examples ====================================== Using the client against your dev environment --------------------------------------------- Typically the designate client talks to Keystone (or a Keystone like service) via the OS_AUTH_URL setting & retrives the designate endpoint from the returned service catalog. Using ``--os-endpoint`` or ``OS_ENDPOINT`` you can specify the end point directly, this is useful if you want to point the client at a test environment that's running without a full Keystone service. .. code-block:: shell-session $ designate --os-endpoint http://127.0.0.1:9001/v1 server-create --name ns.foo.com. +------------+--------------------------------------+ | Field | Value | +------------+--------------------------------------+ | created_at | 2013-07-09T13:20:23.664811 | | id | 1af2d561-b802-44d7-8208-46475dcd45f9 | | name | ns.foo.com. | | updated_at | None | +------------+--------------------------------------+ $ designate --os-endpoint http://127.0.0.1:9001/v1 domain-create --name testing123.net. --email simon@mccartney.ie +------------+--------------------------------------+ | Field | Value | +------------+--------------------------------------+ | name | testing123.net. | | created_at | 2013-07-09T13:20:30.826155 | | updated_at | None | | id | 5c02c519-4928-4a38-bd10-c748c200912f | | ttl | 3600 | | serial | 1373376030 | | email | simon@mccartney.ie | +------------+--------------------------------------+ $ designate --os-endpoint http://127.0.0.1:9001/v1 record-create --name myhost.testing123.net. --type A --data 1.2.3.4 5c02c519-4928-4a38-bd10-c748c200912f python-designateclient-1.0.0/doc/source/contributing.rst0000664000175300017540000000141112234457733024643 0ustar jenkinsjenkins00000000000000Contributing ============ Code is hosted `on GitHub`_. Submit bugs to the Designate project on `Launchpad`_. Submit code to the stackforge/python-designateclient project using `Gerrit`_. .. _on GitHub: https://github.com/stackforge/python-designateclient .. _Launchpad: https://launchpad.net/designate .. _Gerrit: http://wiki.openstack.org/GerritWorkflow Here's a quick summary: Install the git-review package to make life easier .. code-block:: shell-session pip install git-review Branch, work, & submit: .. code-block:: shell-session # cut a new branch, tracking master git checkout --track -b bug/id origin/master # work work work git add stuff git commit # rebase/squash to a single commit before submitting git rebase -i # submit git-review python-designateclient-1.0.0/doc/source/conf.py0000664000175300017540000001734612234457733022717 0ustar jenkinsjenkins00000000000000# -*- coding: utf-8 -*- # # designateclient documentation build configuration file, created by # sphinx-quickstart on Wed Oct 31 18:58:17 2012. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'designateclient' copyright = u'2012, Managed I.T.' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. from designateclient.version import version_info as designateclient_version version = designateclient_version.canonical_version_string() # The full version, including alpha/beta/rc tags. release = designateclient_version.version_string_with_vcs() # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'designateclientdoc' # -- Options for LaTeX output -------------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'designateclient.tex', u'Designate Client Documentation', u'Managed I.T.', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). #man_pages = [] # If true, show URL addresses after external links. #man_show_urls = False # -- Options for Texinfo output ------------------------------------------------ # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'designateclient', u'Designate Client Documentation', u'Managed I.T.', 'designateclient', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. #texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' python-designateclient-1.0.0/doc/source/index.rst0000664000175300017540000000127312234457733023251 0ustar jenkinsjenkins00000000000000====================== python-designateclient ====================== This is a client for Designate API. There's a :doc:`Python API ` (the :program:`designateclient` module), and a :doc:`command-line tool ` (installed as :program:`designate`). You'll need credentials for an OpenStack cloud that is implementing the Designate API , such as HP's `Cloud DNS`_, in order to use the designate client. Contents ====================== .. toctree:: :maxdepth: 1 installation bindings shell shell-examples contributing Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` .. _Cloud DNS: http://www.hpcloud.com/products-services/dns python-designateclient-1.0.0/doc/source/installation.rst0000664000175300017540000000272212234457733024643 0ustar jenkinsjenkins00000000000000============ Installation ============ Install the client from PyPI ---------------------------- The :program:`python-designateclient` package is published on `PyPI`_ and so can be installed using the pip tool, which will manage installing all python dependencies: .. code-block:: shell-session pip install python-designateclient *Warning: the packages on PyPI may lag behind the git repo in functionality.* Setup the client from source ---------------------------- If you want the latest version, straight from github: .. code-block:: shell-session git clone git@github.com:stackforge/python-designateclient.git cd python-designateclient virtualenv .venv . .venv/bin/activate pip install -r requirements.txt -r test-requirements.txt python setup.py install Setup the client in development mode ------------------------------------ Installing in development mode allows your to make changes to the source code & test directly without having to re-run the "python setup.py install" step. You can find out more about `Development Mode`_ .. code-block:: shell-session git clone git@github.com:stackforge/python-designateclient.git cd python-designateclient virtualenv .venv . .venv/bin/activate pip install -r requirements.txt -r test-requirements.txt python setup.py develop .. _Development Mode: http://pythonhosted.org/distribute/setuptools.html#development-mode .. _PyPI: https://pypi.python.org/pypi/python-designateclient/ python-designateclient-1.0.0/doc/source/shell.rst0000664000175300017540000002142512234457733023252 0ustar jenkinsjenkins00000000000000=========================== designate command line tool =========================== The python-designateclient package comes with a command line tool (installed as :program:`designate`), this can be used to access a Designate API without having to manipulate JSON by hand, it can also produce the output in a variety of formats (JSON, CSV) and allow you to select columns to be displayed. Credentials ----------- As with any OpenStack utility, :program:`designate` requires certain information to talk to the REST API, username, password, auth url (from where the other required endpoints are retrieved once you are authenticated). To provide your access credentials (username, password, tenant name or tenant id) you can pass them on the command line with the ``--os-username``, ``--os-password``, ``--os-tenant-name`` or ``--os-tenant-id`` params, but it's easier to just set them as environment variables:: export OS_USERNAME=openstack export OS_PASSWORD=yadayada export OS_TENANT_NAME=myproject export OS_TENANT_ID=123456789 You will also need to define the authentication url with ``--os-auth-url`` or set is as an environment variable as well:: export OS_AUTH_URL=https://example.com:5000/v2.0/ Since Keystone can return multiple regions in the Service Catalog, you can specify the one you want with ``--os-region-name`` (or ``export OS_REGION_NAME``). It defaults to the first in the list returned. Using the command line tool --------------------------- With enough details now in environment, you can use the designate client to create a domain & populate it with some records: .. code-block:: shell-session $ designate domain-create --name doctestdomain.eu. --email admin@doctestdomain.eu +-------------+--------------------------------------+ | Field | Value | +-------------+--------------------------------------+ | description | None | | created_at | 2013-09-19T11:45:25.295355 | | updated_at | None | | email | admin@doctestdomain.eu | | ttl | 3600 | | serial | 1379591125 | | id | eacbe2a5-95f1-4a9f-89f5-b9c58009b163 | | name | doctestdomain.eu. | +-------------+--------------------------------------+ You can see more details on the arguments domain-create accepts at the `REST API create-domain`_. Now that the domain has been created, we can start adding records. You'll note that the name (www.doctestdomain.eu) has a trailing ``.``, as per the DNS standard, we didn't set a TTL and we had to specify the parent zone/domain by domain_id ``eacbe2a5-95f1-4a9f-89f5-b9c58009b163``. .. code-block:: shell-session $ designate record-create eacbe2a5-95f1-4a9f-89f5-b9c58009b163 --name www.doctestdomain.eu. --type A --data 1.2.3.4 +-------------+--------------------------------------+ | Field | Value | +-------------+--------------------------------------+ | name | www.doctestdomain.eu. | | data | 1.2.3.4 | | created_at | 2013-09-19T13:44:42.295428 | | updated_at | None | | id | 147f6082-8466-4951-8d13-37a10e92b11e | | priority | None | | ttl | None | | type | A | | domain_id | eacbe2a5-95f1-4a9f-89f5-b9c58009b163 | | description | None | +-------------+--------------------------------------+ subcommands ----------- We've already seen the ``domain-create`` and ``record-create`` subcommands, here the full list of subcommands: ======================= ====================================================== =============== subcommand Notes Admin Required ======================= ====================================================== =============== diagnostics-ping Ping a service on a given host diagnostics-sync-all Sync Everything diagnostics-sync-domain Sync a single Domain diagnostics-sync-record Sync a single Record domain-create Create Domain domain-delete Delete Domain domain-get Get Domain domain-list List Domains domain-servers-list List Domain Servers domain-update Update Domain help print detailed help for another command record-create Create Record record-delete Delete Record record-get Get Record record-list List Records record-update Update Record report-count-all Get count totals for all tenants, domains and records report-count-domains Get counts for total domains report-count-records Get counts for total records report-count-tenants Get counts for total tenants report-tenant-domains Get a list of domains for given tenant report-tenants-all Get list of tenants and domain count for each server-create Create Server server-delete Delete Server server-get Get Server server-list List Servers server-update Update Server ======================= ====================================================== =============== Builtin designate documentation ------------------------------- You'll find complete documentation on the shell by running ``designate --help``:: usage: designate [--version] [-v] [--log-file LOG_FILE] [-q] [-h] [--debug] [--os-endpoint OS_ENDPOINT] [--os-auth-url OS_AUTH_URL] [--os-username OS_USERNAME] [--os-password OS_PASSWORD] [--os-tenant-id OS_TENANT_ID] [--os-tenant-name OS_TENANT_NAME] [--os-token OS_TOKEN] [--os-service-type OS_SERVICE_TYPE] [--os-region-name OS_REGION_NAME] [--sudo-tenant-id SUDO_TENANT_ID] [--insecure] Designate Client optional arguments: --version show program's version number and exit -v, --verbose Increase verbosity of output. Can be repeated. --log-file LOG_FILE Specify a file to log output. Disabled by default. -q, --quiet suppress output except warnings and errors -h, --help show this help message and exit --debug show tracebacks on errors --os-endpoint OS_ENDPOINT Defaults to env[OS_DNS_ENDPOINT] --os-auth-url OS_AUTH_URL Defaults to env[OS_AUTH_URL] --os-username OS_USERNAME Defaults to env[OS_USERNAME] --os-password OS_PASSWORD Defaults to env[OS_PASSWORD] --os-tenant-id OS_TENANT_ID Defaults to env[OS_TENANT_ID] --os-tenant-name OS_TENANT_NAME Defaults to env[OS_TENANT_NAME] --os-token OS_TOKEN Defaults to env[OS_SERVICE_TOKEN] --os-service-type OS_SERVICE_TYPE Defaults to env[OS_DNS_SERVICE_TYPE], or 'dns' --os-region-name OS_REGION_NAME Defaults to env[OS_REGION_NAME] --sudo-tenant-id SUDO_TENANT_ID Defaults to env[DESIGNATE_SUDO_TENANT_ID] --insecure Explicitly allow 'insecure' SSL requests Commands: diagnostics-ping Ping a service on a given host diagnostics-sync-all Sync Everything diagnostics-sync-domain Sync a single Domain diagnostics-sync-record Sync a single Record domain-create Create Domain domain-delete Delete Domain domain-get Get Domain domain-list List Domains domain-servers-list List Domain Servers domain-update Update Domain help print detailed help for another command record-create Create Record record-delete Delete Record record-get Get Record record-list List Records record-update Update Record report-count-all Get count totals for all tenants, domains and records report-count-domains Get counts for total domains report-count-records Get counts for total records report-count-tenants Get counts for total tenants report-tenant-domains Get a list of domains for given tenant report-tenants-all Get list of tenants and domain count for each server-create Create Server server-delete Delete Server server-get Get Server server-list List Servers server-update Update Server .. _REST API create-domain: https://designate.readthedocs.org/en/latest/rest/domains.html#create-domain python-designateclient-1.0.0/doc/source/bindings.rst0000664000175300017540000002577712234457733023756 0ustar jenkinsjenkins00000000000000=============== Python Bindings =============== The python-designateclient package comes with python bindings for the Designate API. This can be used to interact with the Designate API from any python program. Introduction ============ Below is a simple example of how to instantiate and perform basic tasks using the bindings. .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client, providing the necessary credentials client = Client( auth_url="https://example.com:5000/v2.0/", username="openstack", password="yadayada", tenant_id="123456789" ) # Fetch a list of the domains this user/tenant has access to domains = client.domains.list() # Iterate the list, printing some useful information for domain in domains: print "Domain ID: %s, Name: %s" % (domain.id, domain.name) And the output this program might produce: .. code-block:: console $ python /tmp/example.py Domain ID: 467f97b4-f074-4839-ae85-1a61fccfb83d, Name: example-one.com. Domain ID: 6d3bf479-8a93-47ae-8c65-3dff8dba1b0d, Name: example-two.com. Authentication ============== Designate supports either Keystone authentication, or no authentication at all. Keystone Authentication ----------------------- Below is a sample of standard authentication with keystone: .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client, providing the necessary credentials client = Client( auth_url="https://example.com:5000/v2.0/", username="openstack", password="yadayada", tenant_id="123456789" ) Below is a sample of standard authentication with keystone, but also explicitly providing the endpoint to use: .. note:: This is useful when a development Designate instances authenticates against a production Keystone. .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client, providing the necessary credentials client = Client( auth_url="https://example.com:5000/v2.0/", username="openstack", password="yadayada", tenant_id="123456789", endpoint="https://127.0.0.1:9001/v1/" ) No Authentication ----------------- Below is a sample of interaction with a non authenticated designate: .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client, providing the endpoint directly client = Client( endpoint="https://127.0.0.1:9001/v1/" ) Working with Domains ==================== The Domain Object ----------------- Object Properties: ======================= ======================================================= Property Description ======================= ======================================================= id Domain ID name Domain Name (e.g. example.com.) email Domain Responsible Person Email (e.g. fred@example.com) ttl Default TTL for records serial Domain Server Number created_at Date and time this domain was created at updated_at Date and time this domain was last updated description Domain Description ======================= ======================================================= Listing Domains --------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) # List All Domains domains = client.domains.list() Fetching a Domain by ID ----------------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) domain_id = 'fb505f10-25df-11e3-8224-0800200c9a66' # Fetch the domain domain = client.domains.get(domain_id) Creating a Domain ----------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client from designateclient.v1.domains import Domain # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) # Create a new Domain object domain = Domain(name="example.com.", email="fred@example.com") # Send the Create Domain API call domain = client.domains.create(domain) Updating a Domain ----------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) domain_id = 'fb505f10-25df-11e3-8224-0800200c9a66' # Fetch the domain domain = client.domains.get(domain_id) # Update a value on the Domain domain.ttl = 300 # Send the Update Domain API call domain = client.domains.update(domain) Deleting a Domain ----------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) domain_id = 'fb505f10-25df-11e3-8224-0800200c9a66' # Fetch the domain domains = client.domains.delete(domain_id) Working with Records ==================== The Record Object ----------------- Object Properties: ======================= ======================================================= Property Description ======================= ======================================================= id Record ID domain_id Domain ID name Record Name (e.g. example.com.) type Record Type (e.g. A, AAAA, CNAME, MX, SRV etc) data Record Data (e.g. 127.0.0.1) priority Rercord Priority (Valid only for MX and SRV records) ttl Record TTL created_at Date and time this record was created at updated_at Date and time this record was last updated description Record Description ======================= ======================================================= Listing Records --------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) domain_id = 'fb505f10-25df-11e3-8224-0800200c9a66' # List All Records records = client.records.list(domain_id) Fetching a Record by ID ----------------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) domain_id = 'fb505f10-25df-11e3-8224-0800200c9a66' record_id = 'bd3e8520-25e0-11e3-8224-0800200c9a66' # Fetch the record records = client.records.get(domain_id, record_id) Creating a Record ----------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client from designateclient.v1.records import Record # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) domain_id = 'fb505f10-25df-11e3-8224-0800200c9a66' # Create a new Record object record = Record(name="www.example.com.", type="A", content="127.0.0.1") # Send the Create Record API call record = client.records.create(domain_id, record) Updating a Record ----------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) domain_id = 'fb505f10-25df-11e3-8224-0800200c9a66' record_id = 'bd3e8520-25e0-11e3-8224-0800200c9a66' # Fetch the record record = client.records.get(record_id) # Update a value on the Record record.ttl = 300 # Send the Update Record API call record = client.records.update(domain_id, record) Deleting a Record ----------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) domain_id = 'fb505f10-25df-11e3-8224-0800200c9a66' record_id = 'bd3e8520-25e0-11e3-8224-0800200c9a66' # Fetch the record records = client.records.delete(domain_id, record_id) Working with Servers ==================== The Server Object ----------------- Object Properties: ======================= ======================================================= Property Description ======================= ======================================================= id Server ID name Server Name (e.g. example.com.) created_at Date and time this server was created at updated_at Date and time this server was last updated ======================= ======================================================= Listing Servers --------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) # List All Servers servers = client.servers.list() Fetching a Server by ID ----------------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) server_id = 'fb505f10-25df-11e3-8224-0800200c9a66' # Fetch the server server = client.servers.get(server_id) Creating a Server ----------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client from designateclient.v1.servers import Server # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) # Create a new Server object server = Server(name="ns1.example.com.") # Send the Create Server API call server = client.servers.create(server) Updating a Server ----------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) server_id = 'fb505f10-25df-11e3-8224-0800200c9a66' # Fetch the server server = client.servers.get(server_id) # Update a value on the Server server.name = "ns2.example.com" # Send the Update Server API call server = client.servers.update(server) Deleting a Server ----------------- .. code-block:: python #!/usr/bin/env python from designateclient.v1 import Client # Create an instance of the client client = Client( endpoint="https://127.0.0.1:9001/v1/" ) server_id = 'fb505f10-25df-11e3-8224-0800200c9a66' # Fetch the server servers = client.servers.delete(server_id) python-designateclient-1.0.0/MANIFEST.in0000664000175300017540000000041312234457733021074 0ustar jenkinsjenkins00000000000000include AUTHORS include ChangeLog include designateclient/versioninfo include *.txt *.ini *.cfg *.rst *.md recursive-include designateclient/resources * recursive-include tools * exclude .gitignore exclude .gitreview exclude *.sublime-project global-exclude *.pyc python-designateclient-1.0.0/setup.cfg0000664000175300017540000000640212234460017021150 0ustar jenkinsjenkins00000000000000[metadata] name = python-designateclient summary = DNS as a Service - Client description-file = README.rst author = Kiall Mac Innes author-email = kiall@managedit.ie home-page = https://launchpad.net/python-designateclientclient classifier = Environment :: OpenStack Intended Audience :: Information Technology Intended Audience :: System Administrators License :: OSI Approved :: Apache Software License Operating System :: POSIX :: Linux Programming Language :: Python Programming Language :: Python :: 2 Programming Language :: Python :: 2.7 Programming Language :: Python :: 2.6 Topic :: Internet :: Name Service (DNS) [global] setup-hooks = pbr.hooks.setup_hook [files] packages = designateclient scripts = bin/designate [entry_points] designateclient.v1.controllers = reports = designateclient.v1.reports:ReportsController diagnostics = designateclient.v1.diagnostics:DiagnosticsController domains = designateclient.v1.domains:DomainsController records = designateclient.v1.records:RecordsController servers = designateclient.v1.servers:ServersController designateclient.cli = domain-list = designateclient.cli.domains:ListDomainsCommand domain-get = designateclient.cli.domains:GetDomainCommand domain-create = designateclient.cli.domains:CreateDomainCommand domain-update = designateclient.cli.domains:UpdateDomainCommand domain-delete = designateclient.cli.domains:DeleteDomainCommand domain-servers-list = designateclient.cli.domains:ListDomainServersCommand record-list = designateclient.cli.records:ListRecordsCommand record-get = designateclient.cli.records:GetRecordCommand record-create = designateclient.cli.records:CreateRecordCommand record-update = designateclient.cli.records:UpdateRecordCommand record-delete = designateclient.cli.records:DeleteRecordCommand server-list = designateclient.cli.servers:ListServersCommand server-get = designateclient.cli.servers:GetServerCommand server-create = designateclient.cli.servers:CreateServerCommand server-update = designateclient.cli.servers:UpdateServerCommand server-delete = designateclient.cli.servers:DeleteServerCommand diagnostics-ping = designateclient.cli.diagnostics:PingCommand diagnostics-sync-all = designateclient.cli.diagnostics:SyncAllCommand diagnostics-sync-domain = designateclient.cli.diagnostics:SyncDomainCommand diagnostics-sync-record = designateclient.cli.diagnostics:SyncRecordCommand report-count-all = designateclient.cli.reports:CountsCommand report-count-domains = designateclient.cli.reports:DomainCountCommand report-count-records = designateclient.cli.reports:RecordCountCommand report-count-tenants = designateclient.cli.reports:TenantCountCommand report-tenants-all = designateclient.cli.reports:TenantsCommand report-tenant-domains = designateclient.cli.reports:TenantCommand [build_sphinx] all_files = 1 build-dir = doc/build source-dir = doc/source [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 [compile_catalog] directory = designateclient/locale domain = designateclient [update_catalog] domain = designateclient output_dir = designateclient/locale input_file = designateclient/locale/designateclient.pot [extract_messages] keywords = _ gettext ngettext l_ lazy_gettext mapping_file = babel.cfg output_file = designateclient/locale/designateclient.pot python-designateclient-1.0.0/designateclient/0000775000175300017540000000000012234460017022467 5ustar jenkinsjenkins00000000000000python-designateclient-1.0.0/designateclient/resources/0000775000175300017540000000000012234460017024501 5ustar jenkinsjenkins00000000000000python-designateclient-1.0.0/designateclient/resources/schemas/0000775000175300017540000000000012234460017026124 5ustar jenkinsjenkins00000000000000python-designateclient-1.0.0/designateclient/resources/schemas/v1/0000775000175300017540000000000012234460017026452 5ustar jenkinsjenkins00000000000000python-designateclient-1.0.0/designateclient/resources/schemas/v1/domain.json0000664000175300017540000000405512234457733030633 0ustar jenkinsjenkins00000000000000{ "id": "domain", "$schema": "http://json-schema.org/draft-03/hyper-schema", "title": "domain", "description": "Domain", "additionalProperties": false, "properties": { "id": { "type": "string", "description": "Domain Identifier", "pattern": "^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$", "readonly": true }, "name": { "type": "string", "description": "Domain name", "format": "domain-name", "maxLength": 255, "required": true, "readonly": true }, "email": { "type": "string", "description": "Hostmaster email address", "format": "email", "maxLength": 255, "required": true }, "ttl": { "type": "integer", "description": "Time to live", "minimum": 0, "maximum": 2147483647 }, "serial": { "type": "integer", "description": "Serial Number", "minimum": 1, "maximum": 4294967295, "readonly": true }, "description": { "type": ["string", "null"], "description": "Description for the Domain", "maxLength": 160 }, "created_at": { "type": "string", "description": "Date and time of domain creation", "format": "date-time", "readonly": true }, "updated_at": { "type": ["string", "null"], "description": "Date and time of last domain update", "format": "date-time", "readonly": true } }, "links": [{ "rel": "self", "href": "/domains/{id}" }, { "rel": "records", "href": "/domains/{id}/records" }, { "rel": "servers", "href": "/domains/{id}/servers" }, { "rel": "collection", "href": "/domains" }] } python-designateclient-1.0.0/designateclient/resources/schemas/v1/server.json0000664000175300017540000000224612234457733030672 0ustar jenkinsjenkins00000000000000{ "id": "server", "$schema": "http://json-schema.org/draft-03/hyper-schema", "title": "server", "description": "Server", "additionalProperties": false, "properties": { "id": { "type": "string", "description": "Server Identifier", "pattern": "^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$", "readonly": true }, "name": { "type": "string", "description": "Server DNS name", "format": "host-name", "maxLength": 255, "required": true }, "created_at": { "type": "string", "description": "Date and time of server creation", "format": "date-time", "readonly": true }, "updated_at": { "type": ["string", "null"], "description": "Date and time of last server update", "format": "date-time", "readonly": true } }, "links": [{ "rel": "self", "href": "/servers/{id}" }, { "rel": "collection", "href": "/servers" }] } python-designateclient-1.0.0/designateclient/resources/schemas/v1/record.json0000664000175300017540000001447612234457733030652 0ustar jenkinsjenkins00000000000000{ "id": "record", "$schema": "http://json-schema.org/draft-03/hyper-schema", "title": "record", "description": "Record", "additionalProperties": false, "properties": { "id": { "type": "string", "description": "Record Identifier", "pattern": "^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$", "readonly": true }, "domain_id": { "type": "string", "description": "Domain Identifier", "pattern": "^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$", "readonly": true }, "name": { "type": "string", "description": "DNS Record Name", "format": "host-name", "maxLength": 255, "required": true }, "type": { "type": "string", "description": "DNS Record Type", "enum": ["A", "AAAA", "CNAME", "MX", "SRV", "TXT", "SPF", "NS", "PTR", "SSHFP"], "required": true }, "data": { "type": "string", "description": "DNS Record Value", "maxLength": 255, "required": true }, "priority": { "type": ["integer", "null"], "description": "DNS Record Priority", "minimum": 1, "maximum": 65535 }, "ttl": { "type": ["integer", "null"], "description": "Time to live", "minimum": 0, "maximum": 2147483647 }, "description": { "type": ["string", "null"], "description": "Description for the record", "maxLength": 160 }, "created_at": { "type": "string", "description": "Date and time of record creation", "format": "date-time", "readonly": true }, "updated_at": { "type": ["string", "null"], "description": "Date and time of last record update", "format": "date-time", "readonly": true } }, "oneOf": [{ "description": "An A Record", "properties": { "type": { "type": "string", "enum": ["A"] }, "data": { "format": "ip-address", "required": true }, "priority": { "type": "null" } } }, { "description": "An AAAA Record", "properties": { "type": { "type": "string", "enum": ["AAAA"] }, "data": { "format": "ipv6", "required": true }, "priority": { "type": "null" } } }, { "description": "A CNAME Record", "properties": { "type": { "type": "string", "enum": ["CNAME"] }, "data": { "format": "host-name", "required": true }, "priority": { "type": "null" } } }, { "description": "A MX Record", "properties": { "type": { "type": "string", "enum": ["MX"] }, "data": { "format": "host-name", "required": true }, "priority": { "type": "integer", "required": true } } }, { "description": "A SRV Record", "properties": { "type": { "type": "string", "enum": ["SRV"] }, "name": { "type": "string", "pattern": "^(?:_[A-Za-z0-9_\\-]{1,62}\\.){2}" }, "data": { "type": "string", "pattern": "^(?:(?:6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[1-5][0-9]{4}|[1-9][0-9]{1,3}|[0-9])\\s){2}(?!.{255,})((?!\\-)[A-Za-z0-9_\\-]{1,63}(? # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. class Base(Exception): pass class ResourceNotFound(Base): pass class RemoteError(Base): def __init__(self, message=None, code=None, type=None, errors=None, request_id=None): super(RemoteError, self).__init__(message) self.message = message self.code = code self.type = type self.errors = errors self.request_id = request_id class Unknown(RemoteError): pass class BadRequest(RemoteError): pass class Forbidden(RemoteError): pass class Conflict(RemoteError): pass class NotFound(RemoteError): pass python-designateclient-1.0.0/designateclient/__init__.py0000664000175300017540000000000012234457733024601 0ustar jenkinsjenkins00000000000000python-designateclient-1.0.0/designateclient/warlock.py0000664000175300017540000000747212234457733024530 0ustar jenkinsjenkins00000000000000# Copyright 2012 Brian Waldon # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # # Code copied from Warlock, as warlock depends on jsonschema==0.2 # Hopefully we can upstream the changes ASAP. # import copy import logging import jsonschema LOG = logging.getLogger(__name__) class InvalidOperation(RuntimeError): pass class ValidationError(ValueError): pass def model_factory(schema): """Generate a model class based on the provided JSON Schema :param schema: dict representing valid JSON schema """ schema = copy.deepcopy(schema) def validator(obj): """Apply a JSON schema to an object""" try: jsonschema.validate(obj, schema, cls=jsonschema.Draft3Validator) except jsonschema.ValidationError as e: raise ValidationError(str(e)) class Model(dict): """Self-validating model for arbitrary objects""" def __init__(self, *args, **kwargs): d = dict(*args, **kwargs) # we overload setattr so set this manually self.__dict__['validator'] = validator try: self.validator(d) except ValidationError as e: raise ValueError('Validation Error: %s' % str(e)) else: dict.__init__(self, d) self.__dict__['changes'] = {} def __getattr__(self, key): try: return self.__getitem__(key) except KeyError: raise AttributeError(key) def __setitem__(self, key, value): mutation = dict(self.items()) mutation[key] = value try: self.validator(mutation) except ValidationError as e: raise InvalidOperation(str(e)) dict.__setitem__(self, key, value) self.__dict__['changes'][key] = value def __setattr__(self, key, value): self.__setitem__(key, value) def clear(self): raise InvalidOperation() def pop(self, key, default=None): raise InvalidOperation() def popitem(self): raise InvalidOperation() def __delitem__(self, key): raise InvalidOperation() # NOTE(termie): This is kind of the opposite of what copy usually does def copy(self): return copy.deepcopy(dict(self)) def update(self, other): # NOTE(kiall): It seems update() doesn't update the # self.__dict__['changes'] dict correctly. mutation = dict(self.items()) mutation.update(other) try: self.validator(mutation) except ValidationError as e: raise InvalidOperation(str(e)) dict.update(self, other) def iteritems(self): return copy.deepcopy(dict(self)).iteritems() def items(self): return copy.deepcopy(dict(self)).items() def itervalues(self): return copy.deepcopy(dict(self)).itervalues() def keys(self): return copy.deepcopy(dict(self)).keys() def values(self): return copy.deepcopy(dict(self)).values() @property def changes(self): return copy.deepcopy(self.__dict__['changes']) Model.__name__ = str(schema['title']) return Model python-designateclient-1.0.0/designateclient/utils.py0000664000175300017540000000543412234457733024222 0ustar jenkinsjenkins00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import os import pkg_resources import json from designateclient import exceptions def resource_string(*args, **kwargs): if len(args) == 0: raise ValueError() package = kwargs.pop('package', None) if not package: package = 'designateclient' resource_path = os.path.join('resources', *args) if not pkg_resources.resource_exists(package, resource_path): raise exceptions.ResourceNotFound('Could not find the requested ' 'resource: %s' % resource_path) return pkg_resources.resource_string(package, resource_path) def load_schema(version, name, package=None): schema_string = resource_string('schemas', version, '%s.json' % name, package=package) return json.loads(schema_string) def get_item_properties(item, fields, mixed_case_fields=[], formatters={}): """Return a tuple containing the item properties. :param item: a single item resource (e.g. Server, Tenant, etc) :param fields: tuple of strings with the desired field names :param mixed_case_fields: tuple of field names to preserve case :param formatters: dictionary mapping field names to callables to format the values """ row = [] for field in fields: if field in formatters: row.append(formatters[field](item)) else: if field in mixed_case_fields: field_name = field.replace(' ', '_') else: field_name = field.lower().replace(' ', '_') if not hasattr(item, field_name) and \ (isinstance(item, dict) and field_name in item): data = item[field_name] else: data = getattr(item, field_name, '') if data is None: data = '' row.append(data) return tuple(row) def get_columns(data): """ Some row's might have variable count of columns, ensure that we have the same. :param data: Results in [{}, {]}] """ columns = set() def _seen(col): columns.add(str(col)) map(lambda item: map(_seen, item.keys()), data) return list(columns) python-designateclient-1.0.0/designateclient/cli/0000775000175300017540000000000012234460017023236 5ustar jenkinsjenkins00000000000000python-designateclient-1.0.0/designateclient/cli/domains.py0000664000175300017540000001013612234457733025256 0ustar jenkinsjenkins00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import logging from designateclient.cli import base from designateclient.v1.domains import Domain LOG = logging.getLogger(__name__) class ListDomainsCommand(base.ListCommand): """ List Domains """ columns = ['id', 'name', 'serial'] def execute(self, parsed_args): return self.client.domains.list() class GetDomainCommand(base.GetCommand): """ Get Domain """ def get_parser(self, prog_name): parser = super(GetDomainCommand, self).get_parser(prog_name) parser.add_argument('id', help="Domain ID") return parser def execute(self, parsed_args): return self.client.domains.get(parsed_args.id) class CreateDomainCommand(base.CreateCommand): """ Create Domain """ def get_parser(self, prog_name): parser = super(CreateDomainCommand, self).get_parser(prog_name) parser.add_argument('--name', help="Domain Name", required=True) parser.add_argument('--email', help="Domain Email", required=True) parser.add_argument('--ttl', type=int, help="Time To Live (Seconds)") parser.add_argument('--description', help="Description") return parser def execute(self, parsed_args): domain = Domain( name=parsed_args.name, email=parsed_args.email, ) if parsed_args.description: domain.description = parsed_args.description if parsed_args.ttl: domain.ttl = parsed_args.ttl return self.client.domains.create(domain) class UpdateDomainCommand(base.UpdateCommand): """ Update Domain """ def get_parser(self, prog_name): parser = super(UpdateDomainCommand, self).get_parser(prog_name) parser.add_argument('id', help="Domain ID") parser.add_argument('--name', help="Domain Name") parser.add_argument('--email', help="Domain Email") parser.add_argument('--ttl', type=int, help="Time To Live (Seconds)") description_group = parser.add_mutually_exclusive_group() description_group.add_argument('--description', help="Description") description_group.add_argument('--no-description', action='store_true') return parser def execute(self, parsed_args): # TODO(kiall): API needs updating.. this get is silly domain = self.client.domains.get(parsed_args.id) if parsed_args.name: domain.name = parsed_args.name if parsed_args.email: domain.email = parsed_args.email if parsed_args.ttl: domain.ttl = parsed_args.ttl if parsed_args.no_description: domain.description = None elif parsed_args.description: domain.description = parsed_args.description return self.client.domains.update(domain) class DeleteDomainCommand(base.DeleteCommand): """ Delete Domain """ def get_parser(self, prog_name): parser = super(DeleteDomainCommand, self).get_parser(prog_name) parser.add_argument('id', help="Domain ID") return parser def execute(self, parsed_args): return self.client.domains.delete(parsed_args.id) class ListDomainServersCommand(base.ListCommand): """ List Domain Servers """ columns = ['name'] def get_parser(self, prog_name): parser = super(ListDomainServersCommand, self).get_parser(prog_name) parser.add_argument('id', help="Domain ID") return parser def execute(self, parsed_args): return self.client.domains.list_domain_servers(parsed_args.id) python-designateclient-1.0.0/designateclient/cli/__init__.py0000664000175300017540000000000012234457733025350 0ustar jenkinsjenkins00000000000000python-designateclient-1.0.0/designateclient/cli/diagnostics.py0000664000175300017540000000463412234457733026141 0ustar jenkinsjenkins00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import logging from designateclient.cli import base LOG = logging.getLogger(__name__) class PingCommand(base.GetCommand): """ Ping a service on a given host """ def get_parser(self, prog_name): parser = super(PingCommand, self).get_parser(prog_name) parser.add_argument('--service', help="Service Name (e.g. central)", required=True) parser.add_argument('--host', help="Hostname", required=True) return parser def execute(self, parsed_args): return self.client.diagnostics.ping(parsed_args.service, parsed_args.host) class SyncAllCommand(base.Command): """ Sync Everything """ def execute(self, parsed_args): self.client.diagnostics.sync_all() LOG.info('Synchronization of all domains scheduled') class SyncDomainCommand(base.Command): """ Sync a single Domain """ def get_parser(self, prog_name): parser = super(SyncDomainCommand, self).get_parser(prog_name) parser.add_argument('domain_id', help="Domain ID") return parser def execute(self, parsed_args): self.client.diagnostics.sync_domain(parsed_args.domain_id) LOG.info('Synchronization of domain scheduled') class SyncRecordCommand(base.Command): """ Sync a single Record """ def get_parser(self, prog_name): parser = super(SyncRecordCommand, self).get_parser(prog_name) parser.add_argument('domain_id', help="Domain ID") parser.add_argument('record_id', help="Record ID") return parser def execute(self, parsed_args): self.client.diagnostics.sync_record(parsed_args.domain_id, parsed_args.record_id) LOG.info('Synchronization of record scheduled') python-designateclient-1.0.0/designateclient/cli/reports.py0000664000175300017540000000416612234457733025330 0ustar jenkinsjenkins00000000000000# Copyright 2013 Hewlett-Packard Development Company, L.P. All Rights Reserved. # # Author: Patrick Galbraith # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from designateclient.cli import base class DomainCountCommand(base.GetCommand): """ Get counts for total domains """ def execute(self, parsed_args): return self.client.reports.count_domains() class RecordCountCommand(base.GetCommand): """ Get counts for total records """ def execute(self, parsed_args): return self.client.reports.count_records() class TenantCountCommand(base.GetCommand): """ Get counts for total tenants """ def execute(self, parsed_args): return self.client.reports.count_tenants() class CountsCommand(base.GetCommand): """ Get count totals for all tenants, domains and records """ def execute(self, parsed_args): return self.client.reports.count_all() class TenantsCommand(base.ListCommand): """ Get list of tenants and domain count for each """ columns = ['domain_count', 'id'] def execute(self, parsed_args): return self.client.reports.tenants_all() class TenantCommand(base.ListCommand): """ Get a list of domains for given tenant """ columns = ['domain'] def get_parser(self, prog_name): parser = super(TenantCommand, self).get_parser(prog_name) parser.add_argument('--report-tenant-id', help="tenant_id being reported on", required=True) return parser def execute(self, parsed_args): return self.client.reports.tenant_domains(parsed_args.report_tenant_id) python-designateclient-1.0.0/designateclient/cli/servers.py0000664000175300017540000000516312234457733025321 0ustar jenkinsjenkins00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import logging from designateclient.cli import base from designateclient.v1.servers import Server LOG = logging.getLogger(__name__) class ListServersCommand(base.ListCommand): """ List Servers """ columns = ['id', 'name'] def execute(self, parsed_args): return self.client.servers.list() class GetServerCommand(base.GetCommand): """ Get Server """ def get_parser(self, prog_name): parser = super(GetServerCommand, self).get_parser(prog_name) parser.add_argument('id', help="Server ID") return parser def execute(self, parsed_args): return self.client.servers.get(parsed_args.id) class CreateServerCommand(base.CreateCommand): """ Create Server """ def get_parser(self, prog_name): parser = super(CreateServerCommand, self).get_parser(prog_name) parser.add_argument('--name', help="Server Name", required=True) return parser def execute(self, parsed_args): server = Server( name=parsed_args.name, ) return self.client.servers.create(server) class UpdateServerCommand(base.UpdateCommand): """ Update Server """ def get_parser(self, prog_name): parser = super(UpdateServerCommand, self).get_parser(prog_name) parser.add_argument('id', help="Server ID") parser.add_argument('--name', help="Server Name") return parser def execute(self, parsed_args): # TODO(kiall): API needs updating.. this get is silly server = self.client.servers.get(parsed_args.id) if parsed_args.name: server.name = parsed_args.name return self.client.servers.update(server) class DeleteServerCommand(base.DeleteCommand): """ Delete Server """ def get_parser(self, prog_name): parser = super(DeleteServerCommand, self).get_parser(prog_name) parser.add_argument('id', help="Server ID") return parser def execute(self, parsed_args): return self.client.servers.delete(parsed_args.id) python-designateclient-1.0.0/designateclient/cli/records.py0000664000175300017540000001244212234457733025267 0ustar jenkinsjenkins00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import logging from designateclient.cli import base from designateclient.v1.records import Record LOG = logging.getLogger(__name__) class ListRecordsCommand(base.ListCommand): """ List Records """ columns = ['id', 'type', 'name'] def get_parser(self, prog_name): parser = super(ListRecordsCommand, self).get_parser(prog_name) parser.add_argument('domain_id', help="Domain ID") return parser def execute(self, parsed_args): return self.client.records.list(parsed_args.domain_id) class GetRecordCommand(base.GetCommand): """ Get Record """ def get_parser(self, prog_name): parser = super(GetRecordCommand, self).get_parser(prog_name) parser.add_argument('domain_id', help="Domain ID") parser.add_argument('id', help="Record ID") return parser def execute(self, parsed_args): return self.client.records.get(parsed_args.domain_id, parsed_args.id) class CreateRecordCommand(base.CreateCommand): """ Create Record """ def get_parser(self, prog_name): parser = super(CreateRecordCommand, self).get_parser(prog_name) parser.add_argument('domain_id', help="Domain ID") parser.add_argument('--name', help="Record Name", required=True) parser.add_argument('--type', help="Record Type", required=True) parser.add_argument('--data', help="Record Data", required=True) parser.add_argument('--ttl', type=int, help="Record TTL") parser.add_argument('--priority', type=int, help="Record Priority") parser.add_argument('--description', help="Description") return parser def execute(self, parsed_args): record = Record( name=parsed_args.name, type=parsed_args.type, data=parsed_args.data, ) if parsed_args.ttl: record.ttl = parsed_args.ttl if parsed_args.priority: record.priority = parsed_args.priority if parsed_args.description: record.description = parsed_args.description return self.client.records.create(parsed_args.domain_id, record) class UpdateRecordCommand(base.UpdateCommand): """ Update Record """ def get_parser(self, prog_name): parser = super(UpdateRecordCommand, self).get_parser(prog_name) parser.add_argument('domain_id', help="Domain ID") parser.add_argument('id', help="Record ID") parser.add_argument('--name', help="Record Name") parser.add_argument('--type', help="Record Type") parser.add_argument('--data', help="Record Data") description_group = parser.add_mutually_exclusive_group() description_group.add_argument('--description', help="Description") description_group.add_argument('--no-description', action='store_true') ttl_group = parser.add_mutually_exclusive_group() ttl_group.add_argument('--ttl', type=int, help="Record Time To Live (Seconds)") ttl_group.add_argument('--no-ttl', action='store_true') priotity_group = parser.add_mutually_exclusive_group() priotity_group.add_argument('--priority', type=int, help="Record Priority") priotity_group.add_argument('--no-priority', action='store_true') return parser def execute(self, parsed_args): # TODO(kiall): API needs updating.. this get is silly record = self.client.records.get(parsed_args.domain_id, parsed_args.id) if parsed_args.name: record.name = parsed_args.name if parsed_args.type: record.type = parsed_args.type if parsed_args.data: record.data = parsed_args.data if parsed_args.no_ttl: record.ttl = None elif parsed_args.ttl: record.ttl = parsed_args.ttl if parsed_args.no_priority: record.priority = None elif parsed_args.priority: record.priority = parsed_args.priority if parsed_args.no_description: record.description = None elif parsed_args.description: record.description = parsed_args.description return self.client.records.update(parsed_args.domain_id, record) class DeleteRecordCommand(base.DeleteCommand): """ Delete Record """ def get_parser(self, prog_name): parser = super(DeleteRecordCommand, self).get_parser(prog_name) parser.add_argument('domain_id', help="Domain ID") parser.add_argument('id', help="Record ID") return parser def execute(self, parsed_args): return self.client.records.delete(parsed_args.domain_id, parsed_args.id) python-designateclient-1.0.0/designateclient/cli/base.py0000664000175300017540000001007012234457733024533 0ustar jenkinsjenkins00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import abc from cliff.command import Command as CliffCommand from cliff.lister import Lister from cliff.show import ShowOne from designateclient import exceptions from designateclient import utils from designateclient.v1 import Client class Command(CliffCommand): __metaclass__ = abc.ABCMeta def run(self, parsed_args): client_args = { 'endpoint': self.app.options.os_endpoint, 'auth_url': self.app.options.os_auth_url, 'username': self.app.options.os_username, 'password': self.app.options.os_password, 'tenant_id': self.app.options.os_tenant_id, 'tenant_name': self.app.options.os_tenant_name, 'token': self.app.options.os_token, 'service_type': self.app.options.os_service_type, 'region_name': self.app.options.os_region_name, 'sudo_tenant_id': self.app.options.sudo_tenant_id, 'insecure': self.app.options.insecure } if client_args['endpoint'] is None and client_args['auth_url'] is None: raise ValueError('Either the --os-endpoint or --os-auth-url ' 'argument must be supplied') self.client = Client(**client_args) try: return super(Command, self).run(parsed_args) except exceptions.RemoteError as e: columns = ['Code', 'Type'] values = [e.code, e.type] if e.message: columns.append('Message') values.append(e.message) if e.errors: columns.append('Errors') values.append(e.errors) self.error_output(parsed_args, columns, values) return 1 def error_output(self, parsed_args, column_names, data): self.formatter.emit_one(column_names, data, self.app.stdout, parsed_args) self.app.log.error('The requested action did not complete sucessfully') @abc.abstractmethod def execute(self, parsed_args): """ Execute something, this is since we overload self.take_action() in order to format the data This method __NEEDS__ to be overloaded! :param parsed_args: The parsed args that are given by take_action() """ def post_execute(self, data): """ Format the results locally if needed, by default we just return data :param data: Whatever is returned by self.execute() """ return data def take_action(self, parsed_args): results = self.execute(parsed_args) return self.post_execute(results) class ListCommand(Command, Lister): columns = None def post_execute(self, results): if len(results) > 0: columns = self.columns or utils.get_columns(results) data = [utils.get_item_properties(i, columns) for i in results] return columns, data else: return [], () class GetCommand(Command, ShowOne): def post_execute(self, results): return results.keys(), results.values() class CreateCommand(Command, ShowOne): def post_execute(self, results): return results.keys(), results.values() class UpdateCommand(Command, ShowOne): def post_execute(self, results): return results.keys(), results.values() class DeleteCommand(Command, ShowOne): def post_execute(self, results): return [], [] python-designateclient-1.0.0/designateclient/v1/0000775000175300017540000000000012234460017023015 5ustar jenkinsjenkins00000000000000python-designateclient-1.0.0/designateclient/v1/domains.py0000664000175300017540000000523312234457733025037 0ustar jenkinsjenkins00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import json from designateclient import warlock from designateclient import utils from designateclient.v1.base import CrudController Domain = warlock.model_factory(utils.load_schema('v1', 'domain')) Server = warlock.model_factory(utils.load_schema('v1', 'server')) class DomainsController(CrudController): def list(self): """ Retrieve a list of domains :returns: A list of :class:`Domain`s """ response = self.client.get('/domains') return [Domain(i) for i in response.json()['domains']] def get(self, domain_id): """ Retrieve a domain :param domain_id: Domain Identifier :returns: :class:`Domain` """ response = self.client.get('/domains/%s' % domain_id) return Domain(response.json()) def create(self, domain): """ Create a domain :param domain: A :class:`Domain` to create :returns: :class:`Domain` """ response = self.client.post('/domains', data=json.dumps(domain)) return Domain(response.json()) def update(self, domain): """ Update a domain :param domain: A :class:`Domain` to update :returns: :class:`Domain` """ response = self.client.put('/domains/%s' % domain.id, data=json.dumps(domain.changes)) return Domain(response.json()) def delete(self, domain): """ Delete a domain :param domain: A :class:`Domain`, or Domain Identifier to delete """ if isinstance(domain, Domain): self.client.delete('/domains/%s' % domain.id) else: self.client.delete('/domains/%s' % domain) def list_domain_servers(self, domain_id): """ Retrieve the list of nameservers for a domain :param domain_id: Domain Identifier :returns: A list of :class:`Server`s """ response = self.client.get('/domains/%s/servers' % domain_id) return [Server(i) for i in response.json()['servers']] python-designateclient-1.0.0/designateclient/v1/__init__.py0000664000175300017540000001027412234457733025145 0ustar jenkinsjenkins00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import requests from stevedore import extension from designateclient import exceptions from designateclient.auth import KeystoneAuth class Client(object): """ Client for the Designate v1 API """ def __init__(self, endpoint=None, auth_url=None, username=None, password=None, tenant_id=None, tenant_name=None, token=None, region_name=None, service_type='dns', endpoint_type='publicURL', sudo_tenant_id=None, insecure=False): """ :param endpoint: Endpoint URL :param auth_url: Keystone auth_url :param username: The username to auth with :param password: The password to auth with :param tenant_id: The tenant ID :param tenant_name: The tenant name :param token: A token instead of username / password :param region_name: The region name :param endpoint_type: The endpoint type (publicURL for example) :param insecure: Allow "insecure" HTTPS requests """ if auth_url: auth = KeystoneAuth(auth_url, username, password, tenant_id, tenant_name, token, service_type, endpoint_type, sudo_tenant_id) if endpoint: self.endpoint = endpoint else: self.endpoint = auth.get_url() elif endpoint: auth = None self.endpoint = endpoint else: raise ValueError('Either an endpoint or auth_url must be supplied') self.insecure = insecure headers = {'Content-Type': 'application/json'} if token is not None: headers['X-Auth-Token'] = token self.requests = requests.Session() self.requests.auth = auth self.requests.headers.update(headers) def _load_controller(ext): controller = ext.plugin(client=self) setattr(self, ext.name, controller) # Load all controllers mgr = extension.ExtensionManager('designateclient.v1.controllers') mgr.map(_load_controller) def wrap_api_call(self, func, *args, **kw): """ Wrap a self. with exception handling :param func: The function to wrap """ # Prepend the endpoint URI args = list(args) args[0] = '%s/%s' % (self.endpoint, args[0]) if self.insecure is True: kw['verify'] = False # Trigger the request response = func(*args, **kw) # Decode is response, if possible try: response_payload = response.json() except ValueError: response_payload = {} if response.status_code == 400: raise exceptions.BadRequest(**response_payload) elif response.status_code in (401, 403): raise exceptions.Forbidden(**response_payload) elif response.status_code == 404: raise exceptions.NotFound(**response_payload) elif response.status_code == 409: raise exceptions.Conflict(**response_payload) elif response.status_code >= 500: raise exceptions.Unknown(**response_payload) else: return response def get(self, path, **kw): return self.wrap_api_call(self.requests.get, path, **kw) def post(self, path, **kw): return self.wrap_api_call(self.requests.post, path, **kw) def put(self, path, **kw): return self.wrap_api_call(self.requests.put, path, **kw) def delete(self, path, **kw): return self.wrap_api_call(self.requests.delete, path, **kw) python-designateclient-1.0.0/designateclient/v1/diagnostics.py0000664000175300017540000000313412234457733025712 0ustar jenkinsjenkins00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from designateclient.v1.base import Controller class DiagnosticsController(Controller): def ping(self, service, host): """ Ping a service on a given host """ response = self.client.get('/diagnostics/ping/%s/%s' % (service, host)) return response.json() def sync_all(self): """ Sync Everything """ response = self.client.post('/diagnostics/sync/all') return response.json() def sync_domain(self, domain_id): """ Sync Single Domain """ response = self.client.post('/diagnostics/sync/domain/%s' % domain_id) return response.json() def sync_record(self, domain_id, record_id): """ Sync Single Record """ response = self.client.post('/diagnostics/sync/record/%s/%s' % (domain_id, record_id)) return response.json() python-designateclient-1.0.0/designateclient/v1/reports.py0000664000175300017540000000360212234457733025101 0ustar jenkinsjenkins00000000000000# Copyright 2013 Hewlett-Packard Development Company, L.P. All Rights Reserved. # # Author: Patrick Galbraith # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from designateclient.v1.base import Controller class ReportsController(Controller): def count_all(self): """ Domain, Records and tenant total count """ response = self.client.get('/reports/counts') return response.json() def count_domains(self): """ Domain total count """ response = self.client.get('/reports/counts/domains') return response.json() def count_tenants(self): """ Tenant total count """ response = self.client.get('/reports/counts/tenants') return response.json() def count_records(self): """ Record total count """ response = self.client.get('/reports/counts/records') return response.json() def tenants_all(self): """ Per tenant count """ response = self.client.get('/reports/tenants') return response.json()['tenants'] def tenant_domains(self, other_tenant_id): """ Tenant's domain count """ response = self.client.get('/reports/tenants/%s' % other_tenant_id) return [{'domain': d} for d in response.json()['domains']] python-designateclient-1.0.0/designateclient/v1/servers.py0000664000175300017540000000437412234457733025103 0ustar jenkinsjenkins00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import json from designateclient import warlock from designateclient import utils from designateclient.v1.base import CrudController Server = warlock.model_factory(utils.load_schema('v1', 'server')) class ServersController(CrudController): def list(self): """ Retrieve a list of servers :returns: A list of :class:`Server`s """ response = self.client.get('/servers') return [Server(i) for i in response.json()['servers']] def get(self, server_id): """ Retrieve a server :param server_id: Server Identifier :returns: :class:`Server` """ response = self.client.get('/servers/%s' % server_id) return Server(response.json()) def create(self, server): """ Create a server :param server: A :class:`Server` to create :returns: :class:`Server` """ response = self.client.post('/servers', data=json.dumps(server)) return Server(response.json()) def update(self, server): """ Update a server :param server: A :class:`Server` to update :returns: :class:`Server` """ response = self.client.put('/servers/%s' % server.id, data=json.dumps(server.changes)) return Server(response.json()) def delete(self, server): """ Delete a server :param server: A :class:`Server`, or Server Identifier to delete """ if isinstance(server, Server): self.client.delete('/servers/%s' % server.id) else: self.client.delete('/servers/%s' % server) python-designateclient-1.0.0/designateclient/v1/records.py0000664000175300017540000000667012234457733025054 0ustar jenkinsjenkins00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import json from designateclient import warlock from designateclient import utils from designateclient.v1.base import CrudController from designateclient.v1.domains import Domain Record = warlock.model_factory(utils.load_schema('v1', 'record')) class RecordsController(CrudController): def list(self, domain): """ Retrieve a list of records :param domain: :class:`Domain` or Domain Identifier :returns: A list of :class:`Record`s """ domain_id = domain.id if isinstance(domain, Domain) else domain response = self.client.get('/domains/%(domain_id)s/records' % { 'domain_id': domain_id }) return [Record(i) for i in response.json()['records']] def get(self, domain, record_id): """ Retrieve a record :param domain: :class:`Domain` or Domain Identifier :param record_id: Record Identifier :returns: :class:`Record` """ domain_id = domain.id if isinstance(domain, Domain) else domain uri = '/domains/%(domain_id)s/records/%(record_id)s' % { 'domain_id': domain_id, 'record_id': record_id } response = self.client.get(uri) return Record(response.json()) def create(self, domain, record): """ Create a record :param domain: :class:`Domain` or Domain Identifier :param record: A :class:`Record` to create :returns: :class:`Record` """ domain_id = domain.id if isinstance(domain, Domain) else domain uri = '/domains/%(domain_id)s/records' % { 'domain_id': domain_id } response = self.client.post(uri, data=json.dumps(record)) return Record(response.json()) def update(self, domain, record): """ Update a record :param domain: :class:`Domain` or Domain Identifier :param record: A :class:`Record` to update :returns: :class:`Record` """ domain_id = domain.id if isinstance(domain, Domain) else domain uri = '/domains/%(domain_id)s/records/%(record_id)s' % { 'domain_id': domain_id, 'record_id': record.id } response = self.client.put(uri, data=json.dumps(record.changes)) return Record(response.json()) def delete(self, domain, record): """ Delete a record :param domain: :class:`Domain` or Domain Identifier :param record: A :class:`Record`, or Record Identifier to delete """ domain_id = domain.id if isinstance(domain, Domain) else domain record_id = record.id if isinstance(record, Record) else record uri = '/domains/%(domain_id)s/records/%(record_id)s' % { 'domain_id': domain_id, 'record_id': record_id } self.client.delete(uri) python-designateclient-1.0.0/designateclient/v1/base.py0000664000175300017540000000252612234457733024321 0ustar jenkinsjenkins00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import abc class Controller(object): __metaclass__ = abc.ABCMeta def __init__(self, client): self.client = client class CrudController(Controller): __metaclass__ = abc.ABCMeta @abc.abstractmethod def list(self, *args, **kw): """ List a resource """ @abc.abstractmethod def get(self, *args, **kw): """ Get a resouce """ @abc.abstractmethod def create(self, *args, **kw): """ Create a resource """ @abc.abstractmethod def update(self, *args, **kw): """ Update a resource """ @abc.abstractmethod def delete(self, *args, **kw): """ Delete a resource """ python-designateclient-1.0.0/designateclient/tests/0000775000175300017540000000000012234460017023631 5ustar jenkinsjenkins00000000000000python-designateclient-1.0.0/designateclient/tests/__init__.py0000664000175300017540000000000012234457733025743 0ustar jenkinsjenkins00000000000000python-designateclient-1.0.0/designateclient/shell.py0000664000175300017540000000732012234457733024165 0ustar jenkinsjenkins00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import logging import os from cliff.app import App from cliff.commandmanager import CommandManager from designateclient.version import version_info as version class DesignateShell(App): CONSOLE_MESSAGE_FORMAT = '%(levelname)s: %(message)s' def __init__(self): super(DesignateShell, self).__init__( description='Designate Client', version=version.version_string(), command_manager=CommandManager('designateclient.cli'), ) self.log = logging.getLogger(__name__) def configure_logging(self): super(DesignateShell, self).configure_logging() # Set requests logging requests_logger = logging.getLogger('requests') if self.options.verbose_level <= 1: requests_logger.setLevel(logging.WARN) else: requests_logger.setLevel(logging.DEBUG) def build_option_parser(self, description, version): parser = super(DesignateShell, self).build_option_parser( description, version) parser.add_argument('--os-endpoint', default=os.environ.get('OS_DNS_ENDPOINT'), help="Defaults to env[OS_DNS_ENDPOINT]") parser.add_argument('--os-auth-url', default=os.environ.get('OS_AUTH_URL'), help="Defaults to env[OS_AUTH_URL]") parser.add_argument('--os-username', default=os.environ.get('OS_USERNAME'), help="Defaults to env[OS_USERNAME]") parser.add_argument('--os-password', default=os.environ.get('OS_PASSWORD'), help="Defaults to env[OS_PASSWORD]") parser.add_argument('--os-tenant-id', default=os.environ.get('OS_TENANT_ID'), help="Defaults to env[OS_TENANT_ID]") parser.add_argument('--os-tenant-name', default=os.environ.get('OS_TENANT_NAME'), help="Defaults to env[OS_TENANT_NAME]") parser.add_argument('--os-token', default=os.environ.get('OS_SERVICE_TOKEN'), help="Defaults to env[OS_SERVICE_TOKEN]") parser.add_argument('--os-service-type', default=os.environ.get('OS_DNS_SERVICE_TYPE', 'dns'), help=("Defaults to env[OS_DNS_SERVICE_TYPE], or " "'dns'")) parser.add_argument('--os-region-name', default=os.environ.get('OS_REGION_NAME'), help="Defaults to env[OS_REGION_NAME]") parser.add_argument('--sudo-tenant-id', default=os.environ.get('DESIGNATE_SUDO_TENANT_ID'), help="Defaults to env[DESIGNATE_SUDO_TENANT_ID]") parser.add_argument('--insecure', action='store_true', help="Explicitly allow 'insecure' SSL requests") return parser python-designateclient-1.0.0/designateclient/auth.py0000664000175300017540000000556012234457733024023 0ustar jenkinsjenkins00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from urlparse import urlparse from requests.auth import AuthBase from keystoneclient.v2_0.client import Client class KeystoneAuth(AuthBase): def __init__(self, auth_url, username=None, password=None, tenant_id=None, tenant_name=None, token=None, service_type=None, endpoint_type=None, sudo_tenant_id=None): self.auth_url = str(auth_url).rstrip('/') self.username = username self.password = password self.tenant_id = tenant_id self.tenant_name = tenant_name self.token = token self.sudo_tenant_id = sudo_tenant_id if (not username and not password) and not token: raise ValueError('A username and password, or token is required') if not service_type or not endpoint_type: raise ValueError("Need service_type and/or endpoint_type") self.service_type = service_type self.endpoint_type = endpoint_type self.refresh_auth() def __call__(self, request): if not self.token: self.refresh_auth() request.headers['X-Auth-Token'] = self.token if self.sudo_tenant_id: request.headers['X-Designate-Sudo-Tenant-ID'] = self.sudo_tenant_id return request def get_ksclient(self): insecure = urlparse(self.auth_url).scheme != 'https' return Client(username=self.username, password=self.password, tenant_id=self.tenant_id, tenant_name=self.tenant_name, auth_url=self.auth_url, insecure=insecure) def get_endpoints(self, service_type=None, endpoint_type=None): return self.service_catalog.get_endpoints( service_type=service_type, endpoint_type=endpoint_type) def get_url(self, service_type=None, endpoint_type=None): service_type = service_type or self.service_type endpoint_type = endpoint_type or self.endpoint_type endpoints = self.get_endpoints(service_type, endpoint_type) return endpoints[service_type][0][endpoint_type].rstrip('/') def refresh_auth(self): ks = self.get_ksclient() self.token = ks.auth_token self.service_catalog = ks.service_catalog python-designateclient-1.0.0/designateclient/version.py0000664000175300017540000000130712234457733024542 0ustar jenkinsjenkins00000000000000# Copyright 2012 Managed I.T. # # Author: Kiall Mac Innes # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import pbr.version version_info = pbr.version.VersionInfo('python-designateclient') python-designateclient-1.0.0/python_designateclient.egg-info/0000775000175300017540000000000012234460017025562 5ustar jenkinsjenkins00000000000000python-designateclient-1.0.0/python_designateclient.egg-info/dependency_links.txt0000664000175300017540000000000112234460017031630 0ustar jenkinsjenkins00000000000000 python-designateclient-1.0.0/python_designateclient.egg-info/SOURCES.txt0000664000175300017540000000264512234460017027455 0ustar jenkinsjenkins00000000000000.testr.conf AUTHORS ChangeLog MANIFEST.in README.rst requirements.txt setup.cfg setup.py test-requirements.txt tox.ini bin/designate designateclient/__init__.py designateclient/auth.py designateclient/exceptions.py designateclient/shell.py designateclient/utils.py designateclient/version.py designateclient/warlock.py designateclient/cli/__init__.py designateclient/cli/base.py designateclient/cli/diagnostics.py designateclient/cli/domains.py designateclient/cli/records.py designateclient/cli/reports.py designateclient/cli/servers.py designateclient/resources/schemas/v1/domain.json designateclient/resources/schemas/v1/record.json designateclient/resources/schemas/v1/server.json designateclient/tests/__init__.py designateclient/v1/__init__.py designateclient/v1/base.py designateclient/v1/diagnostics.py designateclient/v1/domains.py designateclient/v1/records.py designateclient/v1/reports.py designateclient/v1/servers.py doc/requirements.txt doc/source/bindings.rst doc/source/conf.py doc/source/contributing.rst doc/source/index.rst doc/source/installation.rst doc/source/shell-examples.rst doc/source/shell.rst python_designateclient.egg-info/PKG-INFO python_designateclient.egg-info/SOURCES.txt python_designateclient.egg-info/dependency_links.txt python_designateclient.egg-info/entry_points.txt python_designateclient.egg-info/not-zip-safe python_designateclient.egg-info/requires.txt python_designateclient.egg-info/top_level.txtpython-designateclient-1.0.0/python_designateclient.egg-info/top_level.txt0000664000175300017540000000002012234460017030304 0ustar jenkinsjenkins00000000000000designateclient python-designateclient-1.0.0/python_designateclient.egg-info/not-zip-safe0000664000175300017540000000000112234457735030025 0ustar jenkinsjenkins00000000000000 python-designateclient-1.0.0/python_designateclient.egg-info/PKG-INFO0000664000175300017540000000142412234460017026660 0ustar jenkinsjenkins00000000000000Metadata-Version: 1.1 Name: python-designateclient Version: 1.0.0 Summary: DNS as a Service - Client Home-page: https://launchpad.net/python-designateclientclient Author: Kiall Mac Innes Author-email: kiall@managedit.ie License: UNKNOWN Description: Platform: UNKNOWN Classifier: Environment :: OpenStack Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 2.6 Classifier: Topic :: Internet :: Name Service (DNS) python-designateclient-1.0.0/python_designateclient.egg-info/entry_points.txt0000664000175300017540000000376612234460017031074 0ustar jenkinsjenkins00000000000000[designateclient.cli] domain-list = designateclient.cli.domains:ListDomainsCommand report-count-tenants = designateclient.cli.reports:TenantCountCommand diagnostics-ping = designateclient.cli.diagnostics:PingCommand report-tenants-all = designateclient.cli.reports:TenantsCommand diagnostics-sync-all = designateclient.cli.diagnostics:SyncAllCommand record-update = designateclient.cli.records:UpdateRecordCommand domain-servers-list = designateclient.cli.domains:ListDomainServersCommand diagnostics-sync-record = designateclient.cli.diagnostics:SyncRecordCommand server-delete = designateclient.cli.servers:DeleteServerCommand record-create = designateclient.cli.records:CreateRecordCommand report-count-all = designateclient.cli.reports:CountsCommand record-delete = designateclient.cli.records:DeleteRecordCommand server-create = designateclient.cli.servers:CreateServerCommand server-update = designateclient.cli.servers:UpdateServerCommand domain-get = designateclient.cli.domains:GetDomainCommand report-tenant-domains = designateclient.cli.reports:TenantCommand domain-update = designateclient.cli.domains:UpdateDomainCommand diagnostics-sync-domain = designateclient.cli.diagnostics:SyncDomainCommand server-get = designateclient.cli.servers:GetServerCommand report-count-domains = designateclient.cli.reports:DomainCountCommand domain-create = designateclient.cli.domains:CreateDomainCommand report-count-records = designateclient.cli.reports:RecordCountCommand server-list = designateclient.cli.servers:ListServersCommand record-get = designateclient.cli.records:GetRecordCommand record-list = designateclient.cli.records:ListRecordsCommand domain-delete = designateclient.cli.domains:DeleteDomainCommand [designateclient.v1.controllers] domains = designateclient.v1.domains:DomainsController records = designateclient.v1.records:RecordsController servers = designateclient.v1.servers:ServersController reports = designateclient.v1.reports:ReportsController diagnostics = designateclient.v1.diagnostics:DiagnosticsController python-designateclient-1.0.0/python_designateclient.egg-info/requires.txt0000664000175300017540000000016212234460017030161 0ustar jenkinsjenkins00000000000000cliff>=1.4.3 jsonschema>=1.3.0,!=1.4.0 pbr>=0.5.21,<1.0 python-keystoneclient>=0.3.2 requests>=1.1 stevedore>=0.10python-designateclient-1.0.0/AUTHORS0000664000175300017540000000055012234460017020375 0ustar jenkinsjenkins00000000000000Brian DeHamer Davide Guerri Dirk Mueller Endre Karlson Graham Hayes Kiall Mac Innes Kiall Mac Innes Monty Taylor Patrick Galbraith Simon McCartney