How to avoid passing environment variables to puppet agent - environment-variables

I am trying to use a 3rd party puppet module which relies on the fact the puppet agent which will run has the JAVA_HOME correctly set.
The JAVA_HOME is required because there is a command defined in a provider (see here).
I have 2 options which I can use now:
Pass the variable when executing the puppet agent (but works only in interactive)
Put in place a file to be sourced by the user executing puppet with the cron (self managed by puppet)
My question is: is it possible to pass the environment to a provider?
POSSIBLE SOLUTION
Taking inspiration from the following post
I created a new type and a provider for it which inside sets the ENV[myvar] = myvalue. Note that the type is not ensurable.
The variable will "leak" and will allow other modules relying on it to work properly.
E.g.
### ... Provider code
def ensure
if value = ENV[resource[:name]]
value
else
:absent
end
end
def ensure=(new_value)
if new_value == :absent
ENV.delete(resource[:name])
else
ENV[resource[:name]] = new_value
end
end
### Usage in puppet code
mytype { 'MYVAR':
ensure => 'MYVAL',
}
Note that puppet will report at each run the value has changed from absent to a specific value. To avoid so, I think it is enough to always return :absent (I must verify that).

is it possible to pass the environment to a provider?
No, Puppet has no mechanism for customizing the environment for external commands on a per-provider basis. I think you have more options than those you've enumerated, however. Among them:
wrap the puppet command in a shell script that sets the environment variables you want
if you are indeed using cron to schedule agent runs, then use cron's built-in support for setting environment variables for the commands it runs.
The latter seems a promising alternative.

Related

Is there a way to find current environment in a Ruby application similar to rails.env?

I need to implement a feature that sets some Env vars conditionally based on current environment(dev,test,prod). I know in rails this can be accomplished with rails.env. Is there a similar method for Ruby?
No, vanilla ruby doesn't have a concept of "environment". You will have to build this yourself. One simple way is to use an environment variable and read it.
For example, you can require a MYAPP_ENVIRONMENT environment variable. Then you read it with myapp_environment = ENV['MYAPP_ENVIRONMENT']. Then you might have hashes or some other data structure to determine values that are specific to that environment:
ENDPOINT_A = {
prod: 'https://prod.my_company.com',
stage: 'https://stage.my_company.com'
}
Similarly for other variables. Note that the endpoint string is a ruby variable, not an environment variable. You should NOT set environment variables from the ruby code that uses them. The whole point of environment variables is that they are set externally to your app and your app takes them as input to configure how it behaves.
If you want to specify the endpoint through an environment variable, you should set it in the operating system where your ruby app runs. You can do this manually on the machine or through a deployment pipeline or script.

How to setup basic ManageIQ automate environment in Rails console?

I used to run some operations in ManageIQ through automate simulation, which is available from UI.
I'd like to find a way to reproduce these operations from rails console.
For example operations for Instance management - migrate, evacuate or relocate instance.
How do I make it?
There's the common way to do this:
Set up a basic $evm context in a Rails console
# rails c
# $evm = MiqAeMethodService::MiqAeService.new(MiqAeEngine::MiqAeWorkspaceRuntime.new)
For example you can find any VM in vmdb and define it into a variable:
# vm = $evm.vmdb('vm').find('some_id')
Similar with other objects, e.g.
flavor = $evm.vmdb('flavor').find(flavor_id)

data driven ios-Calabash automated testing using xml or css or global variables

i am doing automated testing using calabash-ios. I want to be able to run cucumber once and have it run x times for x user names and run through the gamut of test scenarios.
i want to use this:
Given I login as [#{country-name}] user using id [#{Login-name}] and pwd "PASSWORD"
and have a global variable that can store the values for both country and user name.
i had hoped to use scripts to run cucumber x times and set the value for the global variables each time. is this possible? and if so, could someone point me in the right direction?
i tried using :
##Loginname=value
but got this error:
features/step_definitions/common.rb:1: warning: class variable access from toplevel
uninitialized class variable ##Login in Object (NameError)
failing which, will it be possible to access data stored in a xml or css file using calabash?
If you want to run the same cucumber run many times with some different variables you can just use environment variables.
Given I login as "ENV['COUNTRY_NAME']" user using id "ENV['LOGIN_NAME']" and pwd "PASSWORD"
And then when you run the tests
LOGIN_NAME='login name' COUNTRY_NAME=country bundle exec cucumber
And then of course you can put all of the lines you want to run into a bat or sh script.
One thing to be careful of is to use the environment variables or another one to change the path for the outputs so you don't overwrite them.
However, a more elegant solution would be to handle it with a rake task that ran all of the other tasks. The most efficient way to write that would depend on how many different runs you need.
task :all => [:task1, :task2, :task3]
EDIT: To make your scenarios more readable, you should use a generic placeholder in the scenario and hide the environment variables in the step definition.
Given I login as a user
Might have a step definition that looked like:
Given /^I login as a user$/ do
... set up your page object here ...
login_page.login(ENV['COUNTRY_NAME'], ENV['LOGIN_NAME'])
end

How to specify environment dependencies in Rails?

Where does one list the environment variable dependencies for a Rails application?
I don't want the app to run if the user hasn't specified the variables or at a minimum output some form of notice that says ***Don't run until you've set the following environment variables..."
I'd put something like that in config/boot.rb:
# usual boot.rb stuff...
raise 'Set PANCAKES in your environment!' unless ENV.has_key? 'PANCAKES'
The nice thing about boot.rb is that it is run very early in the start up process so you don't have to wait for all the Rails machinery to start (which can take a long time) before you know there's a problem.

Supplying an argument at Rails runtime

I'm looking for a way to supply an argument to a ruby on rails project at runtime. Essentially, our project uses public key cryptography to encrypt some sensitive client data and we want the ability to supply the password to the private key file at runtime.
Any Ruby script has access to local environment variables through the ENV hash.
puts ENV['PATH']
So with any posix system (Linux, Unix, Mac OS) you can simply set it when calling the script, like this:
MY_ARG=supersecret ruby script.rb
The same is also valid for rails. If you put puts ENV['MY_ARG'] in your environment.rb and start your server:
$ MY_ARG=supersecret mongrel_rails start
** Starting Mongrel listening at 0.0.0.0:3000
** Starting Rails with development environment...
supersecret
** Rails loaded.
** Loading any Rails specific GemPlugins
** Signals ready. TERM => stop. USR2 => restart. INT => stop (no restart).
** Rails signals registered. HUP => reload (without restart). It might not work well.
** Mongrel 1.1.5 available at 0.0.0.0:3000
** Use CTRL-C to stop.
An environment variable is by far the simplest solution in my opinion.
An easy way to do this would be to create a Rails plugin that takes arguments using 'gets' in its 'init.rb'. Allow me to cook-up a quick code sample:
Make a directory: '$railsRoot/vendor/plugins/startup_args/lib'
Create an object to store argument data in '$railsRoot/vendor/plugins/startup_args/lib/startup_args.rb':
module StartupArgs
##argHash = {}
def self.setArg(key, value)
##argHash[key.to_sym] = value
end
def self.getArg(key)
return ##argHash[key.to_sym]
end
end
Load the StartupArgs module into the Rails project's namespace and populate it with arguments in '$railsRoot/vendor/plugins/startup_args/init.rb':
require "startup_args"
promptString = "Enter arg name (type nothing to continue):"
puts promptString
while (newArg = gets.chomp) != ""
puts "Enter value for '#{newArg}':"
newVal = gets.chomp
StartupArgs.setArg(newArg, newVal)
puts promptString
end
Now, during the Rails project's start-up process, it will try to take key-value pairs from the console. These pairs will be stored in the global-namespace object StartupArgs for later access (via 'StartupArgs.getArg()').
If you anticipate that your Rails project might be deployed in scenarios where the daemon will not have access to the console during startup-time, you could read from a named-pipe instead of the console's standard input.
Going one step further, you could remove all parts of 'init.rb' except for the 'require' statement and add an action that performs this setup to a controller that would take the relevant parameters as a post over the web. Make sure to configure Rails to prevent potentially sensitive parameters (e.g. passwords) from being entered into log files recording accesses or errors (especially if it might be used as an HTTP GET, with parameters in the URL).
(You get the same effect this way as with the system described above if you configure your other Rails actions to ignore requests until the setup action has stored the appropriate parameters to the global object.)
A Note For Micah: I don't have the reputation to comment directly on your post, so I will include my comment here. There might be a few reasons to consider a system that never requires the password to be represented in the filesystem. For example, a developer might be planning a Rails project that could be deployed on varying operating systems and in varying environments. If the developer determines that there could be scenarios in which an administrative or root user could be compromised, cannot be trusted, or cannot be asked to sign confidentiality and security agreements, the developer might decide to add the additional obfuscation of placing the password in memory only (in the interest of requiring a slightly less secure system or a slightly more clever attack to steal the password). Perhaps it could be considered a matter of relative costs: at low cost, the password can be hidden in a way that requires more expensive knowledge in order to retrieve.
What is wrong with putting the password in a file that is chmod'ed to only be readable by the web server user?

Resources