Giter Site home page Giter Site logo

chef-api's Introduction

ChefAPI Client

Gem Version Build status

ChefAPI is a dependency-minimal Ruby client for interacting with a Chef Server. It adopts many patterns and principles from Rails

DEPRECATED

The chef-api gem is no longer maintained. Please use the supported Chef::ServerAPI library from the Chef gem. Documentation is provided at https://docs.chef.io/server/api_chef_server/.

Quick start

Install via Rubygems:

$ gem install chef-api

or add it to your Gemfile if you are using Bundler:

gem 'chef-api', '~> 0.1'

In your library or project, you will likely want to include the ChefAPI::Resource namespace:

include ChefAPI::Resource

This will give you "Rails-like" access to the top-level Chef resources like:

Client.all
Node.all

If you choose not to include the module, you will need to specify the full module path to access resources:

ChefAPI::Resource::Client.all
ChefAPI::Resource::Node.all

Create a connection

Before you can make a request, you must give the ChefAPI your connection information and credentials.

ChefAPI.configure do |config|
  # The endpoint for the Chef Server. This can be an Open Source Chef Server,
  # Hosted Chef Server, or Enterprise Chef Server.
  config.endpoint = 'https://api.opscode.com/organizations/meats'

  # ChefAPI will try to determine if you are running on an Enterprise Chef
  # Server or Open Source Chef depending on the URL you provide for the
  # +endpoint+ attribute. However, it may be incorrect. If is seems like the
  # generated schema does not match the response from the server, it is
  # possible this value was calculated incorrectly. Thus, you should set it
  # manually. Possible values are +:enterprise+ and +:open_source+.
  config.flavor = :enterprise

  # The client and key must also be specified (unless you are running Chef Zero
  # in no-authentication mode). The +key+ attribute may be the raw private key,
  # the path to the private key on disk, or an +OpenSSLL::PKey+ object.
  config.client = 'bacon'
  config.key    = '~/.chef/bacon.pem'

  # If you are running your own Chef Server with a custom SSL certificate, you
  # will need to specify the path to a pem file with your custom certificates
  # and ChefAPI will wire everything up correctly. (NOTE: it must be a valid
  # PEM file).
  config.ssl_pem_file = '/path/to/my.pem'

  # If you would like to be vulnerable to MITM attacks, you can also turn off
  # SSL verification. Despite what Internet blog posts may suggest, you should
  # exhaust other methods before disabling SSL verification. ChefAPI will emit
  # a warning message for every request issued with SSL verification disabled.
  config.ssl_verify = false

  # If you are behind a proxy, Chef API can run requests through the proxy as
  # well. Just set the following configuration parameters as needed.
  config.proxy_username = 'user'
  config.proxy_password = 'password'
  config.proxy_address  = 'my.proxy.server' # or 10.0.0.50
  config.proxy_port     = '8080'

  # If you want to make queries that return a very large result chef, you might
  # need to adjust the timeout limits for the network request. (NOTE: time is
  # given in seconds).
  config.read_timeout = 120
end

All of these configuration options are available via the top-level ChefAPI object.

ChefAPI.endpoint = '...'

You can also configure everything via environment variables (great solution for Docker-based usage). All the environment variables are of the format CHEF_API_{key}, where key is the uppercase equivalent of the item in the configuration object.

# ChefAPI will use these values
export CHEF_API_ENDPOINT=https://api.opscode.com/organizations/meats
export CHEF_API_CLIENT=bacon
export CHEF_API_KEY=~/.chef/bacon.pem

In addition, you can configure the environment variables in a JSON-formatted config file either placed in ~/.chef-api or placed in a location configured via the environment variable CHEF_API_CONFIG. For example:

{
  "CHEF_API_ENDPOINT": "https://api.opscode.com/organizations/meats",
  "CHEF_API_CLIENT": "bacon",
  "CHEF_API_KEY": "~/.chef/bacon.pem"
}

If you prefer a more object-oriented approach (or if you want to support multiple simultaneous connections), you can create a raw ChefAPI::Connection object. All of the options that are available on the ChefAPI object are also available on a raw connection:

connection = ChefAPI::Connection.new(
  endpoint: 'https://api.opscode.com/organizations/meats',
  client:   'bacon',
  key:      '~/.chef/bacon.pem'
)

connection.clients.fetch('chef-webui')
connection.environments.delete('production')

If you do not want to manage a ChefAPI::Connection object, or if you just prefer an alternative syntax, you can use the block-form:

ChefAPI::Connection.new do |connection|
  connection.endpoint = 'https://api.opscode.com/organizations/meats'
  connection.client   = 'bacon'
  connection.key      = '~/.chef/bacon.pem'

  # The connection object is now setup, so you can use it directly:
  connection.clients.fetch('chef-webui')
  connection.environments.delete('production')
end

Making Requests

The ChefAPI gem attempts to wrap the Chef Server API in an object-oriented and Rubyesque way. All of the methods and API calls are heavily documented inline using YARD. For a full list of every possible option, please see the inline documentation.

Most resources can be listed, retrieved, created, updated, and destroyed. In programming, this is commonly referred to as "CRUD".

Create

There are multiple ways to create a new Chef resource on the remote Chef Server. You can use the native create method. It accepts a list of parameters as a hash:

Client.create(name: 'new-client') #=> #<Resource::Client name: "new-client", admin: false, ...>

Or you can create an instance of the object, setting parameters as you go.

client = Client.new
client.name = 'new-client'
client.save #=> #<Resource::Client name: "new-client", admin: false, ...>

You can also mix-and-match the hash and object initialization:

client = Client.new(name: 'new-client')
client.validator = true
client.admin = true
client.save #=> #<Resource::Client name: "new-client", admin: false, ...>

Read

Most resources have the following "read" functions:

  • .list, .all, and .each for listing Chef resources
  • .fetch for getting a single Chef resource with the given identifier
Listing

You can get a list of all the identifiers for a given type of resource using the .list method. This is especially useful when you only want to list items by their identifier, since it only issues a single API request. For example, to get the names of all of the Client resources:

Client.list #=> ["chef-webui", "validator"]

You can also get the full collection of Chef resources using the .all method:

Client.all #=> [#<Resource::Client name: "chef-webui", admin: false ...>,
                #<Resource::Client name: "validator", admin: false ...>]

However, this is incredibly inefficient. Because of the way the Chef Server serves requests, this will make N+1 queries to the Chef Server. Unless you absolutely need every resource in the collection, you are much better using the lazy enumerable:

Client.each do |client|
  puts client.name
end

Because the resources include Ruby's custom Enumerable, you can treat the top-level resources as if they were native Ruby enumerable objects. Here are just a few examples:

Client.first #=> #<Resource::Client name: "chef-webui" ...>
Client.first(3) #=> [#<Resource::Client name: "chef-webui" ...>, ...]
Client.map(&:public_key) #=> ["-----BEGIN PUBLIC KEY-----\nMIGfMA...", "-----BEGIN PUBLIC KEY-----\nMIIBI..."]
Fetching

You can also fetch a single resource from the Chef Server using the given identifier. Each Chef resource has a unique identifier; internally this is called the "primary key". For most resources, this attribute is "name". You can fetch a resource by it's primary key using the .fetch method:

Client.fetch('chef-webui') #=> #<Resource::Client name: "chef-webui" ...>

If a resource with the given identifier does not exist, it will return nil:

Client.fetch('not-a-real-client') #=> nil

Update

You can update a resource using it's unique identifier and a list of hash attributes:

Client.update('chef-webui', admin: true)

Or you can get an instance of the object and update the attributes manually:

client = Client.fetch('chef-webui')
client.admin = true
client.save

Delete

You can destroy a resource using it's unique identifier:

Client.destroy('chef-webui') #=> true

Or you can get an instance of the object and delete it manually:

client = Client.fetch('chef-webui')
client.destroy #=> true

Validations

Each resource includes its own validations. If these validations fail, they exhibit custom errors messages that are added to the resource. For example, Chef clients must have a name attribute. This is validated on the client side:

client = Client.new
client.save #=> false

Notice that the client.save call returned false? This is an indication that the resource did not commit back to the server because of a failed validation. You can get the error(s) that prevented the object from saving using the .errors method on an instance:

client.errors #=> { :name => ["must be present"] }

Just like Rails, you can also get the human-readable list of these errors by calling #full_messages on the errors hash. This is useful if you are using ChefAPI as a library and want to give developers a semantic error:

client.errors.full_messages #=> ["`name' must be present"]

You can also force ChefAPI to raise an exception if the validations fail, using the "bang" version of save - save!:

client.save! #=> InvalidResource: There were errors saving your resource: `name' must be present

Objects on Disk

ChefAPI also has the ability to read and manipulate objects on disk. This varies from resource-to-resource, but the .from_file method accepts a path to a resource on disk and loads as much information about the object on disk as it can. The attributes are then merged with the remote resource, if one exists. For example, you can read a Client resource from disk:

client = Client.from_file('~/.chef/bacon.pem') #=> #<Resource::Client name: "bacon", admin: false, public_key: nil, private_key: "..." ...>

Searching

ChefAPI employs both search and partial search functionality.

# Using regular search
results = Search.query(:node, '*:*', start: 1)
results.total #=> 5_000
results.rows.each do |result|
  puts result
end

# Using partial search
results = PartialSearch.query(:node, { data: ['fqdn'] }, start: 1)
results.total #=> 2
results.rows.each do |result|
  puts result
end

FAQ

Q: How is this different than Ridley?
A: Ridley is optimized for highly concurrent connections with support for multiple Chef Servers. ChefAPI is designed for the "average user" who does not need the advanced use cases that Ridley provides. For this reason, the ChefAPI is incredibly opinionated about the features it will include. If you need complex features, take a look at Ridley.

Development

  1. Clone the project on GitHub
  2. Create a feature branch
  3. Submit a Pull Request

Important Notes:

  • All new features must include test coverage. At a bare minimum, Unit tests are required. It is preferred if you include acceptance tests as well.
  • The tests must be be idempotent. The HTTP calls made during a test should be able to be run over and over.
  • Tests are order independent. The default RSpec configuration randomizes the test order, so this should not be a problem.

License & Authors

Copyright 2013-2014 Seth Vargo

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.

chef-api's People

Contributors

aalmenar avatar antonofthewoods avatar ares avatar bbaugher avatar btm avatar chef-ci avatar craig-day avatar igorshp avatar j-rust avatar kejadlen avatar loganhasson avatar mattray avatar nicolasleger avatar nvwls avatar olleolleolle avatar phiggins avatar punkle avatar samdunne avatar schrd avatar sethvargo avatar stevendanna avatar tas50 avatar thheinen avatar yuta1024 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

chef-api's Issues

What is the best external chef api to integrate with an external project?

In order to verify health and perform actions based on it we need a stable API for chef. In this sensu plugin we have re-written it as chef/rest was deprecated and now ridley is deprecating external support. Before switching to another set of api's I'd like to make sure that next week we are not replacing it yet again or have to considerably updates to our plugin. Any idea on how far out you are from calling it a stable 1.0?

Incompatible with chefspec

Hi -

The Chef-api .gemspec doesn't specify a version for the mime-types gem and as a result a much older version of the 'mime-types' gem gets installed.

On my project (and possibly others) this leads to a conflict when trying to use stove and chefspec in the same project.

Note: I do not observe this issue when starting a new project and listing both stove/chefspec in the Gemfile.

Failure to expand tilde to resolve home

The following error occurs when I run my script from within another tool. I'm not exactly sure how it calls the script, but it consistently fails like this:

Error: headnode: remove_chef_node.rb: return code=1. Error message=/opt/ruby/2.4.0/lib/ruby/gems/2.4.0/gems/chef-api-0.7.0/lib/chef-api/defaults.rb:27:in `expand_path': couldn't find login name -- expanding `~' (ArgumentError)
        from /opt/ruby/2.4.0/lib/ruby/gems/2.4.0/gems/chef-api-0.7.0/lib/chef-api/defaults.rb:27:in `config'
        from /opt/ruby/2.4.0/lib/ruby/gems/2.4.0/gems/chef-api-0.7.0/lib/chef-api/defaults.rb:48:in `endpoint'
        from /opt/ruby/2.4.0/lib/ruby/gems/2.4.0/gems/chef-api-0.7.0/lib/chef-api/defaults.rb:19:in `block in options'
        from /opt/ruby/2.4.0/lib/ruby/gems/2.4.0/gems/chef-api-0.7.0/lib/chef-api/defaults.rb:19:in `map'
        from /opt/ruby/2.4.0/lib/ruby/gems/2.4.0/gems/chef-api-0.7.0/lib/chef-api/defaults.rb:19:in `options'
        from /opt/ruby/2.4.0/lib/ruby/gems/2.4.0/gems/chef-api-0.7.0/lib/chef-api/configurable.rb:59:in `block in reset!'
        from /opt/ruby/2.4.0/lib/ruby/gems/2.4.0/gems/chef-api-0.7.0/lib/chef-api/configurable.rb:58:in `each'
        from /opt/ruby/2.4.0/lib/ruby/gems/2.4.0/gems/chef-api-0.7.0/lib/chef-api/configurable.rb:58:in `reset!'
        from /opt/ruby/2.4.0/lib/ruby/gems/2.4.0/gems/chef-api-0.7.0/lib/chef-api.rb:98:in `<top (required)>'
        from /opt/ruby/2.4.0/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:133:in `require'
        from /opt/ruby/2.4.0/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:133:in `rescue in require'
        from /opt/ruby/2.4.0/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:40:in `require'
        from /install/prescripts/remove_chef_node.rb:10:in `<main>'

When I run the script from the command line this error does not happen.
I'll submit a PR to fix this - we just need to replace '~/.chef-api' with "#{ENV['HOME']}/.chef-api"

User.authenticate broken

Seems that User.authenticate is not working...

irb(main):052:0> ChefAPI::Resource::User.authenticate username: 'joelmoss', password: 'something'
             ChefAPI::Connection | ===> POST /authenticate_user...
             ChefAPI::Connection |      Chef flavor: :open_source
             ChefAPI::Connection | ===> Building URI...
             ChefAPI::Connection |      Detected URI is relative
             ChefAPI::Connection |      Appending /authenticate_user to https://X.com
             ChefAPI::Connection | ===> Adding request headers...
             ChefAPI::Connection |      Accept: application/json
             ChefAPI::Connection |      Content-Type: application/json
             ChefAPI::Connection |      Connection: keep-alive
             ChefAPI::Connection |      Keep-Alive: 30
             ChefAPI::Connection |      User-Agent: ChefAPI Ruby Gem 0.5.0
             ChefAPI::Connection |      X-Chef-Version: 11.4.0
             ChefAPI::Connection | ===> Detected form data
             ChefAPI::Connection | ===> Adding signed header authentication...
         ChefAPI::Authentication | ===> Parsing private key...
         ChefAPI::Authentication |      Detected private key is the path to a file
             ChefAPI::Connection |      X-Ops-Sign: algorithm=sha1;version=1.0;
             ChefAPI::Connection |      X-Ops-Userid: chef-webui
             ChefAPI::Connection |      X-Ops-Timestamp: 2014-07-23T22:22:24Z
             ChefAPI::Connection |      X-Ops-Content-Hash: MX2/hAzVT2IPTTXtlKrGf9AzXOo=
             ChefAPI::Connection |      X-Ops-Authorization-1: x
             ChefAPI::Connection |      X-Ops-Authorization-2: x
             ChefAPI::Connection |      X-Ops-Authorization-3: x
             ChefAPI::Connection |      X-Ops-Authorization-4: x
             ChefAPI::Connection |      X-Ops-Authorization-5: x
             ChefAPI::Connection |      X-Ops-Authorization-6: x
             ChefAPI::Connection |      Raw response:
             ChefAPI::Connection |      {"error":["internal service error"]}
             ChefAPI::Connection | ===> Parsing response as error...
             ChefAPI::Connection |      Detected error response as JSON
             ChefAPI::Connection |      Parsing error response as JSON
ChefAPI::Error::HTTPServerUnavailable: The Chef Server is currently unavailable or is not currently accepting client connections. Please ensure the server is accessible via ping or telnet on your local network. If this error persists, please contact your network administrator.

    from /usr/local/opt/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/chef-api-0.5.0/lib/chef-api/connection.rb:425:in `error'
    from /usr/local/opt/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/chef-api-0.5.0/lib/chef-api/connection.rb:282:in `block in request'
    from /usr/local/opt/rbenv/versions/2.1.2/lib/ruby/2.1.0/net/http.rb:853:in `start'
    from /usr/local/opt/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/chef-api-0.5.0/lib/chef-api/connection.rb:268:in `request'
    from /usr/local/opt/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/chef-api-0.5.0/lib/chef-api/connection.rb:122:in `post'
    from /usr/local/opt/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/chef-api-0.5.0/lib/chef-api/resources/user.rb:78:in `authenticate'
    from (irb):52
    from /usr/local/opt/rbenv/versions/2.1.2/bin/irb:11:in `<main>'

Ridley's user.authenticate method works with the same server and credentials.

thx

URI exception trying to pull Cookbook.all or cookbook info

Howdy;
When I try:
irb(main):093:0> cbs = Cookbook.all
URI::InvalidURIError: bad URI(is not URI?): {"url"=>"https://chef.hostname/organizations/homeslice/cookbooks/airbrake_handler", "versions"=>[{"version"=>"1.1.1", "url"=>"https://chef.hostname/organizations/homeslice/cookbooks/airbrake_handler/1.1.1"}]}
from /usr/lib/ruby/1.9.1/uri/common.rb:176:in split' from /usr/lib/ruby/1.9.1/uri/common.rb:211:inparse'
from /usr/lib/ruby/1.9.1/uri/common.rb:747:in parse' from /var/lib/gems/1.9.1/gems/chef-api-0.5.0/lib/chef-api/connection.rb:320:inbuild_uri'
from /var/lib/gems/1.9.1/gems/chef-api-0.5.0/lib/chef-api/connection.rb:193:in request' from /var/lib/gems/1.9.1/gems/chef-api-0.5.0/lib/chef-api/connection.rb:106:inget'
from /var/lib/gems/1.9.1/gems/chef-api-0.5.0/lib/chef-api/resources/base.rb:366:in block in each' from /var/lib/gems/1.9.1/gems/chef-api-0.5.0/lib/chef-api/resources/base.rb:365:ineach'
from /var/lib/gems/1.9.1/gems/chef-api-0.5.0/lib/chef-api/resources/base.rb:365:in each' from /var/lib/gems/1.9.1/gems/chef-api-0.5.0/lib/chef-api/resources/base.rb:392:inentries'
from /var/lib/gems/1.9.1/gems/chef-api-0.5.0/lib/chef-api/resources/base.rb:392:in all' from (irb):93 from /usr/bin/irb:12:in

'

Cookbook.list works correct; .fetch pulls a Cookbook object but cb.versions.first also throws URI errors with all versions listed inside a hash table with "url", and some..recursive arrays?. It looks like the Cookbook or CookbookVersion class is passing a hash to the URI handler:

irb(main):104:0> cb.versions.first
URI::InvalidURIError: bad URI(is not URI?): {"url"=>"https://chef.server.com/organizations/homeslice/cookbooks/windows", "versions"=>[{"version"=>"1.36.1", "url"=>"https://chef.server.com/organizations/homeslice/cookbooks/windows/1.36.1"}, {"version"=>"1.34.8", "url"=>"https://chef.server.com/organizations/homeslice/cookbooks/windows/1.34.8"}, {"version"=>"1.34.6", "url"=>"https://chef.server.com/organizations/homeslice/cookbooks/windows/1.34.6"}, {"version"=>"1.34.2", "url"=>"https://chef.server.com/organizations/homeslice/cookbooks/windows/1.34.2"}, {"version"=>"1.34.0", "url"=>"https://chef.server.com/organizations/homeslice/cookbooks/windows/1.34.0"}, {"version"=>"1.33.1", "url"=>"https://chef.server.com/organizations/homeslice/cookbooks/windows/1.33.1"}, {"version"=>"1.32.0", "url"=>"https://chef.server.com/organizations/homeslice/cookbooks/windows/1.32.0"}, {"version"=>"1.31.0", "url"=>"https://chef.server.com/organizations/homeslice/cookbooks/windows/1.31.0"}, {"version"=>"1.11.0", "url"=>"https://chef.server.com/organizations/homeslice/cookbooks/windows/1.11.0"}]}

I'll try to dig in deeper on this when I get back to work, but I'm new at Ruby... we'll see. Any thoughts would be appreciated.

Get server cookbooks

Seth,
Is there a way I can pull a list of cookbooks on the server using your API? I'm sorry, I'm just not seeing how to do that. Basically I need to get a list of all of the versions of the cookbooks on the server.

Thanks!

Cheers
Jon

`update` method in Resource::Group cannot update resouces.

Description

update method in Resource::Group cannot update resouces.

ChefDK Version

I don't use chefdk when I reproduce this issue.
I use chef-api gem version 0.10.7.

Platform Version

  • macOS High Sierra(10.13.6/17G11023)
  • chef-api 0.10.7

Replication Case

This issue seems like that difference schema between GET and PUT is caused.
GET /organizations/NAME/groups/GROUP_NAME: https://docs.chef.io/api_chef_server/#get-36
PUT /organizations/NAME/groups/GROUP_NAME: https://docs.chef.io/api_chef_server/#put-9

GET endpoint returns actors, users, clients and groups on root. However PUT endpoint require actors nested users, clients and groups.

I wrote the following verification code.

require 'chef-api'

con = ChefAPI::Connection.new(
    client: 'pivotal',
    endpoint: 'https://<my_chef_server>/organizations/<my_org>',
    flavor: :enterprise,
    key: './pivotal.pem'
)

# Match schema of `GET` endpoint
p con.groups.update('admins', groups: ['test_group'])
p con.groups.fetch('admins')

# Match schema of `PUT` endpoint
p con.groups.update('admins', {actors: {groups: ['test_group']}})
p con.groups.fetch('admins')

The output of this code is following. But, test_groups does not belong to admins group after updating.

#<Resource::Group groupname: "admins", name: "admins", orgname: "<my_org>", actors: ["pivotal", "<my_account>"], users: ["pivotal", "<my_account>"], clients: [], groups: ["test_group"]>
#<Resource::Group groupname: "admins", name: "admins", orgname: "<my_org>", actors: ["pivotal", "<my_account>"], users: ["pivotal", "<my_account>"], clients: [], groups: []>
#<Resource::Group groupname: "admins", name: "admins", orgname: "<my_org>", actors: {:groups=>["test_group"]}, users: ["pivotal", "<my_account>"], clients: [], groups: []>
#<Resource::Group groupname: "admins", name: "admins", orgname: "<my_org>", actors: ["pivotal", "<my_account>"], users: ["pivotal", "<my_account>"], clients: [], groups: []>

Stacktrace

Validation is fixed as #89. So I patched that resources/base.rb#L709 replace false to raise and ran above the verification code.

con.groups.update('admins', {actors: {groups: ['test_group']}}) is correct request, but it was failed validation.

#<Resource::Group groupname: "admins", name: "admins", orgname: "<my_org>", actors: ["pivotal", "<my_account>"], users: ["pivotal", "<my_account>"], clients: [], groups: ["test_group"]>
#<Resource::Group groupname: "admins", name: "admins", orgname: "<my_org>", actors: ["pivotal", "<my_account>"], users: ["pivotal", "<my_account>"], clients: [], groups: []>
Traceback (most recent call last):
	4: from test.rb:15:in `<main>'
	3: from /Users/<my_account>/Workspace/chef-api-test/vendor/bundle/ruby/2.5.0/gems/chef-api-0.10.7/lib/chef-api/resources/base.rb:343:in `update'
	2: from /Users/<my_account>/Workspace/chef-api-test/vendor/bundle/ruby/2.5.0/gems/chef-api-0.10.7/lib/chef-api/resources/base.rb:707:in `save'
	1: from /Users/<my_account>/Workspace/chef-api-test/vendor/bundle/ruby/2.5.0/gems/chef-api-0.10.7/lib/chef-api/resources/base.rb:680:in `save!'
/Users/<my_account>/Workspace/chef-api-test/vendor/bundle/ruby/2.5.0/gems/chef-api-0.10.7/lib/chef-api/resources/base.rb:779:in `validate!': There were errors saving your resource: `actors' must be a kind of [Array] (ChefAPI::Error::InvalidResource)

Support for partial search syntax in regular search API call

Partial search functionality is being rolled into the regular search API call - just add your filter hash as a search parameter against Chef 12, now you're searching with partial.

(The Partial Search special call will disappear in Chef 13 apparently ... see #28 for more conversation on this issue)

Finishing implementing protected resources

The original idea behind protected resources was to provide a list of resources (either by name or regex), that are "protected" from modification by the client. This is useful, especially when ChefAPI is used as a library.

If an organization has a master admin or chef-webui (for example), the system will protect that resource from modification.

Cannot iterate on Cookbook

Cookbook.each produces:

URI::InvalidURIError: bad URI(is not URI?): {"url"=>"https://api.opscode.com/organizations/xxx/cookbooks/yyy", "versions"=>[{"version"=>"0.1.0", "url"=>"https://api.opscode.com/organizations/xxx/cookbooks/yyy/0.1.0"}]}
from /Users/redondos/.rbenv/versions/2.1.2/lib/ruby/2.1.0/uri/common.rb:176:in `split'

Can't expand `~` when running as service

I ran into this issue when using this gem (version 0.7.0) to deregister a node from the chef server on shutdown.

I'm manually configuring the gem (ChefAPI.configure { ... }) rather than passing in a path to the config options, so I don't have an environment variable set for CHEF_API_CONFIG, which caused it to default to trying to expand ~, which isn't defined when running as a service.

The bug happened on this line, and the full stack trace is:

/usr/local/lib/ruby/gems/2.1.0/gems/chef-api-0.7.0/lib/chef-api/defaults.rb:27:in `expand_path': couldn't find HOME environment -- expanding `~' (ArgumentError)
    from /usr/local/lib/ruby/gems/2.1.0/gems/chef-api-0.7.0/lib/chef-api/defaults.rb:27:in `config'
    from /usr/local/lib/ruby/gems/2.1.0/gems/chef-api-0.7.0/lib/chef-api/defaults.rb:48:in `endpoint'
    from /usr/local/lib/ruby/gems/2.1.0/gems/chef-api-0.7.0/lib/chef-api/defaults.rb:19:in `block in options'
    from /usr/local/lib/ruby/gems/2.1.0/gems/chef-api-0.7.0/lib/chef-api/defaults.rb:19:in `map'
    from /usr/local/lib/ruby/gems/2.1.0/gems/chef-api-0.7.0/lib/chef-api/defaults.rb:19:in `options'
    from /usr/local/lib/ruby/gems/2.1.0/gems/chef-api-0.7.0/lib/chef-api/configurable.rb:59:in `block in reset!'
    from /usr/local/lib/ruby/gems/2.1.0/gems/chef-api-0.7.0/lib/chef-api/configurable.rb:58:in `each'
    from /usr/local/lib/ruby/gems/2.1.0/gems/chef-api-0.7.0/lib/chef-api/configurable.rb:58:in `reset!'
    from /usr/local/lib/ruby/gems/2.1.0/gems/chef-api-0.7.0/lib/chef-api.rb:98:in `<top (required)>'

Happy to submit a PR to fix, but not sure what the best approach would be. For now I'm working around it by manually setting ENV['CHEF_API_CONFIG'] to a non-existent path to short-circuit the bug.

Thanks!

{"error":["Field 'policy_name' invalid"]} running @ v0.10.0 gem chef-api

Hi, @tas50 Good day!

We tried using the latest gem v0.10.0, but we're having issues into it. Below are the error encountered.

Description

 {"error":["Field 'policy_name' invalid"]}
    from /home/jenkins/.chefdk/gem/ruby/2.6.0/gems/chef-api-0.10.0/lib/chef-api/connection.rb:304:in `block in request'
    from /opt/chefdk/embedded/lib/ruby/2.6.0/net/http.rb:920:in `start'
    from /home/jenkins/.chefdk/gem/ruby/2.6.0/gems/chef-api-0.10.0/lib/chef-api/connection.rb:290:in `request'
    from /home/jenkins/.chefdk/gem/ruby/2.6.0/gems/chef-api-0.10.0/lib/chef-api/connection.rb:142:in `put'
    from /home/jenkins/.chefdk/gem/ruby/2.6.0/gems/chef-api-0.10.0/lib/chef-api/resources/base.rb:162:in `put'
    from /home/jenkins/.chefdk/gem/ruby/2.6.0/gems/chef-api-0.10.0/lib/chef-api/resources/base.rb:685:in `save!'
    from /home/jenkins/.chefdk/gem/ruby/2.6.0/gems/chef-api-0.10.0/lib/chef-api/aclable.rb:23:in `save!'
    from patch_build_core.rb:76:in `block (3 levels) in <main>'
    from patch_build_core.rb:70:in `each'
    from patch_build_core.rb:70:in `block (2 levels) in <main>'
    from patch_build_core.rb:66:in `each'
    from patch_build_core.rb:66:in `block in <main>'
    from patch_build_core.rb:61:in `each'

chef-api should not require chef

The stated goal of chef-api is to have as few dependencies as possible. There is an implicit dependency on the chef gem.

`rescue in block in deep_const_get': can't get const Chef::Environment: uninitialized constant Chef (ArgumentError)

This can be avoided by passing create_additions: false into JSON.parse.

PR forthcoming.

Role wont save to Chef Server

Even a simple call wont work.

@role = ChefAPI::Resource::Role.fetch('test_role')
@role.save!

The output is:

ChefAPI::Error::HTTPBadRequest: The Chef Server did not understand the request because it was malformed.

    {"error"=>["Must supply role data"]}

Any ideas?

Encrypted Data Bag Support

Describe the Enhancement:

Implement encoding/decoding of encrypted data bags

Describe the Need:

As a user I want to create, retrieve and update encrypted data bags.

Current Alternative

require 'chef-api'
require 'chef'

connection = ::ChefAPI::Connection.new(
      endpoint: 'https://chef-server.example.com',
     
)

raw = connection.data_bag_item.fetch('data-bag-item-name', bag: 'data-bag')
secret = ::File.read('/path/to/encrypted_data_bag_secret')
 
dbi = Chef::DataBagItem.from_hash(raw.to_hash)
data = Chef::EncryptedDataBagItem.new(dbi, secret)

or use "core" chef instead of chef-infra-api

Can We Help You Implement This?:

New release?

Hi Seth,

do you have any plans to release the changes/fixes of the recent months? Is there something we can help with?

Best regards,
Jochen

chef-api 0.9.0 on rubygems misses the templates directory

for example:

# 0.9.0 (missing)
curl https://rubygems.org/downloads/chef-api-0.9.0.gem | tar xv && tar xfvz data.tar.gz && ls -la

# 0.8.0 (with templates)
curl https://rubygems.org/downloads/chef-api-0.8.0.gem | tar xv && tar xfvz data.tar.gz && ls -la

The missing templates cause the following error in a production setup:

Errno::ENOENT: No such file or directory @ rb_sysopen - /Users/rmoriz/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/chef-api-0.9.0/templates/errors/http_forbidden_request.erb
        /Users/rmoriz/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/chef-api-0.9.0/lib/chef-api/errors.rb:26:in `read'
        /Users/rmoriz/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/chef-api-0.9.0/lib/chef-api/errors.rb:26:in `message'
        /Users/rmoriz/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/sinatra-2.0.0/lib/sinatra/base.rb:1123:in `handle_exception!'
        /Users/rmoriz/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/sinatra-2.0.0/lib/sinatra/base.rb:1097:in `block in dispatch!'
        /Users/rmoriz/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/sinatra-2.0.0/lib/sinatra/base.rb:1073:in `block in invoke'
        /Users/rmoriz/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/sinatra-2.0.0/lib/sinatra/base.rb:1073:in `catch'
        /Users/rmoriz/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/sinatra-2.0.0/lib/sinatra/base.rb:1073:in `invoke'
        /Users/rmoriz/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/sinatra-2.0.0/lib/sinatra/base.rb:1097:in `rescue in dispatch!'
        /Users/rmoriz/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/sinatra-2.0.0/lib/sinatra/base.rb:1096:in `dispatch!'
        /Users/rmoriz/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/sinatra-2.0.0/lib/sinatra/base.rb:923:in `block in call!'
        /Users/rmoriz/.asdf/installs/ruby/2.6.5/lib/ruby/gems/2.6.0/gems/sinatra-2.0.0/lib/sinatra/base.rb:1073:in `block in invoke'

Client resource creates clones

Supposing I have client on chef server (open-source server in my case)

connection.clients.update('name', :name => 'new')

It saves new client but old one remains there as well, so basically it clones the client and saves it under new name. That's probably not expected.

SSL Verify still failing with custom pem

I'm getting an error of

OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed

Even when using a custom pem. In order to create this pem, I went to the chef server, found the .key and .crt used by nginx, catted them into a newfile.pem, and copied that to where I'm using chef-api. What more is necessary to get this working without turning sslverify off?

No policy support

Currently policies are not supported. Initial (readonly?) support for nodes that have policies is provided in #56.

Frequent "Invalid signature for user or client"

I cannot reproduce it consistently, but I frequently get transient errors for the api key when connecting to the chef server. I've verified that I'm using the correct key, and there are no time sync issues between the servers.

obsolete errors with ruby 2.7.1

Description

Getting the following errors (code works fine, just annoying):

/var/task/vendor/bundle/ruby/2.7.0/gems/chef-api-0.10.5/lib/chef-api/resources/base.rb:515: warning: URI.escape is obsolete
/var/task/vendor/bundle/ruby/2.7.0/gems/chef-api-0.10.5/lib/chef-api/connection.rb:379: warning: URI.escape is obsolete

ChefDK Version

using AWS lambda ruby 2.7

Platform Version

AWS Lambda

Replication Case

require 'chef-api'
include ChefAPI::Resource

ChefAPI.configure do |config|
  config.endpoint = 'https://api.opscode.com/organizations/myorg'
  config.flavor = :enterprise
  config.key = 'KEY'
  config.client = 'name'
end

results = Search.query(:node, 'fqdn:xxx.myhost.com')

Cookbook enumerator methods 'all', 'each' fail

Iterating over all the clients works fine:

Client.each do |client|
  pp client
end

However, attempting to iterate (.all, .each) over all the cookbooks the same way fails. It seems like chef-api is trying to process the JSON response as if it is a URL.

Cookbook.each do |cookbook|
  pp cookbook
end
/opt/chefdk/embedded/bin/ruby -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) /Users/rhornsby/projects/git/cookbook_version_check/analyze.rb
             ChefAPI::Connection | ===> GET cookbooks...
             ChefAPI::Connection |      Chef flavor: :open_source
             ChefAPI::Connection | ===> Building URI...
             ChefAPI::Connection |      Detected URI is relative
             ChefAPI::Connection |      Appending cookbooks to https://chef.ourdomain.org/organizations/our_org
             ChefAPI::Connection | ===> Adding request headers...
             ...
             ChefAPI::Connection |      Raw response:
/opt/chefdk/embedded/lib/ruby/2.5.0/uri/rfc3986_parser.rb:18:in `rescue in split': bad URI(is not URI?): {"url"=>"https://chef.ourdomain.org/organizations/our_org/cookbooks/vagrant", "versions"=>[{"version"=>"0.8.0", "url"=>"https://chef.ourdomain.org/organizations/our_org/cookbooks/vagrant/0.8.0"}]} (URI::InvalidURIError)
	from /opt/chefdk/embedded/lib/ruby/2.5.0/uri/rfc3986_parser.rb:15:in `split'
	from /opt/chefdk/embedded/lib/ruby/2.5.0/uri/rfc3986_parser.rb:73:in `parse'
	from /opt/chefdk/embedded/lib/ruby/2.5.0/uri/common.rb:237:in `parse'
	from /opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/chef-api-0.8.0/lib/chef-api/connection.rb:340:in `build_uri'
	from /opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/chef-api-0.8.0/lib/chef-api/connection.rb:204:in `request'
	from /opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/chef-api-0.8.0/lib/chef-api/connection.rb:108:in `get'
	from /opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/chef-api-0.8.0/lib/chef-api/resources/base.rb:366:in `block in each'
	from /opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/chef-api-0.8.0/lib/chef-api/resources/base.rb:365:in `each'
	from /opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/chef-api-0.8.0/lib/chef-api/resources/base.rb:365:in `each'
	from /Users/rhornsby/projects/git/cookbook_version_check/analyze.rb:24:in `<top (required)>'
	from -e:1:in `load'
	from -e:1:in `<main>'
             ChefAPI::Connection |

             ### ***** JSON object containing entire(?) cookbook list **** ###

             ChefAPI::Connection | ===> Parsing response as success...
             ChefAPI::Connection |      Detected response as JSON
             ChefAPI::Connection |      Parsing response body as JSON
             ChefAPI::Connection | ===> GET {"url"=>"https://chef.ourdomain.org/organizations/our_org/cookbooks/vagrant", "versions"=>[{"version"=>"0.8.0", "url"=>"https://chef.ourdomain.org/organizations/our_org/cookbooks/vagrant/0.8.0"}]}...
             ChefAPI::Connection |      Chef flavor: :open_source
             ChefAPI::Connection | ===> Building URI...

Process finished with exit code 1

The intermediate workaround is to a two step process. Use .list, which gives back just the cookbook names, and then iterate over those names calling Cookbook.fetch. In terms of workarounds, it's not horrible.

Is this the correct way to pull from a databag.

The documentation on databags could use some more examples. I'm happy to provide them, but I have the following questions before I open a merge request.

Do you need a double fetch to get a databag item?

foo.data_bags.fetch('aDatabag').items.fetch('aDataBagID').data['aDataBagItem']

This is the only way I can get databags to work. It has the strange side effect that this one databag item establishes 4 server connections. Is there no more efficient way?

2.2.0 :114 > foo.data_bags.fetch('nd-web').items.fetch('deploy-version').data['deploy-version-ecm2']
W: Disabling SSL verification...
W: Neither ChefAPI nor the maintainers are responsible for damanges incurred as a result of disabling SSL verification. Please use this with extreme caution, or consider specifying a custom certificate using `config.ssl_pem_file'.
W: Disabling SSL verification...
W: Neither ChefAPI nor the maintainers are responsible for damanges incurred as a result of disabling SSL verification. Please use this with extreme caution, or consider specifying a custom certificate using `config.ssl_pem_file'.
W: Disabling SSL verification...
W: Neither ChefAPI nor the maintainers are responsible for damanges incurred as a result of disabling SSL verification. Please use this with extreme caution, or consider specifying a custom certificate using `config.ssl_pem_file'.
W: Disabling SSL verification...
W: Neither ChefAPI nor the maintainers are responsible for damanges incurred as a result of disabling SSL verification. Please use this with extreme caution, or consider specifying a custom certificate using `config.ssl_pem_file'.
 => "20150708.1"

Also, is the 'data_bag_item' not implemented? It doesn't appear to be something that you can call directly. (I don't know ruby well enough to understand what is going on with it)

2.2.0 :116 > foo.data_bag_item
NoMethodError: undefined method `data_bag_item' for #<ChefAPI::Connection:0x007fc670ab8bd0>
    from (irb):116
    from /Users/sowen/.rvm/rubies/ruby-2.2.0/bin/irb:11:in `<main>'
2.2.0 :117 > foo.data_bag_items
NoMethodError: undefined method `data_bag_items' for #<ChefAPI::Connection:0x007fc670ab8bd0>
    from (irb):117
    from /Users/sowen/.rvm/rubies/ruby-2.2.0/bin/irb:11:in `<main>'

Seemingly spurious SSL Key Error

When I leave SSL verification enabled, chef-api fails to connect toe the chef server with this error:

OpenSSL::PKey::RSAError: Neither PUB key nor PRIV key: nested asn1 error
from /var/lib/gems/2.0.0/gems/chef-api-0.5.0/lib/chef-api/connection.rb:250:in `initialize'

I have chef-api configured to point at the same crt file I use with knife to verify SSL connections to my chef server, so I presume it's an OK file. It is a self-signed file generated by the server if that matters. Is there some sort of conversion or something I need to do to get it to work with chef-api?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.