Vendor the external cookbooks

Knife-Zero doesn't include Berkshelf support, so vendoring everything in
the repo is convenient again
This commit is contained in:
Greg Karékinian
2019-10-13 19:17:42 +02:00
parent f4bfe31ac1
commit a32f34b408
1245 changed files with 100630 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
# Poise-Javascript Changelog
## v1.2.0
* Updated Node.js versions. The default version is now the Boron LTS series.
* Chef 13 support.
## v1.1.0
* New version list for Node.js.
* Support new SCL structure and packages.
## v1.0.1
* Update for Chef 12.6 compatibility.
* Update version list for `nodejs` provider.
## v1.0.0
* Initial release!

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@@ -0,0 +1,332 @@
# Poise-Javascript Cookbook
[![Build Status](https://img.shields.io/travis/poise/poise-javascript.svg)](https://travis-ci.org/poise/poise-javascript)
[![Gem Version](https://img.shields.io/gem/v/poise-javascript.svg)](https://rubygems.org/gems/poise-javascript)
[![Cookbook Version](https://img.shields.io/cookbook/v/poise-javascript.svg)](https://supermarket.chef.io/cookbooks/poise-javascript)
[![Coverage](https://img.shields.io/codecov/c/github/poise/poise-javascript.svg)](https://codecov.io/github/poise/poise-javascript)
[![Gemnasium](https://img.shields.io/gemnasium/poise/poise-javascript.svg)](https://gemnasium.com/poise/poise-javascript)
[![License](https://img.shields.io/badge/license-Apache_2-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
A [Chef](https://www.chef.io/) cookbook to provide a unified interface for
installing server-side JavaScript runtimes like Node.js and io.js.
## Quick Start
To install the latest available version of Node.js 0.12:
```ruby
javascript_runtime '0.12'
```
## Supported JavaScript Runtimes
This cookbook can install Node.js and io.js on Linux and OS X.
## Requirements
Chef 12.1 or newer is required.
## Attributes
Attributes are used to configure the default recipe.
* `node['poise-javascript']['install_nodejs']` Install a Node.js runtime. *(default: true)*
* `node['poise-javascript']['install_iojs']` Install an io.js runtime. *(default: false)*
## Recipes
### `default`
The default recipe installs Node.js or io.js based on the node attributes. It is
entirely optional and can be ignored in favor of direct use of the
`javascript_runtime` resource.
## Resources
### `javascript_runtime`
The `javascript_runtime` resource installs a JavaScript interpreter.
```ruby
javascript_runtime '0.12'
```
#### Actions
* `:install` Install the JavaScript interpreter. *(default)*
* `:uninstall` Uninstall the JavaScript interpreter.
#### Properties
* `version` Version of the runtime to install. If a partial version is given,
use the latest available version matching that prefix. *(name property)*
#### Provider Options
The `poise-javascript` library offers an additional way to pass configuration
information to the final provider called "options". Options are key/value pairs
that are passed down to the `javascript_runtime` provider and can be used to control how it
installs JavaScript. These can be set in the `javascript_runtime`
resource using the `options` method, in node attributes or via the
`javascript_runtime_options` resource. The options from all sources are merged
together in to a single hash.
When setting options in the resource you can either set them for all providers:
```ruby
javascript_runtime 'myapp' do
version '0.10'
options dev_package: false
end
```
or for a single provider:
```ruby
javascript_runtime 'myapp' do
version '0.10'
options :system, dev_package: false
end
```
Setting via node attributes is generally how an end-user or application cookbook
will set options to customize installations in the library cookbooks they are using.
You can set options for all installations or for a single runtime:
```ruby
# Global, for all installations.
override['poise-javascript']['options']['version'] = '0.10'
# Single installation.
override['poise-javascript']['myapp']['version'] = 'iojs'
```
The `javascript_runtime_options` resource is also available to set node attributes
for a specific installation in a DSL-friendly way:
```ruby
javascript_runtime_options 'myapp' do
version 'iojs'
end
```
Unlike resource attributes, provider options can be different for each provider.
Not all providers support the same options so make sure to the check the
documentation for each provider to see what options the use.
### `javascript_runtime_options`
The `javascript_runtime_options` resource allows setting provider options in a
DSL-friendly way. See [the Provider Options](#provider-options) section for more
information about provider options overall.
```ruby
javascript_runtime_options 'myapp' do
version 'iojs'
end
```
#### Actions
* `:run` Apply the provider options. *(default)*
#### Properties
* `resource` Name of the `javascript_runtime` resource. *(name property)*
* `for_provider` Provider to set options for.
All other attribute keys will be used as options data.
### `javascript_execute`
The `javascript_execute` resource executes a JavaScript script using the configured runtime.
```ruby
javascript_execute 'myapp.js' do
user 'myuser'
end
```
This uses the built-in `execute` resource and supports all the same properties.
#### Actions
* `:run` Execute the script. *(default)*
#### Properties
* `command` Script and arguments to run. Must not include the `node`. *(name attribute)*
* `javascript` Name of the `javascript_runtime` resource to use. If not specified, the
most recently declared `javascript_runtime` will be used. Can also be set to the
full path to a `node` binary.
For other properties see the [Chef documentation](https://docs.chef.io/resource_execute.html#attributes).
### `node_package`
The `node_package` resource installs Node.js packages using
[NPM](https://www.npmjs.com/).
```ruby
node_package 'express' do
version '4.13.3'
end
```
This uses the built-in `package` resource and supports the same actions and
properties. Multi-package installs are supported using the standard syntax.
#### Actions
* `:install` Install the package. *(default)*
* `:upgrade` Upgrade the package.
* `:remove` Uninstall the package.
The `:purge` and `:reconfigure` actions are not supported.
#### Properties
* `group` System group to install the package.
* `package_name` Package or packages to install. *(name property)*
* `path` Path to install the package in to. If unset install using `--global`.
*(default: nil)*
* `version` Version or versions to install.
* `javascript` Name of the `javascript_runtime` resource to use. If not specified, the
most recently declared `javascript_runtime` will be used. Can also be set to the
full path to a `node` binary.
* `unsafe_perm` Enable `--unsafe-perm`. *(default: true)*
* `user` System user to install the package.
For other properties see the [Chef documentation](https://docs.chef.io/resource_package.html#attributes).
The `response_file`, `response_file_variables`, and `source` properties are not
supported.
### `npm_install`
The `npm_install` resource runs `npm install` for a package.
```ruby
npm_install '/opt/myapp'
```
The underlying `npm install` command will run on every converge, but notifications
will only be triggered if a package is actually installed.
#### Actions
* `:install` Run `npm install`. *(default)*
#### Properties
* `path` Path to the package folder containing a `package.json`. *(name attribute)*
* `group` System group to install the packages.
* `javascript` Name of the `javascript_runtime` resource to use. If not specified, the
most recently declared `javascript_runtime` will be used. Can also be set to the
full path to a `node` binary.
* `production` Enable production install mode. *(default: true)*
* `unsafe_perm` Enable `--unsafe-perm`. *(default: true)*
* `user` System user to install the packages.
## Javascript Providers
### Common Options
These provider options are supported by all providers.
* `version` Override the runtime version.
### `system`
The `system` provider installs Node.js using system packages. This is currently
only tested on platforms using `apt-get` and `yum` (Debian, Ubuntu, RHEL, CentOS
Amazon Linux, and Fedora). It may work on other platforms but is untested.
```ruby
javascript_runtime 'myapp' do
provider :system
version '0.10'
end
```
#### Options
* `dev_package` Install the package with the headers and other development
files. Can be set to a string to select the dev package specifically.
*(default: true)*
* `package_name` Override auto-detection of the package name.
* `package_upgrade` Install using action `:upgrade`. *(default: false)*
* `package_version` Override auto-detection of the package version.
### `scl`
The `scl` provider installs Node.js using the [Software Collections](https://www.softwarecollections.org/)
packages. This is only available on RHEL and CentOS. SCL offers more
recent versions of Node.js than the system packages for the most part. If an SCL
package exists for the requests version, it will be used in preference to the
`system` provider.
```ruby
javascript_runtime 'myapp' do
provider :scl
version '0.10'
end
```
### `nodejs`
The `nodejs` provider installs Node.js from the static binaries on nodejs.org.
Support is included for Linux and OS X.
```ruby
javascript_runtime 'myapp' do
provider :nodejs
version '0.12'
end
```
#### Options
* `path` Folder to install Node.js to. *(default: /opt/nodejs-<version>)*
* `static_version` Specific version number to use for computing the URL and
path. *(default: automatic from `version`)*
* `strip_components` Value to pass to tar --strip-components. *(automatic)*
* `url` URL template to download the archive from. *(default: automatic)*
### `iojs`
The `iojs` provider installs io.js from the static binaries on iojs.org.
Support is included for Linux and OS X.
```ruby
javascript_runtime 'myapp' do
provider :iojs
version '3'
end
```
#### Options
* `path` Folder to install io.js to. *(default: /opt/iojs-<version>)*
* `static_version` Specific version number to use for computing the URL and
path. *(default: automatic from `version`)*
* `strip_components` Value to pass to tar --strip-components. *(automatic)*
* `url` URL template to download the archive from. *(default: automatic)*
## Sponsors
The Poise test server infrastructure is sponsored by [Rackspace](https://rackspace.com/).
## License
Copyright 2015-2017, Noah Kantrowitz
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.

View File

@@ -0,0 +1,23 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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 inversion options.
default['poise-javascript']['provider'] = 'auto'
default['poise-javascript']['options'] = {}
# Used for the default recipe.
default['poise-javascript']['install_nodejs'] = true
default['poise-javascript']['install_iojs'] = false

View File

@@ -0,0 +1,24 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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.
#
module PoiseJavascript
autoload :Error, 'poise_javascript/error'
autoload :Resources, 'poise_javascript/resources'
autoload :JavascriptCommandMixin, 'poise_javascript/javascript_command_mixin'
autoload :JavascriptProviders, 'poise_javascript/javascript_providers'
autoload :VERSION, 'poise_javascript/version'
end

View File

@@ -0,0 +1,18 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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 'poise_javascript/resources'
require 'poise_javascript/javascript_providers'

View File

@@ -0,0 +1,23 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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 'poise_languages'
module PoiseJavascript
class Error < PoiseLanguages::Error
end
end

View File

@@ -0,0 +1,56 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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 'poise/utils'
require 'poise_languages'
module PoiseJavascript
# Mixin for resources and providers which run Javascript commands.
#
# @since 1.0.0
module JavascriptCommandMixin
include Poise::Utils::ResourceProviderMixin
# Mixin for resources which run Javascript commands.
module Resource
include PoiseLanguages::Command::Mixin::Resource(:javascript, default_binary: 'node')
# @!attribute npm_binary
# Path to the npm binary.
# @return [String]
attribute(:npm_binary, kind_of: String, default: lazy { default_npm_binary })
private
# Find the default gem binary. If there is a parent use that, otherwise
# use the same logic as {PoiseRuby::RubyProviders::Base#npm_binary}.
#
# @return [String]
def default_npm_binary
if parent_javascript
parent_javascript.npm_binary
else
::File.expand_path('../npm', javascript)
end
end
end
module Provider
include PoiseLanguages::Command::Mixin::Provider(:javascript)
end
end
end

View File

@@ -0,0 +1,40 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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/platform/provider_priority_map'
require 'poise_javascript/javascript_providers/dummy'
require 'poise_javascript/javascript_providers/iojs'
require 'poise_javascript/javascript_providers/nodejs'
require 'poise_javascript/javascript_providers/scl'
require 'poise_javascript/javascript_providers/system'
module PoiseJavascript
# Inversion providers for the javascript_runtime resource.
#
# @since 1.0.0
module JavascriptProviders
autoload :Base, 'poise_javascript/javascript_providers/base'
Chef::Platform::ProviderPriorityMap.instance.priority(:javascript_runtime, [
PoiseJavascript::JavascriptProviders::IOJS,
PoiseJavascript::JavascriptProviders::NodeJS,
PoiseJavascript::JavascriptProviders::Scl,
PoiseJavascript::JavascriptProviders::System,
])
end
end

View File

@@ -0,0 +1,97 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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/provider'
require 'poise'
module PoiseJavascript
module JavascriptProviders
class Base < Chef::Provider
include Poise(inversion: :javascript_runtime)
# Set default inversion options.
#
# @api private
def self.default_inversion_options(node, new_resource)
super.merge({
version: new_resource.version,
})
end
# The `install` action for the `javascript_runtime` resource.
#
# @return [void]
def action_install
notifying_block do
install_javascript
end
end
# The `uninstall` action for the `javascript_runtime` resource.
#
# @abstract
# @return [void]
def action_uninstall
notifying_block do
uninstall_javascript
end
end
# The path to the `javascript` binary. This is an output property.
#
# @abstract
# @return [String]
def javascript_binary
raise NotImplementedError
end
# The environment variables for this Javascript. This is an output property.
#
# @return [Hash<String, String>]
def javascript_environment
{}
end
# The path to the `npm` binary. This is an output property.
#
# @abstract
# @return [String]
def npm_binary
::File.expand_path(::File.join('..', 'npm'), javascript_binary)
end
private
# Install the Javascript runtime. Must be implemented by subclass.
#
# @abstract
# @return [void]
def install_javascript
raise NotImplementedError
end
# Uninstall the Javascript runtime. Must be implemented by subclass.
#
# @abstract
# @return [void]
def uninstall_javascript
raise NotImplementedError
end
end
end
end

View File

@@ -0,0 +1,77 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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 'poise_javascript/javascript_providers/base'
module PoiseJavascript
module JavascriptProviders
# Inversion provider for the `javascript_runtime` resource to use a fake Javascript,
# for use in unit tests.
#
# @since 1.0.0
# @provides dummy
class Dummy < Base
provides(:dummy)
def self.default_inversion_options(node, resource)
super.merge({
# Manual overrides for dummy data.
javascript_binary: ::File.join('', 'node'),
javascript_environment: nil,
npm_binary: nil,
})
end
# The `install` action for the `javascript_runtime` resource.
#
# @return [void]
def action_install
# This space left intentionally blank.
end
# The `uninstall` action for the `javascript_runtime` resource.
#
# @return [void]
def action_uninstall
# This space left intentionally blank.
end
# Path to the non-existent Javascript.
#
# @return [String]
def javascript_binary
options['javascript_binary']
end
# Environment for the non-existent Javascript.
#
# @return [String]
def javascript_environment
options['javascript_environment'] || super
end
# Path to the non-existent npm.
#
# @return [String]
def npm_binary
options['npm_binary'] || super
end
end
end
end

View File

@@ -0,0 +1,64 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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'
require 'poise_languages/static'
require 'poise_javascript/error'
require 'poise_javascript/javascript_providers/base'
module PoiseJavascript
module JavascriptProviders
class IOJS < Base
provides(:iojs)
include PoiseLanguages::Static(
versions: %w{3.3.1 3.2.0 3.1.0 3.0.0 2.5.0 2.4.0 2.3.4 2.2.1 2.1.0 2.0.2 1.8.4 1.7.1 1.6.4 1.5.1 1.4.3 1.3.0 1.2.0 1.1.0 1.0.4},
machines: %w{linux-i686 linux-x86_64 darwin-x86_64},
url: 'https://iojs.org/dist/v%{version}/iojs-v%{version}-%{kernel}-%{machine}.tar.gz',
)
def self.provides_auto?(node, resource)
# Also work if we have a version starting with 1. 2. or 3. since that has
# to be io.js and no other mechanism supports that.
super || (resource.version.to_s =~ /^[123](\.|$)/ && static_machines.include?(static_machine_label(node)))
end
MACHINE_LABELS = {'i386' => 'x86', 'i686' => 'x86', 'x86_64' => 'x64'}
def static_url_variables
machine = node['kernel']['machine']
super.merge(machine: MACHINE_LABELS[machine] || machine)
end
def javascript_binary
::File.join(static_folder, 'bin', 'iojs')
end
private
def install_javascript
install_static
end
def uninstall_javascript
uninstall_static
end
end
end
end

View File

@@ -0,0 +1,65 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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'
require 'poise_languages/static'
require 'poise_javascript/error'
require 'poise_javascript/javascript_providers/base'
module PoiseJavascript
module JavascriptProviders
class NodeJS < Base
provides(:nodejs)
include PoiseLanguages::Static(
# LTS version is first so that it is what you get for version ''.
versions: %w{8.11.1 10.0.0 9.11.1 9.10.1 9.9.0 9.8.0 9.7.1 9.6.1 9.5.0 9.4.0 9.3.0 9.2.1 9.1.0 9.0.0 8.10.0 8.9.4 8.8.1 8.7.0 8.6.0 8.5.0 8.4.0 8.3.0 8.2.1 8.1.4 8.0.0 7.10.1 7.9.0 7.8.0 7.7.4 7.6.0 7.5.0 7.4.0 7.3.0 7.2.1 7.1.0 7.0.0 6.14.2 6.13.1 6.12.3 6.11.5 6.10.3 6.9.5 6.8.1 6.7.0 6.6.0 6.5.0 6.4.0 6.3.1 6.2.2 6.1.0 6.0.0 5.12.0 5.11.1 5.10.1 5.9.1 5.8.0 5.7.1 5.6.0 5.5.0 5.4.1 5.3.0 5.2.0 5.1.1 5.0.0 4.9.1 4.8.7 4.7.3 4.6.2 4.5.0 4.4.7 4.3.2 4.2.6 4.1.2 4.0.0 0.12.18 0.11.16 0.10.48 0.9.12 0.8.28 0.7.12 0.6.21 0.5.10 0.4.12 0.3.8 0.2.6 0.1.104},
machines: %w{linux-i686 linux-x86_64 linux-armv6l linux-armv7l linux-arm64 darwin-x86_64},
url: 'https://nodejs.org/dist/v%{version}/node-v%{version}-%{kernel}-%{machine}.tar.gz',
)
def self.provides_auto?(node, resource)
# Also work if we have a blank or numeric-y version. This should make
# it the default provider on supported platforms.
super || (resource.version.to_s =~ /^(\d|$)/ && static_machines.include?(static_machine_label(node)))
end
MACHINE_LABELS = {'i386' => 'x86', 'i686' => 'x86', 'x86_64' => 'x64'}
def static_url_variables
machine = node['kernel']['machine']
super.merge(machine: MACHINE_LABELS[machine] || machine)
end
def javascript_binary
::File.join(static_folder, 'bin', 'node')
end
private
def install_javascript
install_static
end
def uninstall_javascript
uninstall_static
end
end
end
end

View File

@@ -0,0 +1,53 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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'
require 'poise_languages'
require 'poise_javascript/error'
require 'poise_javascript/javascript_providers/base'
module PoiseJavascript
module JavascriptProviders
class Scl < Base
include PoiseLanguages::Scl::Mixin
provides(:scl)
scl_package('4.4.2', 'rh-nodejs4', 'rh-nodejs4-nodejs-devel', '>= 7.0')
scl_package('0.10.35', 'nodejs010', 'nodejs010-nodejs-devel')
def javascript_binary
::File.join(scl_folder, 'root', 'usr', 'bin', 'node')
end
def javascript_environment
scl_environment
end
private
def install_javascript
install_scl_package
end
def uninstall_javascript
uninstall_scl_package
end
end
end
end

View File

@@ -0,0 +1,71 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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'
require 'poise_languages'
require 'poise_javascript/error'
require 'poise_javascript/javascript_providers/base'
module PoiseJavascript
module JavascriptProviders
class System < Base
include PoiseLanguages::System::Mixin
provides(:system)
packages('nodejs', {
debian: {default: %w{nodejs}},
ubuntu: {default: %w{nodejs}},
# Empty arrays because no package in the base OS.
redhat: {default: %w{}},
centos: {default: %w{}},
fedora: {default: %w{nodejs}},
amazon: {default: %w{}},
})
def self.provides_auto?(node, resource)
# Don't auto on platforms I know have no system package by default. Kind
# of pointless since the nodejs provider will hit on these platforms
# anyway so this shouldn't ever happen.
super && !node.platform_family?('rhel') && !node.platform?('amazon')
end
def javascript_binary
# Debian and Ubuntu after 12.04 changed the binary name ಠ_ಠ.
binary_name = node.value_for_platform(debian: {default: 'nodejs'}, ubuntu: {'12.04' => 'node', default: 'nodejs'}, default: 'node')
::File.join('', 'usr', 'bin', binary_name)
end
private
def install_javascript
install_system_packages
package %w{npm nodejs-legacy} if node.platform_family?('debian')
end
def uninstall_javascript
uninstall_system_packages
package(%w{npm nodejs-legacy}) { action :purge } if node.platform_family?('debian')
end
def system_package_candidates(version)
# Boring :-(.
%w{nodejs nodejs-legacy node}
end
end
end
end

View File

@@ -0,0 +1,29 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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 'poise_javascript/resources/javascript_execute'
require 'poise_javascript/resources/javascript_runtime'
require 'poise_javascript/resources/node_package'
require 'poise_javascript/resources/npm_install'
module PoiseJavascript
# Chef resources and providers for poise-javascript.
#
# @since 1.0.0
module Resources
end
end

View File

@@ -0,0 +1,83 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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/which'
require 'chef/provider/execute'
require 'chef/resource/execute'
require 'poise'
require 'poise_javascript/javascript_command_mixin'
module PoiseJavascript
module Resources
# (see JavascriptExecute::Resource)
# @since 1.0.0
module JavascriptExecute
# A `javascript_execute` resource to run Javascript scripts and commands.
#
# @provides javascript_execute
# @action run
# @example
# javascript_execute 'myapp.js' do
# user 'myuser'
# end
class Resource < Chef::Resource::Execute
include PoiseJavascript::JavascriptCommandMixin
provides(:javascript_execute)
actions(:run)
end
# The default provider for `javascript_execute`.
#
# @see Resource
# @provides javascript_execute
class Provider < Chef::Provider::Execute
include Chef::Mixin::Which
provides(:javascript_execute)
private
# Command to pass to shell_out.
#
# @return [String, Array<String>]
def command
if new_resource.command.is_a?(Array)
[new_resource.javascript] + new_resource.command
else
"#{new_resource.javascript} #{new_resource.command}"
end
end
# Environment variables to pass to shell_out.
#
# @return [Hash]
def environment
if new_resource.parent_javascript
environment = new_resource.parent_javascript.javascript_environment
if new_resource.environment
environment = environment.merge(new_resource.environment)
end
environment
else
new_resource.environment
end
end
end
end
end
end

View File

@@ -0,0 +1,85 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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'
require 'poise'
module PoiseJavascript
module Resources
# (see JavascriptRuntime::Resource)
# @since 1.0.0
module JavascriptRuntime
# A `javascript_runtime` resource to manage Javascript installations.
#
# @provides javascript_runtime
# @action install
# @action uninstall
# @example
# javascript_runtime '2.7'
class Resource < Chef::Resource
include Poise(inversion: true, container: true)
provides(:javascript_runtime)
actions(:install, :uninstall)
# @!attribute version
# Version of Javascript to install. This is generally a NodeJS version
# but because of io.js there are shenanigans.
# @return [String]
# @example Install any version
# javascript_runtime 'any' do
# version ''
# end
attribute(:version, kind_of: String, name_attribute: true)
# The path to the `node` binary for this Javascript installation. This is
# an output property.
#
# @return [String]
# @example
# execute "#{resources('javascript_runtime[nodejs]').javascript_binary} myapp.js"
def javascript_binary
provider_for_action(:javascript_binary).javascript_binary
end
# The environment variables for this Javascript installation. This is an
# output property.
#
# @return [Hash<String, String>]
# @example
# execute '/opt/myapp.js' do
# environment resources('javascript_runtime[nodejs]').javascript_environment
# end
def javascript_environment
provider_for_action(:javascript_environment).javascript_environment
end
# The path to the `npm` binary for this Javascript installation. This is
# an output property. Can raise an exception if NPM is not supported for
# this runtime.
#
# @return [String]
# @example
# execute "#{resources('javascript_runtime[nodejs]').npm_binary} install"
def npm_binary
provider_for_action(:npm_binary).npm_binary
end
end
# Providers can be found under lib/poise_javascript/javascript_providers/
end
end
end

View File

@@ -0,0 +1,226 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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/provider'
require 'chef/resource'
require 'poise'
module PoiseJavascript
module Resources
# (see JavascriptRuntimeTest::Resource)
# @since 1.0.0
# @api private
module JavascriptRuntimeTest
# A `javascript_runtime_test` resource for integration testing of this
# cookbook. This is an internal API and can change at any time.
#
# @provides javascript_runtime_test
# @action run
class Resource < Chef::Resource
include Poise
provides(:javascript_runtime_test)
actions(:run)
attribute(:version, kind_of: String, name_attribute: true)
attribute(:runtime_provider, kind_of: Symbol)
attribute(:path, kind_of: String, default: lazy { default_path })
attribute(:test_yo, equal_to: [true, false], default: true)
def default_path
::File.join('', 'root', "javascript_test_#{name}")
end
end
# The default provider for `javascript_runtime_test`.
#
# @see Resource
# @provides javascript_runtime_test
class Provider < Chef::Provider
include Poise
provides(:javascript_runtime_test)
# The `run` action for the `javascript_runtime_test` resource.
#
# @return [void]
def action_run
notifying_block do
# Top level directory for this test.
directory new_resource.path
# Install and log the version.
javascript_runtime new_resource.name do
provider new_resource.runtime_provider if new_resource.runtime_provider
version new_resource.version
end
test_version
# Create a package and test npm_install.
pkg_path = ::File.join(new_resource.path, 'pkg')
directory pkg_path
file ::File.join(pkg_path, 'package.json') do
content <<-EOH
{
"name": "mypkg",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \\"Error: no test specified\\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "4.13.3"
},
"devDependencies": {
"handlebars": "4.0.2"
}
}
EOH
end
npm_install pkg_path do
notifies :create, sentinel_file('npm_install_one'), :immediately
end
npm_install pkg_path+'2' do
path pkg_path
notifies :create, sentinel_file('npm_install_two'), :immediately
end
test_require('express', pkg_path)
test_require('handlebars', pkg_path)
# Test node_package.
test1_path = ::File.join(new_resource.path, 'test1')
directory test1_path
node_package 'express' do
path test1_path
notifies :create, sentinel_file('test1_express_one'), :immediately
end
node_package 'express two' do
package_name 'express'
path test1_path
notifies :create, sentinel_file('test1_express_two'), :immediately
end
node_package %w{gulp less} do
path test1_path
notifies :create, sentinel_file('test1_multi'), :immediately
end
node_package %w{express bower} do
path test1_path
notifies :create, sentinel_file('test1_multi_overlap'), :immediately
end
node_package 'bower' do
path test1_path
notifies :create, sentinel_file('test1_bower'), :immediately
end
node_package 'yo' do
path test1_path
version '1.4.5'
end if new_resource.test_yo
node_package 'forever' do
path test1_path
version '0.13.0'
end
test_require('express', test1_path, 'node_package_express')
test_require('gulp', test1_path)
test_require('less', test1_path)
test_require('bower', test1_path)
if new_resource.test_yo
test_require('yo', test1_path)
else
file ::File.join(new_resource.path, 'no_yo')
end
test_require('forever', test1_path)
# Check we don't get cross talk between paths.
test2_path = ::File.join(new_resource.path, 'test2')
directory test2_path
node_package 'express' do
path test2_path
notifies :create, sentinel_file('test2_express'), :immediately
end
# Test global installs.
node_package 'grunt-cli' do
notifies :create, sentinel_file('grunt_one'), :immediately
end
node_package 'grunt-cli two' do
package_name 'grunt-cli'
notifies :create, sentinel_file('grunt_two'), :immediately
end
test_require('grunt-cli', new_resource.path)
javascript_execute 'grunt-cli --version' do
command lazy {
# Check local/bin first and then just bin/.
grunt_path = ::File.expand_path('../../local/bin/grunt', javascript)
grunt_path = ::File.expand_path('../grunt', javascript) unless ::File.exist?(grunt_path)
"#{grunt_path} --version > #{::File.join(new_resource.path, 'grunt_version')}"
}
end
end
end
def sentinel_file(name)
file ::File.join(new_resource.path, "sentinel_#{name}") do
action :nothing
end
end
private
def test_version(javascript: new_resource.name)
# Only queue up this resource once, the ivar is just for tracking.
@javascript_version_test ||= file ::File.join(new_resource.path, 'javascript_version.js') do
user 'root'
group 'root'
mode '644'
content <<-EOH
var fs = require('fs');
fs.writeFileSync(process.argv[2], process.version);
EOH
end
javascript_execute "#{@javascript_version_test.path} #{::File.join(new_resource.path, 'version')}" do
javascript javascript if javascript
end
end
def test_require(name, cwd, path=name, javascript: new_resource.name)
javascript_require_test = file ::File.join(cwd, 'javascript_require.js') do
user 'root'
group 'root'
mode '644'
content <<-EOH
var fs = require('fs');
try {
var version = require(process.argv[2] + '/package.json').version;
fs.writeFileSync(process.argv[3], version);
} catch(e) {
}
EOH
end
javascript_execute "#{javascript_require_test.path} #{name} #{::File.join(new_resource.path, "require_#{path}")}" do
javascript javascript if javascript
cwd cwd
end
end
end
end
end
end

View File

@@ -0,0 +1,254 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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/json_compat'
require 'chef/provider/package'
require 'chef/resource/package'
require 'poise'
require 'poise_javascript/error'
require 'poise_javascript/javascript_command_mixin'
module PoiseJavascript
module Resources
# (see NodePackage::Resource)
# @since 1.0.0
module NodePackage
# A `node_package` resource to manage Node.js packages using npm.
#
# @provides node_package
# @action install
# @action upgrade
# @action uninstall
# @example
# node_package 'express' do
# javascript '0.10'
# version '1.8.3'
# end
class Resource < Chef::Resource::Package
include PoiseJavascript::JavascriptCommandMixin
provides(:node_package)
# Manually create matchers because #actions is unreliable.
%i{install upgrade remove}.each do |action|
Poise::Helpers::ChefspecMatchers.create_matcher(:node_package, action)
end
# @!attribute group
# System group to install the package.
# @return [String, Integer, nil]
attribute(:group, kind_of: [String, Integer, NilClass])
# @!attribute path
# Path to install the package in to. If unset install using --global.
# @return [String, nil, false]
attribute(:path, kind_of: [String, NilClass, FalseClass])
# @!attribute unsafe_perm
# Enable --unsafe-perm.
# @return [Boolean, nil]
attribute(:unsafe_perm, equal_to: [true, false, nil], default: true)
# @!attribute user
# System user to install the package.
# @return [String, Integer, nil]
attribute(:user, kind_of: [String, Integer, NilClass])
def initialize(*args)
super
# For older Chef.
@resource_name = :node_package
# We don't have these actions.
@allowed_actions.delete(:purge)
@allowed_actions.delete(:reconfig)
end
# Upstream attribute we don't support. Sets are an error and gets always
# return nil.
#
# @api private
# @param arg [Object] Ignored
# @return [nil]
def response_file(arg=nil)
raise NoMethodError if arg
end
# (see #response_file)
def response_file_variables(arg=nil)
raise NoMethodError if arg && arg != {}
end
end
# The default provider for the `node_package` resource.
#
# @see Resource
class Provider < Chef::Provider::Package
include PoiseJavascript::JavascriptCommandMixin
provides(:node_package)
# Load current and candidate versions for all needed packages.
#
# @api private
# @return [Chef::Resource]
def load_current_resource
@current_resource = new_resource.class.new(new_resource.name, run_context)
current_resource.package_name(new_resource.package_name)
check_package_versions(current_resource)
current_resource
end
# Populate current and candidate versions for all needed packages.
#
# @api private
# @param resource [PoiseJavascript::Resources::NodePackage::Resource]
# Resource to load for.
# @return [void]
def check_package_versions(resource)
version_data = Hash.new {|hash, key| hash[key] = {current: nil, candidate: nil} }
# Get the version for everything currently installed.
list_args = npm_version?('>= 1.4.16') ? %w{--depth 0} : []
npm_shell_out!('list', list_args).fetch('dependencies', {}).each do |pkg_name, pkg_data|
version_data[pkg_name][:current] = pkg_data['version']
end
# If any requested packages are currently installed, run npm outdated
# to look for candidate versions. Older npm doesn't support --json
# here so you get slow behavior, sorry.
requested_packages = Set.new(Array(resource.package_name))
if npm_version?('>= 1.3.16') && version_data.any? {|pkg_name, _pkg_vers| requested_packages.include?(pkg_name) }
outdated = npm_shell_out!('outdated', returns: [0, 1]) || {}
version_data.each do |pkg_name, pkg_vers|
pkg_vers[:candidate] = if outdated.include?(pkg_name)
outdated[pkg_name]['wanted']
else
# If it was already installed and not listed in outdated, it
# must have been up to date already.
pkg_vers[:current]
end
end
end
# Check for candidates for anything else we didn't get from outdated.
requested_packages.each do |pkg_name|
version_data[pkg_name][:candidate] ||= npm_shell_out!('show', [pkg_name])['version']
end
# Populate the current resource and candidate versions. Youch this is
# a gross mix of data flow.
if(resource.package_name.is_a?(Array))
@candidate_version = []
versions = []
[resource.package_name].flatten.each do |name|
ver = version_data[name.downcase]
versions << ver[:current]
@candidate_version << ver[:candidate]
end
resource.version(versions)
else
ver = version_data[resource.package_name.downcase]
resource.version(ver[:current])
@candidate_version = ver[:candidate]
end
end
# Install package(s) using npm.
#
# @param name [String, Array<String>] Name(s) of package(s).
# @param version [String, Array<String>] Version(s) of package(s).
# @return [void]
def install_package(name, version)
args = []
# Set --unsafe-perm unless the property is nil.
unless new_resource.unsafe_perm.nil?
args << '--unsafe-perm'
args << new_resource.unsafe_perm.to_s
end
# Build up the actual package install args.
if new_resource.source
args << new_resource.source
else
Array(name).zip(Array(version)) do |pkg_name, pkg_ver|
args << "#{pkg_name}@#{pkg_ver}"
end
end
npm_shell_out!('install', args, parse_json: false)
end
# Upgrade and install are the same for NPM.
alias_method :upgrade_package, :install_package
# Uninstall package(s) using npm.
#
# @param name [String, Array<String>] Name(s) of package(s).
# @param version [String, Array<String>] Version(s) of package(s).
# @return [void]
def remove_package(name, version)
npm_shell_out!('uninstall', [name].flatten, parse_json: false)
end
private
# Run an npm command.
#
# @param subcmd [String] Subcommand to run.
# @param args [Array<String>] Command arguments.
# @param parse_json [Boolean] Parse the JSON on stdout.
# @return [Hash]
def npm_shell_out!(subcmd, args=[], parse_json: true, **kwargs)
cmd = [new_resource.npm_binary, subcmd, '--json']
# If path is nil, we are in global mode.
cmd << '--global' unless new_resource.path
# Add the rest.
cmd.concat(args)
# If we are in global mode, cwd will be nil so probably just fine. Add
# the directory for the node binary to $PATH for post-install stuffs.
new_path = [::File.dirname(new_resource.javascript), ENV['PATH'].to_s].join(::File::PATH_SEPARATOR)
out = javascript_shell_out!(cmd, cwd: new_resource.path, group: new_resource.group, user: new_resource.user, environment: {'PATH' => new_path}, **kwargs)
if parse_json
# Parse the JSON.
if out.stdout.strip.empty?
{}
else
Chef::JSONCompat.parse(out.stdout)
end
else
out
end
end
# Find the version of the current npm binary.
#
# @return [Gem::Version]
def npm_version
@npm_version ||= begin
out = javascript_shell_out!([new_resource.npm_binary, 'version'])
# Older NPM doesn't support --json here we get to regex!
# The line we want looks like:
# npm: '2.12.1'
if out.stdout =~ /npm: '([^']+)'/
Gem::Version.new($1)
else
raise PoiseJavascript::Error.new("Unable to parse NPM version from #{out.stdout.inspect}")
end
end
end
# Check the NPM version against a requirement.
#
# @param req [String] Requirement string in Gem::Requirement format.
# @return [Boolean]
def npm_version?(req)
Gem::Requirement.new(req).satisfied_by?(npm_version)
end
end
end
end
end

View File

@@ -0,0 +1,98 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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/provider'
require 'chef/resource'
require 'poise'
require 'poise_javascript/javascript_command_mixin'
module PoiseJavascript
module Resources
# (see NpmInstall::Resource)
# @since 1.0.0
module NpmInstall
# A `npm_install` resource to install NPM packages based on a package.json.
#
# @provides npm_install
# @action install
# @example
# npm_install '/opt/myapp'
class Resource < Chef::Resource
include PoiseJavascript::JavascriptCommandMixin
provides(:npm_install)
actions(:install)
# @!attribute path
# Directory to run `npm install` from.
# @return [String]
attribute(:path, kind_of: String, name_attribute: true)
# @!attribute group
# System group to install the packages.
# @return [String, Integer, nil]
attribute(:group, kind_of: [String, Integer, NilClass])
# @!attribute production
# Enable production install mode.
# @return [Boolean]
attribute(:production, equal_to: [true, false], default: true)
# @!attribute timeout
# Command execution timeout.
# @return [Integer]
attribute(:timeout, kind_of: Integer, default: 900)
# @!attribute unsafe_perm
# Enable --unsafe-perm.
# @return [Boolean, nil]
attribute(:unsafe_perm, equal_to: [true, false, nil], default: true)
# @!attribute user
# System user to install the packages.
# @return [String, Integer, nil]
attribute(:user, kind_of: [String, Integer, NilClass])
end
# The default provider for `npm_install`.
#
# @see Resource
# @provides npm_install
class Provider < Chef::Provider
include Poise
include PoiseJavascript::JavascriptCommandMixin
provides(:npm_install)
# The `install` action for the `npm_install` resource.
#
# @return [void]
def action_install
cmd = [new_resource.npm_binary, 'install', '--no-audit']
cmd << '--production' if new_resource.production
# Set --unsafe-perm unless the property is nil.
unless new_resource.unsafe_perm.nil?
cmd << '--unsafe-perm'
cmd << new_resource.unsafe_perm.to_s
end
# Add the directory for the node binary to $PATH for post-install stuffs.
new_path = [::File.dirname(new_resource.javascript), ENV['PATH'].to_s].join(::File::PATH_SEPARATOR)
output = javascript_shell_out!(cmd, cwd: new_resource.path, user: new_resource.user, group: new_resource.group, environment: {'PATH' => new_path}, timeout: new_resource.timeout).stdout
unless output.strip.empty? || output.include?('up to date')
# Any output means it did something for old NPM, "up to date" for newer.
new_resource.updated_by_last_action(true)
end
end
end
end
end
end

View File

@@ -0,0 +1,20 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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.
#
module PoiseJavascript
VERSION = '1.2.1.pre'
end

View File

@@ -0,0 +1,19 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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.
#
raise 'Halite is not compatible with no_lazy_load false, please set no_lazy_load true in your Chef configuration file.' unless Chef::Config[:no_lazy_load]
$LOAD_PATH << File.expand_path('../../files/halite_gem', __FILE__)
require "poise_javascript/cheftie"

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,19 @@
#
# Copyright 2015-2017, Noah Kantrowitz
#
# 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 runtimes, last one will be the default.
javascript_runtime 'iojs' if node['poise-javascript']['install_iojs']
javascript_runtime 'nodejs' if node['poise-javascript']['install_nodejs']