Update cookbooks for Ubuntu 16.04 TLS

This commit is contained in:
Greg Karékinian
2017-03-31 19:20:00 +02:00
parent 6430d71006
commit 8923d0d7ef
219 changed files with 2770 additions and 11511 deletions

View File

@@ -1,370 +0,0 @@
SMF
===
## Description
Service Management Facility (SMF) is a tool in many Illumos and Solaris-derived operating systems
that treats services as first class objects of the system. It provides an XML syntax for
declaring how the system can interact with and control a service.
The SMF cookbook contains providers for creating or modifying a service within the SMF framework.
## Requirements
Any operating system that uses SMF, ie Solaris, SmartOS, OpenIndiana etc.
The `smf` provider depends on the `builder` gem, which can be installed
via the `smf::default` recipe.
Requires the RBAC cookbook, which can be found at <https://supermarket.getchef.com/cookbooks/rbac>.
Processes can be run inside a project wrapper. In this case, look to the Resource Control cookbook,
which can be found at <https://supermarket.getchef.com/cookbooks/resource-control>. Note that the SMF LWRP
does not create or manage the project.
## Basic Usage
Note that we run the `smf::default` recipe before using LWRPs from this
cookbook.
```ruby
include_recipe 'smf'
smf 'my-service' do
user 'non-root-user'
start_command 'my-service start'
start_timeout 10
stop_command 'pkill my-service'
stop_timeout 5
restart_command 'my-service restart'
restart_timeout 60
environment 'PATH' => '/home/non-root-user/bin',
'RAILS_ENV' => 'staging'
locale 'C'
manifest_type 'application'
service_path '/var/svc/manifest'
notifies :restart, 'service[my-service]'
end
service 'my-service' do
action :enable
end
service 'my-service' do
action :restart
end
```
## Attributes
Ownership:
* `user` - User to run service commands as
* `group` - Group to run service commands as
RBAC
* `authorization` - What management and value authorizations should be
created for this service. Defaults to the service name.
Dependency management:
* `include_default_dependencies` - Service should depend on file system
and network services. Defaults to `true`. See [Dependencies](#dependencies)
for more info.
* `dependency` - an optional array of hashes signifying service and path
dependencies for this service to run. See [Dependencies](#dependencies).
Process management:
* `project` - Name of project to run commands in
* `start_command`
* `start_timeout`
* `stop_command` - defaults to `:kill`, which basically means it will destroy every PID generated from the start command
* `stop_timeout`
* `restart_command` - defaults to `stop_command`, then `start_command`
* `restart_timeout`
* `refresh_command` - by default SMF treats this as `true`. This will be called when the SMF definition changes or
when a `notify :reload, 'service[thing]'` is called.
* `refresh_timeout`
* `duration` - Can be either `contract`, `wait`, `transient` or
`child`, but defaults to `contract`. See the [Duration](#duration) section below.
* `environment` - Hash - Environment variables to set while running commands
* `ignore` - Array - Faults to ignore in subprocesses. For example,
if core dumps in children are handled by a master process and you
don't want SMF thinking the service is exploding, you can ignore
["core", "signal"].
* `privileges` - Array - An array of privileges to be allowed for started processes.
Defaults to ['basic', 'net_privaddr']
* `property_groups` - Hash - This should be in the form `{"group name" => {"type" => "application", "key" => "value", ...}}`
* `working_directory` - PWD that SMF should cd to in order to run commands
* `locale` - Character encoding to use (default "C")
Manifest/FMRI metadata:
* `service_path` - defaults to `/var/svc/manifest`
* `manifest_type` - defaults to `application`
* `stability` - String - defaults to "Evolving". Valid options are
"Standard", "Stable", "Evolving", "Unstable", "External" and
"Obsolete"
Deprecated:
* `credentials_user` - deprecated in favor of `user`
## Provider Actions
### :install (default)
This will drop a manifest XML file into `#{service_path}/#{manifest_type}/#{name}.xml`. If there is already a service
with a name that is matched by `new_resource.name` then the FMRI of our manifest will be set to the FMRI of the
pre-existing service. In this case, our properties will be merged into the properties of the pre-existing service.
In this way, updates to recipes that use the SMF provider will not delete existing service properties, but will add
or overwrite them.
Because of this, the SMF provider can be used to update properties for
services that are installed via a package manager.
### :delete
Remove an SMF definition. This stops the service if it is running.
### :add_rbac
This uses the `rbac` cookbook to define permissions that can then be applied to a user. This can be useful when local
users should manage services that are added via packages.
```ruby
smf "nginx" do
action :add_rbac
end
rbac_auth "Allow my user to manage nginx" do
user "my_user"
auth "nginx"
end
```
## Resource Notes
### `user`, `working_directory` and `environment`
SMF does a remarkably good job running services as delegated users, and removes a lot of pain if you configure a
service correctly. There are many examples online (blogs, etc) of users wrapping their services in shell scripts with
`start`, `stop`, `restart` arguments. In general it seems as if the intention of these scripts is to take care of the
problem of setting environment variables and shelling out as another user.
The use of init scripts to wrap executables can be unnecessary with SMF, as it provides hooks for all of these use cases.
When using `user`, SMF will assume that the `working_directory` is the user's home directory. This can be
easily overwritten (to `/home/user/app/current` for a Rails application, for example). One thing to be careful of is
that shell profile files will not be loaded. For this reason, if environment variables (such as PATH) are different
on your system or require additional entries arbitrary key/values may be set using the `environment` attribute.
All things considered, one should think carefully about the need for an init script when working with SMF. For
well-behaved applications with simple configuration, an init script is overkill. Applications with endless command-line
options or that need a real login shell (for instance ruby applications that use RVM) an init script may make life
easier.
### Role Based Authorization
By default the SMF definition creates authorizations based on the
service name. The service user is then granted these authorizations. If
the service is named `asplosions`, then `solaris.smf.manage.asplosions`
and `solaris.smf.value.asplosions` will be created.
The authorization can be changed by manually setting `authorization` on
the smf block:
```ruby
smf 'asplosions' do
user 'monkeyking'
start_command 'asplode'
authorization 'booms'
end
```
This can be helpful if there are many services configured on a single
host, as multiple services can be collapsed into the same
authorizations. For instance: https://illumos.org/issues/4968
### Dependencies
SMF allows services to explicitly list their dependencies on other
services. Among other things, this ensures that services are enabled in
the proper order on boot, so that a service doesn't fail to start
because another service has not yet been started.
By default, services created by the SMF LWRP depend on the following other services:
* svc:/milestone/sysconfig
* svc:/system/filesystem/local
* svc:/milestone/name-services
* svc:/milestone/network
On Solaris11, `svc:/milestone/sysconfig` is replaced with
`svc:/milestone/config`.
These are configured with the attribute `include_default_dependencies`,
which defaults to `true`.
Other dependencies can be specified with the `dependencies` attribute,
which takes an array of hashes as follows:
```ruby
smf 'redis'
smf 'redis-6999' do
start_command "..."
dependencies [
{name: 'redis', fmris: ['svc:/application/management/redis'],
grouping: 'require_all', restart_on: 'restart', type: 'service'}
]
end
```
Valid options for grouping:
* require_all - All listed FMRIs must be online
* require_any - Any of the listed FMRIs must be online
* exclude_all - None of the listed FMRIs can be online
* optional_all - FMRIs are either online or unable to come online
Valid options for restart_on:
* error - Hardware fault
* restart - Restarts service if the depedency is restarted
* refresh - Restarted if the dependency is restarted or refreshed for
any reason
* none - Don't do anything
Valid options for type:
* service - expects dependency FMRIs to be other services ie: svc:/type/of/service:instance
* path - expects FMRIs to be paths, ie file://localhost/etc/redis/redis.conf
Note: the provider currently does not do any validation of these values. Also, type:path has not been extensively
tested. Use this at your own risk, or improve the provider's compatibility with type:path and submit a pull request!
### Duration
There are several different ways that SMF can track your service. By default it uses `contract`.
Basically, this means that it will keep track of the PIDs of all daemonized processes generated from `start_command`.
If SMF sees that processes are cycling, it may try to restart the service. If things get too hectic, it
may think that your service is flailing and put it into maintenance mode. If this is normal for your service,
for instance if you have a master that occasionally reaps processes, you may want to specify additional
configuration options.
If you have a job that you want managed by SMF, but which is not daemonized, another duration option is
`transient`. In this mode, SMF will not watch any processes, but will expect that the main process exits cleanly.
This can be used, for instance, for a script that must be run at boot time, or for a script that you want to delegate
to particular users with Role Based Access Control. In this case, the script can be registered with SMF to run as root,
but with the start_command delegated to your user.
A third option is `wait`. This covers non-daemonized processes.
A fourth option is `child`.
### Ignore
Sometimes you have a case where your service behaves poorly. The Ruby server Unicorn, for example, has a master
process that likes to kill its children. This causes core dumps that SMF will interpret to be a failing service.
Instead you can `ignore ["core", "signal"]` and SMF will stop caring about core dumps.
### Privileges
Some system calls require privileges generally only granted to superusers or particular roles. In Solaris, an
SMF definition can also set specific privileges for contracted processes.
By default the SMF provider will grant 'basic' and 'net_privaddr' permissions, but this can be set as follows:
```ruby
smf 'elasticsearch' do
start_command 'elasticsearch'
privileges ['basic', 'proc_lock_memory']
end
```
See the (privileges man page)[https://www.illumos.org/man/5/privileges] for more information.
### Property Groups
Property Groups are where you can store extra information for SMF to use later. They should be used in the
following format:
```ruby
smf "my-service" do
start_command "do-something"
property_groups({
"config" => {
"type" => "application",
"my-property" => "property value"
}
})
end
```
`type` will default to `application`, and is used in the manifest XML to declare how the property group will be
used. For this reason, `type` can not be used as a property name (ie variable).
One way to use property groups is to pass variables on to commands, as follows:
```ruby
rails_env = node["from-chef-environment"]["rails-env"]
smf "unicorn" do
start_command "bundle exec unicorn_rails -c /home/app_user/app/current/config/%{config/rails_env} -E %{config/rails_env} -D"
start_timeout 300
restart_command ":kill -SIGUSR2"
restart_timeout 300
working_directory "/home/app_user/app/current"
property_groups({
"config" => {
"rails_env" => rails_env
}
})
end
```
This is especially handy if you have a case where your commands may come from role attributes, but can
only work if they have access to variables set in an environment or computed in a recipe.
### Stability
This is for reference more than anything, so that administrators of a service know what to expect of possible changes to
the service definition.
See: <http://www.cuddletech.com/blog/pivot/entry.php?id=182>
## Working Examples
Please see the [examples](https://github.com/livinginthepast/smf/blob/master/EXAMPLES.md) page for
example usages.
## Cookbook upgrades, possible side effects
Changes to this cookbook may change the way that its internal checksums are generated for a service.
If you `notify :restart` any service from within the `smf` block or include a `refresh_command`, please
be aware that upgrading this cookbook may trigger a refresh or a registered notification on the first
subsequent chef run.
## Contributing
* fork
* file an issue to track updates/communication
* add tests
* rebase master into your branch
* issue a pull request
Please do not increment the cookbook version in a fork. Version updates
will be done on the master branch after any pull requests are merged.
When upstream changes are added to the master branch while you are
working on a contribution, please rebase master into your branch and
force push. A pull request should be able to be merged through a
fast-forward, without a merge commit.
## Testing
```bash
bundle
vagrant plugin install vagrant-smartos-zones
bundle exec strainer test
```

View File

@@ -1,9 +0,0 @@
unless defined?(SMFManifest::Helper)
module SMFManifest
# Generic helper that other helpers can inherit from.
# Takes the current node object, as well as an optional
# resource.
class Helper < Struct.new(:node, :resource)
end
end
end

View File

@@ -1,9 +0,0 @@
if defined?(ChefSpec)
def install_smf(name)
ChefSpec::Matchers::ResourceMatcher.new(:smf, :install, name)
end
def delete_smf(name)
ChefSpec::Matchers::ResourceMatcher.new(:smf, :delete, name)
end
end

View File

@@ -1,31 +0,0 @@
module SMFManifest
# Helper methods for determining whether work needs to be done
# with respect to assigning RBAC values to a service.
class RBACHelper < SMFManifest::Helper
include Chef::Mixin::ShellOut
def authorization_set?
current_authorization == authorization
end
def value_authorization_set?
current_value_authorization == value_authorization
end
def current_authorization
shell_out("svcprop -p general/action_authorization #{resource.name}").stdout.chomp
end
def current_value_authorization
shell_out("svcprop -p general/value_authorization #{resource.name}").stdout.chomp
end
def authorization
"solaris.smf.manage.#{resource.authorization_name}"
end
def value_authorization
"solaris.smf.value.#{resource.authorization_name}"
end
end
end

View File

@@ -1,209 +0,0 @@
## This is kind of a hack, to ensure that the cookbook can be
# loaded. On first load, nokogiri may not be present. It is
# installed at load time by recipes/default.rb, so that at run
# time nokogiri will be present.
#
require 'forwardable'
# rubocop:disable Metrics/ClassLength
module SMFManifest
# XMLBuilder manages the translation of the SMF Chef resource attributes into
# XML that can be parsed by `svccfg import`.
#
# SMFManifest::XMLBuilder.new(resource, node).to_xml
#
class XMLBuilder
# allow delegation
extend Forwardable
attr_reader :resource, :node
# delegate methods to :resource
def_delegators :resource, :name, :authorization_name, :dependencies, :duration, :environment, :group, :ignore,
:include_default_dependencies, :locale, :manifest_type, :project, :property_groups,
:service_path, :stability, :working_directory
public
def initialize(smf_resource, node)
@resource = smf_resource
@node = node
end
def to_xml
@xml_output ||= xml_output
end
protected
## methods that need to be called from within the context
# of the Nokogiri builder block need to be protected, rather
# than private.
def commands
@commands ||= {
'start' => resource.start_command,
'stop' => resource.stop_command,
'restart' => resource.restart_command,
'refresh' => resource.refresh_command
}
end
def timeout
@timeouts ||= {
'start' => resource.start_timeout,
'stop' => resource.stop_timeout,
'restart' => resource.restart_timeout,
'refresh' => resource.refresh_timeout
}
end
def default_dependencies
if node.platform == 'solaris2' && node.platform_version == '5.11'
[
{ 'name' => 'milestone', 'value' => '/milestone/config' },
{ 'name' => 'fs-local', 'value' => '/system/filesystem/local' },
{ 'name' => 'name-services', 'value' => '/milestone/name-services' },
{ 'name' => 'network', 'value' => '/milestone/network' }
]
else
[
{ 'name' => 'milestone', 'value' => '/milestone/sysconfig' },
{ 'name' => 'fs-local', 'value' => '/system/filesystem/local' },
{ 'name' => 'name-services', 'value' => '/milestone/name-services' },
{ 'name' => 'network', 'value' => '/milestone/network' }
]
end
end
private
def xml_output
xml_builder = ::Builder::XmlMarkup.new(indent: 2)
xml_builder.instruct!
xml_builder.declare! :DOCTYPE, :service_bundle, :SYSTEM, '/usr/share/lib/xml/dtd/service_bundle.dtd.1'
xml_builder.service_bundle('name' => name, 'type' => 'manifest') do |xml|
xml.service('name' => service_fmri, 'type' => 'service', 'version' => '1') do |service|
service.create_default_instance('enabled' => 'false')
service.single_instance
if include_default_dependencies
default_dependencies.each do |dependency|
service.dependency('name' => dependency['name'],
'grouping' => 'require_all',
'restart_on' => 'none',
'type' => 'service') do |dep|
dep.service_fmri('value' => "svc:#{dependency['value']}")
end
end
end
dependencies.each do |dependency|
service.dependency('name' => dependency['name'],
'grouping' => dependency['grouping'],
'restart_on' => dependency['restart_on'],
'type' => dependency['type']) do |dep|
dependency['fmris'].each do |service_fmri|
dep.service_fmri('value' => service_fmri)
end
end
end
service.method_context(exec_context) do |context|
context.method_credential(credentials) if user != 'root'
if environment
context.method_environment do |env|
environment.each_pair do |var, value|
env.envvar('name' => var, 'value' => value)
end
end
end
end
commands.each_pair do |type, command|
if command
service.exec_method('type' => 'method', 'name' => type, 'exec' => command, 'timeout_seconds' => timeout[type])
end
end
service.property_group('name' => 'general', 'type' => 'framework') do |group|
group.propval('name' => 'action_authorization',
'type' => 'astring',
'value' => "solaris.smf.manage.#{authorization_name}")
group.propval('name' => 'value_authorization',
'type' => 'astring',
'value' => "solaris.smf.value.#{authorization_name}")
end
if sets_duration? || ignores_faults?
service.property_group('name' => 'startd', 'type' => 'framework') do |group|
group.propval('name' => 'duration', 'type' => 'astring', 'value' => duration) if sets_duration?
group.propval('name' => 'ignore_error', 'type' => 'astring', 'value' => ignore.join(',')) if ignores_faults?
end
end
property_groups.each_pair do |name, properties|
service.property_group('name' => name, 'type' => properties.delete('type') { |_type| 'application' }) do |group|
properties.each_pair do |key, value|
group.propval('name' => key, 'value' => value, 'type' => check_type(value))
end
end
end
service.stability('value' => stability)
service.template do |template|
template.common_name do |common_name|
common_name.loctext(name, 'xml:lang' => locale)
end
end
end
end
xml_builder.target!
end
def credentials
creds = { 'user' => user, 'privileges' => resource.privilege_list }
creds.merge!('group' => group) unless group.nil?
creds
end
def user
resource.user || resource.credentials_user || 'root'
end
def exec_context
context = {}
context['working_directory'] = working_directory unless working_directory.nil?
context['project'] = project unless project.nil?
context
end
def check_type(value)
if value == value.to_i
'integer'
else
'astring'
end
end
def ignores_faults?
!ignore.nil?
end
def sets_duration?
duration != 'contract'
end
# resource.fmri is set in the SMF :install action of the default provider.
# If there is already a service with a name that is matched by our resource.name
# then we grab the FMRI (fault management resource identifier) from the system.
# If a service is not found, we set this to our own FMRI.
def service_fmri
resource.fmri.nil? || resource.fmri.empty? ? "#{manifest_type}/management/#{name}" : resource.fmri.gsub(/^\//, '')
end
end
end
# rubocop:enable Metrics/ClassLength

File diff suppressed because one or more lines are too long

View File

@@ -1,13 +0,0 @@
name 'smf'
maintainer 'Eric Saxby'
maintainer_email 'sax@livinginthepast.org'
license 'MIT'
description 'A light weight resource provider (LWRP) for SMF (Service Management Facility)'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '2.2.8'
supports 'smartos'
depends 'rbac', '>= 1.0.1'
suggests 'resource-control' # For managing Solaris projects, when setting project on a manifest

View File

@@ -1,143 +0,0 @@
require 'chef/mixin/shell_out'
require 'fileutils'
include Chef::Mixin::ShellOut
def load_current_resource
find_fmri unless new_resource.fmri
@current_resource = Chef::Resource::Smf.new(new_resource.name)
@current_resource.fmri(new_resource.fmri)
@current_resource.load
end
action :install do
create_directories
write_manifest
create_rbac_definitions
import_manifest
deduplicate_manifest
add_rbac_permissions
new_resource.updated_by_last_action(smf_changed?)
new_resource.save_checksum if smf_changed?
end
action :add_rbac do
create_rbac_definitions
service new_resource.name
manage = execute "add SMF authorization to allow RBAC for #{new_resource.name}" do
command "svccfg -s #{new_resource.name} " \
'setprop general/action_authorization=astring:' \
"'solaris.smf.manage.#{new_resource.authorization_name}'"
not_if { SMFManifest::RBACHelper.new(node, new_resource).authorization_set? }
notifies :reload, "service[#{new_resource.name}]"
end
value = execute "add SMF value to allow RBAC for #{new_resource.name}" do
command "svccfg -s #{new_resource.name} " \
'setprop general/value_authorization=astring: ' \
'solaris.smf.value.#{new_resource.authorization_name}'
not_if { SMFManifest::RBACHelper.new(node, new_resource).value_authorization_set? }
notifies :reload, "service[#{new_resource.name}]"
end
new_resource.updated_by_last_action(manage.updated_by_last_action? || value.updated_by_last_action?)
end
action :delete do
new_resource.updated_by_last_action(false)
if @current_resource.smf_exists?
service new_resource.name do
action [:stop, :disable]
end
execute "remove service #{new_resource.name} from SMF" do
command "svccfg delete #{new_resource.name}"
end
delete_manifest
new_resource.remove_checksum
new_resource.updated_by_last_action(true)
end
end
private
def smf_changed?
@current_resource.checksum != new_resource.checksum || !@current_resource.smf_exists?
end
def find_fmri
fmri_check = shell_out(%(svcs -H -o FMRI #{new_resource.name}))
if fmri_check.exitstatus == 0
new_resource.fmri fmri_check.stdout.chomp.split(':')[1]
else
new_resource.fmri "/#{new_resource.manifest_type}/management/#{new_resource.name}"
end
end
def create_directories
Chef::Log.debug "Creating manifest directory at #{new_resource.xml_path}"
FileUtils.mkdir_p new_resource.xml_path
end
def write_manifest
return unless smf_changed?
Chef::Log.debug "Writing SMF manifest for #{new_resource.name}"
::File.open(new_resource.xml_file, 'w') do |file|
file.puts SMFManifest::XMLBuilder.new(new_resource, node).to_xml
end
end
def delete_manifest
return unless ::File.exist?(new_resource.xml_file)
Chef::Log.debug "Removing SMF manifest for #{new_resource.name}"
::File.delete(new_resource.xml_file)
end
def create_rbac_definitions
rbac new_resource.authorization_name do
action :create
end
end
def add_rbac_permissions
user = new_resource.user || new_resource.credentials_user || 'root'
rbac_auth "Add RBAC for #{new_resource.name} to #{user}" do
user user
auth new_resource.authorization_name
not_if { user == 'root' }
end
end
def import_manifest
return unless smf_changed?
Chef::Log.debug("importing SMF manifest #{new_resource.xml_file}")
shell_out!("svccfg import #{new_resource.xml_file}")
end
def deduplicate_manifest
# If we are overwriting properties from an old SMF definition (from pkgsrc, etc)
# there may be redundant XML files that we want to dereference
name = new_resource.name
duplicate_manifest = shell_out("svcprop #{name} | grep -c manifestfiles").stdout.strip.to_i > 1
return unless duplicate_manifest
Chef::Log.debug "Removing duplicate SMF manifest reference from #{name}"
shell_out! "svccfg -s #{name} delprop " \
"`svcprop #{name} | grep manifestfiles | grep -v #{new_resource.xml_file} | awk '{ print $1 }'` " \
"&& svcadm refresh #{name}"
end
def smf_defined?(fmri)
shell_out("svcs #{fmri}").exitstatus == 0
end

View File

@@ -1,25 +0,0 @@
directory '/opt/scripts' do
action :create
mode '0755'
owner 'root'
group 'root'
end
directory '/opt/local/etc/snmp/conf.d' do
action :create
mode '0755'
owner 'root'
group 'root'
end
template '/opt/scripts/SMFServicesOK.sh' do
path '/opt/scripts/SMFServicesOK.sh'
source 'SMFServicesOK.sh.erb'
mode '0755'
end
template 'SMFServicesOK.snmpd.conf' do
path '/opt/local/etc/snmp/conf.d/SMFServicesOK.snmpd.conf'
source 'SMFServicesOK.snmpd.conf.erb'
mode '0644'
end

View File

@@ -1,7 +0,0 @@
## These libraries need to be installed when the cookbook
# is loaded, otherwise they are not available when the
# cookbook runs.
chef_gem 'builder'
require 'builder'

View File

@@ -1,124 +0,0 @@
require 'chef/mixin/shell_out'
include Chef::Mixin::ShellOut
actions :install, :add_rbac, :delete
default_action :install
attribute :name, kind_of: String, name_attribute: true, required: true
attribute :user, kind_of: [String, NilClass], default: nil
attribute :group, kind_of: [String, NilClass], default: nil
attribute :project, kind_of: [String, NilClass], default: nil
attribute :authorization, kind_of: [String, NilClass], default: nil
attribute :start_command, kind_of: [String, NilClass], default: nil
attribute :start_timeout, kind_of: Integer, default: 5
attribute :stop_command, kind_of: String, default: ':kill'
attribute :stop_timeout, kind_of: Integer, default: 5
attribute :restart_command, kind_of: [String, NilClass], default: nil
attribute :restart_timeout, kind_of: Integer, default: 5
attribute :refresh_command, kind_of: [String, NilClass], default: nil
attribute :refresh_timeout, kind_of: Integer, default: 5
attribute :include_default_dependencies, kind_of: [TrueClass, FalseClass], default: true
attribute :dependencies, kind_of: [Array], default: []
attribute :privileges, kind_of: [Array], default: %w(basic net_privaddr)
attribute :working_directory, kind_of: [String, NilClass], default: nil
attribute :environment, kind_of: [Hash, NilClass], default: nil
attribute :locale, kind_of: String, default: 'C'
attribute :manifest_type, kind_of: String, default: 'application'
attribute :service_path, kind_of: String, default: '/var/svc/manifest'
attribute :duration, kind_of: String, default: 'contract', regex: '(contract|wait|transient|child)'
attribute :ignore, kind_of: [Array, NilClass], default: nil
attribute :fmri, kind_of: String, default: nil
attribute :stability, kind_of: String, equal_to: %w(Standard Stable Evolving Unstable External Obsolete),
default: 'Evolving'
attribute :property_groups, kind_of: Hash, default: {}
# Deprecated
attribute :credentials_user, kind_of: [String, NilClass], default: nil
## internal methods
def xml_path
"#{service_path}/#{manifest_type}"
end
def xml_file
"#{xml_path}/#{name}.xml"
end
require 'fileutils'
require 'digest/md5'
# Save a checksum out to a file, for future chef runs
#
def save_checksum
Chef::Log.debug("Saving checksum for SMF #{name}: #{checksum}")
::FileUtils.mkdir_p(Chef::Config.checksum_path)
f = ::File.new(checksum_file, 'w')
f.write checksum
end
def remove_checksum
return unless ::File.exist?(checksum_file)
Chef::Log.debug("Removing checksum for SMF #{name}")
::File.delete(checksum_file)
end
# Load current resource from checksum file and projects database.
# This should only ever be called on @current_resource, never on new_resource.
#
def load
@checksum ||= ::File.exist?(checksum_file) ? ::File.read(checksum_file) : ''
@smf_exists = shell_out("svcs #{fmri}").exitstatus == 0
Chef::Log.debug("Loaded checksum for SMF #{name}: #{@checksum}")
Chef::Log.debug("SMF service already exists for #{fmri}? #{@smf_exists.inspect}")
end
def authorization_name
authorization || name
end
def checksum
attributes = [
user, credentials_user, group,
project, start_command, start_timeout, stop_command,
stop_timeout, restart_command, restart_timeout,
refresh_command, refresh_timeout, working_directory,
locale, authorization, manifest_type, service_path,
duration, ignore.to_s, include_default_dependencies,
dependencies, fmri, stability, environment_as_string,
privilege_list, property_groups_as_string, '0'
]
@checksum ||= Digest::MD5.hexdigest(attributes.join(':'))
end
def checksum_file
"#{Chef::Config.checksum_path}/smf--#{name}"
end
def environment_as_string
return nil if environment.nil?
environment.inject('') { |memo, k, v| memo << [k, v].join('|') }
end
def privilege_list
privileges.join(',')
end
def property_groups_as_string
return nil if property_groups.empty?
property_groups.inject('') { |memo, k, v| memo << [k, v].join('|') }
end
def smf_exists?
!!@smf_exists
end

View File

@@ -1,13 +0,0 @@
#!/bin/bash
# if we're on SunOS 5.10+, we should check for beat services.
if [ "`uname -s`" = "SunOS" ] && [ `uname -r|cut -d. -f1` -ge 5 ] && [ `uname -r|cut -d. -f2` -ge 10 ]
then
B=`svcs -Ha |egrep -v "disabled|online|legacy_run"`
if [ "foo$B" == "foo" ]
then
echo "OK"
else
echo $B
fi
fi

View File

@@ -1 +0,0 @@
extend SMFServicesOK /opt/scripts/SMFServicesOK.sh