Does Oozie support decision node to call either fork-join or single action node? - switch-statement

I am trying to have a workflow where, based upon a variable, either the full fork-join runs or just a single action runs. I'm getting an error saying no fork for join to pair with. Is this supported? This is what I am doing:
<start to="path_decision"/>
<decision name="path_decision">
<switch>
<case to="fork-join-path">${some_var eq "foo"}</case>
<default to="node1"/>
<switch/>
<decision>
<fork name="fork-join-path>
<path start="node1"/>
<path start="node2"/>
</fork>
<action name="node1">
<ok to="path_end_decision"/>
</action>
<action name="node2">
<ok to="path_end_decision"/>
</action>
<decision name="path_end_decision">
<switch>
<case to="join_end>${some_var eq "foo"}</case>
<default to="normal_end"/>
</switch>
</decision>
<join name="join_end to="normal_end">
<action name="normal_end">
...clean up
</action>

In your example the following path looks valid:
start->path_decision->fork-join-path->node1->path_end_decision->normal_end
In this path you have a fork but you don't have a join which is not good. Oozie's forkjoin validator will find this and give you an error. It will not recognize that you added the same condition to path_decision and path_end_decision.
I would use node1 and node2 for the fork path. In this case you don't need the path_end_decision node, just go to join_end directly from node1 and node2. For the non-join path I would go to a new node3 from path_decision and to normal_end from there.
You also have a missing " at join_end but I hope it's only a typo.

Related

setting and reading environment variables in IIS 10

I can not figure out how to set and read environment variables in Microsoft Internet Information Services (IIS) version 10. I have a Fast CGI app that requires environment variables. In previous versions of IIS I just set system-wide variables in the Windows "System Properties". However in IIS 10 my FCGI app isn't reading them. So my first question is if there are steps that need to be taken so that the IIS process can read system variables?
Alternatively, how do I set environment variables within IIS 10? This Microsoft site explains it but not in enough detail for me to get it working. Specifically, in what file and in which section do you put the <environmentVariables> section? The example XML and the command line example have name="Contoso" (see below) but what is that - the name of the application pool, or my FCGI app, or something else?
<applicationPools>
<add name="Contoso" managedRuntimeVersion="v4.0" managedPipelineMode="Classic">
<environmentVariables>
<add name="foo" value="bar" />
</environmentVariables>
</add>
</applicationPools>
Edit in response to Jokies Ding:
MAP22 and PROJ_LIB are the two environment variables that I need. In C:\Windows\System32\inetsrv\Config\applicationHost.config
I have:
<applicationPools>
<add name="DefaultAppPool" />
<add name=".NET v4.5 Classic" managedRuntimeVersion="v4.0" managedPipelineMode="Classic" />
<add name=".NET v4.5" managedRuntimeVersion="v4.0" />
<add name="ASP.NET v4.0" autoStart="true" managedRuntimeVersion="v4.0" />
<applicationPoolDefaults managedRuntimeVersion="v4.0">
<processModel identityType="ApplicationPoolIdentity" />
<environmentVariables>
<add name="PROJ_LIB" value="/gdal/bin/proj6/SHARE" />
<add name="MAP22" value="/tetonwy/mapserv/main.map" />
</environmentVariables>
</applicationPoolDefaults>
</applicationPools>
and
<fastCgi>
<application fullPath="C:\gdal\bin\ms\apps\mapserv.exe">
<environmentVariables>
<environmentVariable name="MAP22" value="C:\tetonwy\mapserv\main.map" />
<environmentVariable name="PROJ_LIB" value="C:\gdal\bin\proj6\SHARE" />
</environmentVariables>
</application>
</fastCgi>
and in a cmd window the environment variables are visible
C:\>set MAP22
MAP22=C:\tetonwy\mapserv\main.map
C:\>set PROJ_LIB
PROJ_LIB=C:\gdal\bin\proj6\SHARE
So it seems like I've got the variables set all over the place but the app isn't seeing them. C:\gdal\bin\ms\apps\mapserv.exe is the FastCGI app that isn't seeing the environment variables. It's a compiled C program that I have used in previous versions of IIS.
There is an issue with MapServer not reading environment variables on Windows when used through FastCGI.
This is resolved by applying https://github.com/MapServer/MapServer/pull/6304 which will be backported to the 7.x MapServer releases.
See Environment variables ignored using FastCGI and IIS #6289 for more details.
<environmentVariables> section is displayed as a collection under specific application pool.
You could find it in IIS global configuration file C:\Windows\System32\inetsrv\config\applicationhost.config.
"Contoso" is the name of application pool.
I think read system-wide variable is still supported in IIS 10 and PHP FAST-CGI. I can get these configuration by running commandline SET in IIS PHP-CGI.
Could you post the code that you used to read the variable?
In some condition, Your application code require elevated permission. You could try to change application pool identity to local system and set Anonymous authenticated user to Application pool identity

CSPACK sitePhysicalDirectories being ignored?

Yet another issue with CSPACK...
I have a service definition file like this:
<ServiceDefinition name="core-eur" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2014-01.2.3">
<LoadBalancerProbes>
<LoadBalancerProbe name="discovery.probe" protocol="http" path="/HealthMonitoring" port="80" intervalInSeconds="8" timeoutInSeconds="16" />
</LoadBalancerProbes>
<WebRole name="Discovery.UI" vmsize="ExtraSmall" enableNativeCodeExecution="false">
<Startup>
<Task commandLine="startup\CreateCustomEventSource.cmd" executionContext="elevated" taskType="simple" />
</Startup>
<Sites>
<Site name="main">
<Bindings>
<Binding name="https.root" endpointName="https" hostHeader="testingblah.com" />
</Site>
<Site name="api" physicalDirectory="..\..\..\catalog\Catalog.Search.API">
<Bindings>
<Binding name="https.root" endpointName="https" hostHeader="api.testingblah.com" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="http" protocol="http" port="80" loadBalancerProbe="discovery.probe" />
<InputEndpoint name="https" protocol="https" port="443" certificate="bibliothecatest.com" />
</Endpoints>
<Imports>
<Import moduleName="RemoteAccess" />
<Import moduleName="Diagnostics" />
<Import moduleName="RemoteForwarder" />
</Imports>
<Certificates>
<Certificate name="testingblah.com" storeLocation="LocalMachine" storeName="CA" />
</Certificates>
</WebRole>
The key points are the Sites "main" and "api". I've not included the physical directory because, as expected, when they are put in and point to the project files in the solution, the "api" site is not packaged correctly as the Visual Studio package process will only package the first site (i.e. "api" has all the un-transformed .config files and .cs files in it's packaged folder whereas "main" does not - it is correctly packaged, but this is a known issue so I'm not going to complain too much about this.
So to workaround it, for my build server I want to introduce a CSPACK step to do this properly. I pre-build the "main" and "api" web sites using MSDEPLOY to a temporary location, and then use CSPACK to create the package file.
This fails every time with "CloudService077: Need to specify the physical directory for the virtual path 'main/ of role "Discovery.UI". However, I am including the /sitePhysicalDirectories value in CSPACK, i.e.
cspack %root%\ServiceDefinition.csdef ^
/role:Discovery.UI;%compiled%\discovery\Discovery.UI\ ^
/sitePhysicalDirectories:Discovery.UI;main;%compiled%\discovery\Discovery.UI\ ^
/sitePhysicalDirectories:Discovery.UI;api;%compiled%\catalog\Catalog.Search.Api\ ^
/rolePropertiesFile:Discovery.UI;Properties.txt ^
/out:%output% /copyOnly
If I put the sitePhysicalDirectories attribute back into the ServiceDefinition file, and point it to the project directory location in Visual Studio (e.g.)
<Site name="main" physicalDirectory="..\..\..\discovery\Discovery.UI">
then CSPACK fails with CloudServices079: Cannot find the physical directory "nnn" for virtual path main/
This is despite the fact that the CSPACK command line /sitePhysicalDirectories are correct. What's happening is that CSPACK is taking the ServiceDefinition values, applying the relative path values and pointing to completely the wrong place.
If I update ServiceDefinition to use the same physical location (e.g. C:\....\nnnn as opposed to "......\nnnn" that I'm passing in the CSPACK command line, everything works !
So it seems that CSPACK ignores parameters and cannot override values, which isn't what I really need. Is this correct or should I be passing something else to CSPACK?
Azure SDK 2.3
I know this is long after the fact, but I also had endless trouble with CSPACK. It is basically impossible to find any useful information on it.
What I've found, is that if you don't provide the arguments properly, you get all sorts of "Cannot find the physical directory..." and "Need to specify the physical directory..." errors, sometimes with directories that you did not provide.
Thanks to this powershell script I was able to execute it using the correct format and learned these things:
1. You must specify the /role: argument. The /sites argument is an extension of the role you specify here.
2. Put all your sites in one /sites argument or in one /sitePhysicalDirectories argument. I use the /sites argument for my builds.
For the above example, I would try:
cspack %root%\ServiceDefinition.csdef
/role:Discovery.UI;%compiled%\discovery\Discovery.UI\ /sites:Discovery.UI;main;%compiled%\discovery\Discovery.UI\;api;%compiled%\catalog\Catalog.Search.Api\ /rolePropertiesFile:Discovery.UI;Properties.txt
/out:%output% /copyOnly

CCnet queue priorities not sequencing

I am setting up a nightly build using ccnet 1.6 to run projects sequentially and exclusively, but however I set up the queues when the build is triggered the projects do not start in the expected order as defined by the queue priority. The config below randomly starts queues 1, 2, 3 or 4 first then completes the remaining projects in the defined sequence order (ie 2, 1, 3, 4 or 3, 1, 2, 4 etc). I've tried xlmns 1.6 and 1.5 with same results. I can't see why this is not working, am I missing something?
Thanks
<cb:define name="Common">
<webURL>http://hostname/ccnet/server/local/project\$(CCProjectName)\ViewLatestBuildReport.aspx</webURL>
<workingDirectory>D:\source\$(ProjectName)</workingDirectory>
<sourcecontrol type="svn"/>
<modificationDelaySeconds>60</modificationDelaySeconds>
<triggers>
<scheduleTrigger time="11:05" buildCondition="ForceBuild "/>
</triggers>
<state type="state" directory="C:\Program Files\CruiseControl.NET\server" />
</cb:define>
<cb:define name="BuildProject">
<project name="$(CCProjectName)" queue="SequentialQueue" queuePriority="$(QueuePriority)">
<cb:Common />
<tasks>
<exec>
<executable>$(ANT_HOME)\bin\ant.bat</executable>
<buildArgs>-logger org.apache.tools.ant.XmlLogger -logfile build_log.xml -f build\$(ProjectName).xml</buildArgs>
</exec>
</tasks>
<publishers>
<merge>
<files>
<file>D:\source\$(ProjectName)\build\*.xml</file>
</files>
</merge>
<xmllogger />
</publishers>
</project>
</cb:define>
<cb:BuildProject CCProjectName="API" ProjectName="api" QueuePriority="1" />
<cb:BuildProject CCProjectName="Ack" ProjectName="acknowledgement" QueuePriority="2" />
<cb:BuildProject CCProjectName="Error" ProjectName="error" QueuePriority="3" />
<cb:BuildProject CCProjectName="Monitoring" ProjectName="monitoring" QueuePriority="4" />
I'm guessing this is a bug in CruiseControl.Net, your scenario (variable priority projects in one queue triggered by the same schedule trigger) is not a common one. You should file a bug on cruisecontrolnet.org.
A more usual solution for this kind of setup is having the projects trigger each other using <projectTrigger/>, which also results in a sequential build. You'll probably want to change the triggerStatus parameter so that a failed build does not stop the chain.

IISExpress Log File Location

IISExpress writes log and configuration data to pre-determined location out of the box.
The directory is an "IISExpress" directory stored in a user's Documents directory.
In the directory is stored the following folders files underneath.
Config
Logs
TraceLogFiles
The location of my home directory is on a network share, determined by group policy
Currently we are encountering scenarios where visual studio locks up when stopping debugging Silverlight applications using IIS Express.
I was looking to change the location for the log & configuration data for IISExpress to see if this fixes the problem of visual studio locking up. Is it possible to change the default location of log & config files ?
1 . By default applicationhost.config file defines following two log file locations. Here IIS_USER_HOME would be expanded as %userprofile%\documents\IISExpress\.
<siteDefaults>
<logFile logFormat="W3C" directory="%IIS_USER_HOME%\Logs" />
<traceFailedRequestsLogging directory="%IIS_USER_HOME%\TraceLogFiles" enabled="true" />
</siteDefaults>
You can update above directory paths to change the log file locations.
2 . If you are running IIS Express from command line, you can use '/config' switch to provide configuration file of your choice. Following link may help you http://learn.iis.net/page.aspx/870/running-iis-express-from-the-command-line/
http://www.iis.net/configreference/system.applicationhost/sites/sitedefaults
<configuration>
<system.applicationHost>
<sites>
<siteDefaults>
<logFile
logFormat="W3C"
directory="%SystemDrive%\inetpub\logs\LogFiles"
enabled="true"
/>
<traceFailedRequestsLogging
enabled="true"
directory="%SystemDrive%\inetpub\logs\FailedReqLogFiles"
maxLogFiles="20"
/>
<limits connectionTimeout="00:01:00" />
<ftpServer serverAutoStart="true" />
<bindings>
<binding
protocol="http"
bindingInformation="127.0.0.1:8080:"
/>
</bindings>
</siteDefaults>
</sites>
</system.applicationHost>
</configuration>
I find web.config documentation is a messy. It is therefore better to provide a complete parent history than a floating snippet with the expectation that the reader naturally knows where it goes.
By default it will be in:
C:\Users\ user_name \Documents\IISExpress\Logs\

How to search for a string in files with Ant (make sure certain string isn't found in source files)

I'd like to search for a string within my source files with Ant. (I'd like my build to fail in case certain string is found within my source files).
So, I should be able to recursively search for a certain string within a file set.
I already found that I can use loadfile task to check whether a string pattern is found within one file. But that seems to be working & sensible only with a single file.
On the other hand, replace task would provide recursively search-and-replace. I guess I could do that before build and replace my string with something that would break the build but I wonder if there is some cleaner solution?
br, Touko
You might consider using fileset selectors to do this. Selectors allow you to choose files based on content, size, editability and so on. You can combine selectors with name-based includes and excludes, or patternsets.
Below is an example. The second fileset is derived from the first, with a selector that simply matches on file content. For more sophisticated matching there is the containsregexp selector. The result is a fileset containing only files matching the string. A fail task with a resourcecount condition is then used to fail the build, unless that fileset is empty.
<property name="src.dir" value="src" />
<property name="search.string" value="BAD" />
<fileset id="existing" dir="${src.dir}">
<patternset id="files">
<!-- includes/excludes for your source here -->
</patternset>
</fileset>
<fileset id="matches" dir="${src.dir}">
<patternset refid="files" />
<contains text="${search.string}" />
</fileset>
<fail message="Found '${search.string}' in one or more files in '${src.dir}'">
<condition>
<resourcecount when="greater" count="0" refid="matches" />
</condition>
</fail>
(Old answer): If adjusting or reusing filesets might be problematic, here's an illustration of a relatively simple alternative.
The idea is to make a copy of the files,
then replace the string you wish to search for
with some flag value in the copied files.
This will update the last modified time on any matching file.
The uptodate task can then be used to look for affected files.
Finally, unless no files matched, you can fail the build.
<property name="src.dir" value="src" />
<property name="work.dir" value="work" />
<property name="search.string" value="BAD" />
<delete dir="${work.dir}" />
<mkdir dir="${work.dir}" />
<fileset dir="${src.dir}" id="src.files">
<include name="*.txt" />
</fileset>
<copy todir="${work.dir}" preservelastmodified="true">
<fileset refid="src.files" />
</copy>
<fileset dir="${work.dir}" id="work.files">
<include name="*.txt" />
</fileset>
<replaceregexp match="${search.string}"
replace="FOUND_${search.string}">
<fileset refid="work.files" />
</replaceregexp>
<uptodate property="files.clean">
<srcfiles refid="work.files" />
<regexpmapper from="(.*)" to="${basedir}/${src.dir}/\1" />
</uptodate>
<fail message="Found '${search.string}' in one or more files in dir '${src.dir}'"
unless="files.clean" />
This was very helpful as a start, but I have a list of strings which should be checked in a fileset.
My current code sofar is:
<property name="search4" value="XYZ"/>
<fileset id="existing" dir="../src">
<patternset id="files">
<include name="content/**/*.txt"/>
</patternset>
</fileset>
<resourcecount property="count">
<fileset id="matches" dir="../src">
<patternset refid="files" />
<contains text="${search4}" />
</fileset>
</resourcecount>
<echo message="Found '${search4}' in files : '${count}'"/>
That works well, but how to expand that so the ${search4} is read from a list. Actually the list can be read from a file containing each search item is on a separate line.
Slightly more concise variation on the first part of #martinclayton's answer:
<property name="log.dir" value="logs" />
<property name="fail.string" value=" FAILED " />
<fileset id="build.failures" dir="${log.dir}" includes="*.log">
<contains text="${fail.string}"/>
</fileset>
<fail status="1" message="One or more failures detected">
<condition>
<resourcecount when="greater" count="0" refid="build.failures" />
</condition>
</fail>

Resources