DevOps Automation

 View Only

UrbanCode Deploy 10 Minute Tips: Sharing Properties Between Components

By IBM DevOps Expert posted Mon May 09, 2022 01:23 PM

  

There are times when we need to share a property between components but how best to achieve that?

In IBM UrbanCode Deploy (now IBM DevOps Deploy) processes, we normally seek to minimize the scope of visibility of properties so that there is no confusion between similar / same-named properties between components and also because we generally have no need for a wider scope.


So, how can I share a property between components?  Well I suppose we should start out by asking – Why do we need to?

There are some usecases where this can be required, but they are usually along the lines of: you have a resource provider and a resource consumer, and they are in different components.

For example, I have a database component for my application which manages the database itself and I have another component that uses the database.  They both have a need to access the database and they both need credentials to do so.

Another complication to this scenario is that these kinds of situations you often want different values for the properties in one or more environments.  This limits us immediately to the environment or resource properties.

If I use a component environment property definition, they are only in scope for the component that defines the property.  So how can I share the value?  I don’t want to have to define the property in several places, I would then have to remember where all the copies were.  If say the database password had to be changed I’d then have to try and find all the copies to update them or risk a deployment failure.

As a general rule and best practice, it’s best to define something only once, and use it in many places. So, if I was writing code, I’d have the database component retrieve its credentials from wherever they are stored and then provide an interface to let others a means to retrieve them in some form.

How can we do this with UCD?

I’m sure there are going to be other solutions to this problem, some of which may have a process change the value of another property on-the-fly.  But this means that the number of versions of your property sheet is going to skyrocket and it’s also going to provide some ‘interesting’ challenges with snapshots.

Well, that is along the lines of the solution I’ll present here, but what I use are process properties. Yes, that’s right, processes have properties too.  First, I would decide on what component owns the property.  Usually, this is logically the resource provider. This component is where I define my component environment properties and then I have a component process that is always run, from the application process; something like an operational process with no version.  This process then uses a step from the UrbanCode Deploy Processes plugin to create each property I want to share on the parent application process so that now all components can see the properties you expose. 


So how did I Build It?

  • I created two components, provider and consumer and an application.
  • I added both my components to my application.
  • I created an environment for the application, added a resource tree to it with an agent and my two components under it. 
  • I created my component environment property definitions inside my provider component.  Three properties called databaseNamedatabaseUser and databasePassword the later one being a secure property.  In this example I used default values.  If you need different values then you would need to set the values of these properties in each of the environments.
  • In the provider component, I created an Operational (No version needed process) called share
  • I created a step for each of the properties I wanted to share using the Set Process Request Property Step

Each step looked something like this:

The key thing here is setting the Process Request ID field to ${p:parentRequest.id} This is the application process request that is executing this component process. If we’d used the component process, it would not have been in scope for other components.

Note that I decided to change the name of the property databaseName inside my provider component to dbName when I exposed it to a wider audience.

You may want to consider employing some kind of naming convention so that when you share a property in this way, you know what shared it and to avoid potential naming conflicts.  While generic names like dbName or databaseName might be ok inside a component, its very likely to be too generic when exposed to a wider audience. The dbName of what exactly??  Since the property name we’re creating in the step is dynamic, we could dynamically create its name.  eg we could use the component name as a prefix, something like ${p:component.name}-dbName. This would work nicely if our components were created from a component template. Of course, you can’t then change the name of the component or the property without breaking the consumers.  So whatever the constructed name is, it must be repeatable.

  • In the consumer component process I created a simple shell step that echo’s each of the shared properties. 

When we examine the execution history, we can see the values used by our provider component in the environment properties for provider section.  The consumer component makes use of the property values from the other Request Properties section.  So we still have visibility.

 

This technique allows us to easily share property values between components while still allowing us to have the rigor of property definitions and automated property creation where they are needed. It permits the provider control over the property value and allows easy access for consumers.

It avoids having multiple independent definitions or property sheets getting 100’s+ of versions and it neatly avoids the challenges you can get with snapshots which refer to specific versions of property sheets while maintaining the traceability of values used.


#UrbanCodeDeploy
#10minutetip

0 comments
6 views

Permalink