Skip to content
This repository has been archived by the owner on Nov 23, 2017. It is now read-only.

Commit

Permalink
[COOK-505] create a powershell cookbook
Browse files Browse the repository at this point in the history
* downloads, installs and configures PowerShell 2.0 depending on the Windows version.
* exposes a powershell resource for executing scripts using the PowerShell interpreter
  • Loading branch information
schisamo committed May 20, 2011
1 parent 8626840 commit c2a9126
Show file tree
Hide file tree
Showing 7 changed files with 421 additions and 0 deletions.
130 changes: 130 additions & 0 deletions powershell/README.md
@@ -0,0 +1,130 @@
Description
===========

Installs and configures PowerShell 2.0. Also includes a resource/provider for executing scripts using the PowerShell interpreter.

Requirements
============

Platform
--------

* Windows XP
* Windows Server 2003
* Windows Vista
* Windows 7
* Windows Server 2008 (R1, R2)

Attributes
==========

Resource/Provider
=================

`powershell`
------------
Execute a script using the powershell interpreter (much like the script resources for bash, csh, perl, python and ruby). A temporary file is created and executed like other script resources, rather than run inline. By their nature, Script resources are not idempotent, as they are completely up to the user's imagination. Use the `not_if` or `only_if` meta parameters to guard the resource for idempotence.

### Actions

- :run: run the script

### Attribute Parameters

- command: name attribute. Name of the command to execute.
- code: quoted string of code to execute.
- creates: a file this command creates - if the file exists, the command will not be run.
- cwd: current working directory to run the command from.
- flags: command line flags to pass to the interpreter when invoking.
- environment: A hash of environment variables to set before running this command.
- user: A user name or user ID that we should change to before running this command.
- group: A group name or group ID that we should change to before running this command.

### Examples

# write out to an interpolated path
powershell "write-to-interpolated-path" do
code <<-EOH
$stream = [System.IO.StreamWriter] "#{Chef::Config[:file_cache_path]}/powershell-test.txt"
$stream.WriteLine("In #{Chef::Config[:file_cache_path]}...word.")
$stream.close()
EOH
end

# use the change working directory attribute
powershell "cwd-then-write" do
cwd Chef::Config[:file_cache_path]
code <<-EOH
$stream = [System.IO.StreamWriter] "C:/powershell-test2.txt"
$pwd = pwd
$stream.WriteLine("This is the contents of: $pwd")
$dirs = dir
foreach ($dir in $dirs) {
$stream.WriteLine($dir.fullname)
}
$stream.close()
EOH
end

# cwd to a winodws env variable
powershell "cwd-to-win-env-var" do
cwd "%TEMP%"
code <<-EOH
$stream = [System.IO.StreamWriter] "./temp-write-from-chef.txt"
$stream.WriteLine("chef on windows rox yo!")
$stream.close()
EOH
end

# pass an env var to script
powershell "read-env-var" do
cwd Chef::Config[:file_cache_path]
environment ({'foo' => 'BAZ'})
code <<-EOH
$stream = [System.IO.StreamWriter] "./test-read-env-var.txt"
$stream.WriteLine("FOO is $foo")
$stream.close()
EOH
end

Usage
=====

default
-------

Include the default recipe in a run list, to ensure PowerShell 2.0 is installed.

On the following versions of Windows the PowerShell 2.0 package will be downloaded from Microsoft and installed:

* Windows XP
* Windows Server 2003
* Windows Server 2008 R1
* Windows Vista

On the following versions of Windows, PowerShell 2.0 is present and must just be enabled:

* Windows 7
* Windows Server 2008 R2
* Windows Server 2008 R2 Core

**PLEASE NOTE** - The installation may require a restart of the node being configured before PowerShell (or the powershell script resource) can be used (yeah Windows!).

License and Author
==================

Author:: Seth Chisamore (<schisamo@opscode.com>)

Copyright:: 2011, Opscode, Inc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
21 changes: 21 additions & 0 deletions powershell/attributes/default.rb
@@ -0,0 +1,21 @@
#
# Author:: Seth Chisamore (<schisamo@opscode.com>)
# Cookbook Name:: powershell
# Attribute:: default
#
# Copyright:: Copyright (c) 2011 Opscode, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

default['powershell']['version'] = 2.0
106 changes: 106 additions & 0 deletions powershell/libraries/core.rb
@@ -0,0 +1,106 @@
#
# Author:: Seth Chisamore (<schisamo@opscode.com>)
# Copyright:: Copyright (c) 2011 Opscode, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

require 'chef/resource/execute'
require 'chef/resource/script'

# PLEASE NOTE - This is not a good example of shipping a Resource/Provider
# with a cookbook. Please check the Chef Wiki for more traditional DSL driven
# LWRPs. This 'heavyweight' resource will eventually be moved into Core Chef.

class Chef
class Resource
class Powershell < Chef::Resource::Script

def initialize(name, run_context=nil)
super
@resource_name = :powershell
@provider = Chef::Provider::PowershellScript
@interpreter = "powershell.exe"
@returns = [0,42] # successful commands return exit code 42
end

end
end

class Provider
class PowershellScript < Chef::Provider::Execute

def action_run
script_file.puts(@new_resource.code)
script_file.close
set_owner_and_group

# always set the ExecutionPolicy flag
# see http://technet.microsoft.com/en-us/library/ee176961.aspx
@new_resource.flags("#{@new_resource.flags} -ExecutionPolicy RemoteSigned -Command".strip)

# cwd hax...shell_out on windows needs to support proper 'cwd'
# follow CHEF-2357 for more
cwd = @new_resource.cwd ? "cd #{@new_resource.cwd} & " : ""
@new_resource.command("#{cwd}#{@new_resource.interpreter} #{@new_resource.flags} \"#{build_powershell_scriptblock}\"")
super
ensure
unlink_script_file
end

def set_owner_and_group
# FileUtils itself implements a no-op if +user+ or +group+ are nil
# You can prove this by running FileUtils.chown(nil,nil,'/tmp/file')
# as an unprivileged user.
FileUtils.chown(@new_resource.user, @new_resource.group, script_file.path)
end

def script_file
@script_file ||= Tempfile.open(['chef-script', '.ps1'])
end

def unlink_script_file
@script_file && @script_file.close!
end

private
# take advantage of PowerShell scriptblocks
# to pass scoped environment variables to the
# command
def build_powershell_scriptblock
# environment var hax...shell_out on windows needs to support proper 'environment'
# follow CHEF-2358 for more
env_string = if @new_resource.environment
@new_resource.environment.inject("") {|a, (k,v)| a << "$#{k} = '#{v}'; "; a}
else
""
end
"& { #{env_string}#{ensure_windows_friendly_path(script_file.path)} }"
end
end
end

module Mixin
module Language
def ensure_windows_friendly_path(path)
if path
path.gsub(::File::SEPARATOR, ::File::ALT_SEPARATOR)
else
path
end
end
end
end
end
Chef::Platform.platforms[:default].merge! :powershell => Chef::Provider::PowershellScript
33 changes: 33 additions & 0 deletions powershell/libraries/helper.rb
@@ -0,0 +1,33 @@
#
# Author:: Seth Chisamore (<schisamo@opscode.com>)
# Cookbook Name:: powershell
# Library:: helper
#
# Copyright:: Copyright (c) 2011 Opscode, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

require 'chef/mixin/shell_out'

module Powershell
module Helper
include Chef::Mixin::ShellOut

def installed?
cmd = shell_out('powershell.exe -Command "& {Get-Host}"')
cmd.stderr.empty? && (cmd.stdout =~ /Version\s*:\s*2.0/i)
end

end
end
29 changes: 29 additions & 0 deletions powershell/metadata.json
@@ -0,0 +1,29 @@
{
"name": "powershell",
"description": "Installs/Configures PowerShell 2.0 on the Windows platform",
"long_description": "Description\n===========\n\nInstalls and configures PowerShell 2.0. Also include an LWRP for executing scripts using the PowerShell interpreter.\n\nRequirements\n============\n\nPlatform\n--------\n\n* Windows XP\n* Windows Server 2003\n* Windows Vista\n* Windows 7\n* Windows Server 2008 (R1, R2)\n\nAttributes\n==========\n\nResource/Provider\n=================\n\n`powershell_script`\n-------------------\n\nfoooooooooo\n\n# Actions\n\n- :run: run the script\n\n# Attribute Parameters\n\n- command: name attribute. Name of the command to execute.\n- creates: a file this command creates - if the file exists, the command will not be run.\n- code: quoted string of code to execute.\n- cwd: current working directory to run the command from.\n- environment: A hash of environment variables to set before running this command.\n- group: A group name or group ID that we should change to before running this command.\n- path: An array of paths to use when searching for the command.\n- user: A user name or user ID that we should change to before running this command.\n\nUsage\n=====\n\nLicense and Author\n==================\n\nAuthor:: Seth Chisamore (<schisamo@opscode.com>)\n\nCopyright:: 2011, Opscode, Inc\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\n",
"maintainer": "Opscode, Inc.",
"maintainer_email": "cookbooks@opscode.com",
"license": "Apache 2.0",
"platforms": {
},
"dependencies": {
},
"recommendations": {
},
"suggestions": {
},
"conflicting": {
},
"providing": {
},
"replacing": {
},
"attributes": {
},
"groupings": {
},
"recipes": {
},
"version": "1.0.0"
}
8 changes: 8 additions & 0 deletions powershell/metadata.rb
@@ -0,0 +1,8 @@
maintainer "Opscode, Inc."
maintainer_email "cookbooks@opscode.com"
license "Apache 2.0"
description "Installs/Configures PowerShell 2.0 on the Windows platform"
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version "1.0.0"

recipe "powershell::default", "Installs and configures PowerShell 2.0"

0 comments on commit c2a9126

Please sign in to comment.