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