Chef execute fails for the first time - ruby

I have a weird problem with a Chef Recipe. Let me tell you that I'm new to Chef so pardon me if something looks awfully wrong.
I have my war file, which is built by Spring Boot. I just need to run java -jar <file>.war -config=config/ to run my app.
I recently started experimenting with Chef, and getting to write recipes that do this job.
The code from my recipe is as follows:
#Some code has been omitted intentionally.
directory "#{home}" do
owner 'root'
group 'root'
mode '0755'
recursive true
end
directory "#{home}/config" do
owner 'root'
group 'root'
mode '0755'
end
cookbook_file "#{home}/config/ehcache.xml" do
source "ehcache.xml"
mode "0644"
end
# Get the war file from the repo
remote_file "#{home}/app.war" do
source "#{node['baseos']['files_repo_url']}/wars/app.war"
owner 'root'
group 'root'
mode '0644'
end
execute 'Run the war file' do
command "java -jar '#{home}/app.war' -config='#{home}/config/'"
action :run
end
The war file, and the related config folder along with its contents are successfully being copied to their respective destinations before the execute command gets fired. The problem is when the machine gets freshly created with kitchen create, the first kitchen verify would fail, saying 'Errno::ENOENT: No such file or directory - java -jar /opt/com/app.war -config=config/'.
This only happens for the first time. Surprisingly, after saying kitchen verify again, the app starts up, and successfully runs.
This is weird because of the fact that the required file app.war and the config/ are [or should be] already there in the machine with appropriate privileges.
I know Chef processes these things sequentially, so given that the execute command is the very last line in my recipe, it should already have what is required to run the war file. I'm going nuts, can anyone provide some insight into this one?
Thank you!

While it is somewhat counter-intuitive, this is probably because you don't have java available on your $PATH. This might mean java is not installed, or that it is installed but not in a way that Chef can find it. Remember that environment variables are only inherited when a process starts, so if you installed Java in such a way that the installer set up some global change to $PATH it wouldn't be visible to Chef. A good fix would be to use the full path to the JVM binary (/opt/whatever/bin/java or something).

Related

How to run a file that is "up" one directory from Terminal

I'm fairly new to java and terminal so excuse my ignorance. I have a directory system that contains (other directories)/repo/projectFolder/project/javaclass and I created a new directory located here: (other directories)/repo/projectFolder/testing. I'm trying to run a method in javaclass, so something like java project.javaclass methodName command from inside testing. Because of the nature of the tests I'm trying to run, I must make this call from inside the testing directory and I can't change the ordering/structure of the directories. How do I access /project/javaclass from testing? Do I somehow have to put a file path ../project/javaclass?

spring-boot launch-script: how to avoid pid_folder identity-subdirectory?

We are using spring-boot with the embedded launcher-script in service mode, to have daemonized/init.d behavior.
We however do not have an /etc/init.d symlink to the spring-boot jar as that would require using sudo. we avoid sudo to pass a profile-environmental like -Dspring.profiles.active=$APP_PROFILE in the JAVA_OPTS
(this won't work when started via sudo but defined in /home/appuser/.bashrc (?) )
We have this directory-layout with some indirections. basically app.jar => current/app.jar => build-xx/app.jar
appuser#host:~/apps/services$ ls
app.jar -> /home/appuser/apps/services/current/services-1.0-SNAPSHOT.jar
current -> /home/appuser/apps/services/services-1298
services-1298
When starting the application with app.jar start the launch-script generates an additional pid-subdirectory in the pid-folder based on the "identity" of the program. For us this can look like this:
/home/appuser/apps/services/run/services-1.0-SNAPSHOT_homeappuserappsservicesservices-1298/services.pid
Unlike when used with an symlinked /etc/init.d which gets special treatment and the pid-subdir services-1.0-SNAPSHOT_homeappuserappsservicesservices-1298 is omitted/stays stable.
This dynamic pid-subdir makes it very hard for us to check the daemon's status or start/stop during deployment because you have to always get the sequence right and nobody is stopping you from starting a process twice (the old instance and now a new instance with a new identity-subdir).
So, does anyone know why this pid-subdir-identity stuff must exist and what would be our best way to deal with it?
Do we have a bad setup?
Any advice appreciated.
You can control the identity by using the APP_NAME environment variable.
I'd recommend configuring your service's environment variables using a .conf file next to the jar file. For example, if your app is called app.jar, you conf file should be named app.conf and be placed in the same directory as the jar. You can then configure APP_NAME and JAVA_OPTS etc for your application. This should allow you to use init.d if you so wish.

How do I make a vagrant plugin action occur before synced folder?

I was trying to fix an issue in vagrant-rackspace plugin, which required running a command to remove the requiretty line from the sudoers file before the synced folder ran, as the rsync command would fail with sudo: sorry, you must have a tty to run sudo.
However, regardless of the order in the Vagrantfile, the synced folder action would always go first. It seems that in core Vagrant, the synced folder has the highest priority, and will always run first. I thought it would be like the provisioners, which are run in order they're put in the Vagrantfile.
Eventually I remembered a similar looking line of code in a plugin I'd worked on recently:
action_hook(:install_chef, Plugin::ALL_ACTIONS) do |hook|
require_relative 'action/install_chef'
hook.after(Vagrant::Action::Builtin::Provision, Action::InstallChef)
if defined? VagrantPlugins::AWS::Action::TimedProvision
hook.after(VagrantPlugins::AWS::Action::TimedProvision,
Action::InstallChef)
end
end
So, I just changed that to make sure the task I wanted always ran before the synced folder task:
action_hook(:tty_workaround, Plugin::ALL_ACTIONS) do |hook|
require_relative 'action/tty_workaround'
hook.after(Vagrant::Action::Builtin::SyncedFolders, Action::TTYWorkaround)
end
Worked like a charm!
I'm still trying to figure out if there's a way of doing this in Vagrant core, but for now I'm planning on making a vagrant plugin where you can give a path to a script you want to run on the vagrant node in the config, allowing you to use the above approach in any Vagrant instance, not just vagrant-rackspace.

hdiutil: attach failed - No such file or directory, in Maven Projects using AppleScript

I am trying to mount the application which is present in a module named x. I am using Maven projects here, so for mounting the app I am using a shell script. I have given the path of the application which is present in module x. If I try to run the test from the class where this mounting method is present, it's being compiled and I am getting results properly, but when I use this mounting method in some other test class and ran the test, it's saying "no such file present" I know this looks strange, but I am facing this issue. Please tell me how to overcome this.
do shell script "hdiutil mount ../../common/src/main/resources/Modulex/AdbeRdr11000_en_US.dmg"
I was able to solve the above prob, just i need to change the path, since i was running the same test from testsuite.
do shell script "hdiutil mount ../common/src/main/resources/Modulex/AdbeRdr11000_en_US.dmg"

Set global environment variables inside Xcode build phase run script

I'm using Jenkins to do continuous integration builds. I have quite a few jobs that have much of the same configuration code. I'm in the midst of pulling this all out into a common script file that I'd like to run pre and post build.
I've been unable to figure out how to set some environment variables within that script, so that both the Xcode build command, and the Jenkins build can see them.
Does anyone know if this is possible?
It is not possible to do exactly what you ask. A process cannot change the environment variables of another process. The pre and post and actual build steps run in different processes.
But you can create a script that sets the common environment variables and share that script between all your builds.
The would first call your shell to execute the commands in the script and then call xcodebuild:
# Note the dot in the beginning of the next line. It is not a typo.
. set_environment.sh
xcodebuild myawesomeapp.xcodeproj
The script could look like this:
export VARIABLE1=value1
export VARIABLE2=value2
How exactly your jobs will share the script depends on your environment and use case. You can
place the script in some well-known location on the Jenkins host or
place the script in the version controlled source tree if all your jobs share the same repository or
place the script in a repository of its own and make a Jenkins build which archives the script as a build artifact. All the other jobs would then use Copy Artifact plugin to get a copy of the script from the artifacts of script job.
From Apple's Technical Q&A QA1067 it appears that if you create the file /Users/YOU/.MacOSX/environment.plist and populate it with your desired environment variables that all processes (launched by the user with the environment.plist file in their home dir) will pick up these environment variables. You may need to restart your computer (or just log out and back in) before a newly launched process will pick up the variables.
This article also claims that Xcode will also pass these variables to a build phase script. I have not tested it yet but next time I restart my MacBook I will let you know if it worked.
From http://developer.apple.com/library/mac/#/legacy/mac/library/qa/qa1067/_index.html
Q: How do I set environment for all processes launched by a specific
user?
A: It is actually a fairly simple process to set environment variables
for processes launched by a specific user.
There is a special environment file which loginwindow searches for
each time a user logs in. The environment file is:
~/.MacOSX/environment.plist (be careful it's case sensitive). Where
'~' is the home directory of the user we are interested in. You will
have to create the .MacOSX directory yourself using terminal (by
typing mkdir .MacOSX). You will also have to create the environment
file yourself. The environment file is actually in XML/plist format
(make sure to add the .plist extension to the end of the filename or
this won't work).

Resources