From 49d269d0374c0d0e8759c11ac04956b6a1941d01 Mon Sep 17 00:00:00 2001 From: Tim Meusel Date: Sat, 19 Sep 2020 21:57:41 +0200 Subject: [PATCH] Implement hyperglass-agent support --- REFERENCE.md | 50 ++++++++++++++++++++ files/hyperglass-agent.service | 14 ++++++ files/hyperglass.service | 6 +-- manifests/agent.pp | 28 +++++++++++- manifests/agent/config.pp | 17 +++++++ manifests/agent/install.pp | 58 ++++++++++++++++++++++++ manifests/agent/service.pp | 13 ++++++ manifests/gcc.pp | 11 +++++ manifests/hyperglassdir.pp | 14 ++++++ manifests/python.pp | 13 ++++++ manifests/server.pp | 11 +++-- manifests/server/config.pp | 8 ++-- manifests/server/dependencies.pp | 15 ++++-- manifests/server/install.pp | 22 ++++----- manifests/server/service.pp | 4 +- spec/acceptance/agent_and_server_spec.rb | 18 ++++++++ spec/acceptance/agent_spec.rb | 26 +++++++++++ spec/acceptance/server_spec.rb | 6 +-- spec/classes/hyperglass_server_spec.rb | 18 ++++---- 19 files changed, 308 insertions(+), 44 deletions(-) create mode 100644 files/hyperglass-agent.service create mode 100644 manifests/agent/config.pp create mode 100644 manifests/agent/install.pp create mode 100644 manifests/agent/service.pp create mode 100644 manifests/gcc.pp create mode 100644 manifests/hyperglassdir.pp create mode 100644 manifests/python.pp create mode 100644 spec/acceptance/agent_and_server_spec.rb create mode 100644 spec/acceptance/agent_spec.rb diff --git a/REFERENCE.md b/REFERENCE.md index a498972..bfb0048 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -13,6 +13,12 @@ #### Private Classes +* `hyperglass::agent::config`: configures the hyperglass looking agent +* `hyperglass::agent::install`: installs the hyperglass agent on linux nodes +* `hyperglass::agent::service`: manages the hyperglass agent service + unit file +* `hyperglass::gcc`: module to workaround the broken puppetlabs/gcc class. Installs just gcc +* `hyperglass::hyperglassdir`: private class to create the main dir for hyperglass server and agent +* `hyperglass::python`: private class used by server/agent to install python3 * `hyperglass::server::config`: writes the hyperglass config files * `hyperglass::server::dependencies`: private class that installs all the services hyperglass depends on * `hyperglass::server::install`: installs the hyperglass server @@ -27,6 +33,34 @@ installs the hyperglass linux agent * **See also** * https://github.com/checktheroads/hyperglass-agent +#### Parameters + +The following parameters are available in the `hyperglass::agent` class. + +##### `manage_python` + +Data type: `Boolean` + +installs python3 + +Default value: ``true`` + +##### `manage_gcc` + +Data type: `Boolean` + +installs gcc + +Default value: ``true`` + +##### `data` + +Data type: `Hash` + +generic hyperglass configuration hash. + +Default value: `{}` + ### `hyperglass::server` installs the hyperglass looking glass @@ -46,6 +80,22 @@ if true, installs all other services that hyperglass requires, like redis, yarn, Default value: ``true`` +##### `manage_python` + +Data type: `Boolean` + +installs python3 + +Default value: ``true`` + +##### `manage_gcc` + +Data type: `Boolean` + +installs gcc + +Default value: ``true`` + ##### `devices` Data type: `Hash` diff --git a/files/hyperglass-agent.service b/files/hyperglass-agent.service new file mode 100644 index 0000000..2a7ba91 --- /dev/null +++ b/files/hyperglass-agent.service @@ -0,0 +1,14 @@ +# THIS FILE IS MANAGED BY PUPPET +[Unit] +Description=hyperglass looking glass agent +After=network.target + +[Service] +User=hyperglass-agent +Group=hyperglass-agent +WorkingDirectory=/opt/hyperglass/hyperglass-server +ExecStart=/opt/hyperglass/hyperglass-server/virtualenv/bin/python3 /opt/hyperglass/hyperglass-server/virtualenv/bin/hyperglass-agent start +PrivateTmp=true + +[Install] +WantedBy=multi-user.target diff --git a/files/hyperglass.service b/files/hyperglass.service index 367c654..56d232f 100644 --- a/files/hyperglass.service +++ b/files/hyperglass.service @@ -2,13 +2,13 @@ [Unit] Description=hyperglass looking glass server After=network.target -Requires=rh-redis5-redis +Requires=rh-redis5-redis.service [Service] User=hyperglass Group=hyperglass -WorkingDirectory=/opt/hyperglass -ExecStart=/opt/hyperglass/virtualenv/bin/python3 /opt/hyperglass/virtualenv/bin/hyperglass start +WorkingDirectory=/opt/hyperglass/hyperglass-server +ExecStart=/opt/hyperglass/hyperglass-server/virtualenv/bin/python3 /opt/hyperglass/hyperglass-server/virtualenv/bin/hyperglass start PrivateTmp=true [Install] diff --git a/manifests/agent.pp b/manifests/agent.pp index 5bf3fbd..61d87a6 100644 --- a/manifests/agent.pp +++ b/manifests/agent.pp @@ -1,6 +1,30 @@ # @summary installs the hyperglass linux agent # +# @param manage_python installs python3 +# @param manage_gcc installs gcc +# @param data generic hyperglass configuration hash. +# # @see https://github.com/checktheroads/hyperglass-agent # -# @author Tim Meusel -class hyperglass::agent {} +# @author Tim Meusel +class hyperglass::agent ( + Boolean $manage_python = true, + Boolean $manage_gcc = true, + Hash $data = { + 'debug' => true, + 'listen_address' => '127.0.0.1', + 'mode' => 'bird', + 'secret' => fqdn_rand_string(20), + 'ssl' => { + 'enable' => false, + }, + }, +) { + require hyperglass::hyperglassdir + contain hyperglass::agent::install + contain hyperglass::agent::config + contain hyperglass::agent::service + Class['hyperglass::agent::install'] + -> Class['hyperglass::agent::config'] + ~> Class['hyperglass::agent::service'] +} diff --git a/manifests/agent/config.pp b/manifests/agent/config.pp new file mode 100644 index 0000000..3f3dd97 --- /dev/null +++ b/manifests/agent/config.pp @@ -0,0 +1,17 @@ +# @summary configures the hyperglass looking agent +# +# @api private +# +class hyperglass::agent::config ( + Hash $data = $hyperglass::agent::data, +) { + assert_private() + + file { '/opt/hyperglass/hyperglass-agent/hyperglass-agent/config.yaml': + ensure => 'file', + owner => 'hyperglass-agent', + group => 'hyperglass-agent', + mode => '0400', + content => to_yaml($data), + } +} diff --git a/manifests/agent/install.pp b/manifests/agent/install.pp new file mode 100644 index 0000000..07de3c2 --- /dev/null +++ b/manifests/agent/install.pp @@ -0,0 +1,58 @@ +# @summary installs the hyperglass agent on linux nodes +# +# @api private +# +# @author Tim Meusel +class hyperglass::agent::install ( + Boolean $manage_python = $hyperglass::agent::manage_python, + Boolean $manage_gcc = $hyperglass::agent::manage_gcc, +) { + assert_private() + + if $manage_python { + require hyperglass::python + } + if $manage_gcc { + require hyperglass::gcc + } + user { 'hyperglass-agent': + ensure => 'present', + managehome => true, + purge_ssh_keys => true, + system => true, + home => '/opt/hyperglass/hyperglass-agent', + } + group { 'hyperglass-agent': + ensure => 'present', + system => true, + } + + file { '/opt/hyperglass/hyperglass-agent': + ensure => 'directory', + owner => 'hyperglass-agent', + group => 'hyperglass-agent', + } + + # we need to explicitly set the version here. During the first puppet run, python3 will be installed but isn't present yet + # due to that the fact is undef and fails. the default of the `version` attribute is the fact. We workaround this by hardcoding + # the python version + python::pyvenv { '/opt/hyperglass/hyperglass-agent/virtualenv': + ensure => 'present', + owner => 'hyperglass-agent', + group => 'hyperglass-agent', + systempkgs => false, + version => pick($facts['python3_version'], '3.6'), + } + + python::pip { 'hyperglass-agent': + virtualenv => '/opt/hyperglass/hyperglass-agent/virtualenv', + owner => 'hyperglass-agent', + group => 'hyperglass-agent', + } + + file { '/opt/hyperglass/hyperglass-agent/hyperglass-agent': + ensure => 'directory', + owner => 'hyperglass-agent', + group => 'hyperglass-agent', + } +} diff --git a/manifests/agent/service.pp b/manifests/agent/service.pp new file mode 100644 index 0000000..21911cc --- /dev/null +++ b/manifests/agent/service.pp @@ -0,0 +1,13 @@ +# @summary manages the hyperglass agent service + unit file +# +# @api private +# +# @author Tim Meusel +class hyperglass::agent::service { + assert_private() + systemd::unit_file { 'hyperglass-agent.service': + source => "puppet:///modules/${module_name}/hyperglass-agent.service", + enable => true, + active => true, + } +} diff --git a/manifests/gcc.pp b/manifests/gcc.pp new file mode 100644 index 0000000..5e34748 --- /dev/null +++ b/manifests/gcc.pp @@ -0,0 +1,11 @@ +# @summary module to workaround the broken puppetlabs/gcc class. Installs just gcc +# +# @api private +# +# @author Tim Meusel +class hyperglass::gcc { + assert_private() + package { 'gcc': + ensure => 'installed', + } +} diff --git a/manifests/hyperglassdir.pp b/manifests/hyperglassdir.pp new file mode 100644 index 0000000..9292682 --- /dev/null +++ b/manifests/hyperglassdir.pp @@ -0,0 +1,14 @@ +# @summary private class to create the main dir for hyperglass server and agent +# +# @api private +# +# @author Tim Meusel +class hyperglass::hyperglassdir { + assert_private() + + file { '/opt/hyperglass/': + ensure => 'directory', + owner => 'root', + group => 'root', + } +} diff --git a/manifests/python.pp b/manifests/python.pp new file mode 100644 index 0000000..26863c7 --- /dev/null +++ b/manifests/python.pp @@ -0,0 +1,13 @@ +# @summary private class used by server/agent to install python3 +# +# @api private +# +# @author Tim Meusel +class hyperglass::python { + assert_private() + + class { 'python': + version => '3', + dev => 'present', + } +} diff --git a/manifests/server.pp b/manifests/server.pp index 53d82b8..e2a3f68 100644 --- a/manifests/server.pp +++ b/manifests/server.pp @@ -1,15 +1,19 @@ # @summary installs the hyperglass looking glass # # @param manage_depended_services if true, installs all other services that hyperglass requires, like redis, yarn, nginx, python +# @param manage_python installs python3 +# @param manage_gcc installs gcc # @param devices hash containing all the devices hyperglass can connect to. Defaults to demo data so the service starts properly. # @param commands specific commands that can be used by the devices # @param data generic hyperglass configuration hash. # # @see https://hyperglass.io/ # -# @author Tim Meusel +# @author Tim Meusel class hyperglass::server ( Boolean $manage_depended_services = true, + Boolean $manage_python = true, + Boolean $manage_gcc = true, Hash $data = {}, Hash $commands = {}, Hash $devices = { @@ -46,11 +50,10 @@ } if $manage_depended_services { - contain hyperglass::server::dependencies - Class['hyperglass::server::dependencies'] - -> Class['hyperglass::server::install'] + require hyperglass::server::dependencies } + require hyperglass::hyperglassdir contain hyperglass::server::install contain hyperglass::server::config contain hyperglass::server::service diff --git a/manifests/server/config.pp b/manifests/server/config.pp index f707473..b644e89 100644 --- a/manifests/server/config.pp +++ b/manifests/server/config.pp @@ -6,27 +6,27 @@ # # @api private # -# @author Tim Meusel +# @author Tim Meusel class hyperglass::server::config ( Hash $devices = $hyperglass::server::devices, Hash $data = $hyperglass::server::data, Hash $commands = $hyperglass::server::commands, ) { assert_private() - file { '/opt/hyperglass/hyperglass/hyperglass.yaml': + file { '/opt/hyperglass/hyperglass-server/hyperglass/hyperglass.yaml': ensure => 'file', owner => 'hyperglass', group => 'hyperglass', content => to_yaml($data), } - file { '/opt/hyperglass/hyperglass/commands.yaml': + file { '/opt/hyperglass/hyperglass-server/hyperglass/commands.yaml': ensure => 'file', owner => 'hyperglass', group => 'hyperglass', content => to_yaml($commands), } - file { '/opt/hyperglass/hyperglass/devices.yaml': + file { '/opt/hyperglass/hyperglass-server/hyperglass/devices.yaml': ensure => 'file', owner => 'hyperglass', group => 'hyperglass', diff --git a/manifests/server/dependencies.pp b/manifests/server/dependencies.pp index 593e547..0f92961 100644 --- a/manifests/server/dependencies.pp +++ b/manifests/server/dependencies.pp @@ -2,14 +2,19 @@ # # @api private # -# @author Tim Meusel -class hyperglass::server::dependencies { +# @author Tim Meusel +class hyperglass::server::dependencies ( + Boolean $manage_python = $hyperglass::server::manage_python, + Boolean $manage_gcc = $hyperglass::server::manage_gcc, +) { assert_private() - package { ['python3-pip', 'python3-devel', 'gcc']: - ensure => 'installed', + if $manage_python { + require hyperglass::python + } + if $manage_gcc { + require hyperglass::gcc } - class { 'redis::globals': scl => 'rh-redis5', } diff --git a/manifests/server/install.pp b/manifests/server/install.pp index 4f381be..55ea061 100644 --- a/manifests/server/install.pp +++ b/manifests/server/install.pp @@ -2,7 +2,7 @@ # # @api private # -# @author Tim Meusel +# @author Tim Meusel class hyperglass::server::install { assert_private() user { 'hyperglass': @@ -10,42 +10,42 @@ managehome => true, purge_ssh_keys => true, system => true, - home => '/opt/hyperglass', + home => '/opt/hyperglass/hyperglass-server', } group { 'hyperglass': ensure => 'present', system => true, } - file { '/opt/hyperglass/hyperglass': + file { '/opt/hyperglass/hyperglass-server/hyperglass': ensure => 'directory', owner => 'hyperglass', group => 'hyperglass', } - file { '/opt/hyperglass/hyperglass/static': + file { '/opt/hyperglass/hyperglass-server/hyperglass/static': ensure => 'directory', owner => 'hyperglass', group => 'hyperglass', - require => File['/opt/hyperglass/hyperglass'], + require => File['/opt/hyperglass/hyperglass-server/hyperglass'], } - file { ['/opt/hyperglass/hyperglass/static/ui', '/opt/hyperglass/hyperglass/static/images', '/opt/hyperglass/hyperglass/static/custom']: + file { ['/opt/hyperglass/hyperglass-server/hyperglass/static/ui', '/opt/hyperglass/hyperglass-server/hyperglass/static/images', '/opt/hyperglass/hyperglass-server/hyperglass/static/custom']: ensure => 'directory', owner => 'hyperglass', group => 'hyperglass', - require => File['/opt/hyperglass/hyperglass/static'], + require => File['/opt/hyperglass/hyperglass-server/hyperglass/static'], } - file { '/opt/hyperglass/hyperglass/static/images/favicons': + file { '/opt/hyperglass/hyperglass-server/hyperglass/static/images/favicons': ensure => 'directory', owner => 'hyperglass', group => 'hyperglass', - require => File['/opt/hyperglass/hyperglass/static/images'], + require => File['/opt/hyperglass/hyperglass-server/hyperglass/static/images'], } # we need to explicitly set the version here. During the first puppet run, python3 will be installed but isn't present yet # due to that the fact is undef and fails. the default of the `version` attribute is the fact. We workaround this by hardcoding # the python version - python::pyvenv { '/opt/hyperglass/virtualenv': + python::pyvenv { '/opt/hyperglass/hyperglass-server/virtualenv': ensure => 'present', owner => 'hyperglass', group => 'hyperglass', @@ -54,7 +54,7 @@ } python::pip { 'hyperglass': - virtualenv => '/opt/hyperglass/virtualenv', + virtualenv => '/opt/hyperglass/hyperglass-server/virtualenv', owner => 'hyperglass', group => 'hyperglass', } diff --git a/manifests/server/service.pp b/manifests/server/service.pp index 05c7b0a..fd278cc 100644 --- a/manifests/server/service.pp +++ b/manifests/server/service.pp @@ -2,13 +2,13 @@ # # @api private # -# @author Tim Meusel +# @author Tim Meusel class hyperglass::server::service { assert_private() systemd::unit_file { 'hyperglass.service': source => "puppet:///modules/${module_name}/hyperglass.service", enable => true, active => true, - require => File['/opt/hyperglass/hyperglass/static/images'], + require => File['/opt/hyperglass/hyperglass-server/hyperglass/static/images'], } } diff --git a/spec/acceptance/agent_and_server_spec.rb b/spec/acceptance/agent_and_server_spec.rb new file mode 100644 index 0000000..a136529 --- /dev/null +++ b/spec/acceptance/agent_and_server_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper_acceptance' +require 'simp/beaker_helpers' + +include Simp::BeakerHelpers + +describe 'hyperglass::server class' do + context 'default parameters' do + # Using puppet_apply as a helper + it 'works with no errors' do + pp = 'include hyperglass::server; include hyperglass::agent' + + # Run it twice and test for idempotency + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_failures: true) # redis dependency needs two runs to start properly on selinux nodes + apply_manifest(pp, catch_changes: true) + end + end +end diff --git a/spec/acceptance/agent_spec.rb b/spec/acceptance/agent_spec.rb new file mode 100644 index 0000000..99d7879 --- /dev/null +++ b/spec/acceptance/agent_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper_acceptance' +require 'simp/beaker_helpers' + +include Simp::BeakerHelpers + +describe 'hyperglass::agent class' do + context 'default parameters' do + # Using puppet_apply as a helper + it 'works with no errors' do + pp = 'include hyperglass::agent' + + # Run it twice and test for idempotency + apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_changes: true) + end + + describe service('hyperglass-agent') do + it { is_expected.to be_running } + it { is_expected.to be_enabled } + end + + describe port(8080) do + it { is_expected.to be_listening.with('tcp') } + end + end +end diff --git a/spec/acceptance/server_spec.rb b/spec/acceptance/server_spec.rb index 4ce4f68..6e31371 100644 --- a/spec/acceptance/server_spec.rb +++ b/spec/acceptance/server_spec.rb @@ -6,11 +6,9 @@ it 'works with no errors' do pp = 'include hyperglass::server' - # Run it three times and test for idempotency - # redis dependency needs two run twice to start properly on selinux nodes - # selinux is only enabled in vagrant images, not docker - apply_manifest(pp, catch_failures: true) + # Run it twice and test for idempotency apply_manifest(pp, catch_failures: true) + apply_manifest(pp, catch_failures: true) # redis dependency needs two runs to start properly on selinux nodes apply_manifest(pp, catch_changes: true) end diff --git a/spec/classes/hyperglass_server_spec.rb b/spec/classes/hyperglass_server_spec.rb index 7e6eb11..7f0e678 100644 --- a/spec/classes/hyperglass_server_spec.rb +++ b/spec/classes/hyperglass_server_spec.rb @@ -19,15 +19,15 @@ it { is_expected.to contain_class('Hyperglass::Server::Dependencies') } it { is_expected.to contain_class('Hyperglass::Server::Install') } it { is_expected.to contain_class('Hyperglass::Server::Service') } - it { is_expected.to contain_file('/opt/hyperglass/hyperglass/commands.yaml').with_ensure('file').with_owner('hyperglass').with_group('hyperglass') } - it { is_expected.to contain_file('/opt/hyperglass/hyperglass/devices.yaml').with_ensure('file').with_owner('hyperglass').with_group('hyperglass') } - it { is_expected.to contain_file('/opt/hyperglass/hyperglass/hyperglass.yaml').with_ensure('file').with_owner('hyperglass').with_group('hyperglass') } - it { is_expected.to contain_file('/opt/hyperglass/hyperglass/static/custom').with_ensure('directory').with_owner('hyperglass').with_group('hyperglass') } - it { is_expected.to contain_file('/opt/hyperglass/hyperglass/static/images/favicons').with_ensure('directory').with_owner('hyperglass').with_group('hyperglass') } - it { is_expected.to contain_file('/opt/hyperglass/hyperglass/static/images').with_ensure('directory').with_owner('hyperglass').with_group('hyperglass') } - it { is_expected.to contain_file('/opt/hyperglass/hyperglass/static/ui').with_ensure('directory').with_owner('hyperglass').with_group('hyperglass') } - it { is_expected.to contain_file('/opt/hyperglass/hyperglass/static').with_ensure('directory').with_owner('hyperglass').with_group('hyperglass') } - it { is_expected.to contain_file('/opt/hyperglass/hyperglass').with_ensure('directory').with_owner('hyperglass').with_group('hyperglass') } + it { is_expected.to contain_file('/opt/hyperglass/hyperglass-server/hyperglass/commands.yaml').with_ensure('file').with_owner('hyperglass').with_group('hyperglass') } + it { is_expected.to contain_file('/opt/hyperglass/hyperglass-server/hyperglass/devices.yaml').with_ensure('file').with_owner('hyperglass').with_group('hyperglass') } + it { is_expected.to contain_file('/opt/hyperglass/hyperglass-server/hyperglass/hyperglass.yaml').with_ensure('file').with_owner('hyperglass').with_group('hyperglass') } + it { is_expected.to contain_file('/opt/hyperglass/hyperglass-server/hyperglass/static/custom').with_ensure('directory').with_owner('hyperglass').with_group('hyperglass') } + it { is_expected.to contain_file('/opt/hyperglass/hyperglass-server/hyperglass/static/images/favicons').with_ensure('directory').with_owner('hyperglass').with_group('hyperglass') } + it { is_expected.to contain_file('/opt/hyperglass/hyperglass-server/hyperglass/static/images').with_ensure('directory').with_owner('hyperglass').with_group('hyperglass') } + it { is_expected.to contain_file('/opt/hyperglass/hyperglass-server/hyperglass/static/ui').with_ensure('directory').with_owner('hyperglass').with_group('hyperglass') } + it { is_expected.to contain_file('/opt/hyperglass/hyperglass-server/hyperglass/static').with_ensure('directory').with_owner('hyperglass').with_group('hyperglass') } + it { is_expected.to contain_file('/opt/hyperglass/hyperglass-server/hyperglass').with_ensure('directory').with_owner('hyperglass').with_group('hyperglass') } end end end