blueboxgroup/safety_razor

View on GitHub
README.md

Summary

Maintainability
Test Coverage
# <a name="title"></a> Safety Razor - A Ruby client for the Razor API

[![Gem Version](https://badge.fury.io/rb/safety_razor.png)](http://badge.fury.io/rb/safety_razor)
[![Build Status](https://travis-ci.org/blueboxgroup/safety_razor.png?branch=master)](https://travis-ci.org/blueboxgroup/safety_razor)
[![Code Climate](https://codeclimate.com/github/blueboxgroup/safety_razor.png)](https://codeclimate.com/github/blueboxgroup/safety_razor)
[![Dependency Status](https://gemnasium.com/blueboxgroup/safety_razor.png)](https://gemnasium.com/blueboxgroup/safety_razor)

There are 2 overriding design decisions at play in this library:

1. Implement a solution using the
   [Faraday gem](https://github.com/lostisland/faraday) to support
   middleware injection such as additional authentication, retry logic, etc.
2. Provide a thin wrapper around Razor's REST API that doesn't hide data
   internals. At the time of authoring this library Razor has not yet hit a
   SemVer-stable release and could therefore change internals at any time.

## <a name="installation"></a> Installation

Add this line to your application's Gemfile:

    gem 'safety_razor'

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install safety_razor

## <a name="usage"></a> Usage

### <a name="usage-active-model"></a> Active Model

* Razor
  [active_model](https://github.com/puppetlabs/Razor/wiki/active_model)
  documentation

```ruby
require 'safety_razor'

client = SafetyRazor::Client.new(uri: 'http://10.0.10.1')

# GET /active_model/{UUID}
client.active_model.get("uuid1-xxxx")

# GET /active_model
client.active_model.all

# DELETE /active_model/{UUID}
client.active_model.destroy("uuid1-xxxx")
```

### <a name="usage-broker"></a> Broker

* Razor
  [broker](https://github.com/puppetlabs/Razor/wiki/broker)
  documentation

```ruby
require 'safety_razor'

client = SafetyRazor::Client.new(uri: 'http://10.0.10.1')

# POST /broker?json_hash=(JSON_STR)
client.broker.create({
  name: "Chefy",
  plugin: "chef",
  description: "Production Chef Server",
  req_metadata_hash: {
    chef_server_url: "https://chef.example.com",
    chef_version: "11.4.0",
    validation_key: "-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAK..."
  }
})

# GET /broker/{UUID}
client.broker.get("uuid1-xxxx")

# GET /broker
client.broker.all

# GET /broker/plugins
client.broker.plugins

# PUT /broker/{UUID}?json_hash=(JSON_STR)
client.broker.update({
  uuid: "uuid1-xxxx",
  name: "Production Chef Server"
})

# DELETE /broker/{UUID}
client.broker.destroy("uuid1-xxxx")

broker = client.broker.get("uuid1-xxxx")
client.broker.destroy(broker)
```

### <a name="usage-model"></a> Model

* Razor
  [model](https://github.com/puppetlabs/Razor/wiki/model)
  documentation

```ruby
require 'safety_razor'

client = SafetyRazor::Client.new(uri: 'http://10.0.10.1')

# POST /model?json_hash=(JSON_STR)
client.model.create({
  label: "Test Model",
  image_uuid: "OTP",
  template: "ubuntu_oneirc",
  req_metadata_hash: {
    hostname_prefix: "test",
    domainname: "testdomain.com",
    root_password: "test4321"
  }
})

# GET /model/{UUID}
client.model.get("uuid1-xxxx")

# GET /model
client.model.all

# GET /model/templates
client.model.templates

# PUT /model/{UUID}?json_hash=(JSON_STR)
client.model.update({
  uuid: "uuid1-xxxx",
  label: "New Test Model Label"
})

# DELETE /model/{UUID}
client.model.destroy("uuid1-xxxx")
```

### <a name="usage-node"></a> Node

* Razor
  [node](https://github.com/puppetlabs/Razor/wiki/node)
  documentation

```ruby
require 'safety_razor'

client = SafetyRazor::Client.new(uri: 'http://10.0.10.1')

# POST /node/register?[registration_param_list]
client.node.register({
  hw_id: "000C29291C95",
  last_state: "idle",
  attributes_hash: {
    attr1: "val1"
  }
})

# POST /node/checkin?[checkin_param_list]
client.node.checkin({
  hw_id: "000C29291C95",
  last_state: "idle"
})

# GET /node/{UUID}
client.node.get("uuid1-xxxx")

# GET /node/{UUID}?field=attributes
client.node.get_attributes("uuid1-xxxx")

# GET /node/{UUID}?field=hardware_ids
client.node.get_hardware_ids("uuid1-xxxx")

# GET /node
client.node.all
```

### <a name="usage-policy"></a> Policy

* Razor
  [policy](https://github.com/puppetlabs/Razor/wiki/policy)
  documentation

```ruby
require 'safety_razor'

client = SafetyRazor::Client.new(uri: 'http://10.0.10.1')

# POST /policy?json_hash=(JSON_STR)
client.policy.create({
  label: "Test Policy",
  model_uuid: "uuid2-yyyy",
  template: "linux_deploy",
  tags: "two_disks,memsize_1GiB,nics_2"
})

# GET /policy/{UUID}
client.policy.get("uuid1-xxxx")

# GET /policy
client.policy.all

# GET /policy/templates
client.policy.templates

# PUT /policy/{UUID}?json_hash=(JSON_STR)
client.policy.update({
  uuid: "uuid1-xxxx",
  tags: "one,two,three"
})

# DELETE /policy/{UUID}
client.policy.destroy("uuid1-xxxx")

policy = client.policy.get("uuid1-xxxx")
client.policy.destroy(policy)
```

### <a name="usage-tag"></a> Tag

* Razor
  [tag](https://github.com/puppetlabs/Razor/wiki/tag)
  documentation

```ruby
require 'safety_razor'

client = SafetyRazor::Client.new(uri: 'http://10.0.10.1')

# POST /tag?json_hash=(JSON_STR)
client.tag.create({
  name: "Test Tag",
  tag: "test_tag"
})

# GET /tag/{UUID}
client.tag.get("uuid1-xxxx")

# GET /tag
client.tag.all

# PUT /tag/{UUID}?json_hash=(JSON_STR)
client.tag.update({
  uuid: "uuid1-xxxx",
  tag: "prod_tag"
})

# DELETE /tag/{UUID}
client.tag.destroy("uuid1-xxxx")

tag = client.tag.get("uuid1-xxxx")
client.tag.destroy(tag)
```

### <a name="usage-tag-matcher"></a> Tag Matcher

* Razor
  [tag](https://github.com/puppetlabs/Razor/wiki/tag)
  documentation (contains tag matcher details)

```ruby
require 'safety_razor'

client = SafetyRazor::Client.new(uri: 'http://10.0.10.1')

# POST /tag/{T_UUID}/matcher?json_hash=(JSON_STR)
client.tag_matcher.create("uuid1-xxxx", {
  key: "mk_hw_nic_count",
  compare: "equal",
  value: "2"
})

# GET /tag/{T_UUID}/matcher/{UUID}
# get(tag_uuid, tag_matcher_uuid)
client.tag_matcher.get("uuid1-xxxx", "uuid2-yyyy")

# PUT /tag/{T_UUID}/matcher/{UUID}?json_hash=(JSON_STR)
client.tag_matcher.update("uuid1-xxxx", {
  uuid: "uuid2-yyyy",
  key: "mk_special_sauce"
})

# DELETE /tag/{T_UUID}/matcher/{UUID}
client.tag_matcher.destroy("uuid1-xxxx", "uuid2-yyyy")
```

## <a name="testing"></a> Testing

To run the unit tests and quality suite:

    ./script/bootstrap
    rake

The acceptance suite requires a Razor service, therefore this projects ships
with a Vagrant VM providing a Razor instance. To run the acceptance suite:

    ./script/bootstrap
    vagrant up
    rake acceptance
    vagrant destroy

## <a name="development"></a> Development

* Source hosted at [GitHub][repo]
* Report issues/questions/feature requests on [GitHub Issues][issues]

Pull requests are very welcome! Make sure your patches are well tested.
Ideally create a topic branch for every separate change you make. For
example:

1. Fork the repo
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Added some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request

## <a name="authors"></a> Authors

Created by [Fletcher Nichol][fnichol] (<fnichol@nichol.ca>), and maintained
by [Blue Box Group][bluebox].

## <a name="license"></a> License

MIT (see [LICENSE][license])

[bluebox]:      http://bluebox.net
[fnichol]:      https://github.com/fnichol
[license]:      https://github.com/blueboxgroup/safety_razor/blob/master/LICENSE
[repo]:         https://github.com/blueboxgroup/safety_razor
[issues]:       https://github.com/blueboxgroup/safety_razor/issues
[contributors]: https://github.com/blueboxgroup/safety_razor/contributors