diff options
author | kamijin_fanta <kamijin@live.jp> | 2019-01-30 16:37:47 +0900 |
---|---|---|
committer | Christian Poessinger <christian@poessinger.com> | 2019-01-30 08:37:47 +0100 |
commit | 959d96ceb38080748b6d195031a8013eb4a67f3b (patch) | |
tree | 6e82034b3fb51acf4e0595317b12fe4f3aa2b1d2 | |
parent | cc07c4727bdffb4c220ce28ab9f697b01fe4afb7 (diff) | |
download | vyos-1x-959d96ceb38080748b6d195031a8013eb4a67f3b.tar.gz vyos-1x-959d96ceb38080748b6d195031a8013eb4a67f3b.zip |
Add build time tests for NTP
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | Pipfile | 17 | ||||
-rw-r--r-- | Pipfile.lock | 248 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rwxr-xr-x | src/conf_mode/ntp.py | 3 | ||||
-rw-r--r-- | src/tests/test_ntp.py | 262 |
7 files changed, 533 insertions, 4 deletions
diff --git a/.gitignore b/.gitignore index af15969c8..132ee4c13 100644 --- a/.gitignore +++ b/.gitignore @@ -21,8 +21,6 @@ parts/ sdist/ var/ wheels/ -Pipfile -Pipfile.lock *.egg-info/ .installed.cfg *.egg @@ -51,6 +49,7 @@ nosetests.xml coverage.xml *.cover .hypothesis/ +cover # Translations *.mo @@ -44,7 +44,7 @@ clean: .PHONY: test test: - PYTHONPATH=python/ python3 -m "nose" --with-xunit src --with-coverage --cover-erase --cover-xml --cover-package src/conf_mode,src/op_mode,src/completion,src/helpers,src/validators,src/tests --verbose + PYTHONPATH=python/ python3 -m "nose" --exe --with-xunit src --with-coverage --cover-erase --cover-xml --cover-package --cover-html src/conf_mode,src/op_mode,src/completion,src/helpers,src/validators,src/tests --verbose .PHONY: sonar sonar: diff --git a/Pipfile b/Pipfile new file mode 100644 index 000000000..5bb9fb73d --- /dev/null +++ b/Pipfile @@ -0,0 +1,17 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] +lxml = "*" +pylint = "*" +nose = "*" +coverage = "*" + +[packages] +vyos = {file = "./python"} +jinja2 = "*" + +[requires] +python_version = "3.6" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 000000000..5aaef5675 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,248 @@ +{ + "_meta": { + "hash": { + "sha256": "5564acff86bcf8ef717129935c288ffed2631f1d795d1c44d0af36779593b89b" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.6" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "jinja2": { + "hashes": [ + "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", + "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" + ], + "index": "pypi", + "version": "==2.10" + }, + "markupsafe": { + "hashes": [ + "sha256:048ef924c1623740e70204aa7143ec592504045ae4429b59c30054cb31e3c432", + "sha256:130f844e7f5bdd8e9f3f42e7102ef1d49b2e6fdf0d7526df3f87281a532d8c8b", + "sha256:19f637c2ac5ae9da8bfd98cef74d64b7e1bb8a63038a3505cd182c3fac5eb4d9", + "sha256:1b8a7a87ad1b92bd887568ce54b23565f3fd7018c4180136e1cf412b405a47af", + "sha256:1c25694ca680b6919de53a4bb3bdd0602beafc63ff001fea2f2fc16ec3a11834", + "sha256:1f19ef5d3908110e1e891deefb5586aae1b49a7440db952454b4e281b41620cd", + "sha256:1fa6058938190ebe8290e5cae6c351e14e7bb44505c4a7624555ce57fbbeba0d", + "sha256:31cbb1359e8c25f9f48e156e59e2eaad51cd5242c05ed18a8de6dbe85184e4b7", + "sha256:3e835d8841ae7863f64e40e19477f7eb398674da6a47f09871673742531e6f4b", + "sha256:4e97332c9ce444b0c2c38dd22ddc61c743eb208d916e4265a2a3b575bdccb1d3", + "sha256:525396ee324ee2da82919f2ee9c9e73b012f23e7640131dd1b53a90206a0f09c", + "sha256:52b07fbc32032c21ad4ab060fec137b76eb804c4b9a1c7c7dc562549306afad2", + "sha256:52ccb45e77a1085ec5461cde794e1aa037df79f473cbc69b974e73940655c8d7", + "sha256:5c3fbebd7de20ce93103cb3183b47671f2885307df4a17a0ad56a1dd51273d36", + "sha256:5e5851969aea17660e55f6a3be00037a25b96a9b44d2083651812c99d53b14d1", + "sha256:5edfa27b2d3eefa2210fb2f5d539fbed81722b49f083b2c6566455eb7422fd7e", + "sha256:7d263e5770efddf465a9e31b78362d84d015cc894ca2c131901a4445eaa61ee1", + "sha256:83381342bfc22b3c8c06f2dd93a505413888694302de25add756254beee8449c", + "sha256:857eebb2c1dc60e4219ec8e98dfa19553dae33608237e107db9c6078b1167856", + "sha256:98e439297f78fca3a6169fd330fbe88d78b3bb72f967ad9961bcac0d7fdd1550", + "sha256:bf54103892a83c64db58125b3f2a43df6d2cb2d28889f14c78519394feb41492", + "sha256:d9ac82be533394d341b41d78aca7ed0e0f4ba5a2231602e2f05aa87f25c51672", + "sha256:e982fe07ede9fada6ff6705af70514a52beb1b2c3d25d4e873e82114cf3c5401", + "sha256:edce2ea7f3dfc981c4ddc97add8a61381d9642dc3273737e756517cc03e84dd6", + "sha256:efdc45ef1afc238db84cb4963aa689c0408912a0239b0721cb172b4016eb31d6", + "sha256:f137c02498f8b935892d5c0172560d7ab54bc45039de8805075e19079c639a9c", + "sha256:f82e347a72f955b7017a39708a3667f106e6ad4d10b25f237396a7115d8ed5fd", + "sha256:fb7c206e01ad85ce57feeaaa0bf784b97fa3cad0d4a5737bc5295785f5c613a1" + ], + "version": "==1.1.0" + }, + "vyos": { + "file": "./python" + } + }, + "develop": { + "astroid": { + "hashes": [ + "sha256:35b032003d6a863f5dcd7ec11abd5cd5893428beaa31ab164982403bcb311f22", + "sha256:6a5d668d7dc69110de01cdf7aeec69a679ef486862a0850cc0fd5571505b6b7e" + ], + "version": "==2.1.0" + }, + "coverage": { + "hashes": [ + "sha256:09e47c529ff77bf042ecfe858fb55c3e3eb97aac2c87f0349ab5a7efd6b3939f", + "sha256:0a1f9b0eb3aa15c990c328535655847b3420231af299386cfe5efc98f9c250fe", + "sha256:0cc941b37b8c2ececfed341444a456912e740ecf515d560de58b9a76562d966d", + "sha256:10e8af18d1315de936d67775d3a814cc81d0747a1a0312d84e27ae5610e313b0", + "sha256:1b4276550b86caa60606bd3572b52769860a81a70754a54acc8ba789ce74d607", + "sha256:1e8a2627c48266c7b813975335cfdea58c706fe36f607c97d9392e61502dc79d", + "sha256:2b224052bfd801beb7478b03e8a66f3f25ea56ea488922e98903914ac9ac930b", + "sha256:447c450a093766744ab53bf1e7063ec82866f27bcb4f4c907da25ad293bba7e3", + "sha256:46101fc20c6f6568561cdd15a54018bb42980954b79aa46da8ae6f008066a30e", + "sha256:4710dc676bb4b779c4361b54eb308bc84d64a2fa3d78e5f7228921eccce5d815", + "sha256:510986f9a280cd05189b42eee2b69fecdf5bf9651d4cd315ea21d24a964a3c36", + "sha256:5535dda5739257effef56e49a1c51c71f1d37a6e5607bb25a5eee507c59580d1", + "sha256:5a7524042014642b39b1fcae85fb37556c200e64ec90824ae9ecf7b667ccfc14", + "sha256:5f55028169ef85e1fa8e4b8b1b91c0b3b0fa3297c4fb22990d46ff01d22c2d6c", + "sha256:6694d5573e7790a0e8d3d177d7a416ca5f5c150742ee703f3c18df76260de794", + "sha256:6831e1ac20ac52634da606b658b0b2712d26984999c9d93f0c6e59fe62ca741b", + "sha256:77f0d9fa5e10d03aa4528436e33423bfa3718b86c646615f04616294c935f840", + "sha256:828ad813c7cdc2e71dcf141912c685bfe4b548c0e6d9540db6418b807c345ddd", + "sha256:85a06c61598b14b015d4df233d249cd5abfa61084ef5b9f64a48e997fd829a82", + "sha256:8cb4febad0f0b26c6f62e1628f2053954ad2c555d67660f28dfb1b0496711952", + "sha256:a5c58664b23b248b16b96253880b2868fb34358911400a7ba39d7f6399935389", + "sha256:aaa0f296e503cda4bc07566f592cd7a28779d433f3a23c48082af425d6d5a78f", + "sha256:ab235d9fe64833f12d1334d29b558aacedfbca2356dfb9691f2d0d38a8a7bfb4", + "sha256:b3b0c8f660fae65eac74fbf003f3103769b90012ae7a460863010539bb7a80da", + "sha256:bab8e6d510d2ea0f1d14f12642e3f35cefa47a9b2e4c7cea1852b52bc9c49647", + "sha256:c45297bbdbc8bb79b02cf41417d63352b70bcb76f1bbb1ee7d47b3e89e42f95d", + "sha256:d19bca47c8a01b92640c614a9147b081a1974f69168ecd494687c827109e8f42", + "sha256:d64b4340a0c488a9e79b66ec9f9d77d02b99b772c8b8afd46c1294c1d39ca478", + "sha256:da969da069a82bbb5300b59161d8d7c8d423bc4ccd3b410a9b4d8932aeefc14b", + "sha256:ed02c7539705696ecb7dc9d476d861f3904a8d2b7e894bd418994920935d36bb", + "sha256:ee5b8abc35b549012e03a7b1e86c09491457dba6c94112a2482b18589cc2bdb9" + ], + "index": "pypi", + "version": "==4.5.2" + }, + "isort": { + "hashes": [ + "sha256:1153601da39a25b14ddc54955dbbacbb6b2d19135386699e2ad58517953b34af", + "sha256:b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8", + "sha256:ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497" + ], + "version": "==4.3.4" + }, + "lazy-object-proxy": { + "hashes": [ + "sha256:0ce34342b419bd8f018e6666bfef729aec3edf62345a53b537a4dcc115746a33", + "sha256:1b668120716eb7ee21d8a38815e5eb3bb8211117d9a90b0f8e21722c0758cc39", + "sha256:209615b0fe4624d79e50220ce3310ca1a9445fd8e6d3572a896e7f9146bbf019", + "sha256:27bf62cb2b1a2068d443ff7097ee33393f8483b570b475db8ebf7e1cba64f088", + "sha256:27ea6fd1c02dcc78172a82fc37fcc0992a94e4cecf53cb6d73f11749825bd98b", + "sha256:2c1b21b44ac9beb0fc848d3993924147ba45c4ebc24be19825e57aabbe74a99e", + "sha256:2df72ab12046a3496a92476020a1a0abf78b2a7db9ff4dc2036b8dd980203ae6", + "sha256:320ffd3de9699d3892048baee45ebfbbf9388a7d65d832d7e580243ade426d2b", + "sha256:50e3b9a464d5d08cc5227413db0d1c4707b6172e4d4d915c1c70e4de0bbff1f5", + "sha256:5276db7ff62bb7b52f77f1f51ed58850e315154249aceb42e7f4c611f0f847ff", + "sha256:61a6cf00dcb1a7f0c773ed4acc509cb636af2d6337a08f362413c76b2b47a8dd", + "sha256:6ae6c4cb59f199d8827c5a07546b2ab7e85d262acaccaacd49b62f53f7c456f7", + "sha256:7661d401d60d8bf15bb5da39e4dd72f5d764c5aff5a86ef52a042506e3e970ff", + "sha256:7bd527f36a605c914efca5d3d014170b2cb184723e423d26b1fb2fd9108e264d", + "sha256:7cb54db3535c8686ea12e9535eb087d32421184eacc6939ef15ef50f83a5e7e2", + "sha256:7f3a2d740291f7f2c111d86a1c4851b70fb000a6c8883a59660d95ad57b9df35", + "sha256:81304b7d8e9c824d058087dcb89144842c8e0dea6d281c031f59f0acf66963d4", + "sha256:933947e8b4fbe617a51528b09851685138b49d511af0b6c0da2539115d6d4514", + "sha256:94223d7f060301b3a8c09c9b3bc3294b56b2188e7d8179c762a1cda72c979252", + "sha256:ab3ca49afcb47058393b0122428358d2fbe0408cf99f1b58b295cfeb4ed39109", + "sha256:bd6292f565ca46dee4e737ebcc20742e3b5be2b01556dafe169f6c65d088875f", + "sha256:cb924aa3e4a3fb644d0c463cad5bc2572649a6a3f68a7f8e4fbe44aaa6d77e4c", + "sha256:d0fc7a286feac9077ec52a927fc9fe8fe2fabab95426722be4c953c9a8bede92", + "sha256:ddc34786490a6e4ec0a855d401034cbd1242ef186c20d79d2166d6a4bd449577", + "sha256:e34b155e36fa9da7e1b7c738ed7767fc9491a62ec6af70fe9da4a057759edc2d", + "sha256:e5b9e8f6bda48460b7b143c3821b21b452cb3a835e6bbd5dd33aa0c8d3f5137d", + "sha256:e81ebf6c5ee9684be8f2c87563880f93eedd56dd2b6146d8a725b50b7e5adb0f", + "sha256:eb91be369f945f10d3a49f5f9be8b3d0b93a4c2be8f8a5b83b0571b8123e0a7a", + "sha256:f460d1ceb0e4a5dcb2a652db0904224f367c9b3c1470d5a7683c0480e582468b" + ], + "version": "==1.3.1" + }, + "lxml": { + "hashes": [ + "sha256:0dd6589fa75d369ba06d2b5f38dae107f76ea127f212f6a7bee134f6df2d1d21", + "sha256:1afbac344aa68c29e81ab56c1a9411c3663157b5aee5065b7fa030b398d4f7e0", + "sha256:1baad9d073692421ad5dbbd81430aba6c7f5fdc347f03537ae046ddf2c9b2297", + "sha256:1d8736421a2358becd3edf20260e41a06a0bf08a560480d3a5734a6bcbacf591", + "sha256:1e1d9bddc5afaddf0de76246d3f2152f961697ad7439c559f179002682c45801", + "sha256:1f179dc8b2643715f020f4d119d5529b02cd794c1c8f305868b73b8674d2a03f", + "sha256:241fb7bdf97cb1df1edfa8f0bcdfd80525d4023dac4523a241907c8b2f44e541", + "sha256:2f9765ee5acd3dbdcdc0d0c79309e01f7c16bc8d39b49250bf88de7b46daaf58", + "sha256:312e1e1b1c3ce0c67e0b8105317323e12807955e8186872affb667dbd67971f6", + "sha256:3273db1a8055ca70257fd3691c6d2c216544e1a70b673543e15cc077d8e9c730", + "sha256:34dfaa8c02891f9a246b17a732ca3e99c5e42802416628e740a5d1cb2f50ff49", + "sha256:3aa3f5288af349a0f3a96448ebf2e57e17332d99f4f30b02093b7948bd9f94cc", + "sha256:51102e160b9d83c1cc435162d90b8e3c8c93b28d18d87b60c56522d332d26879", + "sha256:56115fc2e2a4140e8994eb9585119a1ae9223b506826089a3ba753a62bd194a6", + "sha256:69d83de14dbe8fe51dccfd36f88bf0b40f5debeac763edf9f8325180190eba6e", + "sha256:99fdce94aeaa3ccbdfcb1e23b34273605c5853aa92ec23d84c84765178662c6c", + "sha256:a7c0cd5b8a20f3093ee4a67374ccb3b8a126743b15a4d759e2a1bf098faac2b2", + "sha256:abe12886554634ed95416a46701a917784cb2b4c77bfacac6916681d49bbf83d", + "sha256:b4f67b5183bd5f9bafaeb76ad119e977ba570d2b0e61202f534ac9b5c33b4485", + "sha256:bdd7c1658475cc1b867b36d5c4ed4bc316be8d3368abe03d348ba906a1f83b0e", + "sha256:c6f24149a19f611a415a51b9bc5f17b6c2f698e0d6b41ffb3fa9f24d35d05d73", + "sha256:d1e111b3ab98613115a208c1017f266478b0ab224a67bc8eac670fa0bad7d488", + "sha256:d6520aa965773bbab6cb7a791d5895b00d02cf9adc93ac2bf4edb9ac1a6addc5", + "sha256:dd185cde2ccad7b649593b0cda72021bc8a91667417001dbaf24cd746ecb7c11", + "sha256:de2e5b0828a9d285f909b5d2e9d43f1cf6cf21fe65bc7660bdaa1780c7b58298", + "sha256:f726444b8e909c4f41b4fde416e1071cf28fa84634bfb4befdf400933b6463af" + ], + "index": "pypi", + "version": "==4.3.0" + }, + "mccabe": { + "hashes": [ + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + ], + "version": "==0.6.1" + }, + "nose": { + "hashes": [ + "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac", + "sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a", + "sha256:f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98" + ], + "index": "pypi", + "version": "==1.3.7" + }, + "pylint": { + "hashes": [ + "sha256:689de29ae747642ab230c6d37be2b969bf75663176658851f456619aacf27492", + "sha256:771467c434d0d9f081741fec1d64dfb011ed26e65e12a28fe06ca2f61c4d556c" + ], + "index": "pypi", + "version": "==2.2.2" + }, + "six": { + "hashes": [ + "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", + "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" + ], + "version": "==1.12.0" + }, + "typed-ast": { + "hashes": [ + "sha256:023625bfa9359e29bd6e24cac2a4503495b49761d48a5f1e38333fc4ac4d93fe", + "sha256:07591f7a5fdff50e2e566c4c1e9df545c75d21e27d98d18cb405727ed0ef329c", + "sha256:153e526b0f4ffbfada72d0bb5ffe8574ba02803d2f3a9c605c8cf99dfedd72a2", + "sha256:3ad2bdcd46a4a1518d7376e9f5016d17718a9ed3c6a3f09203d832f6c165de4a", + "sha256:3ea98c84df53ada97ee1c5159bb3bc784bd734231235a1ede14c8ae0775049f7", + "sha256:51a7141ccd076fa561af107cfb7a8b6d06a008d92451a1ac7e73149d18e9a827", + "sha256:52c93cd10e6c24e7ac97e8615da9f224fd75c61770515cb323316c30830ddb33", + "sha256:6344c84baeda3d7b33e157f0b292e4dd53d05ddb57a63f738178c01cac4635c9", + "sha256:64699ca1b3bd5070bdeb043e6d43bc1d0cebe08008548f4a6bee782b0ecce032", + "sha256:74903f2e56bbffe29282ef8a5487d207d10be0f8513b41aff787d954a4cf91c9", + "sha256:7891710dba83c29ee2bd51ecaa82f60f6bede40271af781110c08be134207bf2", + "sha256:91976c56224e26c256a0de0f76d2004ab885a29423737684b4f7ebdd2f46dde2", + "sha256:9bad678a576ecc71f25eba9f1e3fd8d01c28c12a2834850b458428b3e855f062", + "sha256:b4726339a4c180a8b6ad9d8b50d2b6dc247e1b79b38fe2290549c98e82e4fd15", + "sha256:ba36f6aa3f8933edf94ea35826daf92cbb3ec248b89eccdc053d4a815d285357", + "sha256:bbc96bde544fd19e9ef168e4dfa5c3dfe704bfa78128fa76f361d64d6b0f731a", + "sha256:c0c927f1e44469056f7f2dada266c79b577da378bbde3f6d2ada726d131e4824", + "sha256:c0f9a3708008aa59f560fa1bd22385e05b79b8e38e0721a15a8402b089243442", + "sha256:f0bf6f36ff9c5643004171f11d2fdc745aa3953c5aacf2536a0685db9ceb3fb1", + "sha256:f5be39a0146be663cbf210a4d95c3c58b2d7df7b043c9047c5448e358f0550a2", + "sha256:fcd198bf19d9213e5cbf2cde2b9ef20a9856e716f76f9476157f90ae6de06cc6" + ], + "markers": "python_version < '3.7' and implementation_name == 'cpython'", + "version": "==1.2.0" + }, + "wrapt": { + "hashes": [ + "sha256:4aea003270831cceb8a90ff27c4031da6ead7ec1886023b80ce0dfe0adf61533" + ], + "version": "==1.11.1" + } + } +} @@ -53,6 +53,8 @@ The guidelines in a nutshell: Tests are executed at build time, you can also execute them by hand with: ``` +pipenv install +pipenv shell make test ``` diff --git a/src/conf_mode/ntp.py b/src/conf_mode/ntp.py index 68a046939..fccec3575 100755 --- a/src/conf_mode/ntp.py +++ b/src/conf_mode/ntp.py @@ -21,6 +21,7 @@ import os import jinja2 import ipaddress +import copy from vyos.config import Config from vyos import ConfigError @@ -79,7 +80,7 @@ default_config_data = { } def get_config(): - ntp = default_config_data + ntp = copy.deepcopy(default_config_data) conf = Config() if not conf.exists('system ntp'): return None diff --git a/src/tests/test_ntp.py b/src/tests/test_ntp.py new file mode 100644 index 000000000..08e1b665e --- /dev/null +++ b/src/tests/test_ntp.py @@ -0,0 +1,262 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2018 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# + +import os +import tempfile +import unittest +from unittest import TestCase, mock +import ipaddress +from contextlib import ExitStack +import textwrap + +from vyos import ConfigError +from vyos.config import Config +try: + from src.conf_mode import ntp +except ModuleNotFoundError: # for unittest.main() + import sys + sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) + from src.conf_mode import ntp + + +class TestNtp(TestCase): + + def test_get_config(self): + tests = [ + { + 'name': 'empty', + 'config': { + 'system ntp': None, + }, + 'expected': None, + }, + { + 'name': 'full-options', + 'config': { + 'system ntp': 'yes', + 'allow-clients address': ['192.0.2.0/24'], + 'listen-address': ['198.51.100.0/24'], + 'server': ['example.com'], + 'server example.com noselect': 'yes', + 'server example.com preempt': 'yes', + 'server example.com prefer': 'yes', + }, + 'expected': { + 'allowed_networks': [{ + 'address': ipaddress.ip_address('192.0.2.0'), + 'netmask': ipaddress.ip_address('255.255.255.0'), + 'network': '192.0.2.0/24', + }], + 'listen_address': ['198.51.100.0/24'], + 'servers': [ + {'name': 'example.com', 'options': ['noselect', 'preempt', 'prefer']} + ] + }, + }, + { + 'name': 'non-options', + 'config': { + 'system ntp': 'yes', + 'allow-clients address': ['192.0.2.0/24'], + 'listen-address': ['198.51.100.0/24'], + 'server': ['example.com'], + }, + 'expected': { + 'allowed_networks': [{ + 'address': ipaddress.ip_address('192.0.2.0'), + 'netmask': ipaddress.ip_address('255.255.255.0'), + 'network': '192.0.2.0/24', + }], + 'listen_address': ['198.51.100.0/24'], + 'servers': [ + {'name': 'example.com', 'options': []} + ] + }, + }, + ] + for case in tests: + def mocked_fn(path): + return case['config'].get(path) + + with self.subTest(msg = case['name']): + m = { + 'return_value': mock.Mock(side_effect = mocked_fn), + 'return_values': mock.Mock(side_effect = mocked_fn), + 'list_nodes': mock.Mock(side_effect = mocked_fn), + 'exists': mock.Mock(side_effect = mocked_fn), + } + with mock.patch.multiple(Config, **m): + actual = ntp.get_config() + self.assertEqual(actual, case['expected']) + + def test_verify(self): + tests = [ + { + 'name': 'none', + 'config': None, + 'expected': None + }, + { + 'name': 'valid', + 'config': { + 'allowed_networks': [{ + 'address': ipaddress.ip_address('192.0.2.1'), + 'netmask': ipaddress.ip_address('255.255.255.0'), + 'network': '192.0.2.0/24', + }], + 'listen_address': ['198.51.100.0/24'], + 'servers': [ + {'name': 'example.com', 'options': ['noselect', 'preempt', 'prefer']} + ] + }, + 'expected': None, + }, + { + 'name': 'not configure servers', + 'config': { + 'allowed_networks': [{ + 'address': ipaddress.ip_address('192.0.2.1'), + 'netmask': ipaddress.ip_address('255.255.255.0'), + 'network': '192.0.2.0/24', + }], + 'servers': [] + }, + 'expected': ConfigError, + }, + { + 'name': 'does not exist in the network', + 'config': { + 'allowed_networks': [{ + 'address': ipaddress.ip_address('192.0.2.1'), + 'netmask': ipaddress.ip_address('255.255.255.0'), + 'network': '192.0.2.0/50', # invalid netmask + }], + 'listen_address': ['198.51.100.0/24'], + 'servers': [ + {'name': 'example.com', 'options': []} + ] + }, + 'expected': ConfigError, + }, + ] + for case in tests: + with self.subTest(msg = case['name']): + if case['expected'] is not None: + with self.assertRaises(case['expected']): + ntp.verify(case['config']) + else: + ntp.verify(case['config']) + + def test_generate(self): + tests = [ + { + 'name': 'empty', + 'config': None, + 'expected': '', + }, + { + 'name': 'valid', + 'config': { + 'allowed_networks': [ + { + 'address': ipaddress.ip_address('192.0.2.1'), + 'netmask': ipaddress.ip_address('255.255.255.0'), + 'network': '192.0.2.0/24', + }, + { + 'address': ipaddress.ip_address('198.51.100.1'), + 'netmask': ipaddress.ip_address('255.255.255.0'), + 'network': '198.51.100.0/24', + }, + ], + 'listen_address': ['198.51.100.0/24'], + 'servers': [ + {'name': '1.example.com', 'options': ['noselect', 'preempt', 'prefer']}, + {'name': '2.example.com', 'options': []}, + ] + }, + 'expected': textwrap.dedent(''' + ### Autogenerated by ntp.py ### + + # + # Non-configurable defaults + # + driftfile /var/lib/ntp/ntp.drift + # By default, only allow ntpd to query time sources, ignore any incoming requests + restrict default noquery nopeer notrap nomodify + # Local users have unrestricted access, allowing reconfiguration via ntpdc + restrict 127.0.0.1 + restrict -6 ::1 + + + # + # Configurable section + # + + # Server configuration for: 1.example.com + server 1.example.com iburst noselect preempt prefer + + # Server configuration for: 2.example.com + server 2.example.com iburst + + + + # Client configuration for network: 192.0.2.0/24 + restrict 192.0.2.1 mask 255.255.255.0 nomodify notrap nopeer + + # Client configuration for network: 198.51.100.0/24 + restrict 198.51.100.1 mask 255.255.255.0 nomodify notrap nopeer + + + + # NTP should listen on configured addresses only + interface ignore wildcard + interface listen 198.51.100.0/24 + + '''), + }, + ] + + for case in tests: + with self.subTest(msg = case['name']): + with tempfile.NamedTemporaryFile() as fp: + ntp.config_file = fp.name + + ntp.generate(case['config']) + actual = fp.file.read().decode('ascii') + # print(actual) + self.assertEqual(case['expected'], actual) + + def test_apply(self): + with tempfile.NamedTemporaryFile(delete = False) as fp: + ntp.config_file = fp.name + with mock.patch('os.system') as os_system: + ntp.apply({}) # some configure + os_system.assert_has_calls([ + mock.call('sudo systemctl restart ntp.service'), + ]) + self.assertTrue(os.path.exists(fp.name)) + + ntp.apply(None) # empty configure + os_system.assert_has_calls([ + mock.call('sudo systemctl stop ntp.service'), + ]) + self.assertFalse(os.path.exists(fp.name)) + +if __name__ == "__main__": + unittest.main() |