summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--Makefile2
-rw-r--r--Pipfile17
-rw-r--r--Pipfile.lock248
-rw-r--r--README.md2
-rwxr-xr-xsrc/conf_mode/ntp.py3
-rw-r--r--src/tests/test_ntp.py262
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
diff --git a/Makefile b/Makefile
index dd3d2d00f..565964dec 100644
--- a/Makefile
+++ b/Makefile
@@ -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"
+ }
+ }
+}
diff --git a/README.md b/README.md
index af4692007..896f28b3d 100644
--- a/README.md
+++ b/README.md
@@ -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()