Select Page

Job steps with agent filter based pre-conditions in Anthill Pro

Previously, we discussed: Creating environment specific pre-conditions for job steps in Anthill Pro. Perhaps, you want to have job step preconditions based on agent filters, and not the environment shortname. If so, here’s an example of how that would go down. Let’s say you have a role in your farm called “weblogic-ejb” and you set an agent variable called “role” as “weblogic-ejb”. If you wanted to execute a job step only on servers of this role, you’d set a pre-condition step script as such:

Criteria myCriteria = new Criteria() {
public boolean matches(Object obj)
 throws Exception {
 return "weblogic-ejb".equalsIgnoreCase(AgentVarHelper.getCurrentAgentVar("role"));
 }
};

return Logic.and(
 StepStatus.priorIn(
  new JobStatusEnum[] { 
   JobStatusEnum.SUCCESS, 
   JobStatusEnum.SUCCESS_WARN,
   JobStatusEnum.NOT_NEEDED  
  }),
  myCriteria
 );

Again, we see here that our Logic.and() method ensures we have our agent filter set AND the previous jobs that were run were successful or not needed, which is just as important.

Creating environment specific pre-conditions for job steps in Anthill Pro

When creating deploy workflows in Anthill Pro, it’s best practice to try and keep the deploying in 1 job if possible and have your environment specific steps inside that job function using prerequisites to those jobs. For example, if you wanted to deploy configuration artifact sets as part of your deploy job and have the proper artifact sets deploy to the chosen environment, you would want to program a pre-condition step for each of those environments, then tag those jobs with these pre-condition steps.

For example, lets say we’re dealing with “dev”, “qa”, “stage” and “prod” artifact sets. We would make 4 pre-condition scripts:

is_dev:

Logic.and(
 JobStatus.allAncestorsIn(
  new JobStatusEnum[]{
   JobStatusEnum.SUCCESS,
   JobStatusEnum.NOT_NEEDED
  }
 ),
 new Criteria() {
  public boolean matches(Object obj) throws Exception {
   return EnvironmentLookup.getCurrent().getShortName().equals("dev");      
  }
 }
);

is_qa:

Logic.and(
 JobStatus.allAncestorsIn(
  new JobStatusEnum[]{
   JobStatusEnum.SUCCESS,
   JobStatusEnum.NOT_NEEDED
  }
 ),
 new Criteria() {
  public boolean matches(Object obj) throws Exception {
   return EnvironmentLookup.getCurrent().getShortName().equals("qa");      
  }
 }
);

is_stage:

Logic.and(
 JobStatus.allAncestorsIn(
  new JobStatusEnum[]{
   JobStatusEnum.SUCCESS,
   JobStatusEnum.NOT_NEEDED
  }
 ),
 new Criteria() {
  public boolean matches(Object obj) throws Exception {
   return EnvironmentLookup.getCurrent().getShortName().equals("stage");      
  }
 }
); 

is_prod:

Logic.and(
 JobStatus.allAncestorsIn(
  new JobStatusEnum[]{
   JobStatusEnum.SUCCESS,
   JobStatusEnum.NOT_NEEDED
  }
 ),
 new Criteria() {
  public boolean matches(Object obj) throws Exception {
   return EnvironmentLookup.getCurrent().getShortName().equals("prod");      
  }
 }
);

Using this method requires that the environment shortname be named exactly “dev”, “qa”, “stage” and “prod”. This is defined in the environments section under the systems tab. It’s also especially useful to make your environment shortnames as statuses in your life cycle model, but that is another topic. Also, take note of the part of the script:

--> JobStatus.allAncestorsIn(new JobStatusEnum[] { JobStatusEnum.SUCCESS, JobStatusEnum.NOT_NEEDED })

This portion of the script ensures that not only are we executing in a specific environment, but all previous jobs executed successfully, or “not needed” meaning, a job in the past may not have executed because it was not needed.

Selecting agents using agent filters using roles and hosts with Anthill Pro

Best practice when setting up your deployment workflows with Anthill Pro (or any other tool for that matter) is to classify the hosts in your farm by role and host. This way, you can deploy common artifacts to your roles and specific artifacts to your hosts in an elegant way. As an environment grows and becomes more complex, the need to do this becomes more obvious, however It’s my opinion to set this up from the start. This way, when deploying new hosts to your environments, all that is needed is your system environment as some simple agent properties set. Then, by your hosts simply being members of an environment in Anthill Pro, they automatically receive the proper artifacts that they need. Recommendations on how to separate and organize such artifacts (especially configuration artifacts) is a topic for another post. What I want to discuss is the non-obvious part about setting up anthill to correctly select agents you want for xALL iterations in a given workflow. The additional benefit of this is to ensure your workflows remain autononymous from your environments, so that as you deploy to more non-critical environments (like QA) you have more confidence in the deployment process to more critical environments (like Staging / Production) because you’re using the same workflows.

In a given workflow, it’s common to need to perform similar operations to the same hosts within a given role, for instance. You may want to shut down all “coldfusion” servers, or all “websphere-ejb” servers within those given roles. With anthill pro, you can use a simple agent filter beanshell script to isolate operations to those specific hosts of that role, but it’s not completely straight forward.  Let’s say you have 3 roles in your farm, “coldfusion”, “websphere-ejb” and “apache”. If you wanted to create an agent filter for one of these roles (“apache”) you would use this syntax:

return
 Where.is(
  Variable.equals("role", "apache")
 );
)
Simple enough, but understand that this syntax will only work with 1 criteria, if you wanted to have 2, like “apache” and “coldfusion” you would need to do:
return
 Where.any(
  Variable.equals("role", "apache"),
  Variable.equals("role", "coldfusion"),
 );
)
Notice we’ve changed the “Where.is” to “Where.any”, this is great when you want to have 2 criteria. However, if you want to do 3 or more, “apache”, “coldfusion” and “websphere-ejb” then you have to create an instance of a “Criteria” object like so:
return
 Where.any( new Criteria[] {
  Variable.equals("role", "apache"),
  Variable.equals("role", "coldfusion"),
  Variable.equals("role", "websphere-ejb")
 });
)

Hopefully this post will save you some time when creating custom agent filters based on agent properties in Anthill Pro, if you try to use 3 or more criteria with the Where.any() method, you may be left banging your head against the keyboard trying to understand why you are getting a beanshell error.

Terminology used in this blog

In order for all readers to put our posts in perspective, here’s a listing of the terminology that will be used with explanations.

  • Environment
    An environment is a distinct “Farm” of computers designed to run an application. Multiple environments are required to exist to facilitate the “Full lifecycle” of a given application. Common examples of environments would be called:

    • dev: common environment for a development team to test new code
    • sit: “systems integration testing” an environment used to test the interaction of multiple components of an application before testers do.
    • qa: An environment used to run automated and manual test cases
    • uat: An environment used for common use cases by stakeholders or testers.
    • stage: An environment used to test the deployment of the application.
    • production: Real, customer facing environment.
  • Farm
    A collection of  “roles” in a given environment. In a common lamp stack scenario, one may see a farm consisting of, a mysql role and an apache role, and perhaps a memcache role.
  • Role
    A role is a distinct role that 1 or many servers can perform. To clarify, just because multiple servers run jboss doesn’t mean they are all performing a ‘jboss role’. These jboss servers can be performing very different functions, requiring different configuration and even versions of jboss. A role is essentially a logical grouping of servers in the service of creating a conceptual reality, which together, all roles in an environment create a “farm”.
  • Host
    A host is a distinct server or VM that exists inside a “role”.
  • Buildlife
    A buildlife is a distinct instance of 1 or more artifact sets consisting of all required components to run an application, including all configurations for all environments.
  • Artifact set
    An artifact set is a collection of files which are logically separated based upon their use and / or destination. Typically, one would create separate artifact sets for configurations for each environment, while configuration themselves may be separated into separate artifact sets. Example:  “apache dev configs”, “apache qa configs”, “apache prod configs”  “jboss dev configs”, “jboss qa configs”, “jboss prod configs”.