├── .fixtures.yml ├── .gitignore ├── .rspec ├── .travis.yml ├── CHANGELOG ├── CONTRIBUTING.md ├── CONTRIBUTORS ├── Gemfile ├── Guardfile ├── LICENSE ├── README.markdown ├── Rakefile ├── lib └── puppet │ ├── parser │ └── functions │ │ ├── cidr_to_broadcast.rb │ │ ├── cidr_to_netmask.rb │ │ ├── cidr_to_network.rb │ │ ├── cidr_to_range.rb │ │ ├── gethostbyaddr2array.rb │ │ ├── gethostbyname2array.rb │ │ ├── int_to_ip.rb │ │ ├── ip_in_cidr.rb │ │ ├── ip_to_int.rb │ │ ├── ip_to_signed_int.rb │ │ ├── mac_to_eui64.rb │ │ ├── netmask_to_masklen.rb │ │ └── parse_http_uri.rb │ ├── provider │ └── .gitkeep │ └── type │ └── .gitkeep ├── metadata.json ├── spec ├── acceptance │ ├── class_spec.rb │ └── nodesets │ │ ├── centos-64-x64.yml │ │ ├── default.yml │ │ └── ubuntu-server-12042-x64.yml ├── classes │ └── coverage_spec.rb ├── functions │ ├── cidr_to_broadcast_spec.rb │ ├── cidr_to_netmask_spec.rb │ ├── cidr_to_network_spec.rb │ ├── cidr_to_range_spec.rb │ ├── int_to_ip_spec.rb │ ├── ip_in_cidr_spec.rb │ ├── ip_to_int_spec.rb │ ├── ip_to_signed_int_spec.rb │ ├── mac_to_eui64_spec.rb │ ├── netmask_to_masklen_spec.rb │ └── parse_http_uri_spec.rb ├── spec_helper.rb └── spec_helper_acceptance.rb └── tests └── init.pp /.fixtures.yml: -------------------------------------------------------------------------------- 1 | fixtures: 2 | repositories: 3 | stdlib: "git://github.com/puppetlabs/puppetlabs-stdlib.git" 4 | symlinks: 5 | netstdlib: "#{source_dir}" 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | .*.sw? 3 | pkg 4 | spec/fixtures 5 | .rspec_system 6 | .vagrant 7 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | language: ruby 3 | bundler_args: --without development 4 | before_install: rm Gemfile.lock || true 5 | rvm: 6 | - 1.9.3 7 | - 2.0.0 8 | script: bundle exec rake test 9 | env: 10 | - PUPPET_VERSION="~> 2.7.0" 11 | - PUPPET_VERSION="~> 3.1.0" 12 | - PUPPET_VERSION="~> 3.2.0" 13 | - PUPPET_VERSION="~> 3.3.0" 14 | - PUPPET_VERSION="~> 3.4.0" 15 | matrix: 16 | exclude: 17 | - rvm: 2.0.0 18 | env: PUPPET_VERSION="~> 2.7.0" 19 | - rvm: 2.0.0 20 | env: PUPPET_VERSION="~> 3.1.0" 21 | - rvm: 1.9.3 22 | env: PUPPET_VERSION="~> 2.7.0" 23 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yelp/puppet-netstdlib/5a62ea51c1371b797e905afe6aa2d519db92e062/CHANGELOG -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | This module has grown over time based on a range of contributions from 2 | people using it. If you follow these contributing guidelines your patch 3 | will likely make it into a release a little quicker. 4 | 5 | 6 | ## Contributing 7 | 8 | 1. Fork the repo. 9 | 10 | 2. Run the tests. We only take pull requests with passing tests, and 11 | it's great to know that you have a clean slate 12 | 13 | 3. Add a test for your change. Only refactoring and documentation 14 | changes require no new tests. If you are adding functionality 15 | or fixing a bug, please add a test. 16 | 17 | 4. Make the test pass. 18 | 19 | 5. Push to your fork and submit a pull request. 20 | 21 | 22 | ## Dependencies 23 | 24 | The testing and development tools have a bunch of dependencies, 25 | all managed by [bundler](http://bundler.io/) according to the 26 | [Puppet support matrix](http://docs.puppetlabs.com/guides/platforms.html#ruby-versions). 27 | 28 | By default the tests use a baseline version of Puppet. 29 | 30 | If you have Ruby 2.x or want a specific version of Puppet, 31 | you must set an environment variable such as: 32 | 33 | export PUPPET_VERSION="~> 3.2.0" 34 | 35 | Install the dependencies like so... 36 | 37 | bundle install 38 | 39 | ## Syntax and style 40 | 41 | The test suite will run [Puppet Lint](http://puppet-lint.com/) and 42 | [Puppet Syntax](https://github.com/gds-operations/puppet-syntax) to 43 | check various syntax and style things. You can run these locally with: 44 | 45 | bundle exec rake lint 46 | bundle exec rake syntax 47 | 48 | ## Running the unit tests 49 | 50 | The unit test suite covers most of the code, as mentioned above please 51 | add tests if you're adding new functionality. If you've not used 52 | [rspec-puppet](http://rspec-puppet.com/) before then feel free to ask 53 | about how best to test your new feature. Running the test suite is done 54 | with: 55 | 56 | bundle exec rake spec 57 | 58 | Note also you can run the syntax, style and unit tests in one go with: 59 | 60 | bundle exec rake test 61 | 62 | ## Integration tests 63 | 64 | The unit tests just check the code runs, not that it does exactly what 65 | we want on a real machine. For that we're using 66 | [beaker](https://github.com/puppetlabs/beaker). 67 | 68 | This fires up a new virtual machine (using vagrant) and runs a series of 69 | simple tests against it after applying the module. You can run this 70 | with: 71 | 72 | bundle exec rake acceptance 73 | 74 | This will run the tests on an Ubuntu 12.04 virtual machine. You can also 75 | run the integration tests against Centos 6.5 with. 76 | 77 | RS_SET=centos-64-x64 bundle exec rake acceptances 78 | 79 | If you don't want to have to recreate the virtual machine every time you 80 | can use `RS_DESTROY=no` and `RS_PROVISION=no`. On the first run you will 81 | at least need `RS_PROVISION` set to yes (the default). The Vagrantfile 82 | for the created virtual machines will be in `.vagrant/beaker_vagrant_fies`. 83 | 84 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | yelp 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | group :development do 4 | gem "beaker", "> 2.0.0" 5 | gem "beaker-rspec", ">= 5.1.0" 6 | gem "beaker-puppet_install_helper" 7 | gem "pry" 8 | gem "puppet-blacksmith" 9 | gem "serverspec" 10 | gem "vagrant-wrapper" 11 | end 12 | 13 | group :test do 14 | gem "json", '~> 1.8.3' 15 | gem "json_pure", '~> 1.8.3' 16 | # Pin for 1.8.7 compatibility for now 17 | gem "rake", '< 11.0.0' 18 | gem "puppet", ENV['PUPPET_VERSION'] || '~> 3.7.0' 19 | gem "puppet-lint" 20 | 21 | # Pin for 1.8.7 compatibility for now 22 | gem "rspec", '< 3.2.0' 23 | gem "rspec-core", "3.1.7" 24 | gem "rspec-puppet", "~> 2.1" 25 | 26 | gem "puppet-syntax" 27 | gem "puppetlabs_spec_helper" 28 | gem "hiera" 29 | gem "hiera-puppet-helper" 30 | end 31 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | notification :off 2 | 3 | guard 'rake', :task => 'test' do 4 | watch(%r{^manifests\/(.+)\.pp$}) 5 | end 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | ## Overview 2 | [![Build Status](https://travis-ci.org/Yelp/puppet-netstdlib.png)](https://travis-ci.org/Yelp/puppet-netstdlib) 3 | 4 | `netstdlib` is a collection of puppet functions and facts for network related work. 5 | 6 | These functions and facts are very handy when using puppet to do complex logic 7 | on code that deals with configuring or interpreting network interfaces. 8 | 9 | Most of them simply expose the native ruby implementations into the puppet 10 | manifest so you can use them to say, edit OpenStack config files, or 11 | manipulate DCHP server pools. 12 | 13 | ## Examples 14 | 15 | ```puppet 16 | # Use macaddress_rand instead of FQDNs because we have lots of VMs with 17 | # the same hostname 18 | cron::d { 'puppet_agent': 19 | ensure => $ensure, 20 | minute => macaddress_rand(60), 21 | user => 'root', 22 | command => 'puppet agent -t >/dev/null 2>&1', 23 | } 24 | ``` 25 | 26 | ```puppet 27 | # Have the puppet server query DNS to get the current round-robin A records 28 | $web_server_ips_array = gethostbyname2array("webs.yourdomain.com") 29 | validate_array($web_server_ips_array) 30 | ``` 31 | 32 | ```puppet 33 | # Reverse Lookup your ip to a name: 34 | $my_name = gethostbyaddr2array($::ipaddress) 35 | notify { "My reverse dns seems to be: ${my_name}": } 36 | ``` 37 | 38 | ## Functions 39 | 40 | cidr_to_broadcast 41 | ------------------- 42 | Converts an CIDR address of the form 192.168.0.1/24 into its broadcast address 43 | 44 | cidr_to_netmask 45 | ------------------- 46 | Converts an CIDR address of the form 192.168.0.1/24 into its netmask address 47 | 48 | cidr_to_network 49 | ------------------- 50 | Converts an CIDR address of the form 192.168.0.1/24 into its network address 51 | 52 | cidr_to_range 53 | ------------------- 54 | Converts an CIDR address of the form 192.168.0.1/24 into a range of IP addresses, excluding the network and 55 | broadcast addresses. 56 | 57 | fqdn_mac 58 | ------------------- 59 | Generate MAC addresses based on the results of fqdn_rand. Useful for VMs that 60 | might have the same hostname. 61 | 62 | gethostbyaddr2array 63 | ------------------- 64 | Resolve an IP address into one or more names. (Looks up reverse DNS PTRs) 65 | 66 | gethostbyname2array 67 | ------------------- 68 | Resolve a name into one or more IP addresses. 69 | 70 | int_to_ip 71 | ------------------- 72 | Converts an IP in its 32 bit integer representation to a dotted address of the form 192.168.0.1 73 | 74 | ip_in_cidr 75 | ------------------- 76 | Checks if an ip address is contained within a CIDR address of the form 192.168.0.1/24 77 | 78 | ip_to_int 79 | ------------------- 80 | Converts a dotted address of the form 192.168.0.1 into its 32 bit integer representation 81 | 82 | mac_to_eui64 83 | ------------------- 84 | Converts a MAC address of the form 52:54:00:12:09:f3 into its EUI64 representation 85 | of the form 5054:00ff:fe12:09f3 86 | 87 | netmask_to_masklen 88 | ------------------- 89 | Converts a netmask of the form 255.255.0.0 to the mask length (e.g. 16) 90 | 91 | ## Limitations 92 | 93 | Puppet functions are server-side, facts are client side. Keep this in mind as 94 | any DNS related functions will take place on the server. 95 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'puppetlabs_spec_helper/rake_tasks' 2 | require 'puppet-lint/tasks/puppet-lint' 3 | require 'puppet-syntax/tasks/puppet-syntax' 4 | 5 | # These two gems aren't always present, for instance 6 | # on Travis with --without development 7 | begin 8 | require 'puppet_blacksmith/rake_tasks' 9 | rescue LoadError 10 | end 11 | 12 | PuppetLint.configuration.send("disable_80chars") 13 | PuppetLint.configuration.log_format = "%{path}:%{linenumber}:%{check}:%{KIND}:%{message}" 14 | PuppetLint.configuration.fail_on_warnings = true 15 | 16 | # Forsake support for Puppet 2.6.2 for the benefit of cleaner code. 17 | # http://puppet-lint.com/checks/class_parameter_defaults/ 18 | PuppetLint.configuration.send('disable_class_parameter_defaults') 19 | # http://puppet-lint.com/checks/class_inherits_from_params_class/ 20 | PuppetLint.configuration.send('disable_class_inherits_from_params_class') 21 | 22 | exclude_paths = [ 23 | "pkg/**/*", 24 | "vendor/**/*", 25 | "spec/**/*", 26 | ] 27 | PuppetLint.configuration.ignore_paths = exclude_paths 28 | PuppetSyntax.exclude_paths = exclude_paths 29 | 30 | desc "Run acceptance tests" 31 | RSpec::Core::RakeTask.new(:acceptance) do |t| 32 | t.pattern = 'spec/acceptance' 33 | end 34 | 35 | desc "Run syntax, lint, and spec tests." 36 | task :test => [ 37 | :syntax, 38 | :lint, 39 | :spec, 40 | ] 41 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/cidr_to_broadcast.rb: -------------------------------------------------------------------------------- 1 | module Puppet::Parser::Functions 2 | 3 | newfunction(:cidr_to_broadcast, :type => :rvalue, :doc => <<-'ENDHEREDOC' 4 | Converts an CIDR address of the form 192.168.0.1/24 into its broadcast address 5 | 6 | ENDHEREDOC 7 | ) do |args| 8 | 9 | unless args.length == 1 then 10 | raise Puppet::ParseError, ("cidr_to_broadcast(): wrong number of arguments (#{args.length}; must be 1)") 11 | end 12 | arg = args[0] 13 | unless arg.respond_to?('to_s') then 14 | raise Puppet::ParseError, ("#{arg.inspect} is not a string. It looks to be a #{arg.class}") 15 | end 16 | 17 | arg = arg.to_s 18 | begin 19 | IPAddr.new(arg).to_range.last.to_s 20 | rescue ArgumentError => e 21 | raise Puppet::ParseError, (e) 22 | end 23 | end 24 | 25 | end 26 | 27 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/cidr_to_netmask.rb: -------------------------------------------------------------------------------- 1 | module IPAddrSubnetExtension 2 | def subnet_mask 3 | return _to_string(@mask_addr) 4 | end 5 | end 6 | 7 | module Puppet::Parser::Functions 8 | 9 | newfunction(:cidr_to_netmask, :type => :rvalue, :doc => <<-'ENDHEREDOC' 10 | Converts an CIDR address of the form 192.168.0.1/24 into its netmask. 11 | 12 | ENDHEREDOC 13 | ) do |args| 14 | 15 | unless args.length == 1 then 16 | raise Puppet::ParseError, ("cidr_to_netmask(): wrong number of arguments (#{args.length}; must be 1)") 17 | end 18 | arg = args[0] 19 | unless arg.respond_to?('to_s') then 20 | raise Puppet::ParseError, ("#{arg.inspect} is not a string. It looks to be a #{arg.class}") 21 | end 22 | 23 | arg = arg.to_s 24 | begin 25 | IPAddr.new(arg).extend(IPAddrSubnetExtension).subnet_mask.to_s 26 | rescue ArgumentError => e 27 | raise Puppet::ParseError, (e) 28 | end 29 | end 30 | 31 | end 32 | 33 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/cidr_to_network.rb: -------------------------------------------------------------------------------- 1 | module Puppet::Parser::Functions 2 | 3 | newfunction(:cidr_to_network, :type => :rvalue, :doc => <<-'ENDHEREDOC' 4 | Converts an CIDR address of the form 192.168.0.1/24 into its network address 5 | 6 | ENDHEREDOC 7 | ) do |args| 8 | 9 | unless args.length == 1 then 10 | raise Puppet::ParseError, ("cidr_to_network(): wrong number of arguments (#{args.length}; must be 1)") 11 | end 12 | arg = args[0] 13 | unless arg.respond_to?('to_s') then 14 | raise Puppet::ParseError, ("#{arg.inspect} is not a string. It looks to be a #{arg.class}") 15 | end 16 | arg = arg.to_s 17 | begin 18 | IPAddr.new(arg).to_range.first.to_s 19 | rescue ArgumentError => e 20 | raise Puppet::ParseError, (e) 21 | end 22 | end 23 | 24 | end 25 | 26 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/cidr_to_range.rb: -------------------------------------------------------------------------------- 1 | module Puppet::Parser::Functions 2 | 3 | newfunction(:cidr_to_range, :type => :rvalue, :doc => <<-'ENDHEREDOC' 4 | Converts an CIDR address of the form 192.168.0.1/24 into a range of IP address excluding the network and broadcast 5 | addresses. 6 | 7 | ENDHEREDOC 8 | ) do |args| 9 | 10 | unless args.length == 1 11 | raise Puppet::ParseError, ("cidr_to_range(): wrong number of arguments (#{args.length}; must be 1)") 12 | end 13 | 14 | arg = args[0] 15 | unless arg.kind_of? String 16 | raise Puppet::ParseError, ("#{arg.inspect} is not a string. It looks to be a #{arg.class}") 17 | end 18 | 19 | begin 20 | cidr = IPAddr.new(arg.to_s) 21 | rescue ArgumentError => e 22 | raise Puppet::ParseError, (e) 23 | end 24 | 25 | ips = cidr.to_range.map { |ip| ip.to_s } 26 | ips.shift 27 | ips.pop 28 | ips 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/gethostbyaddr2array.rb: -------------------------------------------------------------------------------- 1 | 2 | # Resolve an IP address into one or more names. 3 | # 4 | # E.g. gethostbyaddr2array('10.56.5.8') returns: 5 | # ['rackmaster-r5-devc.dev.yelpcorp.com'] 6 | # And gethostbyaddr2array(['10.56.5.8', '10.56.6.8']) returns: 7 | # ['rackmaster-r5-devc.dev.yelpcorp.com', 'rackmaster-r6-devc.dev.yelpcorp.com' ] 8 | 9 | require 'resolv' 10 | 11 | module Puppet::Parser::Functions 12 | newfunction(:gethostbyaddr2array, :type => :rvalue) do |a| 13 | if (a.size != 1) then 14 | raise(Puppet::ParseError, "gethostbyaddr2array(): Wrong number of arguments "+ 15 | "given #{a.size} for 1.") 16 | end 17 | 18 | lookup_ips = Array(a[0]) # Force into array 19 | 20 | data = nil 21 | begin 22 | data = lookup_ips.map { |ip| Resolv.getname(ip) }.sort 23 | rescue Exception => e 24 | raise(Puppet::ParseError, "Exception finding records for #{lookup_ips.join(', ')}: #{e}") 25 | end 26 | if data.size == 0 27 | raise(Puppet::ParseError, "Could not find any DNS records for #{lookup_ips.join(', ')}") 28 | end 29 | data 30 | end 31 | end 32 | 33 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/gethostbyname2array.rb: -------------------------------------------------------------------------------- 1 | 2 | # Resolve a name into one or more IP addresses 3 | # 4 | # E.g. gethostbyname2array('sensu.local.yelpcorp.com') in devc returns a list containing: 5 | # 10.56.5.8 6 | # 10.56.6.8 7 | 8 | require 'resolv' 9 | 10 | module Puppet::Parser::Functions 11 | newfunction(:gethostbyname2array, :type => :rvalue) do |a| 12 | if (a.size != 1) then 13 | raise(Puppet::ParseError, "gethostbyname2array(): Wrong number of arguments "+ 14 | "given #{a.size} for 1.") 15 | end 16 | 17 | lookup_name = a[0].to_s 18 | 19 | data = nil 20 | begin 21 | data = Resolv::DNS.new.getresources(lookup_name, Resolv::DNS::Resource::IN::A).map { |r| r.address.to_s }.sort 22 | rescue Exception => e 23 | raise(Puppet::ParseError, "Exception finding records for #{lookup_name}: #{e}") 24 | end 25 | if data.size == 0 26 | raise(Puppet::ParseError, "Could not find any DNS records for #{lookup_name}") 27 | end 28 | data 29 | end 30 | end 31 | 32 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/int_to_ip.rb: -------------------------------------------------------------------------------- 1 | require "ipaddr" 2 | module Puppet::Parser::Functions 3 | 4 | newfunction(:int_to_ip, :type => :rvalue, :doc => <<-'ENDHEREDOC' 5 | Converts a dotted address of the form 192.168.0.1 into its 32 bit integer representation 6 | 7 | ENDHEREDOC 8 | ) do |args| 9 | 10 | unless args.length == 1 then 11 | raise Puppet::ParseError, ("int_to_ip(): wrong number of arguments (#{args.length}; must be 1)") 12 | end 13 | arg = args[0] 14 | myint = Integer(arg) rescue false 15 | if myint == false then 16 | raise Puppet::ParseError, ("#{arg.inspect} is not a integer. It looks to be a #{arg.class}") 17 | end 18 | 19 | begin 20 | IPAddr.new(myint, Socket::AF_INET).to_s 21 | rescue ArgumentError => e 22 | raise Puppet::ParseError(e) 23 | end 24 | end 25 | 26 | end 27 | 28 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/ip_in_cidr.rb: -------------------------------------------------------------------------------- 1 | module Puppet::Parser::Functions 2 | 3 | newfunction(:ip_in_cidr, :type => :rvalue, :doc => <<-'ENDHEREDOC' 4 | Checks if an ip address is contained within a CIDR address of the form 192.168.0.1/24 5 | 6 | ENDHEREDOC 7 | ) do |args| 8 | require 'ipaddr' 9 | unless args.length == 2 then 10 | raise Puppet::ParseError, ("ip_in_cidr(): wrong number of arguments (#{args.length}; must be 2: ip and cidr)") 11 | end 12 | ip = args[0] 13 | unless ip.respond_to?('to_s') then 14 | raise Puppet::ParseError, ("#{ip.inspect} is not a string. It looks to be a #{ip.class}") 15 | end 16 | ip = ip.to_s 17 | if args[1].is_a? String 18 | cidr_ary = [ args[1] ] 19 | elsif args[1].is_a? Array 20 | cidr_ary = args[1] 21 | else 22 | raise Puppet::ParseError, ("#{args[1].inspect} is not a string. It looks to be a #{args[1].class}") 23 | end 24 | cidr_ary.each { |cidr| 25 | cidr = cidr.to_s 26 | unless cidr.respond_to?('to_s') then 27 | raise Puppet::ParseError, ("#{cidr.inspect} is not a string. It looks to be a #{cidr.class}") 28 | end 29 | begin 30 | if IPAddr.new(cidr).include? IPAddr.new(ip) 31 | return true 32 | end 33 | rescue ArgumentError => e 34 | raise Puppet::ParseError, (e) 35 | end 36 | } 37 | return false 38 | end 39 | end 40 | 41 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/ip_to_int.rb: -------------------------------------------------------------------------------- 1 | module Puppet::Parser::Functions 2 | 3 | newfunction(:ip_to_int, :type => :rvalue, :doc => <<-'ENDHEREDOC' 4 | Converts a dotted address of the form 192.168.0.1 into its unsigned 32 bit integer representation 5 | 6 | ENDHEREDOC 7 | ) do |args| 8 | 9 | unless args.length == 1 then 10 | raise Puppet::ParseError, ("ip_to_int(): wrong number of arguments (#{args.length}; must be 1)") 11 | end 12 | arg = args[0] 13 | unless arg.respond_to?('to_s') then 14 | raise Puppet::ParseError, ("#{arg.inspect} is not a string. It looks to be a #{arg.class}") 15 | end 16 | 17 | arg = arg.to_s 18 | begin 19 | IPAddr.new(arg).to_i 20 | rescue ArgumentError => e 21 | raise Puppet::ParseError, (e) 22 | end 23 | end 24 | 25 | end 26 | 27 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/ip_to_signed_int.rb: -------------------------------------------------------------------------------- 1 | module Puppet::Parser::Functions 2 | 3 | newfunction(:ip_to_signed_int, :type => :rvalue, :doc => <<-'ENDHEREDOC' 4 | Converts a dotted address of the form 192.168.0.1 into its signed 32 bit integer representation 5 | 6 | ENDHEREDOC 7 | ) do |args| 8 | 9 | unless args.length == 1 then 10 | raise Puppet::ParseError, ("ip_to_signed_int(): wrong number of arguments (#{args.length}; must be 1)") 11 | end 12 | arg = args[0] 13 | unless arg.respond_to?('to_s') then 14 | raise Puppet::ParseError, ("#{arg.inspect} is not a string. It looks to be a #{arg.class}") 15 | end 16 | 17 | arg = arg.to_s 18 | begin 19 | int_val = IPAddr.new(arg).to_i 20 | [int_val].pack('L').unpack('l')[0] # Pack as unsigned int, unpack as signed int 21 | rescue ArgumentError => e 22 | raise Puppet::ParseError, (e) 23 | end 24 | end 25 | 26 | end 27 | 28 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/mac_to_eui64.rb: -------------------------------------------------------------------------------- 1 | # Generate EUI64 used by IPv6 auto address from a MAC address 2 | # 3 | # Example: 4 | # mac_to_eui64("52:54:00:12:09:f3") 5 | # > "5054:00ff:fe12:09f3" 6 | 7 | module Puppet::Parser::Functions 8 | newfunction(:mac_to_eui64, :type => :rvalue) do |a| 9 | if (a.size != 1) then 10 | raise(Puppet::ParseError, "mac_to_eui64(): Wrong number of arguments "+ 11 | "given #{a.size} for 1.") 12 | end 13 | 14 | Puppet::Parser::Functions.autoloader.loadall 15 | 16 | macString = a[0] 17 | 18 | unless (macString =~ /^[0-9a-f]{2}(:[0-9a-f]{2}){5}$/i) then 19 | raise(Puppet::ParseError, "mac_to_eui64(): Argument must be a MAC address") 20 | end 21 | 22 | mac = macString.split(":") 23 | 24 | eui64 = (mac[0].to_i(16)^2).to_s(16)+mac[1]+":"+mac[2]+"ff:fe"+mac[3]+":"+mac[4]+mac[5] 25 | 26 | eui64 27 | end 28 | end -------------------------------------------------------------------------------- /lib/puppet/parser/functions/netmask_to_masklen.rb: -------------------------------------------------------------------------------- 1 | module Puppet::Parser::Functions 2 | 3 | newfunction(:netmask_to_masklen, :type => :rvalue, :doc => <<-'ENDHEREDOC' 4 | Converts a netmask of the form 255.255.0.0 to the mask length (e.g. 16) 5 | 6 | ENDHEREDOC 7 | ) do |args| 8 | 9 | unless args.length == 1 then 10 | raise Puppet::ParseError, ("netmask_to_masklen(): wrong number of arguments (#{args.length}; must be 1)") 11 | end 12 | arg = args[0] 13 | unless arg.respond_to?('to_s') then 14 | raise Puppet::ParseError, ("#{arg.inspect} is not a string. It looks to be a #{arg.class}") 15 | end 16 | 17 | arg = arg.to_s 18 | begin 19 | IPAddr.new(arg).to_i.to_s(2).count('1') 20 | rescue ArgumentError => e 21 | raise Puppet::ParseError, (e) 22 | end 23 | end 24 | 25 | end 26 | 27 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/parse_http_uri.rb: -------------------------------------------------------------------------------- 1 | require 'uri' 2 | 3 | module Puppet::Parser::Functions 4 | newfunction(:parse_http_uri, :type => :rvalue) do |args| 5 | raise(Puppet::ParseError, 6 | 'parse_http_uri: wrong number of args') if args.size != 1 7 | 8 | begin 9 | uri = URI(args.first) 10 | raise "Only supports http or https" unless uri.scheme.downcase =~ /^http/ 11 | rescue => e 12 | raise Puppet::ParseError, "bad arg in parse_http_uri - '#{args.inspect}': #{e}" 13 | end 14 | 15 | { 16 | 'scheme' => uri.scheme.downcase, 17 | 'host' => uri.host.downcase, 18 | 'path' => uri.path.empty? ? '/' : uri.path, 19 | } 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/puppet/provider/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yelp/puppet-netstdlib/5a62ea51c1371b797e905afe6aa2d519db92e062/lib/puppet/provider/.gitkeep -------------------------------------------------------------------------------- /lib/puppet/type/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yelp/puppet-netstdlib/5a62ea51c1371b797e905afe6aa2d519db92e062/lib/puppet/type/.gitkeep -------------------------------------------------------------------------------- /metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yelp-netstdlib", 3 | "version": "0.0.1", 4 | "author": "yelp", 5 | "summary": "A collection of network functions and facts", 6 | "license": "Apache License, Version 2.0", 7 | "source": "https://github.com/Yelp/puppet-netstdlib.git", 8 | "project_page": "https://github.com/Yelp/puppet-netstdlib", 9 | "issues_url": "https://github.com/Yelp/puppet-netstdlib/issues", 10 | "description": "A collection of network functions and facts", 11 | "dependencies": [ 12 | {"name":"puppetlabs/stdlib"} 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /spec/acceptance/class_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper_acceptance' 2 | 3 | describe 'netstdlib class' do 4 | 5 | context 'default parameters' do 6 | # Using puppet_apply as a helper 7 | it 'should work with no errors' do 8 | pp = <<-EOS 9 | class { 'netstdlib': } 10 | EOS 11 | 12 | # Run it twice and test for idempotency 13 | expect(apply_manifest(pp).exit_code).to_not eq(1) 14 | expect(apply_manifest(pp).exit_code).to eq(0) 15 | end 16 | 17 | describe package('netstdlib') do 18 | it { should be_installed } 19 | end 20 | 21 | describe service('netstdlib') do 22 | it { should be_enabled } 23 | it { should be_running } 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /spec/acceptance/nodesets/centos-64-x64.yml: -------------------------------------------------------------------------------- 1 | HOSTS: 2 | centos-64-x64: 3 | roles: 4 | - master 5 | platform: el-6-x86_64 6 | box : centos-64-x64-vbox4210-nocm 7 | box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box 8 | hypervisor : vagrant 9 | CONFIG: 10 | log_level: verbose 11 | type: foss 12 | -------------------------------------------------------------------------------- /spec/acceptance/nodesets/default.yml: -------------------------------------------------------------------------------- 1 | HOSTS: 2 | ubuntu-server-12042-x64: 3 | roles: 4 | - master 5 | platform: ubuntu-server-12.04-amd64 6 | box: ubuntu-server-12042-x64-vbox4210-nocm 7 | box_url: http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box 8 | hypervisor: vagrant 9 | 10 | CONFIG: 11 | log_level: verbose 12 | type: foss 13 | -------------------------------------------------------------------------------- /spec/acceptance/nodesets/ubuntu-server-12042-x64.yml: -------------------------------------------------------------------------------- 1 | HOSTS: 2 | ubuntu-server-12042-x64: 3 | roles: 4 | - master 5 | platform: ubuntu-server-12.04-amd64 6 | box: ubuntu-server-12042-x64-vbox4210-nocm 7 | box_url: http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box 8 | hypervisor: vagrant 9 | 10 | CONFIG: 11 | log_level: verbose 12 | type: foss 13 | -------------------------------------------------------------------------------- /spec/classes/coverage_spec.rb: -------------------------------------------------------------------------------- 1 | at_exit { RSpec::Puppet::Coverage.report! } 2 | -------------------------------------------------------------------------------- /spec/functions/cidr_to_broadcast_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'cidr_to_broadcast' do 4 | cidr = '192.168.1.12/24' 5 | 6 | it { should run.with_params(cidr).and_return('192.168.1.255') } 7 | 8 | it 'should work' do 9 | expect { subject.call([cidr]) }.not_to raise_error() 10 | end 11 | 12 | it 'should fail with no args' do 13 | expect { subject.call([]) }.to raise_error(Puppet::ParseError) 14 | end 15 | it 'should fail with :undef' do 16 | expect { subject.call([:undef]) }.to raise_error(Puppet::ParseError) 17 | end 18 | it 'should fail with many args' do 19 | expect { subject.call(['foo', 'bar']) }.to raise_error(Puppet::ParseError) 20 | end 21 | it 'should fail if given insane data type' do 22 | expect { subject.call([ [] ]) }.to raise_error(Puppet::ParseError) 23 | end 24 | end 25 | 26 | -------------------------------------------------------------------------------- /spec/functions/cidr_to_netmask_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'cidr_to_netmask' do 4 | cidr = '192.168.1.12/24' 5 | 6 | it { should run.with_params(cidr).and_return('255.255.255.0') } 7 | 8 | it 'should work' do 9 | expect { subject.call([cidr]) }.not_to raise_error() 10 | end 11 | 12 | it 'should fail with no args' do 13 | expect { subject.call([]) }.to raise_error(Puppet::ParseError) 14 | end 15 | it 'should fail with :undef' do 16 | expect { subject.call([:undef]) }.to raise_error(Puppet::ParseError) 17 | end 18 | it 'should fail with many args' do 19 | expect { subject.call(['foo', 'bar']) }.to raise_error(Puppet::ParseError) 20 | end 21 | it 'should fail if given insane data type' do 22 | expect { subject.call([ [] ]) }.to raise_error(Puppet::ParseError) 23 | end 24 | end 25 | 26 | -------------------------------------------------------------------------------- /spec/functions/cidr_to_network_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'cidr_to_network' do 4 | cidr = '192.168.1.12/24' 5 | 6 | it { should run.with_params(cidr).and_return('192.168.1.0') } 7 | 8 | it 'should work' do 9 | expect { subject.call([cidr]) }.not_to raise_error() 10 | end 11 | 12 | it 'should fail with no args' do 13 | expect { subject.call([]) }.to raise_error(Puppet::ParseError) 14 | end 15 | it 'should fail with :undef' do 16 | expect { subject.call([:undef]) }.to raise_error(Puppet::ParseError) 17 | end 18 | it 'should fail with many args' do 19 | expect { subject.call(['foo', 'bar']) }.to raise_error(Puppet::ParseError) 20 | end 21 | it 'should fail if given insane data type' do 22 | expect { subject.call([ [] ]) }.to raise_error(Puppet::ParseError) 23 | end 24 | end 25 | 26 | -------------------------------------------------------------------------------- /spec/functions/cidr_to_range_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'cidr_to_range' do 4 | let (:cidr) { '192.168.1.0/29' } 5 | 6 | it 'should return the range ips excluding the network and broadcast addresses' do 7 | ips = [ 8 | '192.168.1.1', 9 | '192.168.1.2', 10 | '192.168.1.3', 11 | '192.168.1.4', 12 | '192.168.1.5', 13 | '192.168.1.6', 14 | ] 15 | should run.with_params(cidr).and_return(ips) 16 | end 17 | 18 | it 'should work' do 19 | expect { subject.call([cidr]) }.not_to raise_error() 20 | end 21 | 22 | it 'should fail with no args' do 23 | expect { subject.call([]) }.to raise_error(Puppet::ParseError) 24 | end 25 | it 'should fail with :undef' do 26 | expect { subject.call([:undef]) }.to raise_error(Puppet::ParseError) 27 | end 28 | it 'should fail with many args' do 29 | expect { subject.call(['foo', 'bar']) }.to raise_error(Puppet::ParseError) 30 | end 31 | it 'should fail if given insane data type' do 32 | expect { subject.call([ [] ]) }.to raise_error(Puppet::ParseError) 33 | end 34 | 35 | context "with a /32 cidr" do 36 | let (:cidr) { '192.168.1.0/32' } 37 | 38 | it 'should return an empty list' do 39 | should run.with_params(cidr).and_return([]) 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/functions/int_to_ip_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'int_to_ip' do 4 | int = 3232235788 5 | 6 | it { should run.with_params(int).and_return('192.168.1.12') } 7 | 8 | it 'should work' do 9 | expect { subject.call([int]) }.not_to raise_error() 10 | end 11 | 12 | it 'should fail with no args' do 13 | expect { subject.call([]) }.to raise_error(Puppet::ParseError) 14 | end 15 | it 'should fail with foobar' do 16 | expect { subject.call(['foobar']) }.to raise_error(Puppet::ParseError) 17 | end 18 | it 'should fail with many args' do 19 | expect { subject.call(['foo', 'bar']) }.to raise_error(Puppet::ParseError) 20 | end 21 | it 'should fail if given insane data type' do 22 | expect { subject.call([ [] ]) }.to raise_error(Puppet::ParseError) 23 | end 24 | end 25 | 26 | -------------------------------------------------------------------------------- /spec/functions/ip_in_cidr_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'ip_in_cidr' do 4 | cidr = '192.168.1.12/24' 5 | 6 | [ 7 | '192.168.1.0', 8 | '192.168.1.12', 9 | '192.168.1.255', 10 | '192.168.1.66' 11 | ].each do |ip| 12 | it { should run.with_params(ip, cidr).and_return true } 13 | end 14 | 15 | [ 16 | '192.168.0.255', 17 | '255.255.255.0' 18 | ].each do |ip| 19 | it { should run.with_params(ip, cidr).and_return false } 20 | end 21 | 22 | it 'should work' do 23 | expect { subject.call(['17.0.0.1', cidr]) }.not_to raise_error() 24 | end 25 | 26 | it 'should fail with no args' do 27 | expect { subject.call([]) }.to raise_error(Puppet::ParseError) 28 | end 29 | it 'should fail with one args' do 30 | expect { subject.call(['foo']) }.to raise_error(Puppet::ParseError) 31 | end 32 | it 'should fail with many args' do 33 | expect { subject.call(['foo', 'bar', 'baz']) }.to raise_error(Puppet::ParseError) 34 | end 35 | it 'should fail if given insane data type' do 36 | expect { subject.call([ [] ]) }.to raise_error(Puppet::ParseError) 37 | end 38 | end 39 | 40 | -------------------------------------------------------------------------------- /spec/functions/ip_to_int_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'ip_to_int' do 4 | ip = '192.168.1.12' 5 | 6 | it { should run.with_params(ip).and_return(3232235788) } 7 | 8 | it 'should work' do 9 | expect { subject.call([ip]) }.not_to raise_error() 10 | end 11 | 12 | it 'should fail with no args' do 13 | expect { subject.call([]) }.to raise_error(Puppet::ParseError) 14 | end 15 | it 'should fail with :undef' do 16 | expect { subject.call([:undef]) }.to raise_error(Puppet::ParseError) 17 | end 18 | it 'should fail with many args' do 19 | expect { subject.call(['foo', 'bar']) }.to raise_error(Puppet::ParseError) 20 | end 21 | it 'should fail if given insane data type' do 22 | expect { subject.call([ [] ]) }.to raise_error(Puppet::ParseError) 23 | end 24 | end 25 | 26 | -------------------------------------------------------------------------------- /spec/functions/ip_to_signed_int_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'ip_to_signed_int' do 4 | lo_ip = '10.1.2.3' 5 | hi_ip = '192.168.1.12' 6 | 7 | it { should run.with_params(lo_ip).and_return(167838211) } 8 | 9 | it { should run.with_params(hi_ip).and_return(-1062731508) } 10 | 11 | it 'should work' do 12 | expect { subject.call([lo_ip]) }.not_to raise_error() 13 | end 14 | 15 | it 'should work' do 16 | expect { subject.call([hi_ip]) }.not_to raise_error() 17 | end 18 | 19 | it 'should fail with no args' do 20 | expect { subject.call([]) }.to raise_error(Puppet::ParseError) 21 | end 22 | it 'should fail with :undef' do 23 | expect { subject.call([:undef]) }.to raise_error(Puppet::ParseError) 24 | end 25 | it 'should fail with many args' do 26 | expect { subject.call(['foo', 'bar']) }.to raise_error(Puppet::ParseError) 27 | end 28 | it 'should fail if given insane data type' do 29 | expect { subject.call([ [] ]) }.to raise_error(Puppet::ParseError) 30 | end 31 | end 32 | 33 | -------------------------------------------------------------------------------- /spec/functions/mac_to_eui64_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'mac_to_eui64' do 4 | 5 | mac = '52:54:00:12:09:f3' 6 | 7 | it { should run.with_params(mac).and_return('5054:00ff:fe12:09f3') } 8 | 9 | it 'should work' do 10 | expect { subject.call([mac]) }.not_to raise_error() 11 | end 12 | 13 | it 'should fail with invalid mac' do 14 | expect { subject.call(['aaa:bb:cc:dd:ee:ff']) }.to raise_error(Puppet::ParseError) 15 | end 16 | it 'should fail with no args' do 17 | expect { subject.call([]) }.to raise_error(Puppet::ParseError) 18 | end 19 | it 'should fail with :undef' do 20 | expect { subject.call([:undef]) }.to raise_error(Puppet::ParseError) 21 | end 22 | it 'should fail with many args' do 23 | expect { subject.call(['foo', 'bar']) }.to raise_error(Puppet::ParseError) 24 | end 25 | it 'should fail if given insane data type' do 26 | expect { subject.call([ [] ]) }.to raise_error(Puppet::ParseError) 27 | end 28 | 29 | end 30 | 31 | -------------------------------------------------------------------------------- /spec/functions/netmask_to_masklen_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'netmask_to_masklen' do 4 | { 5 | '255.255.255.0' => 24, 6 | '255.255.255.128' => 25, 7 | '255.255.0.0' => 16, 8 | }.each do |mask, len| 9 | it { should run.with_params(mask).and_return(len) } 10 | end 11 | 12 | it 'should fail with no args' do 13 | expect { subject.call([]) }.to raise_error(Puppet::ParseError) 14 | end 15 | it 'should fail with one args' do 16 | expect { subject.call(['foo']) }.to raise_error(Puppet::ParseError) 17 | end 18 | it 'should fail with many args' do 19 | expect { subject.call(['foo', 'bar', 'baz']) }.to raise_error(Puppet::ParseError) 20 | end 21 | it 'should fail if given insane data type' do 22 | expect { subject.call([ [] ]) }.to raise_error(Puppet::ParseError) 23 | end 24 | end 25 | 26 | -------------------------------------------------------------------------------- /spec/functions/parse_http_uri_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'parse_http_uri' do 4 | 5 | it 'should fail with no args' do 6 | expect { subject.call([]) }.to \ 7 | raise_error Puppet::ParseError, /number of args/ 8 | end 9 | 10 | it 'should fail with many args' do 11 | expect { subject.call([:undef, :undef1]) }.to \ 12 | raise_error Puppet::ParseError, /number of args/ 13 | end 14 | 15 | it 'should fail with non-http uri' do 16 | expect { subject.call(['smtp://foo.bar']) }.to \ 17 | raise_error Puppet::ParseError, /http or https/ 18 | end 19 | 20 | it 'should fail with undef' do 21 | expect { subject.call([:undef]) }.to \ 22 | raise_error Puppet::ParseError, /bad argument/ 23 | end 24 | 25 | it 'should fail with insane data type' do 26 | expect { subject.call([ [] ]) }.to \ 27 | raise_error Puppet::ParseError, /bad argument/ 28 | end 29 | 30 | it 'should work for http uri' do 31 | should run.with_params('HTTP://example.com').and_return({ 32 | 'scheme' => 'http', 33 | 'host' => 'example.com', 34 | 'path' => '/', 35 | }) 36 | end 37 | 38 | it 'should work for http with trailing / and no path' do 39 | should run.with_params('http://example.com/').and_return({ 40 | 'scheme' => 'http', 41 | 'host' => 'example.com', 42 | 'path' => '/', 43 | }) 44 | end 45 | 46 | it 'should work for https uri' do 47 | should run.with_params('https://example.COM/foo/BAR').and_return({ 48 | 'scheme' => 'https', 49 | 'host' => 'example.com', 50 | 'path' => '/foo/BAR', 51 | }) 52 | end 53 | 54 | end 55 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'puppetlabs_spec_helper/module_spec_helper' 2 | -------------------------------------------------------------------------------- /spec/spec_helper_acceptance.rb: -------------------------------------------------------------------------------- 1 | require 'beaker-rspec/spec_helper' 2 | require 'beaker-rspec/helpers/serverspec' 3 | 4 | hosts.each do |host| 5 | # Install Puppet 6 | install_puppet 7 | end 8 | 9 | RSpec.configure do |c| 10 | # Project root 11 | proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) 12 | 13 | # Readable test descriptions 14 | c.formatter = :documentation 15 | 16 | # Configure all nodes in nodeset 17 | c.before :suite do 18 | # Install module and dependencies 19 | puppet_module_install(:source => proj_root, :module_name => 'netstdlib') 20 | hosts.each do |host| 21 | on host, puppet('module', 'install', 'puppetlabs-stdlib'), { :acceptable_exit_codes => [0,1] } 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /tests/init.pp: -------------------------------------------------------------------------------- 1 | # The baseline for module testing used by Puppet Labs is that each manifest 2 | # should have a corresponding test manifest that declares that class or defined 3 | # type. 4 | # 5 | # Tests are then run by using puppet apply --noop (to check for compilation 6 | # errors and view a log of events) or by fully applying the test in a virtual 7 | # environment (to compare the resulting system state to the desired state). 8 | # 9 | # Learn more about module testing here: 10 | # http://docs.puppetlabs.com/guides/tests_smoke.html 11 | # 12 | include netstdlib 13 | --------------------------------------------------------------------------------