Handling Two Puppet Classes with the Same Name - elasticsearch

I want to use the elasticsearch/elasticsearch module in my own module called rehan. The elasticsearch/elasticsearch module provides a class called elasticsearch. If I also want to create a class in my module that makes use of the one in elasticsearch/elasticsearch, how can I achieve this? I have tried:
class rehan::elasticsearch {
class { 'elasticsearch':
manage_repo => true,
repo_version => '2.2',
require => Class['java']
}
elasticsearch::instance { 'es-01':
require => Package['elasticsearch'],
}
}
The above code errors with:
Error: Duplicate declaration: Class[Rehan::Elasticsearch] is already declared; cannot redeclare at..

In Puppet 3 (even with the future parser!), you need to use:
class { '::elasticsearch':
manage_repo => true,
repo_version => '2.2',
require => Class['java']
}
In Puppet 4, the resolution rules for types, classes and variables changed (it doens't try to resolve them contextually), so your code is valid.

Related

Only run another PP file after one has completed

A chocolatey provider is required, to install packages this will work but only works once another pp file finishes executing.
The problem is that puppet evaluates both files under the node statement and errors on invalid provider; the problem is I run the first pp file by commenting the other out , then let it run & uncomment it then rerun with puppet agent --test it all works.
I have tried tags and used an if statement with the tag , but this doesn't seem to work either.
class windows::chocolatey {
exec { 'set_executionpolicy':
command => "set-executionpolicy unrestricted -force -scope process;
(iex((new-object
net.webclient).DownloadString('https://chocolatey.org/install.ps1')))>\$null
2>&1",
provider => 'powershell',
creates => 'C:/ProgramData/chocolatey',
}
node "web-iis-02" {
class { 'windows':} #chocolatey installing to allow atom.pp to work
class { 'atom': } # init.pp below install using chocolatey
#installs package
class atom {
if tagged(windows) {
include atom::pakages
notify { "Calling Pakagepp script": }
}
}
#if tagged init.pp above calls this:
class atom::pakages {
include chocolatey
package { 'Atom':
ensure => 'latest',
provider => 'chocolatey',
}
I get this from pakages.pp:
Error: Failed to apply catalog: Parameter provider failed on
Package[Atom]: Invalid package provider 'chocolatey' (file:
/etc/puppetlabs/code/environments/production/modules/atom/manifests/pakages.pp, line: 3)
Try adding a require dependency, so the atom class is declared after the windows class:
class { 'windows': }
class { 'atom':
require => Class['windows'],
}
or quick and dirty:
class { 'windows': }
-> class { 'atom': }
You'll need to remove that tagged condition as it isn't needed.
I can't quite tell from your question which classes depend on which, but I'm pretty sure it is require you need. You may need to add a require for the chocolatey class:
class { 'atom':
require => Class['windows', 'chocolatey'],
}

Function to read role, environment file in masterless puppet

I'm working with Puppet 4.5 in masterless configuration and am trying to create a Puppet function to read a simple config file that assigns roles and environments. I don't have any integration with hiera/facter that I can change.
The file format is:
host1::java_app_node::qa
host2::nodejs_app_node::prod
The Puppet function that will read this file is in a module called homebase. I want to function to return a hash or array of hashes that split the config values. This will let me use them in templates.
In modules/homebase/manifests/init.pp I define:
$role_file = 'puppet://role.lst'
I then created modules/homebase/functions/get_roles.pp as follows:
function homebase::get_roles() {
$func_name = 'homebase::get_roles()'
if ! File.exists?($::homebase::role_file) {
fail("Could not find #{$::homebase::role_file}")
}
hosts = { }
File.open($::homebase::role_file).each |line| {
parts = line.split(/::/)
hosts[parts[0]] = { 'host' => parts[0], 'role' => parts[1], 'env' => parts[2] }
}
return hosts
}
In other classes, I then want to call:
class myapp {
$servers = homebase::get_roles().each | k, v | {
$v['host'] if $v['role'] =~ /myapp/ && $v['env'] == $environment
}
file { 'myapp.cfg':
ensure => file,
path => '/opt/myapp/myapp.cfg',
source => template("/myapp/myapp.cfg.erb"),
mode => '0644',
owner => myuser,
group => myuser,
}
}
Seems like there would be a better way to do this. Am I completely off base?
There turned out to be a much easier way to this rather than try to create a function to read a non-standard configuration file. Instead, I used a site.pp file to create node {} entries. I also parameterized the myapp class to take inputs based on the node.
So my site.pp looks like:
node 'server1.mydomain', 'server2.mydomain' {
$myvar = [ 'val1', 'val2' ]
class { 'myapp':
values => $myvar
}
}
This could probably be improved. One of the issues is with a non-Puppet configuration file I was able to also able to control execution in my bash wrapper script. Much of the need for that went away when, though, with the node definitions.

Using model attribute as :filename when using paperclip gem

I'm getting an error when attempting to change the :filename of my paperclip attachment to equal an attribute on the class I'm attaching the paperclip file to.
When I use "#{self.company_name}" it errors out. Apparently in this scope, "self" is not Company. When I wrote this line I assumed that self is the instance of Company that I'm uploading this attachment to. Any idea how I can fix this? The Paperclip docs say to use ":filename" but I'd like to use the value of Company.company_name instead.
class Company < ActiveRecord::Base
include AliasAttrs
has_attached_file :company_logo, {
:storage => :ftp,
:path => "/logos/#{self.company_name}",
:url => FTP_CONFIG[:access_host]+"logos/:filename",
:ftp_servers => [
{
:host => FTP_CONFIG[:host],
:user => FTP_CONFIG[:user],
:password => FTP_CONFIG[:pass],
:port => 21 # optional, 21 by default
}
]
}
end
Update
I tried using the advice found in this post: https://robots.thoughtbot.com/paperclip-tips-and-updates
But now I am getting the following error when starting my server:
undefined method `interpolations' for Paperclip::Attachment:Class (NoMethodError)
It looks like the syntax for interpolations has changed. Updated it and it worked. Add the following to your model or create a paperclip.rb file in config/initializers
Paperclip.interpolates :company_name do |attachment, style|
attachment.instance.company_name
end

How to use puppetlabs/apt module?

I am developing puppet manifests for provisioning a VM through Vagrant. I am also new to puppet. While trying to use puppetlabs/apt module, I am encountering problems:
# manifests/default.pp (with commented lines removed)
import "stdlib"
import "apt"
class { 'apt':
always_apt_update => false,
disable_keys => undef,
proxy_host => false,
proxy_port => '8080',
purge_sources_list => false,
purge_sources_list_d => false,
purge_preferences_d => false
}
apt::release { "sid":}
This is the error message:
Puppet::Parser::AST::Resource failed with error ArgumentError:
Invalid resource type apt::release at /tmp/vagrant-puppet/manifests/default.pp:18
on node vmas1.dokeda.lt
I have been reading puppet docs; however, it hasn't helped. Could someone explain to me how to properly use this module?
I think the README incorrectly implies that apt::release is a define or type, when in fact the source code shows it's a class.
Instead, try calling it like this:
class { 'apt::release':
release_id => 'sid',
}
Also be sure not to use "import" but instead use "include".
Import is deprecated in more recent versions of puppet.

Rack throwing an error when trying to serve a static file

use Rack::Static, :urls => ['/stylesheets', '/images'], :root => 'public'
run proc { |env| [200, { 'Content-Type' => 'text/html', 'Cache-Control' => 'public, max-age=86400' }, File.open('public/index.html')] }
I get private method `open' called for Rack::File:Class when I rackup. Really can't see where the problem is. Running rack 1.1. Help please...
There is a Rack::File class, which has precedence in your rackup file because of the way Ruby looks up names. This is not the class you are looking for, you want Ruby's own File class. That class can be referenced directly without lookup ambiguity by using the prefix ::
::File.open('public/index.html')

Resources