chef

package module
v0.29.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 12, 2024 License: Apache-2.0 Imports: 28 Imported by: 178

README

Stories in Ready Build Status Coverage Status

Chef Server API Client Library in Golang

This is a Library that you can use to write tools to interact with the chef server.

Install

go get github.com/go-chef/chef

Test

go get -t github.com/go-chef/chef
go test -v github.com/go-chef/chef
test_chef_server: kitchen verify  # integration tests

SSL

If you run into an SSL verification problem when trying to connect to a ssl server with self signed certs set up your config object with SkipSSL: true

Usage

This example is setting up a basic client that you can use to interact with all the service endpoints (clients, nodes, cookbooks, etc. At @chefapi) More usage examples can be found in the examples directory.

package main

import (
	"fmt"
	"os"
	"github.com/go-chef/chef"
)

func main() {
	// read a client key
	key, err := os.ReadFile("key.pem")
	if err != nil {
		fmt.Println("Couldn't read key.pem:", err)
		os.Exit(1)
	}

	// build a client
	client, err := chef.NewClient(&chef.Config{
		Name: "foo",
		Key:  string(key),
		// goiardi is on port 4545 by default. chef-zero is 8889
		BaseURL: "http://localhost:4545",
	})
	if err != nil {
		fmt.Println("Issue setting up client:", err)
	}

	// List Cookbooks
	cookList, err := client.Cookbooks.List()
	if err != nil {
		fmt.Println("Issue listing cookbooks:", err)
	}

	// Print out the list
	fmt.Println(cookList)
}

Chef API Error Status

To get the error status and error message returned from calls to the Chef API Server you can use ChefError to unwind the ErrorResponse and access the original http error. These methods are available to get specific information from the the error.

  • Error() returns a formatted error message with the URL and status code.
  • StatusCode() returns the original return status code.
  • StatusMsg() returns the error message extracted from the error message body.
  • StatusText() returns the returned error message body, usually JSON.
  • StatusMethod() returns the name of the method used for the request.
  • StatusURL() returns the URL object used for the request.

CONTRIBUTING

If you feel like contributing, great! Just fork the repo, make your improvements, and submit a pull request. Tests would, of course, be appreciated. Adding tests where there are no tests currently would be even more appreciated. At least, though, try and not break anything worse than it is. Test coverage has improved, but is still an ongoing concern.

AUTHORS

Jesse Nelson @spheromak
AJ Christensen @fujin
Brad Beam @bradbeam
Kraig Amador @bigkraig
Mark Gibbons @mark

Copyright 2013-2014, Jesse Nelson

LICENSE

Like many Chef ecosystem programs, go-chef/chef is licensed under the Apache 2.0 License. See the LICENSE file for details.

Chef is copyright (c) 2008-2014 Chef, Inc. and its various contributors.

Thanks go out to the fine folks of Opscode and the Chef community for all their hard work.

Documentation

Overview

This is a Chef Infra Server API client. This Library can be used to write tools to interact with the chef server.

The testing can be run with go test, and the client can be used as per normal via:

go get github.com/go-chef/chef

Documentation can be found on GoDoc at http://godoc.org/github.com/go-chef/chef

This is an example code generating a new node on a Chef Infra Server:

		package main

		import (
			"encoding/json"
			"fmt"
			"log"
			"os"

			chef "github.com/go-chef/chef
		)

		func main() {
			// read a client key
			key, err := os.ReadFile("key.pem")
			if err != nil {
				fmt.Println("Couldn't read key.pem:", err)
				os.Exit(1)
			}

			// build a client
			client, err := chef.NewClient(&chef.Config{
				Name: "foo",
				Key:  string(key),
				// goiardi is on port 4545 by default. chef-zero is 8889
				BaseURL: "http://localhost:4545",
			})
			if err != nil {
				fmt.Println("unable to setup client:", err)
				os.Exit(1)
			}

			// create a Node object
			ranjib := chef.NewNode("ranjib")

			// create the node on the Chef Infra Server
			_, err = client.Nodes.Post(ranjib)
			if err != nil {
				log.Fatal("couldn't create node. ", err)
			}

			// list nodes
			nodeList, err := client.Nodes.List()
			if err != nil {
				log.Fatal("couldn't list nodes: ", err)
			}

			// dump the node list in Json
			jsonData, err := json.MarshalIndent(nodeList, "", "\t")
			if err != nil {
				log.Fatal("couldn't marshal nodes list: ", err)
			}
			fmt.Println(jsonData)

			// dump the ranjib node we got from server in JSON!
			serverNode, _ := client.Nodes.Get("ranjib")
			if err != nil {
				log.Fatal("couldn't get node: ", err)
			}
			jsonData, err = json.MarshalIndent(serverNode, "", "\t")
			if err != nil {
				log.Fatal("couldn't marshal node: ", err)
			}
			fmt.Println(jsonData)

			// update node
			ranjib.RunList = append(ranjib.RunList, "recipe[works]")
			jsonData, err = json.MarshalIndent(ranjib, "", "\t")
			if err != nil {
				log.Fatal("couldn't marshal node: ", err)
			}
			fmt.Println(jsonData)

			_, err = client.Nodes.Put(ranjib)
			if err != nil {
				log.Fatal("couldn't update node: ", err)
			}

			// delete node
			client.Nodes.Delete(ranjib.Name)
			if err != nil {
				fmt.Println("unable to delete node:", err)
				os.Exit(1)
      }
		}

Index

Constants

View Source
const DefaultChefVersion = "14.0.0"

DefaultChefVersion that we pretend to emulate

Variables

View Source
var (
	ErrPathNotFound   = errors.New("attribute path not found")
	ErrNoPathProvided = errors.New("no path was provided")
)

Functions

func ACLAdminAccess added in v0.28.4

func ACLAdminAccess(acl *ACL) (err error)

ACLAdminAccess Verify that pivotal is in the Users access list for each type of ACL access

func Base64BlockEncode

func Base64BlockEncode(content []byte, limit int) []string

Base64BlockEncode takes a byte slice and breaks it up into a slice of base64 encoded strings

func CheckResponse

func CheckResponse(r *http.Response) error

CheckResponse receives a pointer to a http.Response and generates an Error via unmarshalling

func GenerateDigestSignature added in v0.22.0

func GenerateDigestSignature(priv *rsa.PrivateKey, string_to_sign string) (sig []byte, err error)

GenerateDigestSignature will generate a signature of the given data protocol 1.3

func GenerateSignature

func GenerateSignature(priv *rsa.PrivateKey, data string) (enc []byte, err error)

GenerateSignature will generate a signature ( sign ) the given data

func HashStr

func HashStr(toHash string) string

HashStr returns the base64 encoded SHA1 sum of the toHash string

func HashStr256 added in v0.22.0

func HashStr256(toHash string) string

HashStr256 returns the base64 encoded SHA256 sum of the toHash string

func JSONReader

func JSONReader(v interface{}) (r io.Reader, err error)

JSONReader handles arbitrary types and synthesizes a streaming encoder for them.

func JSONSeeker added in v0.20.2

func JSONSeeker(v interface{}) (r io.ReadSeeker, err error)

JSONSeeker handles arbitrary types and synthesizes a streaming encoder for them.

func PrivateKeyFromString

func PrivateKeyFromString(key []byte) (*rsa.PrivateKey, error)

PrivateKeyFromString parses an private key from a string

func StringParserForMeta added in v0.25.0

func StringParserForMeta(s []string) string

Types

type ACL

type ACL map[string]ACLitems

ACL represents the native Go version of the deserialized ACL type The key string will be one of:

create, delete, grant, read, update

indicating the type of access granted to an accessor in the ACLitems lists

func NewACL

func NewACL(acltype string, actors ACLitem, groups ACLitem, users ACLitem, clients ACLitem) *ACL

type ACLService

type ACLService struct {
	// contains filtered or unexported fields
}

func (*ACLService) Get

func (a *ACLService) Get(subkind string, name string) (acl ACL, err error)

Get gets an ACL from the Chef server.

Warning: This API is not included in the Chef documentation and thus probably not officially supported. Package documentation is based on the `knife` source code and packet capture. It could be wrong or change in future Chef server updates.

Subkind can be one of: clients, containers, cookbook_artifacts, cookbooks, data, environments, groups, nodes, roles, policies, policy_groups.

* map[create:{Groups:[admins clients users] Actors:[] Users:[pivotal] Clients:[]}

delete:{Groups:[admins users] Actors:[] Users:[pivotal] Clients:[]}
grant:{Groups:[admins] Actors:[] Users:[pivotal] Clients:[]}
read:{Groups:[admins clients users] Actors:[] Users:[pivotal] Clients:[]}
update:{Groups:[admins users] Actors:[] Users:[pivotal] Clients:[]}]

* Returns the ACL for multiple perms (create, read, update, delete, grant). Older versions of the Chef server only include ACLs for "groups" and "actors." If you're using a more recent version then the contents of "actors" is split up in "users" and "clients."

func (*ACLService) Put

func (a *ACLService) Put(subkind, name string, perm string, item *ACL) (err error)

Put updates an ACL on the Chef server.

Warning: This API is not included in the Chef documentation and thus probably not officially supported. Package documentation is based on the `knife` source code and packet capture. It could be wrong or change in future Chef server updates.

To change an ACL you have to fetch it from the Chef server first, as it expects the PUT request to contain the same elements as the GET response. While the GET response returns ACLs for all perms, you have to update each one separately.

On newer versions of the Chef server you may need to replace "actors" with an empty list. Looks like the actors list is only included for backwards compatibility but can't be in the PUT request.

type ACLitem

type ACLitem []string

ACLitem A list of a specific type of accessor. In ACLitems the group ACLitem consists of a list of groups.

type ACLitems

type ACLitems struct {
	Actors  ACLitem `json:"actors"`
	Clients ACLitem `json:"clients"`
	Groups  ACLitem `json:"groups"`
	Users   ACLitem `json:"users"`
}

ACLitems

Newer versions of the Chef server split Actors into Users and Clients.

func NewACLItems added in v0.28.4

func NewACLItems(actors ACLitem, groups ACLitem, users ACLitem, clients ACLitem) *ACLitems

type AccessKey added in v0.14.0

type AccessKey struct {
	Name           string `json:"name,omitempty"`
	PublicKey      string `json:"public_key,omitempty"`
	ExpirationDate string `json:"expiration_date,omitempty"`
}

type AddNow added in v0.7.1

type AddNow struct {
	Username string `json:"username"`
}

AddNow represents the body of the request to add a user to an organization POST /organization/NAME/users

type ApiClient

type ApiClient struct {
	Name       string `json:"name"`
	ClientName string `json:"clientname"`
	OrgName    string `json:"orgname"` // returned after get, not returned after update
	Validator  bool   `json:"validator"`
	JsonClass  string `json:"json_class"`
	ChefType   string `json:"chef_type"`
}

ApiClient represents the native Go version of the deserialized Client type

type ApiClientCreateResult

type ApiClientCreateResult struct {
	Uri     string  `json:"uri,omitempty"`
	ChefKey ChefKey `json:"chef_key,omitempty"`
}

ApiNewClientResult

type ApiClientListResult

type ApiClientListResult map[string]string

ApiClientListResult is map of the client names to client Uri

func (ApiClientListResult) String

func (c ApiClientListResult) String() (out string)

String makes ApiClientListResult implement the string result

type ApiClientService

type ApiClientService struct {
	// contains filtered or unexported fields
}

func (*ApiClientService) AddKey added in v0.14.0

func (e *ApiClientService) AddKey(name string, keyadd AccessKey) (key KeyItem, err error)

AddKey add a key for a client on the Chef server. /clients/USERNAME/keys POST 201 - created 401 - not authenticated 403 - not authorizated 404 - client doesn't exist 409 - new name is already in use

Chef API docs: https://docs.chef.io/api_chef_server.html#clients-name

func (*ApiClientService) Create

func (e *ApiClientService) Create(client ApiNewClient) (data *ApiClientCreateResult, err error)

Create makes a Client on the chef server

Chef API docs: https://docs.chef.io/api_chef_server.html#clients

func (*ApiClientService) Delete

func (e *ApiClientService) Delete(name string) (err error)

Delete removes a client on the Chef server

Chef API docs: https://docs.chef.io/api_chef_server.html#clients-name

func (*ApiClientService) DeleteKey added in v0.14.0

func (e *ApiClientService) DeleteKey(name string, keyname string) (key AccessKey, err error)

DeleteKey delete a key for a client. /clients/USERNAME/keys/KEYNAME DELETE 200 - successful 401 - not authenticated 403 - not authorizated 404 - client doesn't exist

Chef API docs: https://docs.chef.io/api_chef_server/#clientskeys

func (*ApiClientService) Get

func (e *ApiClientService) Get(name string) (client ApiClient, err error)

Get gets a client from the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#clients-name

func (*ApiClientService) GetKey

func (e *ApiClientService) GetKey(name string, keyname string) (key AccessKey, err error)

GetKey gets a client key from the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#clients-client-keys-key

func (*ApiClientService) List

func (e *ApiClientService) List() (data ApiClientListResult, err error)

List lists the clients in the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server/#get-11

func (*ApiClientService) ListKeys

func (e *ApiClientService) ListKeys(name string) (data []KeyItem, err error)

ListKeys lists the keys associated with a client on the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#clients-client-keys

func (*ApiClientService) Update added in v0.14.0

func (e *ApiClientService) Update(name string, client ApiNewClient) (data *ApiClient, err error)

Put updates a client on the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#clients-name

func (*ApiClientService) UpdateKey added in v0.14.0

func (e *ApiClientService) UpdateKey(name string, keyname string, keyupd AccessKey) (key AccessKey, err error)

UpdateKey updates a key for a client. /clients/USERNAME/keys/KEYNAME PUT 200 - successful 401 - not authenticated 403 - not authorizated 404 - client doesn't exist

Chef API docs: https://docs.chef.io/api_chef_server/#clientskeys

type ApiNewClient

type ApiNewClient struct {
	Name       string `json:"name,omitempty"` // name or clientname must be specified to create a client
	ClientName string `json:"clientname,omitempty"`
	Validator  bool   `json:"validator,omitempty"`
	Admin      bool   `json:"admin,omitempty"`      // not supported and ignored as of 12.1.0
	CreateKey  bool   `json:"create_key,omitempty"` // not supported for update requests
}

ApiNewClient structure to request a new client

type Association added in v0.7.1

type Association struct {
	Uri              string `json:"uri"` // the last part of the uri is the invitation id
	OrganizationUser struct {
		UserName string `json:"username,omitempty"`
	} `json:"organization_user"`
	Organization struct {
		Name string `json:"name,omitempty"`
	} `json:"organization"`
	User struct {
		Email     string `json:"email,omitempty"`
		FirstName string `json:"first_name,omitempty"`
	} `json:"user"`
}

Association represents the response from creating an invitation to join an organization POST /organization/NAME/association_requests

type AssociationService added in v0.7.1

type AssociationService struct {
	// contains filtered or unexported fields
}

func (*AssociationService) AcceptInvite added in v0.7.1

func (e *AssociationService) AcceptInvite(id string) (data string, err error)

AcceptInvite Accepts an invitation TODO: Gets a 405, code is in knife is it part of erchef?

func (*AssociationService) Add added in v0.7.1

func (e *AssociationService) Add(addme AddNow) (err error)

Add a user immediately

func (*AssociationService) Delete added in v0.7.1

func (e *AssociationService) Delete(name string) (data OrgUser, err error)

Delete removes a user from an organization

func (*AssociationService) DeleteInvite added in v0.7.1

func (e *AssociationService) DeleteInvite(id string) (rescind RescindInvite, err error)

DeleteInvite removes a pending invitation to an organization

func (*AssociationService) Get added in v0.7.1

func (e *AssociationService) Get(name string) (data OrgUser, err error)

Get the details of a user in an organization

func (*AssociationService) Invite added in v0.7.1

func (e *AssociationService) Invite(invite Request) (data Association, err error)

Invite creates an invitation for a user to join an organization on the chef server

func (*AssociationService) InviteId added in v0.7.1

func (e *AssociationService) InviteId(user string) (id string, err error)

InviteID Finds an invitation id for a user

func (*AssociationService) List added in v0.7.1

func (e *AssociationService) List() (data []OrgUserListEntry, err error)

List gets a list of the users in an organization

func (*AssociationService) ListInvites added in v0.7.1

func (e *AssociationService) ListInvites() (invitelist []Invite, err error)

ListInvites gets a list of the pending invitations for an organization.

type AuthConfig

type AuthConfig struct {
	PrivateKey            *rsa.PrivateKey
	ClientName            string
	AuthenticationVersion AuthVersion
	ServerVersion         string
}

AuthConfig representing a client and a private key used for encryption

This is embedded in the Client type

func (AuthConfig) SignRequest

func (ac AuthConfig) SignRequest(request *http.Request) error

SignRequest modifies headers of an http.Request

func (AuthConfig) SignatureContent added in v0.22.0

func (ac AuthConfig) SignatureContent(vals map[string]string) (content string)

type AuthVersion added in v0.29.0

type AuthVersion = string

AuthVersion of server authentication

const (
	AuthVersion10 AuthVersion = "1.0"
	AuthVersion13 AuthVersion = "1.3"
)

type Authenticate added in v0.7.1

type Authenticate struct {
	UserName string `json:"username"`
	Password string `json:"password"`
}

Authenticate represents the body of the /authenticate_user request

type AuthenticateUserService added in v0.7.1

type AuthenticateUserService struct {
	// contains filtered or unexported fields
}

func (*AuthenticateUserService) Authenticate added in v0.7.1

func (e *AuthenticateUserService) Authenticate(authenticate_request Authenticate) (err error)

Authenticate performs an authentication attempt.

https://docs.chef.io/api_chef_server.html#authenticate-user

type Body

type Body struct {
	io.Reader
}

Body wraps io.Reader and adds methods for calculating hashes and detecting content

func (*Body) Buffer

func (body *Body) Buffer() *bytes.Buffer

Buffer creates a byte.Buffer copy from a io.Reader resets read on reader to 0,0

func (*Body) ContentType

func (body *Body) ContentType() string

ContentType returns the content-type string of Body as detected by http.DetectContentType()

func (*Body) Hash

func (body *Body) Hash() (h string)

Hash calculates the body content hash

func (*Body) Hash256 added in v0.22.0

func (body *Body) Hash256() (h string)

Hash256 calculates the body content hash

type CBA added in v0.17.1

type CBA struct {
	Url         string       `json:"url,omitempty"`
	CBAVersions []CBAVersion `json:"versions,omitempty"`
}

type CBADetail added in v0.17.1

type CBADetail struct {
	Version     string         `json:"version"`
	Name        string         `json:"name"`
	Identifier  string         `json:"identifier"`
	RootFiles   []CookbookItem `json:"root_files,omitempty"`
	Providers   []CookbookItem `json:"providers,omitempty"`
	Resources   []CookbookItem `json:"resources,omitempty"`
	Libraries   []CookbookItem `json:"libraries,omitempty"`
	Attributes  []CookbookItem `json:"attributes,omitempty"`
	Recipes     []CookbookItem `json:"recipes,omitempty"`
	Definitions []CookbookItem `json:"definitions,omitempty"`
	Files       []CookbookItem `json:"files,omitempty"`
	Templates   []CookbookItem `json:"templates,omitempty"`
	Frozen      bool           `json:"frozen?,omitempty"`
	ChefType    string         `json:"chef_type,omitempty"`
	Metadata    CBAMeta        `json:"metadata,omitempty"`
}

CBADetail represents the detail for a specific cookbook_artifact

type CBAGetResponse added in v0.17.1

type CBAGetResponse map[string]CBA

CBAGetResponse is returned from the chef-server for Get Requests to /cookbook_artifacts

type CBAMeta added in v0.17.1

type CBAMeta struct {
	Name            string                 `json:"name,omitempty"`
	Version         string                 `json:"version,omitempty"`
	Description     string                 `json:"description,omitempty"`
	LongDescription string                 `json:"long_description,omitempty"`
	Maintainer      string                 `json:"maintainer,omitempty"`
	MaintainerEmail string                 `json:"maintainer_email,omitempty"`
	License         string                 `json:"license,omitempty"`
	Platforms       map[string]string      `json:"platforms,omitempty"`
	Depends         map[string]string      `json:"dependencies,omitempty"`
	Reccomends      map[string]string      `json:"recommendations,omitempty"`
	Suggests        map[string]string      `json:"suggestions,omitempty"`
	Conflicts       map[string]string      `json:"conflicting,omitempty"`
	Provides        map[string]string      `json:"providing,omitempty"`
	Replaces        map[string]string      `json:"replacing,omitempty"`
	Attributes      map[string]interface{} `json:"attributes,omitempty"`
	Groupings       map[string]interface{} `json:"groupings,omitempty"`
	Recipes         map[string]string      `json:"recipes,omitempty"`
	SourceURL       string                 `json:"source_url,omitempty"`
	IssuesURL       string                 `json:"issues_url,omitempty"`
	Privacy         bool                   `json:"privacy,omitempty"`
	ChefVersions    [][]string             `json:"chef_versions,omitempty"`
	OhaiVersions    []string               `json:"ohai_versions,omitempty"`
	Gems            [][]string             `json:"gems,omitempty"`
}

CBAMeta represents the cookbook_artifacts metadata information

type CBAService added in v0.17.1

type CBAService struct {
	// contains filtered or unexported fields
}

CBAService is the service for interacting with chef server cookbook_artifacts endpoint

func (*CBAService) DownloadTo added in v0.23.0

func (c *CBAService) DownloadTo(name, id, localDir string) error

DownloadTo downloads a cookbook artifact to the specified local directory on disk

func (*CBAService) Get added in v0.17.1

func (c *CBAService) Get(name string) (data CBAGetResponse, err error)

Get returns details for a specific cookbook artifact

GET /cookbook_artifacts/name

func (*CBAService) GetVersion added in v0.17.1

func (c *CBAService) GetVersion(name, id string) (data CBADetail, err error)

GetVersion fetches a specific version of a cookbook_artifact from the server api

GET /cookbook_artifacts/foo/1ef062de1bc4cb14e4a78fb739e104eb9508473e

func (*CBAService) List added in v0.17.1

func (c *CBAService) List() (data CBAGetResponse, err error)

List lists the Cookbook_Artifacts in the Chef server.

GET /cookbook_artifacts

type CBAVersion added in v0.17.1

type CBAVersion struct {
	Url        string `json:"url,omitempty"`
	Identifier string `json:"identifier,omitempty"`
}

type ChefKey added in v0.11.0

type ChefKey struct {
	Name           string `json:"name"`
	PublicKey      string `json:"public_key"`
	ExpirationDate string `json:"expiration_date"`
	Uri            string `json:"uri,omitempty"`
	PrivateKey     string `json:"private_key"`
}

type Client

type Client struct {
	Auth    *AuthConfig
	BaseURL *url.URL

	IsWebuiKey bool

	ACLs              *ACLService
	Associations      *AssociationService
	AuthenticateUser  *AuthenticateUserService
	Clients           *ApiClientService
	Containers        *ContainerService
	CookbookArtifacts *CBAService
	Cookbooks         *CookbookService
	DataBags          *DataBagService
	Environments      *EnvironmentService
	Groups            *GroupService
	License           *LicenseService
	Nodes             *NodeService
	Organizations     *OrganizationService
	Policies          *PolicyService
	PolicyGroups      *PolicyGroupService
	Principals        *PrincipalService
	RequiredRecipe    *RequiredRecipeService
	Roles             *RoleService
	Sandboxes         *SandboxService
	Search            *SearchService
	Stats             *StatsService
	Status            *StatusService
	Universe          *UniverseService
	UpdatedSince      *UpdatedSinceService
	Users             *UserService
	// contains filtered or unexported fields
}

Client is vessel for public methods used against the chef-server

func NewClient

func NewClient(cfg *Config) (*Client, error)

NewClient is the client generator used to instantiate a client for talking to a chef-server It is a simple constructor for the Client struct intended as a easy interface for issuing signed requests

func NewClientWithOutConfig added in v0.25.0

func NewClientWithOutConfig(baseurl string) (*Client, error)

func (*Client) Do

func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error)

Do is used either internally via our magic request shite or a user may use it

func (*Client) MagicRequestResponseDecoderWithOutAuth added in v0.25.0

func (c *Client) MagicRequestResponseDecoderWithOutAuth(url, method string, body io.Reader, v interface{}) error

func (*Client) NewRequest

func (c *Client) NewRequest(method string, requestUrl string, body io.Reader) (*http.Request, error)

NewRequest returns a signed request suitable for the chef server

func (*Client) NoAuthNewRequest added in v0.25.0

func (c *Client) NoAuthNewRequest(method string, requestUrl string, body io.Reader) (*http.Request, error)

NoAuthNewRequest returns a request suitable for public apis

type Config

type Config struct {
	// This should be the user ID on the chef server
	Name string

	// This is the plain text private Key for the user
	Key string

	// BaseURL is the chef server URL used to connect to. If using orgs you should include your org in the url and terminate the url with a "/"
	BaseURL string

	// When set to false (default) this will enable SSL Cert Verification. If you need to disable Cert Verification set to true
	SkipSSL bool

	// RootCAs is a reference to x509.CertPool for TLS
	RootCAs *x509.CertPool

	// Time to wait in seconds before giving up on a request to the server
	Timeout int

	// Authentication Protocol Version
	AuthenticationVersion AuthVersion

	// Chef Server Version
	ServerVersion string

	// When set to true corresponding API is using webui key in the request
	IsWebuiKey bool

	// Proxy function to be used when making requests
	Proxy func(*http.Request) (*url.URL, error)

	// Pointer to an HTTP Client to use instead of the default
	Client *http.Client
}

Config contains the configuration options for a chef client. This structure is used primarily in the NewClient() constructor in order to setup a proper client object

type ConfigRb added in v0.25.0

type ConfigRb struct {
	ClientKey     string
	ChefServerUrl string
	NodeName      string
}

func NewClientRb added in v0.25.0

func NewClientRb(data, path string) (c ConfigRb, err error)

type Container added in v0.17.0

type Container struct {
	ContainerName string `json:"containername"`
	ContainerPath string `json:"containerpath"`
}

Container represents the native Go version of the deserialized Container type

type ContainerCreateResult added in v0.17.0

type ContainerCreateResult struct {
	Uri string `json:"uri,omitempty"`
}

NewContainerResult

type ContainerListResult added in v0.17.0

type ContainerListResult map[string]string

ContainerListResult is map of the container names to container Uri

func (ContainerListResult) String added in v0.17.0

func (c ContainerListResult) String() (out string)

String makes ContainerListResult implement the string result

type ContainerService added in v0.17.0

type ContainerService struct {
	// contains filtered or unexported fields
}

func (*ContainerService) Create added in v0.17.0

func (e *ContainerService) Create(container Container) (data *ContainerCreateResult, err error)

Create makes a Container on the chef server

Chef API docs: https://docs.chef.io/api_chef_server.html#containers

func (*ContainerService) Delete added in v0.17.0

func (e *ContainerService) Delete(name string) (err error)

Delete removes a containers on the Chef server

Chef API docs: https://docs.chef.io/api_chef_server.html#container

func (*ContainerService) Get added in v0.17.0

func (e *ContainerService) Get(name string) (container Container, err error)

Get gets a container from the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#containers

func (*ContainerService) List added in v0.17.0

func (e *ContainerService) List() (data ContainerListResult, err error)

List lists the containers in the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server/containers

type Cookbook

type Cookbook struct {
	CookbookName string         `json:"cookbook_name"`
	Name         string         `json:"name"`
	Version      string         `json:"version,omitempty"`
	ChefType     string         `json:"chef_type,omitempty"`
	Frozen       bool           `json:"frozen?,omitempty"`
	JsonClass    string         `json:"json_class,omitempty"`
	Files        []CookbookItem `json:"files,omitempty"`
	Templates    []CookbookItem `json:"templates,omitempty"`
	Attributes   []CookbookItem `json:"attributes,omitempty"`
	Recipes      []CookbookItem `json:"recipes,omitempty"`
	Definitions  []CookbookItem `json:"definitions,omitempty"`
	Libraries    []CookbookItem `json:"libraries,omitempty"`
	Providers    []CookbookItem `json:"providers,omitempty"`
	Resources    []CookbookItem `json:"resources,omitempty"`
	RootFiles    []CookbookItem `json:"root_files,omitempty"`
	Metadata     CookbookMeta   `json:"metadata,omitempty"`
	Access       CookbookAccess `json:"access,omitempty"`
}

Cookbook represents the native Go version of the deserialized api cookbook

type CookbookAccess

type CookbookAccess struct {
	Read   bool `json:"read,omitempty"`
	Create bool `json:"create,omitempty"`
	Grant  bool `json:"grant,omitempty"`
	Update bool `json:"update,omitempty"`
	Delete bool `json:"delete,omitempty"`
}

CookbookAccess represents the permissions on a Cookbook

type CookbookItem

type CookbookItem struct {
	Url         string `json:"url,omitempty"`
	Path        string `json:"path,omitempty"`
	Name        string `json:"name,omitempty"`
	Checksum    string `json:"checksum,omitempty"`
	Specificity string `json:"specificity,omitempty"`
}

CookbookItem represents a object of cookbook file data

type CookbookListResult

type CookbookListResult map[string]CookbookVersions

CookbookListResult is the summary info returned by chef-api when listing http://docs.opscode.com/api_chef_server.html#cookbooks

func (CookbookListResult) String

func (c CookbookListResult) String() (out string)

String makes CookbookListResult implement the string result

type CookbookLock added in v0.16.2

type CookbookLock struct {
	Version          string            `json:"version,omitempty"`
	Identifier       string            `json:"identifier,omitempty"`
	DottedIdentifier string            `json:"dotted_decimal_identifier,omitempty"`
	Origin           string            `json:"origin,omitempty"`
	Source           string            `json:"source,omitempty"`
	CacheKey         string            `json:"cache_key,omitempty"`
	SCM              SCMDetail         `json:"scm_info,omitempty"`
	SourceOptions    map[string]string `json:"source_options,omitempty"`
}

type CookbookMeta

type CookbookMeta struct {
	Name               string                 `json:"name,omitempty"`
	Version            string                 `json:"version,omitempty"`
	Description        string                 `json:"description,omitempty"`
	LongDescription    string                 `json:"long_description,omitempty"`
	Maintainer         string                 `json:"maintainer,omitempty"`
	MaintainerEmail    string                 `json:"maintainer_email,omitempty"`
	License            string                 `json:"license,omitempty"`
	Platforms          map[string]interface{} `json:"platforms,omitempty"`
	Depends            map[string]string      `json:"dependencies,omitempty"`
	Reccomends         map[string]string      `json:"recommendations,omitempty"`
	Suggests           map[string]string      `json:"suggestions,omitempty"`
	Conflicts          map[string]string      `json:"conflicting,omitempty"`
	Provides           map[string]interface{} `json:"providing,omitempty"`
	Replaces           map[string]string      `json:"replacing,omitempty"`
	Attributes         map[string]interface{} `json:"attributes,omitempty"` // this has a format as well that could be typed, but blargh https://github.com/lob/chef/blob/master/cookbooks/apache2/metadata.json
	Groupings          map[string]interface{} `json:"groupings,omitempty"`  // never actually seen this used.. looks like it should be map[string]map[string]string, but not sure http://docs.opscode.com/essentials_cookbook_metadata.html
	Recipes            map[string]string      `json:"recipes,omitempty"`
	SourceUrl          string                 `json:"source_url"`
	IssueUrl           string                 `json:"issues_url"`
	ChefVersion        string
	OhaiVersion        string
	Gems               [][]string `json:"gems"`
	EagerLoadLibraries bool       `json:"eager_load_libraries"`
	Privacy            bool       `json:"privacy"`
}

CookbookMeta represents a Golang version of cookbook metadata

func NewMetaData added in v0.25.0

func NewMetaData(data string) (m CookbookMeta, err error)

func NewMetaDataFromJson added in v0.25.0

func NewMetaDataFromJson(data []byte) (m CookbookMeta, err error)

func ReadMetaData added in v0.25.0

func ReadMetaData(path string) (m CookbookMeta, err error)

type CookbookRecipesResult

type CookbookRecipesResult []string

CookbookRecipesResult is the summary info returned by chef-api when listing http://docs.opscode.com/api_chef_server.html#cookbooks-recipes

type CookbookService

type CookbookService struct {
	// contains filtered or unexported fields
}

CookbookService is the service for interacting with chef server cookbooks endpoint

func (*CookbookService) Delete

func (c *CookbookService) Delete(name, version string) (err error)

DeleteVersion removes a version of a cook from a server

func (*CookbookService) Download added in v0.3.1

func (c *CookbookService) Download(name, version string) error

Download downloads a cookbook to the current directory on disk

func (*CookbookService) DownloadAt added in v0.3.1

func (c *CookbookService) DownloadAt(name, version, localDir string) error

DownloadAt is a deprecated alias for DownloadTo

func (*CookbookService) DownloadTo added in v0.5.1

func (c *CookbookService) DownloadTo(name, version, localDir string) error

DownloadTo downloads a cookbook to the specified local directory on disk

func (*CookbookService) Get

func (c *CookbookService) Get(name string) (data CookbookVersion, err error)

Get retruns a CookbookVersion for a specific cookbook

GET /cookbooks/name

func (*CookbookService) GetAvailableVersions

func (c *CookbookService) GetAvailableVersions(name, numVersions string) (data CookbookListResult, err error)

GetAvailable returns the versions of a coookbook available on a server

func (*CookbookService) GetVersion

func (c *CookbookService) GetVersion(name, version string) (data Cookbook, err error)

GetVersion fetches a specific version of a cookbooks data from the server api

GET /cookbook/foo/1.2.3
GET /cookbook/foo/_latest
Chef API docs: https://docs.chef.io/api_chef_server.html#cookbooks-name-version

func (*CookbookService) List

List returns a CookbookListResult with the latest versions of cookbooks available on the server

func (*CookbookService) ListAllRecipes

func (c *CookbookService) ListAllRecipes() (data CookbookRecipesResult, err error)

ListAllRecipes lists the names of all recipes in the most recent cookbook versions

Chef API docs: https://docs.chef.io/api_chef_server.html#cookbooks-recipes

func (*CookbookService) ListAvailableVersions

func (c *CookbookService) ListAvailableVersions(numVersions string) (data CookbookListResult, err error)

ListVersions lists the cookbooks available on the server limited to numVersions

Chef API docs: https://docs.chef.io/api_chef_server.html#cookbooks-name

type CookbookVersion

type CookbookVersion struct {
	Url     string `json:"url,omitempty"`
	Version string `json:"version,omitempty"`
}

CookbookVersion is the data for a specific cookbook version

type CookbookVersions

type CookbookVersions struct {
	Url      string            `json:"url,omitempty"`
	Versions []CookbookVersion `json:"versions,omitempty"`
}

CookbookVersions is the data container returned from the chef server when listing all cookbooks

type DataBag

type DataBag struct {
	Name      string `json:"name"`
	JsonClass string `json:"json_class"`
	ChefType  string `json:"chef_type"`
}

DataBag is a data bag

type DataBagCreateResult

type DataBagCreateResult struct {
	URI string `json:"uri"`
}

type DataBagItem

type DataBagItem interface{}

DataBagItem is a data bag item

type DataBagListResult

type DataBagListResult map[string]string

DataBagListResult is the list of data bags returned by chef-api when listing https://docs.chef.io/api_chef_server/#data

func (DataBagListResult) String

func (d DataBagListResult) String() (out string)

String makes DataBagListResult implement the string result

type DataBagService

type DataBagService struct {
	// contains filtered or unexported fields
}

DataBagService is the service for interacting with the chef server data endpoint

func (*DataBagService) Create

func (d *DataBagService) Create(databag *DataBag) (result *DataBagCreateResult, err error)

Create adds a data bag to the server

Chef API Docs: https://docs.chef.io/api_chef_server/#post-7

func (*DataBagService) CreateItem

func (d *DataBagService) CreateItem(databagName string, databagItem DataBagItem) (err error)

CreateItem adds an item to a data bag

Chef API Docs: https://docs.chef.io/api_chef_server/#post-8

func (*DataBagService) Delete

func (d *DataBagService) Delete(name string) (result *DataBag, err error)

Delete removes a data bag from the server

Chef API Docs: https://docs.chef.io/api_chef_server/#delete-7

func (*DataBagService) DeleteItem

func (d *DataBagService) DeleteItem(databagName string, databagItem string) (err error)

DeleteItem deletes an item from a data bag

Chef API Docs: https://docs.chef.io/api_chef_server/#delete-8

func (*DataBagService) GetItem

func (d *DataBagService) GetItem(databagName string, databagItem string) (item DataBagItem, err error)

GetItem gets an item from a data bag

Chef API Docs: https://docs.chef.io/api_chef_server/#get-21

func (*DataBagService) List

func (d *DataBagService) List() (data *DataBagListResult, err error)

List returns a list of databags on the server

Chef API Docs: https://docs.chef.io/api_chef_server/#get-19

func (*DataBagService) ListItems

func (d *DataBagService) ListItems(name string) (data *DataBagListResult, err error)

ListItems gets a list of the items in a data bag.

Chef API Docs: https://docs.chef.io/api_chef_server/#get-20

func (*DataBagService) UpdateItem

func (d *DataBagService) UpdateItem(databagName string, databagItemId string, databagItem DataBagItem) (err error)

UpdateItem updates an item in a data bag

Chef API Docs: https://docs.chef.io/api_chef_server/#put-6

type EnvRunList added in v0.15.0

type EnvRunList map[string]RunList

EnvRunList represents the recipes and roles with environment specified for a node or as part of a role.

type Environment

type Environment struct {
	Name               string            `json:"name"`
	Description        string            `json:"description"`
	ChefType           string            `json:"chef_type,omitempty"`
	Attributes         interface{}       `json:"attributes,omitempty"`
	DefaultAttributes  interface{}       `json:"default_attributes,omitempty"`
	OverrideAttributes interface{}       `json:"override_attributes,omitempty"`
	JsonClass          string            `json:"json_class,omitempty"`
	CookbookVersions   map[string]string `json:"cookbook_versions"`
}

Environment represents the native Go version of the deserialized Environment type

type EnvironmentCookbookResult

type EnvironmentCookbookResult map[string]CookbookVersions

type EnvironmentRecipesResult added in v0.23.2

type EnvironmentRecipesResult []string

type EnvironmentResult

type EnvironmentResult map[string]string

func (EnvironmentResult) String

func (e EnvironmentResult) String() (out string)

String makes EnvironmentResult implement the string result

type EnvironmentService

type EnvironmentService struct {
	// contains filtered or unexported fields
}

Environment has a Reader, hey presto

func (*EnvironmentService) Create

func (e *EnvironmentService) Create(environment *Environment) (data *EnvironmentResult, err error)

Create an environment in the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#environments

func (*EnvironmentService) Delete added in v0.15.0

func (e *EnvironmentService) Delete(name string) (data *Environment, err error)

Delete an environment from the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server/#delete-9

func (*EnvironmentService) Get

func (e *EnvironmentService) Get(name string) (data *Environment, err error)

Get gets an environment from the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#environments-name

func (*EnvironmentService) List

func (e *EnvironmentService) List() (data *EnvironmentResult, err error)

List lists the environments in the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#environments

func (*EnvironmentService) ListCookbooks

func (e *EnvironmentService) ListCookbooks(name string, numVersions string) (data EnvironmentCookbookResult, err error)

Get the versions of a cookbook for this environment from the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#environments-name-cookbooks

func (*EnvironmentService) ListRecipes added in v0.23.2

func (e *EnvironmentService) ListRecipes(name string) (data EnvironmentRecipesResult, err error)

ListRecipes get the recipes list of recipes available to a given environment.

Chef API docs: https://docs.chef.io/api_chef_server/#get-33

func (*EnvironmentService) Put

func (e *EnvironmentService) Put(environment *Environment) (data *Environment, err error)

Write an environment to the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#environments-name TODO: Fix the name restriction. The parms should be name, environment

type ErrorMsg added in v0.21.0

type ErrorMsg struct {
	Error interface{} `json:"error"`
}

type ErrorResponse

type ErrorResponse struct {
	Response *http.Response // HTTP response that caused this error
	// extracted error message converted to string if possible
	ErrorMsg string
	// json body raw byte stream from an error
	ErrorText []byte
}

An ErrorResponse reports one or more errors caused by an API request. Thanks to https://github.com/google/go-github

The Response structure includes:

        Status string
	StatusCode int

func ChefError added in v0.17.0

func ChefError(err error) (cerr *ErrorResponse, nerr error)

ChefError tries to unwind a chef client err return embedded in an error Unwinding allows easy access the StatusCode, StatusMethod and StatusURL functions

func (*ErrorResponse) Error

func (r *ErrorResponse) Error() string

Error implements the error interface method for ErrorResponse

func (*ErrorResponse) StatusCode added in v0.17.0

func (r *ErrorResponse) StatusCode() int

StatusCode returns the status code from the http response embedded in the ErrorResponse

func (*ErrorResponse) StatusMethod added in v0.17.0

func (r *ErrorResponse) StatusMethod() string

StatusMethod returns the method used from the http response embedded in the ErrorResponse

func (*ErrorResponse) StatusMsg added in v0.21.0

func (r *ErrorResponse) StatusMsg() string

StatusMsg returns the error msg string from the http response. The message is a best effort value and depends on the Chef Server json return format

func (*ErrorResponse) StatusText added in v0.21.0

func (r *ErrorResponse) StatusText() []byte

StatusText returns the raw json response included in the http response

func (*ErrorResponse) StatusURL added in v0.17.0

func (r *ErrorResponse) StatusURL() *url.URL

StatusURL returns the URL used from the http response embedded in the ErrorResponse

type Group

type Group struct {
	Name      string   `json:"name"`
	GroupName string   `json:"groupname"`
	OrgName   string   `json:"orgname"`
	Actors    []string `json:"actors"`
	Clients   []string `json:"clients"`
	Groups    []string `json:"groups"`
	Users     []string `json:"users"`
}

Group represents the native Go version of the deserialized Group type

type GroupResult

type GroupResult struct {
	Uri string `json:"uri"`
}

type GroupService

type GroupService struct {
	// contains filtered or unexported fields
}

func (*GroupService) Create

func (e *GroupService) Create(group Group) (data *GroupResult, err error)

Creates a Group on the chef server

Chef API docs: https://docs.chef.io/api_chef_server.html#groups

func (*GroupService) Delete

func (e *GroupService) Delete(name string) (err error)

Delete removes a group on the Chef server

Chef API docs: https://docs.chef.io/api_chef_server.html#groups

func (*GroupService) Get

func (e *GroupService) Get(name string) (group Group, err error)

Get gets a group from the Chef server.

Chef API docs: http://docs.opscode.com/api_chef_server.html#id28

func (*GroupService) List

func (e *GroupService) List() (grouplist map[string]string, err error)

List lists the groups in the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#groups

func (*GroupService) Update

func (e *GroupService) Update(g GroupUpdate) (group GroupUpdate, err error)

Update a group on the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#groups

type GroupUpdate added in v0.18.1

type GroupUpdate struct {
	Name      string `json:"name"`
	GroupName string `json:"groupname"`
	Actors    struct {
		Clients []string `json:"clients"`
		Groups  []string `json:"groups"`
		Users   []string `json:"users"`
	} `json:"actors"`
}

GroupUpdate represents the payload needed to update a group

type IncludedPolicyLocks added in v0.17.1

type IncludedPolicyLocks struct {
	Name          string            `json:"name,omitempty"`
	RevisionID    string            `json:"revision_id,omitempty"`
	SourceOptions map[string]string `json:"source_options,omitempty"`
}

IncludedPolicyLocks are the included policies locks

type Invite added in v0.7.1

type Invite struct {
	Id       string `json:"id,omitempty"`
	UserName string `json:"username,omitempty"`
}

Invite represents an entry in the array of responses listing the outstanding invitations GET /organization/NAME/association_requests

type JSearchResult added in v0.27.0

type JSearchResult struct {
	Total int
	Start int
	Rows  []SearchRow
}

JSearchResult will return a slice of json.RawMessage which can then be json.Unmarshaled to any of the chef-like objects (Role/Node/etc)

type KeyItem added in v0.14.0

type KeyItem struct {
	Name    string `json:"name,omitempty"`
	Uri     string `json:"uri,omitempty"`
	Expired bool   `json:"expired,omitempty"`
}

type License added in v0.8.0

type License struct {
	LimitExceeded bool   `json:"limit_exceeded"`
	NodeLicense   int    `json:"node_license"`
	NodeCount     int    `json:"node_count"`
	UpgradeUrl    string `json:"Upgrade_url"`
}

License represents the body of the returned information.

type LicenseService added in v0.8.0

type LicenseService struct {
	// contains filtered or unexported fields
}

func (*LicenseService) Get added in v0.8.0

func (e *LicenseService) Get() (data License, err error)

License gets license information.

https://docs.chef.io/api_chef_server/#license

type Node

type Node struct {
	Name                string                 `json:"name"`
	Environment         string                 `json:"chef_environment,omitempty"`
	ChefType            string                 `json:"chef_type,omitempty"`
	AutomaticAttributes map[string]interface{} `json:"automatic,omitempty"`
	NormalAttributes    map[string]interface{} `json:"normal,omitempty"`
	DefaultAttributes   map[string]interface{} `json:"default,omitempty"`
	OverrideAttributes  map[string]interface{} `json:"override,omitempty"`
	JsonClass           string                 `json:"json_class,omitempty"`
	//TODO: use the RunList struct for this
	RunList     []string `json:"run_list,omitempty"`
	PolicyName  string   `json:"policy_name,omitempty"`
	PolicyGroup string   `json:"policy_group,omitempty"`
}

Node represents the native Go version of the deserialized Node type

func NewNode

func NewNode(name string) (node Node)

NewNode is the Node constructor method

func (*Node) GetAttribute added in v0.28.0

func (e *Node) GetAttribute(paths ...string) (interface{}, error)

GetAttribute will fetch an attribute from the provided path considering the right attribute precedence.

type NodeResult

type NodeResult struct {
	Uri string `json:"uri"`
}

type NodeService

type NodeService struct {
	// contains filtered or unexported fields
}

func (*NodeService) Delete

func (e *NodeService) Delete(name string) (err error)

Delete removes a node on the Chef server

Chef API docs: https://docs.chef.io/api_chef_server.html#nodes-name

func (*NodeService) Get

func (e *NodeService) Get(name string) (node Node, err error)

Get gets a node from the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#nodes-name

func (*NodeService) Head added in v0.20.0

func (e *NodeService) Head(name string) (err error)

Head gets a node from the Chef server. Does not return a json body.

Chef API docs: https://docs.chef.io/api_chef_server.html#nodes-name

func (*NodeService) List

func (e *NodeService) List() (data map[string]string, err error)

List lists the nodes in the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#nodes

func (*NodeService) Post

func (e *NodeService) Post(node Node) (data *NodeResult, err error)

Post creates a Node on the chef server

Chef API docs: https://docs.chef.io/api_chef_server.html#nodes

func (*NodeService) Put

func (e *NodeService) Put(n Node) (node Node, err error)

Put updates a node on the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#nodes-name TODO: We might want to change the name. name and data should be separate structures

type OrgUser added in v0.7.1

type OrgUser struct {
	Username    string `json:"username,omitempty"`
	Email       string `json:"email,omitempty"`
	DisplayName string `json:"display_name,omitempty"`
	FirstName   string `json:"first_name,omitempty"`
	LastName    string `json:"last_name,omitempty"`
	PublicKey   string `json:"public_key,omitempty"`
}

OrgUser represents the detailed information about a user in an organization GET /organization/NAME/user/NAME DELETE /organization/NAME/user/NAME

type OrgUserListEntry added in v0.7.1

type OrgUserListEntry struct {
	User struct {
		Username string `json:"username,omitempty"`
	} `json:"user,omitempty"`
}

Invite represents an entry in the array of responses listing the users in an organization GET /organization/NAME/association_requests

type Organization

type Organization struct {
	Name     string `json:"name"`
	FullName string `json:"full_name"`
	Guid     string `json:"guid"`
}

Organization represents the native Go version of the deserialized Organization type

type OrganizationResult

type OrganizationResult struct {
	ClientName string `json:"clientname"`
	PrivateKey string `json:"private_key"`
	Uri        string `json:"uri"`
}

type OrganizationService

type OrganizationService struct {
	// contains filtered or unexported fields
}

func (*OrganizationService) Create

func (e *OrganizationService) Create(organization Organization) (data OrganizationResult, err error)

Creates an Organization on the chef server

Chef API docs: https://docs.chef.io/api_chef_server.html#organizations

func (*OrganizationService) Delete

func (e *OrganizationService) Delete(name string) (err error)

Delete removes an organization on the Chef server

Chef API docs: https://docs.chef.io/api_chef_server.html#organizations

func (*OrganizationService) Get

func (e *OrganizationService) Get(name string) (organization Organization, err error)

Get gets an organization from the Chef server.

Chef API docs: http://docs.opscode.com/api_chef_server.html#id28

func (*OrganizationService) List

func (e *OrganizationService) List() (organizationlist map[string]string, err error)

List lists the organizations in the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#organizations

func (*OrganizationService) Update

func (e *OrganizationService) Update(g Organization) (organization Organization, err error)

Update an organization on the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#organizations

type PoliciesGetResponse added in v0.16.2

type PoliciesGetResponse map[string]Policy

PolicyGetResponse is returned from the chef-server for Get Requests to /policies

type Policy added in v0.16.2

type Policy struct {
	Uri       string                 `json:"uri,omitempty"`
	Revisions map[string]interface{} `json:"revisions,omitempty"`
}

type PolicyGetResponse added in v0.16.2

type PolicyGetResponse map[string]PolicyRevision

PolicyGetResponse is returned from chef-server for Get Requests to /policies/<policy-name>

type PolicyGroup added in v0.16.2

type PolicyGroup struct {
	Uri      string              `json:"uri,omitempty"`
	Policies map[string]Revision `json:"policies,omitempty"`
}

type PolicyGroupGetResponse added in v0.16.2

type PolicyGroupGetResponse map[string]PolicyGroup

PolicyGroupGetResponse is returned from the chef-server for Get Requests to /policy_groups

type PolicyGroupService added in v0.16.2

type PolicyGroupService struct {
	// contains filtered or unexported fields
}

PolicyGroupService is the service for interacting with chef server policies endpoint

func (*PolicyGroupService) Delete added in v0.19.0

func (e *PolicyGroupService) Delete(policyGroupName string) (data PolicyGroup, err error)

Delete deletes a policy group. DELETE /policy_groups/GROUP Chef API docs: https://docs.chef.io/api_chef_server/#policy_groups

func (*PolicyGroupService) DeletePolicy added in v0.19.0

func (e *PolicyGroupService) DeletePolicy(policyGroupName string, policyName string) (data RevisionDetailsResponse, err error)

DeletePolicy deletes a specific policy in a policy group DELETE /policy_groups/GROUP/policies/NAME Chef API docs: https://docs.chef.io/api_chef_server/#policy_groups

func (*PolicyGroupService) Get added in v0.19.0

func (e *PolicyGroupService) Get(policyGroupName string) (data PolicyGroup, err error)

Get gets the information for a specific policy group GET /policy_groups/GROUP Chef API docs: https://docs.chef.io/api_chef_server/#policy_groups

func (*PolicyGroupService) GetPolicy added in v0.19.0

func (e *PolicyGroupService) GetPolicy(policyGroupName string, policyName string) (data RevisionDetailsResponse, err error)

GetPolicy gets the information for a specific policy in a policy group GET /policy_groups/GROUP/policies/NAME Chef API docs: https://docs.chef.io/api_chef_server/#policy_groups

func (*PolicyGroupService) List added in v0.16.2

func (e *PolicyGroupService) List() (data PolicyGroupGetResponse, err error)

List lists the policy groups in the Chef server. Chef API docs: https://docs.chef.io/api_chef_server/#policy_groups

type PolicyRevision added in v0.16.2

type PolicyRevision map[string]PolicyRevisionDetail

type PolicyRevisionDetail added in v0.16.2

type PolicyRevisionDetail map[string]interface{}

type PolicyService added in v0.16.2

type PolicyService struct {
	// contains filtered or unexported fields
}

PolicyService is the service for interacting with chef server policies endpoint

func (*PolicyService) Delete added in v0.19.0

func (c *PolicyService) Delete(policyName string) (data PolicyGetResponse, err error)

Delete deletes a policy

DELETE /policies/name

func (*PolicyService) DeleteRevision added in v0.19.0

func (c *PolicyService) DeleteRevision(policyName string, revisionID string) (data RevisionDetailsResponse, err error)

DeleteRevision deletes a revisiom from a policy

GET /policies/<policy-name>/revisions/<revision-id>

func (*PolicyService) Get added in v0.16.2

func (c *PolicyService) Get(name string) (data PolicyGetResponse, err error)

Get returns details for a specific policy

GET /policies/name

func (*PolicyService) GetRevisionDetails added in v0.16.2

func (c *PolicyService) GetRevisionDetails(policyName string, revisionID string) (data RevisionDetailsResponse, err error)

GetRevisionDetails returns details of a specific revision from Chef Server

GET /policies/<policy-name>/revisions/<revision-id>

func (*PolicyService) List added in v0.16.2

func (c *PolicyService) List() (data PoliciesGetResponse, err error)

List lists the policies in the Chef server. Chef API docs: https://docs.chef.io/api_chef_server/#policies GET /policies

type Principal

type Principal struct {
	Principals []Principals `json:"principals"`
}

Principal represents the native Go version of the deserialized Principal type

type PrincipalService

type PrincipalService struct {
	// contains filtered or unexported fields
}

func (*PrincipalService) Get

func (e *PrincipalService) Get(name string) (principal Principal, err error)

Get gets a principal from the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#principals-name

type Principals added in v0.17.0

type Principals struct {
	Name      string `json:"name"`
	Type      string `json:"type"`
	PublicKey string `json:"public_key"`
	AuthzId   string `json:"authz_id"`
	OrgMember bool   `json:"org_member"`
}

type Request added in v0.7.1

type Request struct {
	User string `json:"user"`
}

Request represents the body of the request to invite a user to an organization POST /organization/NAME/association_requests

type RequiredRecipe added in v0.17.1

type RequiredRecipe string

RequireRecipe the text of the required recipe.

type RequiredRecipeService added in v0.17.1

type RequiredRecipeService struct {
	// contains filtered or unexported fields
}

func (*RequiredRecipeService) Get added in v0.17.1

func (e *RequiredRecipeService) Get() (data RequiredRecipe, err error)

RequiredRecipe gets the optional required_runlist value.

https://docs.chef.io/api_chef_server/ 200 - required_recipe enabled = true && required_recipe path specified, returns the recipe 404 required_recipe enabled = false

type RescindInvite added in v0.7.1

type RescindInvite struct {
	Id       string `json:"id,omitempty"`
	Orgname  string `json:"orgname,omitempty"`
	Username string `json:"username,omitempty"`
}

RescindInvite respresents the response from deleting an invitation DELETE /organization/NAME/association_requests/ID

type Revision added in v0.16.2

type Revision map[string]string

type RevisionDetailsResponse added in v0.16.2

type RevisionDetailsResponse struct {
	RevisionID           string                  `json:"revision_id,omitempty"`
	Name                 string                  `json:"name,omitempty"`
	RunList              []string                `json:"run_list,omitempty"`
	NamedRunList         map[string][]string     `json:"named_run_lists,omitempty"`
	IncludedPolicyLocks  []IncludedPolicyLocks   `json:"included_policy_locks,omitempty"`
	CookbookLocks        map[string]CookbookLock `json:"cookbook_locks,omitempty"`
	DefaultAttributes    map[string]interface{}  `json:"default_attributes,omitempty"`
	OverrideAttributes   map[string]interface{}  `json:"override_attributes,omitempty"`
	SolutionDependencies SolutionDep             `json:"solution_dependencies,omitempty"`
}

RevisionDetailsResponse is returned from the chef-server for Get Requests to /policies/<policy-name>/revisions/<rev-id>

type Role

type Role struct {
	Name               string      `json:"name"`
	ChefType           string      `json:"chef_type,omitempty"`
	DefaultAttributes  interface{} `json:"default_attributes,omitempty"`
	Description        string      `json:"description"`
	EnvRunList         EnvRunList  `json:"env_run_lists,omitempty"`
	JsonClass          string      `json:"json_class,omitempty"`
	OverrideAttributes interface{} `json:"override_attributes,omitempty"`
	RunList            RunList     `json:"run_list"`
}

Role represents the native Go version of the deserialized Role type

type RoleCreateResult

type RoleCreateResult map[string]string

func (RoleCreateResult) String

func (e RoleCreateResult) String() (out string)

String makes RoleCreateResult implement the string result

type RoleEnvironmentsResult added in v0.15.0

type RoleEnvironmentsResult []string

type RoleListResult

type RoleListResult map[string]string

func (RoleListResult) String

func (e RoleListResult) String() (out string)

String makes RoleListResult implement the string result

type RoleService

type RoleService struct {
	// contains filtered or unexported fields
}

func (*RoleService) Create

func (e *RoleService) Create(role *Role) (data *RoleCreateResult, err error)

Create a new role in the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#roles

func (*RoleService) Delete

func (e *RoleService) Delete(name string) (err error)

Delete a role from the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#roles-name

func (*RoleService) Get

func (e *RoleService) Get(name string) (data *Role, err error)

Get gets a role from the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#roles-name

func (*RoleService) GetEnvironmentRunlist added in v0.15.0

func (e *RoleService) GetEnvironmentRunlist(role string, environment string) (data EnvRunList, err error)

Get the environment-specific run-list for a role

Chef API docs: https://docs.chef.io/api_chef_server.html#roles-name-environments-name

func (*RoleService) GetEnvironments added in v0.15.0

func (e *RoleService) GetEnvironments(role string) (data RoleEnvironmentsResult, err error)

Get a list of environments that have environment specific run-lists for the given role

Chef API docs: https://docs.chef.io/api_chef_server.html#roles-name-environments

func (*RoleService) List

func (e *RoleService) List() (data *RoleListResult, err error)

List lists the roles in the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#roles

func (*RoleService) Put

func (e *RoleService) Put(role *Role) (data *Role, err error)

Update a role in the Chef server.

Chef API docs: https://docs.chef.io/api_chef_server.html#roles-name Trying to rename a role by specifying a new name in the body returns a 400

type RunList

type RunList []string

RunList represents the recipes and roles specified for a node or as part of a role.

type RunListItem added in v0.5.6

type RunListItem struct {
	Name    string
	Type    string
	Version string
}

RunListItem external representation of a run list This module is a direct port of the Chef::RunList::RunListItem class see: https://github.com/chef/chef/blob/master/lib/chef/run_list/run_list_item.rb

func NewRunListItem added in v0.5.6

func NewRunListItem(item string) (rli RunListItem, err error)

NewRunListItem parses a single item from a run list and returns a structure

func (RunListItem) IsRecipe added in v0.5.6

func (r RunListItem) IsRecipe() bool

IsRecipe Determines if the runlist item is a recipe

func (RunListItem) IsRole added in v0.5.6

func (r RunListItem) IsRole() bool

IsRole Determines if the runlist item is a role

func (RunListItem) String added in v0.5.6

func (r RunListItem) String() (s string)

String implements the String interface function

type SCMDetail added in v0.16.2

type SCMDetail struct {
	Name                       string   `json:"scm,omitempty"`
	Remote                     string   `json:"remote,omitempty"`
	Revision                   string   `json:"revision,omitempty"`
	WorkingTreeClean           bool     `json:"working_tree_clean,omitempty"`
	Published                  bool     `json:"published,omitempty"`
	SynchronizedRemoteBranches []string `json:"synchronized_remote_branches,omitempty"`
}

type Sandbox

type Sandbox struct {
	ID           string    `json:"guid"`
	Name         string    `json:"name"`
	CreationTime time.Time `json:"create_time"`
	Completed    bool      `json:"is_completed"`
	Checksums    []string
}

Sandbox Is the structure of an actual sandbox that has been created and returned by the final PUT to the sandbox ID

type SandboxItem

type SandboxItem struct {
	Url    string `json:"url"`
	Upload bool   `json:"needs_upload"`
}

A SandboxItem is embedded into the response from the chef-server and the actual sandbox is the Url and state for a specific Item.

type SandboxPostResponse

type SandboxPostResponse struct {
	ID        string `json:"sandbox_id"`
	Uri       string `json:"uri"`
	Checksums map[string]SandboxItem
}

SandboxPostResponse is the struct returned from the chef-server for Post Requests to /sandboxes

type SandboxRequest

type SandboxRequest struct {
	Checksums map[string]interface{} `json:"checksums"`
}

SandboxRequest is the desired chef-api structure for a Post body

type SandboxService

type SandboxService struct {
	// contains filtered or unexported fields
}

SandboxService is the chef-client Sandbox service used as the entrypoint and caller for Sandbox methods

func (SandboxService) Post

func (s SandboxService) Post(sums []string) (data SandboxPostResponse, err error)

Post creates a new sandbox on the chef-server. Deviates from the Chef-server api in that it takes a []string of sums for the sandbox instead of the IMO rediculous hash of nulls that the API wants. We convert it to the right structure under the hood for the chef-server api. http://docs.getchef.com/api_chef_server.html#id38

func (SandboxService) Put

func (s SandboxService) Put(id string) (box Sandbox, err error)

Put is used to commit a sandbox ID to the chef server. To signal that the sandbox you have Posted is now uploaded.

type SearchQuery

type SearchQuery struct {
	// The index you want to search
	Index string

	// The query you want to execute. This is the 'chef' query ex: 'chef_environment:prod'
	Query string

	// Sort order you want the search results returned
	SortBy string

	// Starting position for search
	Start int

	// Number of rows to return
	Rows int
}

SearchQuery Is the struct for holding a query request

func (SearchQuery) Do

func (q SearchQuery) Do(client *Client) (res SearchResult, err error)

Do will execute the search query on the client

func (SearchQuery) DoJSON added in v0.27.0

func (q SearchQuery) DoJSON(client *Client) (res JSearchResult, err error)

DoJSON will execute the search query on the client and return rawJSON formatted results

func (SearchQuery) DoPartial

func (q SearchQuery) DoPartial(client *Client, params map[string]interface{}) (res SearchResult, err error)

DoPartial will execute the search query on the client with partial mapping

func (SearchQuery) DoPartialJSON added in v0.27.0

func (q SearchQuery) DoPartialJSON(client *Client, params map[string]interface{}) (res JSearchResult, err error)

DoPartialJSON will execute the search query on the client with partial mapping and return raw JSON results

func (SearchQuery) String

func (q SearchQuery) String() string

String implements the Stringer Interface for the SearchQuery

type SearchResult

type SearchResult struct {
	Total int
	Start int
	Rows  []interface{}
}

SearchResult

type SearchRow added in v0.27.0

type SearchRow struct {
	Url  string
	Data json.RawMessage
}

type SearchService

type SearchService struct {
	// contains filtered or unexported fields
}

func (SearchService) Exec

func (e SearchService) Exec(idx, statement string) (res SearchResult, err error)

Exec runs the query on the index passed in. This is a helper method. If you want more control over the query use NewQuery and its Do() method. BUG(spheromak): Should we use Exec or SearchQuery.Do() or have both ?

func (SearchService) ExecJSON added in v0.27.0

func (e SearchService) ExecJSON(idx, statement string) (res JSearchResult, err error)

ExecJSON runs the query on the index passed in. This is a helper method. If you want more control over the query use NewQuery and its Do() method.

func (SearchService) Indexes

func (e SearchService) Indexes() (data map[string]string, err error)

Chef API docs: https://docs.chef.io/api_chef_server/#get-46

func (SearchService) NewQuery

func (e SearchService) NewQuery(idx, statement string) (query SearchQuery, err error)

NewSearch is a constructor for a SearchQuery struct. This is used by other search service methods to perform search requests on the server

func (SearchService) PageSize added in v0.20.2

func (e SearchService) PageSize(setting int)

func (SearchService) PartialExec

func (e SearchService) PartialExec(idx, statement string, params map[string]interface{}) (res SearchResult, err error)

PartialExec Executes a partial search based on passed in params and the query.

func (SearchService) PartialExecJSON added in v0.27.0

func (e SearchService) PartialExecJSON(idx, statement string, params map[string]interface{}) (res JSearchResult, err error)

PartialExecJSON Executes a partial search based on passed in params and the query.

type SolutionDep added in v0.16.2

type SolutionDep struct {
	PolicyFile   [][]string  `json:"Policyfile,omitempty"`
	Dependencies interface{} `json:"dependencies,omitempty"`
}

type Stats added in v0.18.0

type Stats []map[string]interface{}

Stats: represents the body of the returned information.

type StatsService added in v0.18.0

type StatsService struct {
	// contains filtered or unexported fields
}

func (*StatsService) Get added in v0.18.0

func (e *StatsService) Get(user string, password string) (data Stats, err error)

Stat gets the frontend & backend server information.

https://docs.chef.io/api_chef_server/

?format = text or json or nothing, text is supposed to work but returns a 406 This module only implements the json option. using a struct for the parse out data will force JSON output.

type Status added in v0.9.0

type Status struct {
	Status    string            `json:"status"`
	Upstreams map[string]string `json:"upstreams"`
	Keygen    map[string]int    `json:"keygen"`
}

Status represents the body of the returned information.

type StatusService added in v0.9.0

type StatusService struct {
	// contains filtered or unexported fields
}

func (*StatusService) Get added in v0.9.0

func (e *StatusService) Get() (data Status, err error)

Status gets the frontend & backend server information.

https://docs.chef.io/api_chef_server/#_status

type Universe added in v0.9.0

type Universe struct {
	Books map[string]UniverseBook
}

Universe represents the body of the returned information.

type UniverseBook added in v0.9.0

type UniverseBook struct {
	Versions map[string]UniverseVersion
}

type UniverseService added in v0.9.0

type UniverseService struct {
	// contains filtered or unexported fields
}

func (*UniverseService) Get added in v0.9.0

func (e *UniverseService) Get() (universe Universe, err error)

Universe gets available cookbook version information.

https://docs.chef.io/api_chef_server.html#universe

type UniverseVersion added in v0.9.0

type UniverseVersion struct {
	LocationPath string
	LocationType string
	Dependencies map[string]string
}

type UpdatedSince added in v0.13.0

type UpdatedSince struct {
	Action string
	Id     int64
	Path   string
}

UpdatedSince represents the body of the returned information.

type UpdatedSinceService added in v0.13.0

type UpdatedSinceService struct {
	// contains filtered or unexported fields
}

func (UpdatedSinceService) Get added in v0.13.0

func (e UpdatedSinceService) Get(sequenceId int64) (updated []UpdatedSince, err error)

Since gets available cookbook version information.

https://docs.chef.io/api_chef_server/#updated_since This end point has long since been deprecated and is no longer available Calls will always return 404 not found errors

type User

type User struct {
	UserName                      string `json:"username,omitempty"` // V1 uses username instead of V0 name
	DisplayName                   string `json:"display_name,omitempty"`
	Email                         string `json:"email,omitempty"`
	ExternalAuthenticationUid     string `json:"external_authentication_uid,omitempty"` // Specify this or password
	FirstName                     string `json:"first_name,omitempty"`
	LastName                      string `json:"last_name,omitempty"`
	MiddleName                    string `json:"middle_name,omitempty"`
	Password                      string `json:"password,omitempty"`   // Valid password
	CreateKey                     bool   `json:"create_key,omitempty"` // Cannot be passed with PublicKey
	PublicKey                     string `json:"public_key,omitempty"` // Cannot be passed with CreateKey
	RecoveryAuthenticationEnabled bool   `json:"recovery_authentication_enabled,omitempty"`
}

User represents the native Go version of the deserialized User type

type UserResult

type UserResult struct {
	Uri     string  `json:"uri,omitempty"`
	ChefKey ChefKey `json:"chef_key,omitempty"`
}

type UserService

type UserService struct {
	// contains filtered or unexported fields
}

func (*UserService) AddKey added in v0.14.0

func (e *UserService) AddKey(name string, keyadd AccessKey) (key KeyItem, err error)

AddKey add a key for a user on the Chef server. /users/USERNAME/keys POST 201 - created 401 - not authenticated 403 - not authorized 404 - user doesn't exist 409 - new name is already in use

Chef API docs: https://docs.chef.io/api_chef_server.html#users-name

func (*UserService) Create

func (e *UserService) Create(user User) (data UserResult, err error)

Create Creates a User on the chef server /users POST

201 =  success
400 - invalid  (missing display_name, email,( password or external) among other things)
      username must be lower case without spaces
403 - unauthorized
409 - already exists

Chef API docs: https://docs.chef.io/api_chef_server.html#users

func (*UserService) Delete

func (e *UserService) Delete(name string) (err error)

Delete removes a user on the Chef server /users/USERNAME DELETE

200 - deleted
401 - not authenticated
403 - not authorized
404 - not found

Chef API docs: https://docs.chef.io/api_chef_server.html#users-name

func (*UserService) DeleteKey added in v0.14.0

func (e *UserService) DeleteKey(name string, keyname string) (key AccessKey, err error)

DeleteKey delete a key for a user. /users/USERNAME/keys/KEYNAME DELETE 200 - successful 401 - not authenticated 403 - not authorized 404 - user doesn't exist

Chef API docs: https://docs.chef.io/api_chef_server/#usersuserkeys

func (*UserService) Get

func (e *UserService) Get(name string) (user User, err error)

Get gets a user from the Chef server. /users/USERNAME GET 200 - got it 401 - not authenticated 403 - not authorized 404 - user doesn't exist

Chef API docs: https://docs.chef.io/api_chef_server.html#users-name

func (*UserService) GetKey added in v0.14.0

func (e *UserService) GetKey(name string, keyname string) (key AccessKey, err error)

GetKey gets a key for a user. /users/USERNAME/keys/KEYNAME GET 200 - successful 401 - not authenticated 403 - not authorized 404 - user doesn't exist

Chef API docs: https://docs.chef.io/api_chef_server/#usersuserkeys

func (*UserService) List

func (e *UserService) List(filters ...string) (userlist map[string]string, err error)

List lists the users in the Chef server. /users GET Chef API docs: https://docs.chef.io/api_chef_server.html#users

func (*UserService) ListKeys added in v0.14.0

func (e *UserService) ListKeys(name string) (userkeys []KeyItem, err error)

ListKeys gets all the keys for a user. /users/USERNAME/keys GET 200 - successful 401 - not authenticated 403 - not authorized 404 - user doesn't exist

Chef API docs: https://docs.chef.io/api_chef_server/#usersuserkeys

func (*UserService) Update added in v0.11.0

func (e *UserService) Update(name string, user User) (userUpdate UserResult, err error)

Update updates a user on the Chef server. /users/USERNAME PUT 200 - updated 401 - not authenticated 403 - not authorized 404 - user doesn't exist 409 - new user name is already in use

Chef API docs: https://docs.chef.io/api_chef_server.html#users-name

func (*UserService) UpdateKey added in v0.14.0

func (e *UserService) UpdateKey(username string, keyname string, keyUp AccessKey) (userkey AccessKey, err error)

UpdateKey updates a key for a user. /users/USERNAME/keys/KEYNAME PUT 200 - successful 401 - not authenticated 403 - not authorized 404 - user doesn't exist

Chef API docs: https://docs.chef.io/api_chef_server/#usersuserkeys

func (*UserService) VerboseList added in v0.9.2

func (e *UserService) VerboseList(filters ...string) (userlist map[string]UserVerboseResult, err error)

VerboseList lists the users in the Chef server in verbose format. /users GET Chef API docs: https://docs.chef.io/api_chef_server.html#users

type UserVerboseResult added in v0.9.2

type UserVerboseResult struct {
	Email     string `json:"email,omitempty"`
	FirstName string `json:"first_name,omitempty"`
	LastName  string `json:"last_name,omitempty"`
}

Notes

Bugs

  • tightly coupled

  • This is now both a *response* decoder and handles upload.. gettin smelly

  • Should we use Exec or SearchQuery.Do() or have both ?

Directories

Path Synopsis
Test the go-chef/chef chef server api ACL endpoints against a live server
Test the go-chef/chef chef server api ACL endpoints against a live server

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL