andy-dufour / cookbook-cq

Chef cookbook for Adobe CQ (aka AEM)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

CQ/AEM Chef cookbook

This is CQ/AEM cookbook that is primarily a library cookbook.

FYI, this cookbook is not called aem-coobkook, because when I started development CQ was not rebranded to AEM yet and I simply like the old name much better. Nowadays it seems to be already taken anyway, so I no longer have a choice.

Table of contents

Supported platforms

Operating systems

  • CentOS/RHEL 6.x

Chef versions

  • Chef 12.x

AEM/CQ versions

  • AEM 5.6.1
  • AEM 6.0.0
  • AEM 6.1.0
  • AEM 6.2.0

Getting started

TBD

Attributes

For default values please refer to appropriate files.

default.rb


To set Java related attributes please refer to java cookbook. By default it installs Oracle's JDK7.


Attribute Type Description
['cq']['user'] String System user for CQ/AEM
['cq']['user_uid'] String UID of CQ/AEM user
['cq']['user_comment'] String Comment/description of CQ/AEM user
['cq']['user_shell'] String Default shell of CQ/AEM user
['cq']['group'] String System group for CQ/AEM
['cq']['group_gid'] String GID of CQ/AEM group
['cq']['limits']['file_descriptors'] String Max number of open file descriptor for CQ/AEM user
['cq']['base_dir'] String Base directory for CQ/AEM instance(s)
['cq']['home_dir'] String Home directory under wich CQ/AEM instances are deployed
['cq']['version'] String CQ/AEM version
['cq']['custom_tmp_dir'] String Custom directory that JVM uses for temporary files
['cq']['jar']['url'] String URL from which CQ/AEM JAR file is downloaded
['cq']['jar']['checksum'] String SHA256 checksum of CQ/AEM JAR file
['cq']['license']['url'] String URL from which CQ/AEM license is downloaded
['cq']['license']['checksum'] String SHA256 checksum of CQ/AEM license file
['cq']['service']['start_timeout'] Fixnum Max number of seconds to wait until CQ/AEM instance is fully operational after service start
['cq']['service']['kill_delay'] Fixnum Max number of seconds for greceful instance stop before kill signal is sent to the process
['cq']['service']['restart_sleep'] Fixnum Number of seconds to wait between service stop and start
['cq']['init_template_cookbook'] String Cookbook which is a source for init script template
['cq']['conf_template_cookbook'] String Cookbook which is a source for conf file template

author.rb

All attributes in this file refer to CQ/AEM author instance ( ['cq']['author'] namespace).

Attribute Type Description
['cq']['author']['run_mode'] String Instance run mode
['cq']['author']['port'] String Main port of CQ/AEM instance
['cq']['author']['jmx_ip'] String Value of -Djava.rmi.server.hostname JVM parameter. Requires reference to ${CQ_JMX_IP} shell variable in ['cq']['author']['jvm']['jmx_opts'] attribute to be effective
['cq']['author']['jmx_port'] String Value of -Dcom.sun.management.jmxremote.port and/or -Dcom.sun.management.jmxremote.rmi.port JVM parameters. Requires reference to ${CQ_JMX_PORT} shell variable in ['cq']['author']['jvm']['jmx_opts'] attribute to be effective
['cq']['author']['debug_ip'] String IP to listen on with debug interface. Requires reference to ${CQ_DEBUG_IP} shell variable in ['cq']['author']['jvm']['debug_opts'] attribute to be effective
['cq']['author']['debug_port'] String Port of JVM debug interface. Requires reference to ${CQ_DEBUG_PORT} shell variable in ['cq']['author']['jvm']['debug_opts'] attribute to be effective
['cq']['author']['credentials']['login'] String User that's used to perform actions agains your CQ/AEM instance. The most typical scenarios require admin
['cq']['author']['credentials']['password'] String Passowrd of user specified in ['cq']['author']['credentials']['login']
['cq']['author']['jvm']['min_heap'] String Number of megabytes that's passed on to -Xms JVM parameter
['cq']['author']['jvm']['max_heap'] String Number of megabytes that's passed on to -Xmx JVM parameter
['cq']['author']['jvm']['max_perm_size'] String Number of megabytes that's passed on to -XX:MaxPermSize JVM parameter
['cq']['author']['jvm']['code_cache_size'] String Number of megabytes that's passed on to -XX:ReservedCodeCacheSize JVM parameter
['cq']['author']['jvm']['general_opts'] String Generic JVM parameters
['cq']['author']['jvm']['code_cache_opts'] String JVM parameters related to its code cache
['cq']['author']['jvm']['gc_opts'] String JVM parameters related to garbage collection
['cq']['author']['jvm']['jmx_opts'] String JVM parameres related to JMX settings
['cq']['author']['jvm']['debug_opts'] String JVM parameters related to debug interface
['cq']['author']['jvm']['crx_opts'] String CRX related JVM parameters
['cq']['author']['jvm']['extra_opts'] String All other JVM patameters
['cq']['author']['healthcheck']['resource'] String Resource that's queried during instance start to determine whether CQ/AEM is fully operational
['cq']['author']['healthcheck']['response_code'] String Expected HTTP status code of healthcheck resource

publish.rb

All attributes in this file refer to CQ/AEM publish instance ( ['cq']['publish'] namespace).

Attribute Type Description
['cq']['publish']['run_mode'] String Instance run mode
['cq']['publish']['port'] String Main port of CQ/AEM instance
['cq']['publish']['jmx_ip'] String Value of -Djava.rmi.server.hostname JVM parameter. Requires reference to ${CQ_JMX_IP} shell variable in ['cq']['publish']['jvm']['jmx_opts'] attribute to be effective
['cq']['publish']['jmx_port'] String Value of -Dcom.sun.management.jmxremote.port and/or -Dcom.sun.management.jmxremote.rmi.port JVM parameters. Requires reference to ${CQ_JMX_PORT} shell variable in ['cq']['publish']['jvm']['jmx_opts'] attribute to be effective
['cq']['publish']['debug_ip'] String IP to listen on with debug interface. Requires reference to ${CQ_DEBUG_IP} shell variable in ['cq']['publish']['jvm']['debug_opts'] attribute to be effective
['cq']['publish']['debug_port'] String Port of JVM debug interface. Requires reference to ${CQ_DEBUG_PORT} shell variable in ['cq']['publish']['jvm']['debug_opts'] attribute to be effective
['cq']['publish']['credentials']['login'] String User that's used to perform actions agains your CQ/AEM instance. The most typical scenarios require admin
['cq']['publish']['credentials']['password'] String Passowrd of user specified in ['cq']['publish']['credentials']['login']
['cq']['publish']['jvm']['min_heap'] String Number of megabytes that's passed on to -Xms JVM parameter
['cq']['publish']['jvm']['max_heap'] String Number of megabytes that's passed on to -Xmx JVM parameter
['cq']['publish']['jvm']['max_perm_size'] String Number of megabytes that's passed on to -XX:MaxPermSize JVM parameter
['cq']['publish']['jvm']['code_cache_size'] String Number of megabytes that's passed on to -XX:ReservedCodeCacheSize JVM parameter
['cq']['publish']['jvm']['general_opts'] String Generic JVM parameters
['cq']['publish']['jvm']['code_cache_opts'] String JVM parameters related to its code cache
['cq']['publish']['jvm']['gc_opts'] String JVM parameters related to garbage collection
['cq']['publish']['jvm']['jmx_opts'] String JVM parameres related to JMX settings
['cq']['publish']['jvm']['debug_opts'] String JVM parameters related to debug interface
['cq']['publish']['jvm']['crx_opts'] String CRX related JVM parameters
['cq']['publish']['jvm']['extra_opts'] String All other JVM patameters
['cq']['publish']['healthcheck']['resource'] String Resource that's queried during instance start to determine whether CQ/AEM is fully operational
['cq']['publish']['healthcheck']['response_code'] String Expected HTTP status code of healthcheck resource

Recipes

default.rb

Installs core dependencies (Ruby gems and OS packages).

commons.rb

Takes care of common elements of every CQ/AEM deployment, including:

  • system user and its configuration
  • required directory structure
  • Java installation
  • CQ Unix Toolkit installation

author.rb

Installs CQ/AEM author instance.

publish.rb

Installs CQ/AEM publish instance.

Custom resources


All CQ/AEM related resource are idempotent, so action won't be taken if not required.



Whenever you need to deploy 2 or more CQ/AEM instances on a single server please make sure you named all your custom resources differently, as you may get unexpected results otherwise (i.e. when CQ/AEM restart is required afterwards). Please find cq_package example below:

Bad:

cq_package 'package1' do
  instance "http://localhost:#{node['cq']['author']['port']}"

  action :deploy
end

cq_package 'package1' do
  instance "http://localhost:#{node['cq']['publish']['port']}"

  action :deploy
end

Good:

cq_package 'Author: package1' do
  instance "http://localhost:#{node['cq']['author']['port']}"

  action :deploy
end

cq_package 'Publish: package1' do
  instance "http://localhost:#{node['cq']['publish']['port']}"

  action :deploy
end

cq_package

Allows for CRX package manipulation using CRX Package Manager API.

Key features:

  • package specific details (name, group, version) are always extracted from ZIP file (/META-INF/vault/properties.xml), so you don't have to define that anywhere else. All you need is an URL to your package
  • cq_package identifies packages by name/group/version properties
  • packages are automatically downloaded from remote (http://, https://) or local (file://) sources. If HTTP(S) source requires basic auth please use http_user and http_pass
  • by default all packages are downloaded to Chef's cache (/var/chef/cache)
  • installation process is considered finished only when both "foreground" (Package Manager) and "background" (OSGi bundle/component restarts) ones are over - no more 'wait until you see X in error.log'

Actions


If you'd like to upload and install a package, in most cases please use deploy action instead of combined upload and install. Detailed explanation can be found below.


  • upload - uploads package to given CQ instance
  • install - installs already uploaded package
  • deploy - uploads and installs given package as a single action. This action is quicker than separate upload + install as less healthchecks have to be executed
  • uninstall - uninstalls given CQ package
  • delete - deletes given CQ package

Properties

Property Type Description
name String Package name. Can be anything as long as it means something to you. Actual package name is extracted from provided ZIP file. Whenever you use notifies on your package resource and more than a single action was defined (i.e. action [:upload, :install]), two notifications will be triggered (after :upload and :install respectively)
username String Instance username
password String Instance password
instance String Instance URL
source String URL to ZIP package. Accepted protocols: file://, http://, https://
http_user String HTTP basic auth user. Use whenever source requires such authentication
http_pass String HTTP basic auth password. Use whenever source requires such authentication
recursive_install Boolean Whether to use recursive flag when installing packages (required for service packs and some hotfixes). Applies only to install and deploy actions
rescue_mode Boolean Some packages may cause shutdown of the entire OSGi because of dependecy (i.e. cycle) or bundle priority issues. In such case after package installation java process is still running, however the instance is not responding over HTTP. After CQ/AEM restart everyting works perfectly fine again. This flag allows Chef to continue processing if it is not able to get OSGi bundles state error_state_barrier times in a row. In most (if not all) cases it should be combined with restart notification (please see examples below). It is highly discouraged to use this property, as 99% of CRX packages shouldn't require such configuration. Unfortunately that 1% does. This is rather a safety switch than a common pattern that should be used in every single case. Applies only to install and deploy actions.
checksum String ZIP file checksum (passed through to remote_file resource that is used under the hood by cq_package provider)
same_state_barrier Integer How many times in a row the same OSGi state should occur after package (un)installation to consider this process successful. Default is 6
error_state_barrier Integer How many times in a row the OSGi console was unavailable after package (un)installation. Useful only when combined with rescue_mode. By default set to 6
max_attempts Integer Number of attempts while waiting for stable OSGi state after package (un)installation. Set to 30 by default
sleep_time Integer Sleep time between OSGi status checks (in seconds) after package (un)installation. Set to 10 by default

Usage

More comprehensive examples can be found in package test recipes:

cq_package 'Slice 4.2.1' do
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  source 'https://oss.sonatype.org/content/groups/public/com/cognifide/slice'\
    '/slice-assembly/4.2.1/slice-assembly-4.2.1-cq.zip'

  action :upload
end

cq_package 'Upgrade to Oak 1.0.13' do
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  source 'https://artifacts.example.com/aem/6.0.0/hotfixes'\
    '/cq-6.0.0-hotfix-6316-1.1.zip'
  http_user 'john'
  http_pass 'passw0rd'

  action :upload
end

cq_package 'ACS AEM Commons 1.10.2' do
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  source 'https://github.com/Adobe-Consulting-Services/acs-aem-commons'\
    '/releases/download/acs-aem-commons-1.10.2'\
    '/acs-aem-commons-content-1.10.2.zip'

  action [:upload, :install]
end

cq_package 'AEM6 hotfix 6316' do
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  source node['cq']['packages']['aem6']['hf6316']
  recursive_install true

  action :deploy

  notifies :restart, 'service[cq60-author]', :immediately
end

cq_package 'Geometrixx All' do
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  source "http://localhost:#{node['cq']['author']['port']}/etc/packages"\
    '/day/cq60/product/cq-geometrixx-all-pkg-5.7.476.zip'
  http_user node['cq']['author']['credentials']['login']
  http_pass node['cq']['author']['credentials']['password']

  action :uninstall
end

cq_package 'Not really well-thought-out package' do
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  source node['cq']['packages']['myapp']
  http_user node['cq']['author']['credentials']['login']
  http_pass node['cq']['author']['credentials']['password']
  rescue_mode true

  action :deploy

  notifies :restart, 'service[cq60-author]', :immediately
end

cq_package 'Author: Service Pack 2 (upload)' do
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  source node['cq']['packages']['aem6']['sp2']

  action :upload
end

cq_package 'Author: Service Pack 2 (install)' do
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  source node['cq']['packages']['aem6']['sp2']
  recursive_install true

  action :install

  notifies :restart, 'service[cq60-author]', :immediately
end

First cq_package resource will download Slice package from provided URL and upload it to defined AEM Author instance.

Second resource does the same as the first one, but for Oak 1.0.13 hotfix. The only difference is that provided URL requires basic auth, hence the http_user and http_pass properties.

Third package shows how to combine multiple actions in a single cq_package resource usage.

4th cq_package presents how to use deploy action that combines both upload and install in a single execution. This is preferred way of doing package deployment, in particular for those that require AEM service restart as soon as installation is completed. recursive_install was also used here, which is required for majority of hotfixes and every service pack.

Next example describes usage of uninstall action. In this particular case operation was executed against Geometrixx package.

6th cq_package presents usage of rescue_mode property. Imagine that this package provides new OSGi bundles and right after its installation some serious issue occurs (i.e. unresolvable OSGi dependency, conflict or cycle). As a result of this event all (or almost all) bundles will be turned off and effectively instance will stop responding or start serving 404s for all resources (including /system/console). The java process though will still be running. The only solution to that problem is AEM restart, after which all work perfectly fine again. Without rescue_mode property cq_package provider will keep checking OSGi bundles to detect their stable state, but none of these attempts will end successfully, as nothing is reachable over HTTP. After 30 requests Chef run will be aborted. If rescue_mode was activated (set to true) then after 6 unsuccessful attempts an error will be printed and the processing will be continued (restart of cq60-author service in this case).

7th & 8th cq_package resources explain how to deal with AEM instance restarts after package installation.

Moreover it explains how to use combination of upload and install instead of deploy. Such procedure might be required sometimes, i.e. when some extra steps have to be done after package upload, but before its installation.

Please notice that both resources were named differently on purpose to avoid resource merge and 2 restarts. If you'd use:

cq_package 'Author: Service Pack 2' do
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  source node['cq']['packages']['aem6']['sp2']
  recursive_install true

  action [:upload, :install]

  notifies :restart, 'service[cq60-author]', :immediately
end

or

cq_package 'Author: Service Pack 2' do
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  source node['cq']['packages']['aem6']['sp2']

  action :upload
end

cq_package 'Author: Service Pack 2' do
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  source node['cq']['packages']['aem6']['sp2']
  recursive_install true

  action :install

  notifies :restart, 'service[cq60-author]', :immediately
end

two restarts will be triggered.

In the first case during compile phase Chef will generate 2 resources with the same name, but different actions.

In second example restart still will be triggered after upload, even if it's not explicitly defined during 1st usage (upload action). The reason is quite simple - both resources are named the same (Author: Service Pack 2) and Chef will treat this as a single resource on resource collection, which means that notify parameter will be silently merged to the resource with upload action during compile phase.

cq_osgi_config

Provides an interface for CRUD operations in OSGi configs.

Actions

For non-factory (regular) configs:

  • create - updates already existing configuration
  • delete - restores default settings of given OSGi config if all properties match to defined state. If you'd like to restore default settings regardless of current properties please use force parameter

For factory configs:

  • create - creates a new factory config instance if none of existing ones match to defined state
  • delete - deletes factory config instance if there's one that matches to defined state

Properties

Property Type Description
pid String Config name (PID). Important for regular configs only. Can be anything for factory ones
username String Instance username
password String Instance password
instance String Instance URL
factory_pid String Factory PID
properties Hash Key-value pairs that represent OSGi config properties
append Boolean If set to true arrays will be merged. Use if you'd like to specify just a subset of array elements. false by default. Has no impact on other property types (String, Fixnum, etc)
apply_all Boolean If true all properties defined in a cq_osgi_config resource will be used when applying OSGi configuration (despite of the fact just a subset differs). Example: 5 properties were defined as properties, 3 of them require update, but all of them will be set. false by default
include_missing Boolean Properties that were NOT defined by user, but exist in OSGi will be included as a part of an update if this property is set to true for regular OSGi configs. For factory configs it bahaves almost the same. If new instance needs to be created then defaults defined in factory PID will be used. In case of existing instance update, all missing properties will be based on properties defined in that instance. This is recommended property for factory OSGi configs, in particular when you'd like to edit pre-existing factory instances. false by default
unique_fields Array Property names/keys that define uniqueness of given config. Applicable to factory configs only. By deafult all available property keys will be used (defined by factory config on AEM instance). User doesn't need to define that at all, unless you want to cherry pick particular config. Example: log.name key needs to stay unique for your config
count Fixnum Number of duplicated instances of given OSGi configuration. 1 by default. Applicable to factory configs only. Useful when duplicated instances are allowed, i.e. each instance specify some sort of a worker
enforce_count Boolean Reduces number of duplicated configs if more than count has been found. Applicable to factory configs only. false by default
force Boolean If true, defined OSGi config is deleted/updated reagrdless of current settings. Applies to regular OSGi configs only. This violates idempotence, so please use only_if or not_if blocks to prevent constant execution
rescue_mode Boolean Some config operations may cause shutdown of the entire OSGi because of dependecy (i.e. cycle) or bundle/component priority issues. In such case after config update java process is still running, however the instance is not responding over HTTP. After CQ/AEM restart everyting works perfectly fine again. This flag allows Chef to continue processing if it is not able to get OSGi component state error_state_barrier times in a row. In most (if not all) cases it should be combined with AEM restart notification. It is highly discouraged to use this property, as 99% of OSGi configs shouldn't require such configuration. Unfortunately that 1% does. This is rather a safety switch than a common pattern that should be used in every single case.
same_state_barrier Integer How many times in a row the same OSGi component state should occur after configuration update to consider this process successful. 3 by default
error_state_barrier Integer How many times in a row the OSGi console was unavailable after OSGi config update. Useful only when combined with rescue_mode. 3 by default
max_attempts Integer Number of attempts while waiting for stable OSGi state after OSGi config update. 60 by default
sleep_time Integer Sleep time between OSGi component status checks (in seconds) after config update. 2 by default

Compatibility matrix

Property Regular OSGi config Factory OSGi config
pid
username
password
instance
factory_pid
properties
append
apply_all
include_missing
unique_fields
count
enforce_count
force

Usage

Detailed examples can be found here:

Please keep in mind that all recipes above use definitions/osgi_config_wrapper.rb definition for testing purposes.

Regular OSGi configs

cq_osgi_config 'Root Mapping' do
  pid 'com.day.cq.commons.servlets.RootMappingServlet'
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  properties('rootmapping.target' => '/welcome.html')

  action :create
end

cq_osgi_config 'Event Admin' do
  pid 'org.apache.felix.eventadmin.impl.EventAdmin'
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  append true
  properties(
    'org.apache.felix.eventadmin.IgnoreTimeout' => ['com.example*']
  )

  action :create
end

cq_osgi_config 'OAuth Twitter' do
  pid 'com.adobe.granite.auth.oauth.impl.TwitterProviderImpl'
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  properties(
    'oauth.provider.id' => 'twitter'
  )

  action :delete
end

cq_osgi_config 'Promotion Manager' do
  pid 'com.adobe.cq.commerce.impl.promotion.PromotionManagerImpl'
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  force true
  properties({})

  action :delete
end

Root Mapping resource sets / redirect to /welcome.html if it's not already set.

Event Admin merges defined properties with the ones that are already set (because of append property). This is how Event Admin will look like before:

ID VALUE
org.apache.felix.eventadmin.ThreadPoolSize 20
org.apache.felix.eventadmin.Timeout 5000
org.apache.felix.eventadmin.RequireTopic true
org.apache.felix.eventadmin.IgnoreTimeout ["org.apache.felix*","com.adobe*"]

and after Chef run:

ID VALUE
org.apache.felix.eventadmin.ThreadPoolSize 20
org.apache.felix.eventadmin.Timeout 5000
org.apache.felix.eventadmin.RequireTopic true
org.apache.felix.eventadmin.IgnoreTimeout ["com.adobe*","com.example*","org.apache.felix*"]

OAuth Twitter will be deleted (restore to the defaults, as this is regular OSGi config) only if properties match: oauth.provider.id is set to oauth.provider.id.

Promotion Manager will be deleted (restored to defaults) regardless of its current settings because of force flag.

Factory OSGi configs

cq_osgi_config 'Custom Logger' do
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  factory_pid 'org.apache.sling.commons.log.LogManager.factory.config'
  properties(
    'org.apache.sling.commons.log.level' => 'error',
    'org.apache.sling.commons.log.file' => 'logs/custom.log',
    'org.apache.sling.commons.log.pattern' =>
      '{0,date,dd.MM.yyyy HH:mm:ss.SSS} *{4}* [{2}] {3} {5}',
    'org.apache.sling.commons.log.names' => [
      'com.example.custom1',
      'com.example.custom2'
    ]
  )

  action :create
end

cq_osgi_config 'Job Queue' do
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  factory_pid 'org.apache.sling.event.jobs.QueueConfiguration'
  properties(
    'queue.name' => 'Granite Workflow Timeout Queue',
    'queue.type' => 'TOPIC_ROUND_ROBIN',
    'queue.topics' => ['com/adobe/granite/workflow/timeout/job'],
    'queue.maxparallel' => -1,
    'queue.retries' => 10,
    'queue.retrydelay' => 2000,
    'queue.priority' => 'MIN',
    'service.ranking' => 0
  )

  action :delete
end

Custom Logger resource will create a new logger according to defined properties unless it is already present. There's no need to specify an UUID in resource definition.

Job Queue resource will delete a factory instance of org.apache.sling.event.jobs.QueueConfiguration that matches to defined properties. Nothing will happen when there's no such OSGi config.

cq_osgi_bundle

Adds ability to stop and start OSGi bundles

Actions

  • stop - stop given OSGi bundle if it is in Active state
  • start - starts defined bundle, but only when it's in Resolved state

Properties

Property Type Description
symbolic_name String Symbolic name of the bundle, i.e. com.company.example.abc. If not explicitly defined resource name will be used as symbolic name
username String Instance username
password String Instance password
instance String Instance URL
rescue_mode Boolean Same meaning as for cq_package
same_state_barrier Integer Same meaning as for cq_package
error_state_barrier Integer Same meaning as for cq_package
max_attempts Integer Same meaning as for cq_package
sleep_time Integer Same meaning as for cq_package

Usage

cq_osgi_bundle 'Author: org.eclipse.equinox.region' do
  symbolic_name 'org.eclipse.equinox.region'
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  same_state_barrier 3
  sleep_time 5

  action :stop
end

cq_osgi_bundle 'com.adobe.xmp.worker.files.native.fragment.linux' do
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"

  action :start
end

First example stops org.eclipse.equinox.region AEM author instance. Since there's just a few dependencies on this bundle, number of post-stop checks have been limited, as there's no point to wait for so long.

Second instance of cq_osgi_bundle is fairly simple, as it just starts com.adobe.xmp.worker.files.native.fragment.linux bundle.

cq_osgi_component

Management of OSGi components

Actions

  • enable - enable given OSGi component
  • disable - disable defined OSGi component

Properties

Property Type Description
pid String Component PID
username String Instance username
password String Instance password
instance String Instance URL

Usage

cq_osgi_component 'Author: com.example.my.component' do
  symbolic_name 'com.example.my.component'
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"

  action :enable
end

cq_osgi_component 'Author: com.project.email.servlet' do
  symbolic_name 'com.project.email.servlet'
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"

  action :disable
end

Both examples are self-explanatory. First one enables com.example.my.component component if it's in disabled state. Second one will disable com.project.email.servlet component, but only if it's state is not already disabled.


Please keep in mind that OSGi components used to get back to their original state after AEM instance restart. So if you disabled one, most probably it'll become enabled after instance restart.


cq_user

Exposes a resource for CQ/AEM user management. Supports:

  • password updates
  • profile updates (e-mail, job title, etc)
  • status updates (activate/deactivate given user)

Actions

  • modify - use to modify an existing user. Action will be skipped if given user does not exist

Properties

Property Type Description
id String User ID (login)
username String Instance username
password String Instance password
instance String Instance URL
email String E-mail
first_name String First name
last_name String Last name
phone_number String Phone number
job_title String Job title
street String Street
mobile String Mobile
city String City
postal_code String Postal code
country String Country
state String State
gender String Gender
about String About section
user_password String Desired password for non-admin user specified by id property
enabled Boolean True by default, set to false to deactive given user. Has no effect for admin user
old_password String Old password of admin user. Has no effect for non-admin ones

Compatibility matrix

Property admin user All other users
id
username
password
instance
email
first_name
last_name
phone_number
job_title
street
mobile
city
postal_code
country
state
gender
about
user_password
enabled
old_password

Usage

More detailed examples are available here.

cq_user 'admin' do
  username node['cq']['author']['credentials']['login']
  password 'd4rk_kn1ght'
  instance "http://localhost:#{node['cq']['author']['port']}"

  first_name 'Bruce'
  last_name 'Wayne'
  old_password 'passw0rd'

  action :modify
end

cq_user 'author' do
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"

  first_name 'Peter'
  last_name 'Parker'
  job_title 'Spiderman'
  gender 'male'
  enabled false
  user_password 'sp1d3r'

  action :modify
end

Modify action on cq_user 'admin' resource will change CQ/AEM admin's password to d4rk_kn1ght if the current one is either passw0rd or admin (the latter is automatically checked if both password and old_password are incorrect). Moreover admin's first name and last name will be updated (to Bruce and Wayne respectively) if needed.

Second example (cq_user 'author') also updates user password, but this time the old one doesn't have to be specified, as this operation will be executed on admin rights (auth credentials: username/password). Additionally auhtor's profile will be updated and user will be disabled (enabled false), so you won't be able to log in as this user anymore.

cq_jcr

CRUD operations on JCR nodes.

Actions

  • create - creates new node under given path if it doesn't exist. Otherwise it modifies its properties if required
  • delete - deletes node if it exists. Prints error otherwise
  • modify - modifies properties of existing JCR node

Properties

Property Type Description
path String Node path
username String Instance username
password String Instance password
instance String Instance URL
properties Hash Node properties
append Boolean By default set to true. If full overwrite of properties is required please set append property to false. Applies only to :create and :modify actions

Usage

More examples of cq_jcr are available in this recipe.

cq_jcr '/content/test_node' do
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  properties(
    'property_one' => 'first',
    'property_two' => 'second',
    'property_three' => ['item1', 'item2', 'item3']
  )

  action :create
end

cq_jcr '/content/geometrixx/en/products/jcr:content' do
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  append false
  properties(
    'jcr:primaryType' => 'cq:PageContent',
    'jcr:title' => 'New title',
    'subtitle' => 'New subtitle',
    'new_property' => 'Random value'
  )

  action :create
end

cq_jcr '/content/dam/geometrixx-media/articles/en/2012' do
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"

  action :delete
end

cq_jcr '/content/geometrixx/en/services/certification/jcr:content' do
  username node['cq']['author']['credentials']['login']
  password node['cq']['author']['credentials']['password']
  instance "http://localhost:#{node['cq']['author']['port']}"
  properties(
    'jcr:title' => 'New Certification Services',
    'brand_new_prop' => 'ValueX'
  )

  action :modify
end

Create action on cq_jcr '/content/test_node' will create such node with given properties if it doesn't exist yet. Otherwise its properties will be updated if necessary. By default append is set to true, which means existing properties of /content/test_node will stay untouched unless the same properties are specified in your cq_jcr resource.

2nd example sets append property to false, which means that all properties except those specified in your resource should be removed. It will act as a full overwrite (keep in mind that some properties are protected and can't be deleted, moreover Sling API automatically adds things like jcr:createdBy).

Next example is very simple - /content/dam/geometrixx-media/articles/en/2012 will get deleted if it exists. Otherwise warning message will be printed.

Last cq_jcr resource uses :modify action. It applies updates to existing nodes only. If specified path does not exist warning message will be displayed.

Testing

TBD

Author

Jakub Wadolowski (jakub.wadolowski@cognifide.com)

About

Chef cookbook for Adobe CQ (aka AEM)

License:Other


Languages

Language:Ruby 98.2%Language:Java 0.8%Language:HTML 0.5%Language:Shell 0.5%