Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of API calls for cookbook_artifacts end point #21

Merged
merged 3 commits into from
Apr 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions cookbook_artifacts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package chef

import "fmt"

// CBAService is the service for interacting with chef server cookbook_artifacts endpoint
type CBAService struct {
client *Client
}

// CBAGetResponse is returned from the chef-server for Get Requests to /cookbook_artifacts
type CBAGetResponse map[string]CBA
type CBA struct {
Url string `json:"url,omitempty"`
CBAVersions []CBAVersion `json:"versions,omitempty"`
}
type CBAVersion struct {
Url string `json:"url,omitempty"`
Identifier string `json:"identifier,omitempty"`
}

// CBADetail represents the detail for a specific cookbook_artifact
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"`
}

// CBAMeta represents the cookbook_artifacts metadata information
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"`
}

// List lists the Cookbook_Artifacts in the Chef server.
// GET /cookbook_artifacts
func (c *CBAService) List() (data CBAGetResponse, err error) {
err = c.client.magicRequestDecoder("GET", "cookbook_artifacts", nil, &data)
return
}

// Get returns details for a specific cookbook artifact
// GET /cookbook_artifacts/name
func (c *CBAService) Get(name string) (data CBAGetResponse, err error) {
path := fmt.Sprintf("cookbook_artifacts/%s", name)
err = c.client.magicRequestDecoder("GET", path, nil, &data)
return
}

// GetVersion fetches a specific version of a cookbook_artifact from the server api
// GET /cookbook_artifacts/foo/1ef062de1bc4cb14e4a78fb739e104eb9508473e
func (c *CBAService) GetVersion(name, id string) (data CBADetail, err error) {
url := fmt.Sprintf("cookbook_artifacts/%s/%s", name, id)
err = c.client.magicRequestDecoder("GET", url, nil, &data)
return
}
134 changes: 134 additions & 0 deletions cookbook_artifacts_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package chef

import (
"fmt"
"io/ioutil"
"net/http"
"testing"

"github.com/stretchr/testify/assert"
)

const CBAListResponseFile = "test/cookbook_artifacts_list_response.json"
const CBAGetResponseFile = "test/cookbook_artifacts_get_response.json"
const CBAGetVersionResponseFile = "test/cookbook_artifacts_getversion_response.json"

func TestListCBA(t *testing.T) {
setup()
defer teardown()

file, err := ioutil.ReadFile(CBAListResponseFile)
if err != nil {
t.Error(err)
}

mux.HandleFunc("/cookbook_artifacts", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, string(file))
})

data, err := client.CookbookArtifacts.List()
if err != nil {
t.Error(err)
}

if data == nil {
t.Fatal("We should have some data")
}

if len(data) != 2 {
t.Error("Mismatch in expected cookbook artifact count. Expected 2, Got: ", len(data))
}

if _, ok := data["oc-hec-postfix"]; !ok {
t.Error("oc-hec-postfix cookbook artifact should be listed")
}

if _, ok := data["grafana"]; !ok {
t.Error("grafana cookbook artifact should be listed")
}

}

func TestGetCBA(t *testing.T) {
setup()
defer teardown()

file, err := ioutil.ReadFile(CBAGetResponseFile)
if err != nil {
t.Error(err)
}

mux.HandleFunc("/cookbook_artifacts/seven_zip", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, string(file))
})
mux.HandleFunc("/cookbook_artifacts/bad", func(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Not Found", 404)
})

data, err := client.CookbookArtifacts.Get("seven_zip")
if err != nil {
t.Error(err)
}

if data["seven_zip"].Url != "https://localhost/organizations/utility/cookbook_artifacts/seven_zip" {
t.Errorf("URL mismatch, expected '%s', got '%s'\n", "https://api.chef.io/organizations/chef-utility/cookbook_artifacts/seven_zip", data["seven_zip"].Url)
}

if len(data["seven_zip"].CBAVersions) != 7 {
t.Errorf("Expected 7 versions of this cookbook artifact, received %d", len(data["seven_zip"].CBAVersions))
}
_, err = client.CookbookArtifacts.Get("bad")
if err == nil {
t.Error("We expected this bad request to error", err)
}
}

func TestGetVersionCBA(t *testing.T) {
setup()
defer teardown()

file, err := ioutil.ReadFile(CBAGetVersionResponseFile)
if err != nil {
t.Error(err)
}

mux.HandleFunc("/cookbook_artifacts/seven_zip/0e1fed3b56aa5e84205e330d92aca22d8704a014", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, string(file))
})
mux.HandleFunc("/cookbook_artifacts/seven_zip/bad", func(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Not Found", 404)
})

cookbookArtifact, err := client.CookbookArtifacts.GetVersion("seven_zip", "0e1fed3b56aa5e84205e330d92aca22d8704a014")
if err != nil {
t.Error(err)
}

if assert.NotNil(t, cookbookArtifact) {
assert.Equal(t, "seven_zip", cookbookArtifact.Name)
assert.Equal(t, "3.1.2", cookbookArtifact.Version)
assert.Equal(t, "0e1fed3b56aa5e84205e330d92aca22d8704a014", cookbookArtifact.Identifier)
assert.Equal(t, 9, len(cookbookArtifact.RootFiles))
assert.Equal(t, 1, len(cookbookArtifact.Providers))
assert.Equal(t, 2, len(cookbookArtifact.Resources))
assert.Equal(t, 1, len(cookbookArtifact.Libraries))
assert.Equal(t, 1, len(cookbookArtifact.Attributes))
assert.Equal(t, "https://s3-external-1/amazonaws.com:443/test-s3-url", cookbookArtifact.RootFiles[0].Url)
assert.Equal(t, "d07d9934f97445c5187cf86abf107b7b", cookbookArtifact.Providers[0].Checksum)
assert.Equal(t, "archive.rb", cookbookArtifact.Resources[0].Name)
assert.Equal(t, "matchers.rb", cookbookArtifact.Libraries[0].Name)
assert.Equal(t, "https://s3-external-1/amazonaws.com:443/test-s3-url-attribs", cookbookArtifact.Attributes[0].Url)
assert.Equal(t, "https://s3-external-1/amazonaws.com:443/test-s3-url-recipes", cookbookArtifact.Recipes[0].Url)
assert.Equal(t, "seven_zip", cookbookArtifact.Metadata.Name)
assert.Equal(t, "3.1.2", cookbookArtifact.Metadata.Version)
assert.Equal(t, "Apache-2.0", cookbookArtifact.Metadata.License)
assert.Equal(t, "Installs/Configures 7-Zip", cookbookArtifact.Metadata.Description)
assert.Equal(t, ">= 0.0.0", cookbookArtifact.Metadata.Depends["windows"])
assert.Equal(t, ">= 13.0", cookbookArtifact.Metadata.ChefVersions[0][0])
}

_, err = client.CookbookArtifacts.GetVersion("seven_zip", "bad")
if err == nil {
t.Error("We expected this bad request to error", err)
}
}
27 changes: 25 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,37 @@ module github.com/chef/go-chef
go 1.12

require (
github.com/aws/aws-sdk-go v1.30.7 // indirect

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of these dependencies are pulled in for the integration tests. I would love to have those tests pull their own dependencies in with their own go.mod but I think we fix that in #15

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. Thanks @tyler-ball

github.com/axw/gocov v1.0.0 // indirect
github.com/cenkalti/backoff v2.1.1+incompatible
github.com/ctdk/chefcrypto v1.0.0 // indirect
github.com/ctdk/go-trie v0.0.0-20161110000926-fe74c509b12e // indirect
github.com/ctdk/goiardi v0.11.10
github.com/davecgh/go-spew v1.1.1
github.com/google/go-cmp v0.4.0
github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de // indirect
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect
github.com/hashicorp/go-multierror v1.1.0 // indirect
github.com/hashicorp/go-retryablehttp v0.6.6 // indirect
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
github.com/hashicorp/vault/api v1.0.4 // indirect
github.com/jessevdk/go-flags v1.4.0 // indirect
github.com/lib/pq v1.3.0 // indirect
github.com/mattn/goveralls v0.0.5 // indirect
github.com/mitchellh/mapstructure v1.2.2 // indirect
github.com/philhofer/fwd v1.0.0 // indirect
github.com/pierrec/lz4 v2.5.1+incompatible // indirect
github.com/pmylund/go-cache v2.1.0+incompatible // indirect
github.com/r3labs/diff v0.0.0-20191120142937-b4ed99a31f5a
github.com/smartystreets/assertions v1.0.1 // indirect
github.com/smartystreets/goconvey v1.6.4
github.com/stretchr/testify v1.4.0
github.com/stretchr/testify v1.5.1
github.com/tideland/golib v4.24.2+incompatible // indirect
github.com/tinylib/msgp v1.1.2 // indirect
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904 // indirect
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect
golang.org/x/text v0.3.2 // indirect
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 // indirect
golang.org/x/tools v0.0.0-20200416061724-5744cfde56ed // indirect
gopkg.in/square/go-jose.v2 v2.5.0 // indirect
gopkg.in/yaml.v2 v2.2.7 // indirect
)
Loading