Skip to content

Commit

Permalink
Added tests for PR #12. (#13)
Browse files Browse the repository at this point in the history

* Fix for Travis (added missing dependency).
  • Loading branch information
xor-xor committed Jun 7, 2016
1 parent cc09569 commit 734256d
Show file tree
Hide file tree
Showing 16 changed files with 1,006 additions and 103 deletions.
12 changes: 4 additions & 8 deletions actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import (
// PerformScan runs a scan of a given host using a set of scripts.
// At this moment, we assume that there will be only one script here (idrac.py),
// and that only MAC addresses will be created/updated/deleted in Ralph.
func PerformScan(addrStr string, scripts []string, dryRun bool) {
func PerformScan(addrStr string, scripts []string, dryRun bool, cfgDir string) {
if dryRun {
fmt.Println("Running in dry-run mode, no changes will be saved in Ralph.")
}
script, err := NewScript(scripts[0])
script, err := NewScript(scripts[0], cfgDir)
if err != nil {
fmt.Println(err)
return
Expand Down Expand Up @@ -53,11 +53,7 @@ func PerformScan(addrStr string, scripts []string, dryRun bool) {
}
var newEths []*EthernetComponent
for _, mac := range result.MACAddresses {
eth, err := NewEthernetComponent(mac, baseObj, "")
if err != nil {
fmt.Println(err)
break
}
eth := NewEthernetComponent(mac, baseObj, "")
newEths = append(newEths, eth)
}
diff, err := CompareEthernetComponents(oldEths, newEths)
Expand All @@ -68,7 +64,7 @@ func PerformScan(addrStr string, scripts []string, dryRun bool) {
fmt.Println("No changes detected.")
return
}
err = SendDiffToRalph(client, diff, dryRun)
_, err = SendDiffToRalph(client, diff, dryRun, false)
if err != nil {
fmt.Println(err)
}
Expand Down
27 changes: 19 additions & 8 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,24 @@ func NewClient(ralphURL, apiKey string, scannedAddr Addr, client *http.Client) (
if apiKey == "" {
return nil, fmt.Errorf("API key is missing (did you forget to set it via RALPH_API_KEY environment variable?)")
}
if ralphURL == "" {
return nil, fmt.Errorf("Ralph's URL is missing (did you forget to set it via RALPH_API_URL environment variable?)")
}
// TODO(xor-xor): Investigate why url.Parse happily accepts stuff like "httplocalhost" or
// "http/localhost/api", and add some additional checks here for such cases.
u, err := url.Parse(ralphURL)
if err != nil {
return nil, fmt.Errorf("error parsing Ralph's URL: %v", err)
}
if client == nil {
// TODO(xor-xor): This timeout should be taken from config.
client = &http.Client{Timeout: time.Second * 10}
}
return &Client{
scannedAddr: scannedAddr,
ralphURL: u.String(),
apiKey: apiKey,
client: &http.Client{Timeout: time.Second * 10}, // TODO(xor-xor): This should be taken from config.
client: client,
}, nil
}

Expand All @@ -62,9 +71,10 @@ func (c *Client) NewRequest(method, urlStr string, body io.Reader) (*http.Reques

// SendToRalph sends to Ralph json-ed datatypes (EthernetComponent, PhysicalHost, etc.)
// using one of the REST methods on a given endpoint.
func (c *Client) SendToRalph(method, endpoint string, data []byte) error {
// Returned statusCode contains the actual HTTP status code, or a special value 0, which designates
// the case when there was an error caused by anything else than HTTP status code > 299.
func (c *Client) SendToRalph(method, endpoint string, data []byte) (statusCode int, err error) {
url := fmt.Sprintf("%s/%s/", c.ralphURL, endpoint)
var err error
var req *http.Request
switch {
case method == "DELETE":
Expand All @@ -74,23 +84,24 @@ func (c *Client) SendToRalph(method, endpoint string, data []byte) error {
req.Header.Set("Content-Type", "application/json")
}
if err != nil {
return err
return 0, err
}

resp, err := c.client.Do(req)
if err != nil {
return err
return 0, err
}
defer resp.Body.Close()
if resp.StatusCode > 299 {
body, err := readBody(resp)
if err != nil {
return err
return 0, err
}
return fmt.Errorf("error while sending to %s with %s method: %s (%s)",
err = fmt.Errorf("error while sending to %s with %s method: %s (%s)",
url, method, body, resp.Status)
return resp.StatusCode, err
}
return nil
return resp.StatusCode, nil
}

// GetFromRalph sends a GET request on a given endpoint with specified query.
Expand Down
109 changes: 109 additions & 0 deletions client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package main

import (
"net/http"
"strings"
"testing"
"time"

"github.com/juju/testing/checkers"
)

func TestNewClient(t *testing.T) {
var cases = map[string]struct {
scannedAddr Addr
ralphURL string
apiKey string
errMsg string
want *Client
}{
"#0 All params provided are correct": {
Addr("10.20.30.40"),
"http://localhost:8080/api",
"abcdefghijklmnopqrstuwxyz0123456789ABCDE",
"",
&Client{
"10.20.30.40",
"http://localhost:8080/api",
"abcdefghijklmnopqrstuwxyz0123456789ABCDE",
"", // apiVersion
&http.Client{Timeout: time.Second * 10},
},
},
"#1 Missing API key": {
Addr("10.20.30.40"),
"http://localhost:8080/api",
"",
"API key is missing",
nil,
},
"#2 Missing Ralph URL": {
Addr("10.20.30.40"),
"",
"abcdefghijklmnopqrstuwxyz0123456789ABCDE",
"Ralph's URL is missing",
nil,
},
}
for tn, tc := range cases {
got, err := NewClient(tc.ralphURL, tc.apiKey, tc.scannedAddr, nil)
switch {
case tc.errMsg != "":
if err == nil || !strings.Contains(err.Error(), tc.errMsg) {
t.Errorf("%s\ndidn't get expected string: %q in err msg: %q", tn, tc.errMsg, err)
}
default:
if err != nil {
t.Fatalf("err: %s", err)
}
if eq, err := checkers.DeepEqual(got, tc.want); !eq {
t.Errorf("%s\n%s", tn, err)
}
}
}
}

func TestSendToRalph(t *testing.T) {
var cases = map[string]struct {
method string
endpoint string
data []byte
statusCode int
errMsg string
want int
}{
"#0 Ralph responds with >299": {
"POST",
"non-existing-endpoint",
[]byte{},
404,
"error while sending to",
404,
},
// Other cases are covered in TestSendDiffToRalph
}

for tn, tc := range cases {
server, client := MockServerClient(tc.statusCode, `{}`)
defer server.Close()

got, err := client.SendToRalph(tc.method, tc.endpoint, tc.data)
switch {
case tc.errMsg != "":
if err == nil || !strings.Contains(err.Error(), tc.errMsg) {
t.Errorf("%s\ndidn't get expected string: %q in err msg: %q", tn, tc.errMsg, err)
}
if got != tc.want {
t.Errorf("%s\n got: %v\nwant: %v", tn, got, tc.want)
}
default:
if err != nil {
t.Fatalf("err: %s", err)
}
if got != tc.want {
t.Errorf("%s\n got: %v\nwant: %v", tn, got, tc.want)
}
}
}

}
36 changes: 21 additions & 15 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,34 @@ type Config struct {
// List of scripts that are bundled with ralph-cli (at this moment, only idrac.py).
var bundledScripts = []string{"idrac.py"}

// GetCfgDirLocation gets path to current user's home dir and appends ".ralph-cli" to it.
func GetCfgDirLocation() (string, error) {
user, err := user.Current()
if err != nil {
return "", err
// GetCfgDirLocation gets path to current user's home dir and appends ".ralph-cli" to it,
// if baseDir is an empty string, otherwise appends ".ralph-cli" to baseDir path (the former
// case is meant mostly for facilitation of testing).
func GetCfgDirLocation(baseDir string) (string, error) {
switch {
case baseDir == "":
user, err := user.Current()
if err != nil {
return "", err
}
baseDir = user.HomeDir
default:
if _, err := os.Stat(baseDir); err != nil {
return "", err
}
}
return filepath.Join(user.HomeDir, ".ralph-cli"), nil
return filepath.Join(baseDir, ".ralph-cli"), nil
}

// PrepareCfgDir creates ~/.ralph-cli dir with its subdirs and copies bundled
// scripts to "scripts" dir.
func PrepareCfgDir() error {
// PrepareCfgDir creates config dir given as cfgDir (for most cases it will be ~/.ralph-cli)
// along with its subdirs, and copies bundled scripts to the "scripts" subdir.
func PrepareCfgDir(cfgDir string) error {
var err error
loc, err := GetCfgDirLocation()
if err != nil {
return err
}
err = createCfgDir(loc)
err = createCfgDir(cfgDir)
if err != nil {
return err
}
var scriptsDir = filepath.Join(loc, "scripts")
var scriptsDir = filepath.Join(cfgDir, "scripts")
// Copy bundled scripts.
for _, script := range bundledScripts {
if _, err := os.Stat(filepath.Join(scriptsDir, script)); os.IsNotExist(err) {
Expand Down
11 changes: 0 additions & 11 deletions dummy_test.go

This file was deleted.

14 changes: 12 additions & 2 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions glide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,9 @@ import:
- package: github.com/labstack/gommon
subpackages:
- log
- package: github.com/juju/testing
subpackages:
- checkers
- package: github.com/juju/loggo
- package: gopkg.in/check.v1
- package: gopkg.in/yaml.v2
Loading

0 comments on commit 734256d

Please sign in to comment.