Skip to content
This repository has been archived by the owner on Oct 7, 2021. It is now read-only.

Move to Native Testlets #80

Merged
merged 124 commits into from
Sep 26, 2016
Merged
Show file tree
Hide file tree
Changes from 123 commits
Commits
Show all changes
124 commits
Select commit Hold shift + click to select a range
89cc89f
updated testlet doc
Mierdin Jul 16, 2016
573f2b4
Added testlet interface
Mierdin Jul 16, 2016
0a9d723
Simplified error returns for client (#45)
Mierdin Jul 16, 2016
2e1cbc3
Merge branch 'master' of github.com:Mierdin/todd
Mierdin Jul 19, 2016
ebf0001
Saving progress on building native testlet infrastructure
Mierdin Jul 19, 2016
5742306
Docs update
Mierdin Jul 19, 2016
726bc83
Made progress on a native testlet implementation
Mierdin Jul 28, 2016
2f389b6
Implement async handling of testlet running
Mierdin Jul 29, 2016
91ce8ed
Further progress
Mierdin Jul 31, 2016
f023d31
Catch-up commit
Mierdin Aug 2, 2016
8b6d304
Updating docs
Mierdin Aug 15, 2016
412423a
Updates to vagrant and make
Mierdin Aug 19, 2016
7909ab4
Catch up
Mierdin Aug 19, 2016
aec7dd2
Got native testlets working
Mierdin Aug 19, 2016
c09854c
Catch up
Mierdin Aug 23, 2016
0e652b6
Added note about future development efforts around testlets
Mierdin Aug 23, 2016
7b0f02d
Some fixes from reviewing the PR
Mierdin Aug 23, 2016
6875683
Update IP field in DB and TSDB config section to Host (#78)
vcabbage Aug 23, 2016
9a42484
Add comment for 'make start' and increase sleep timers for container …
Mierdin Aug 23, 2016
3e10090
Moved testlets outside to the testing package
Mierdin Aug 24, 2016
f4041cc
Updated testlets.go
Mierdin Sep 18, 2016
69e7caf
Merge branch 'native-testlets' of github.com:Mierdin/todd into native…
Mierdin Sep 18, 2016
588b237
Various moves
Mierdin Sep 19, 2016
eec275f
removed all old work from testlets (moved to archive)
Mierdin Sep 20, 2016
f4734f1
Reorganized testing logic
Mierdin Sep 20, 2016
7cae0cf
updated comment regarding future development script
Mierdin Sep 20, 2016
880e07b
removed sudo from sysctl command in makefile
Mierdin Sep 20, 2016
8c4b981
Updates to makefile and vagrantfile
Mierdin Sep 21, 2016
5f1c30b
Added script to add socket capabilities to testlet binaries on install
Mierdin Sep 22, 2016
14d9929
Made capabilities script exec
Mierdin Sep 22, 2016
7408315
Added some comments about install process
Mierdin Sep 22, 2016
4045257
Saving progress on building native testlet infrastructure
Mierdin Jul 19, 2016
967ed0d
Docs update
Mierdin Jul 19, 2016
b2acddd
Made progress on a native testlet implementation
Mierdin Jul 28, 2016
5a3401f
Implement async handling of testlet running
Mierdin Jul 29, 2016
7ee3fd6
Further progress
Mierdin Jul 31, 2016
62ba6c0
Catch-up commit
Mierdin Aug 2, 2016
7ac7dca
Updating docs
Mierdin Aug 15, 2016
02bd94e
Updates to vagrant and make
Mierdin Aug 19, 2016
0a229bd
Catch up
Mierdin Aug 19, 2016
4929bec
Got native testlets working
Mierdin Aug 19, 2016
19f2de9
Catch up
Mierdin Aug 23, 2016
99c2533
Added note about future development efforts around testlets
Mierdin Aug 23, 2016
4c0d0ce
Some fixes from reviewing the PR
Mierdin Aug 23, 2016
5056f30
Moved testlets outside to the testing package
Mierdin Aug 24, 2016
7adfee1
Updated testlets.go
Mierdin Sep 18, 2016
287aa03
Various moves
Mierdin Sep 19, 2016
7c67377
removed all old work from testlets (moved to archive)
Mierdin Sep 20, 2016
3d96d8a
Reorganized testing logic
Mierdin Sep 20, 2016
6cb591c
updated comment regarding future development script
Mierdin Sep 20, 2016
9d8e7ae
removed sudo from sysctl command in makefile
Mierdin Sep 20, 2016
1c83aea
Updates to makefile and vagrantfile
Mierdin Sep 21, 2016
bd0f9f7
Added script to add socket capabilities to testlet binaries on install
Mierdin Sep 22, 2016
ca56642
Made capabilities script exec
Mierdin Sep 22, 2016
89081e8
Added some comments about install process
Mierdin Sep 22, 2016
823d0cc
Merge branch 'native-testlets' of github.com:Mierdin/todd into native…
Mierdin Sep 22, 2016
2f2f2a3
Removed extra crap from rebase
Mierdin Sep 22, 2016
7235411
Moved capabilities script to 'compile'
Mierdin Sep 22, 2016
5e2dc41
Removed old sysctl command from Makefile
Mierdin Sep 23, 2016
83de4a0
Added comment about folder redir to Vagrantfile
Mierdin Sep 23, 2016
8e79ee7
Moved capabilities back to 'install', where it's likely to get sudo (…
Mierdin Sep 23, 2016
954fe27
Converted to unbuffered channel, and removed comment about server tes…
Mierdin Sep 23, 2016
9be0b0a
Added URL to issue for scheduled testruns
Mierdin Sep 23, 2016
5aa3288
Removed unnecessary comment block
Mierdin Sep 23, 2016
467b552
Removed duplicate code that checks for native testlets and retrieves …
Mierdin Sep 23, 2016
30a312d
Updated docstring for GetTestletPath
Mierdin Sep 23, 2016
06fb854
Removed roadmap (will be re-added in upcoming docs revamp
Mierdin Sep 23, 2016
1115f6d
Removed old DSL files
Mierdin Sep 23, 2016
a6e5a7d
Used correct loglevel in GetTestletPath
Mierdin Sep 23, 2016
1b91cf9
Add error handling to influxdb TSDB plugin (#79)
vcabbage Sep 23, 2016
79d91f6
Saving progress on building native testlet infrastructure
Mierdin Jul 19, 2016
9ce5844
Docs update
Mierdin Jul 19, 2016
6b6fe19
Made progress on a native testlet implementation
Mierdin Jul 28, 2016
e9f72e8
Implement async handling of testlet running
Mierdin Jul 29, 2016
1e6fdf4
Further progress
Mierdin Jul 31, 2016
e1eda3a
Catch-up commit
Mierdin Aug 2, 2016
9b50b20
Updating docs
Mierdin Aug 15, 2016
1e5f023
Updates to vagrant and make
Mierdin Aug 19, 2016
9e0bddf
Catch up
Mierdin Aug 19, 2016
5c44e3e
Got native testlets working
Mierdin Aug 19, 2016
43f3309
Catch up
Mierdin Aug 23, 2016
ca3352b
Added note about future development efforts around testlets
Mierdin Aug 23, 2016
89ea72a
Some fixes from reviewing the PR
Mierdin Aug 23, 2016
25b64d5
Moved testlets outside to the testing package
Mierdin Aug 24, 2016
e632a04
Updated testlets.go
Mierdin Sep 18, 2016
fdf2571
Various moves
Mierdin Sep 19, 2016
84ea3b7
Reorganized testing logic
Mierdin Sep 20, 2016
b5aeda3
updated comment regarding future development script
Mierdin Sep 20, 2016
37fc165
removed sudo from sysctl command in makefile
Mierdin Sep 20, 2016
e53e916
Updates to makefile and vagrantfile
Mierdin Sep 21, 2016
8ddffcf
Added script to add socket capabilities to testlet binaries on install
Mierdin Sep 22, 2016
376693e
Made capabilities script exec
Mierdin Sep 22, 2016
ecf6784
Added some comments about install process
Mierdin Sep 22, 2016
213cc97
Saving progress on building native testlet infrastructure
Mierdin Jul 19, 2016
0b85873
Docs update
Mierdin Jul 19, 2016
c781b56
Made progress on a native testlet implementation
Mierdin Jul 28, 2016
60925b1
Implement async handling of testlet running
Mierdin Jul 29, 2016
a6b5136
Further progress
Mierdin Jul 31, 2016
94fdc30
Catch-up commit
Mierdin Aug 2, 2016
e837048
Updates to vagrant and make
Mierdin Aug 19, 2016
93aef66
Catch up
Mierdin Aug 19, 2016
15536a6
Got native testlets working
Mierdin Aug 19, 2016
eb8a3c3
Catch up
Mierdin Aug 23, 2016
2c87bf3
Moved testlets outside to the testing package
Mierdin Aug 24, 2016
ba132d8
Updated testlets.go
Mierdin Sep 18, 2016
4e6a2ff
Various moves
Mierdin Sep 19, 2016
ecab915
removed all old work from testlets (moved to archive)
Mierdin Sep 20, 2016
5db5c0d
Reorganized testing logic
Mierdin Sep 20, 2016
318a560
removed sudo from sysctl command in makefile
Mierdin Sep 20, 2016
66f43cf
Made capabilities script exec
Mierdin Sep 22, 2016
a91ccfa
Added some comments about install process
Mierdin Sep 22, 2016
9a5a09b
Removed extra crap from rebase
Mierdin Sep 22, 2016
a04a6c9
Moved capabilities script to 'compile'
Mierdin Sep 22, 2016
4163110
Removed old sysctl command from Makefile
Mierdin Sep 23, 2016
cf5da33
Added comment about folder redir to Vagrantfile
Mierdin Sep 23, 2016
5a97598
Removed unnecessary comment block
Mierdin Sep 23, 2016
118c9b5
Removed duplicate code that checks for native testlets and retrieves …
Mierdin Sep 23, 2016
579b7b2
Updated docstring for GetTestletPath
Mierdin Sep 23, 2016
4b63c09
Removed roadmap (will be re-added in upcoming docs revamp
Mierdin Sep 23, 2016
6776423
Removed old DSL files
Mierdin Sep 23, 2016
4905176
Used correct loglevel in GetTestletPath
Mierdin Sep 23, 2016
1fa262b
Merge branch 'native-testlets' of github.com:Mierdin/todd into native…
Mierdin Sep 23, 2016
0b13b92
Incorporated changes suggested in review
Mierdin Sep 24, 2016
6f1db24
Made error handling for testlet not existing more generic
Mierdin Sep 26, 2016
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ docs/_build/
preso_secret/
client/repeattest.sh
*.out
*.DS_Store*
*.DS_Store*
agent/testing/downloaded_testlets/
19 changes: 15 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ build:
docker build -t mierdin/todd -f Dockerfile .

compile:
go install ./cmd/...

install: configureenv
# Installing testlets
./scripts/gettestlets.sh

# Installing ToDD
go install ./cmd/...

fmt:
go fmt github.com/mierdin/todd/...
Expand All @@ -27,12 +30,20 @@ update_deps:

update_assets:
go get -u github.com/jteeuwen/go-bindata/...
go-bindata -o assets/assets_unpack.go -pkg="assets" -prefix="agent" agent/testing/testlets/... agent/facts/collectors/...
go-bindata -o assets/assets_unpack.go -pkg="assets" -prefix="agent" agent/testing/bashtestlets/... agent/facts/collectors/...

start: compile

# This mode is just to get a demo of ToDD running within the VM quickly.
# It made sense to re-use the configurations for integration testing, so
# that's why "server-int.cfg" and "agent-int.cfg" are being used here.
start-containers.sh 3 /etc/todd/server-int.cfg /etc/todd/agent-int.cfg

configureenv:
install:

# Set capabilities on testlets
./scripts/set-testlet-capabilities.sh

# Copy configs if etc and /etc/todd aren't linked
if ! [ "etc" -ef "/etc/todd" ]; then mkdir -p /etc/todd && cp -f ./etc/{agent,server}.cfg /etc/todd/; fi
mkdir -p /opt/todd/{agent,server}/assets/{factcollectors,testlets}
Expand Down
5 changes: 4 additions & 1 deletion Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box_url = "http://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box"
config.vm.synced_folder '.', '/home/vagrant/go/src/github.com/Mierdin/todd', nfs: true

# This is a temporary measure. Once https://github.com/Mierdin/todd/issues/72 is addressed, we can go back
# to a single folder being redirected (namely toddproject). For now, since ToDD is still in "Mierdin",
# we need to do it this way.
config.vm.synced_folder '../../toddproject/todd-nativetestlet-ping', '/home/vagrant/go/src/github.com/toddproject/todd-nativetestlet-ping', nfs: true

config.vm.provider "virtualbox" do |v|
v.memory = 2048
v.cpus = 2
end


config.vm.define "todddev" do |todddev|

todddev.vm.host_name = "todddev"
Expand Down
51 changes: 27 additions & 24 deletions agent/tasks/executetestrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"bytes"
"encoding/json"
"errors"
"fmt"
"os"
"os/exec"
"sync"
Expand All @@ -21,6 +20,7 @@ import (
log "github.com/Sirupsen/logrus"

"github.com/Mierdin/todd/agent/cache"
"github.com/Mierdin/todd/agent/testing"
"github.com/Mierdin/todd/config"
)

Expand All @@ -37,9 +37,19 @@ type ExecuteTestRunTask struct {
// a testrun will be executed once per target, all in parallel.
func (ett ExecuteTestRunTask) Run() error {

// gatheredData represents test data from this agent for all targets.
// Key is target name, value is JSON output from testlet for that target
// This is reset to a blank map every time ExecuteTestRunTask is called
gatheredData := map[string]string{}

// Use a wait group to ensure that all of the testlets have a chance to finish
var wg sync.WaitGroup

// Waiting three seconds to ensure all the agents have their tasks before we potentially hammer the network
// TODO(mierdin): This is a bit of a copout. I would like to do something a little more robust than simply waiting
// for a few seconds in the future.
//
// TODO(mierdin): This is a temporary measure - in the future, testruns will be executed via time schedule,
// making not only this sleep, but also the entire task unnecessary. Testruns will simply be installed, and
// executed when the time is right. This is, in part tracked by https://github.com/Mierdin/todd/issues/89
time.Sleep(3000 * time.Millisecond)

// Retrieve test from cache by UUID
Expand All @@ -50,43 +60,37 @@ func (ett ExecuteTestRunTask) Run() error {
return errors.New("Problem retrieving testrun from agent cache")
}

// Generate path to testlet and make sure it exists.
testlet_path := fmt.Sprintf("%s/assets/testlets/%s", ett.Config.LocalResources.OptDir, tr.Testlet)
if _, err := os.Stat(testlet_path); os.IsNotExist(err) {
log.Errorf("Testlet %s does not exist on this agent", tr.Testlet)
return errors.New("Error executing testrun - testlet doesn't exist on this agent.")
}

log.Debugf("IMMA FIRIN MAH LAZER (for test %s) ", ett.TestUuid)

// Use a wait group to ensure that all of the testlets have a chance to finish
var wg sync.WaitGroup
// Specify size of wait group equal to number of targets
wg.Add(len(tr.Targets))

// gatheredData represents test data from this agent for all targets.
// Key is target name, value is JSON output from testlet for that target
gatheredData := make(map[string]string)
testletPath, err := testing.GetTestletPath(tr.Testlet, ett.Config.LocalResources.OptDir)
if err != nil {
return err
}

// Execute testlets against all targets asynchronously
for i := range tr.Targets {

thisTarget := tr.Targets[i]

go func() {

defer wg.Done()

log.Debugf("Full testlet command and args: '%s %s %s'", testlet_path, thisTarget, tr.Args)
cmd := exec.Command(testlet_path, thisTarget, tr.Args)
log.Debugf("Full testlet command and args: '%s %s %s'", testletPath, thisTarget, tr.Args)
cmd := exec.Command(testletPath, thisTarget, tr.Args)
Copy link
Member

Choose a reason for hiding this comment

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

General note, this could be changed to use exec.CommandContext (added in 1.7) and simplify the timeout logic below.

ctx, cancel := context.WithTimeout(context.Background(), time.Duration(ett.TimeLimit) * time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, testletPath, thisTarget, tr.Args)

Copy link
Member Author

Choose a reason for hiding this comment

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

I created https://github.com/Mierdin/todd/issues/93 to track this so that when I move CI to Go 1.7, I'll add this. Thanks


// Stdout buffer
cmdOutput := &bytes.Buffer{}
// Attach buffer to command
cmd.Stdout = cmdOutput

// Execute collector
// Execute testlet
cmd.Start()

done := make(chan error, 1)
done := make(chan error)
go func() {
done <- cmd.Wait()
}()
Expand All @@ -97,22 +101,21 @@ func (ett ExecuteTestRunTask) Run() error {
select {
case <-time.After(time.Duration(ett.TimeLimit) * time.Second):
if err := cmd.Process.Kill(); err != nil {
log.Errorf("Failed to kill %s after timeout: %s", testlet_path, err)
log.Errorf("Failed to kill %s after timeout: %s", testletPath, err)
} else {
log.Debug("Successfully killed ", testlet_path)
log.Debug("Successfully killed ", testletPath)
}
case err := <-done:
if err != nil {
log.Errorf("Testlet %s completed with error '%s'", testlet_path, err)
log.Errorf("Testlet %s completed with error '%s'", testletPath, err)
gatheredData[thisTarget] = "error"
} else {
log.Debugf("Testlet %s completed without error", testlet_path)
log.Debugf("Testlet %s completed without error", testletPath)
}
}

// Record test data
gatheredData[thisTarget] = string(cmdOutput.Bytes())

}()
}

Expand Down
20 changes: 9 additions & 11 deletions agent/tasks/installtestrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,14 @@ package tasks
import (
"bytes"
"errors"
"fmt"
"os"
"os/exec"
"strings"

log "github.com/Sirupsen/logrus"

"github.com/Mierdin/todd/agent/cache"
"github.com/Mierdin/todd/agent/defs"
"github.com/Mierdin/todd/agent/testing"
"github.com/Mierdin/todd/config"
)

Expand All @@ -42,16 +41,15 @@ func (itt InstallTestRunTask) Run() error {
return errors.New("Testlet parameter for this testrun is null")
}

// Generate path to testlet and make sure it exists.
testlet_path := fmt.Sprintf("%s/assets/testlets/%s", itt.Config.LocalResources.OptDir, itt.Tr.Testlet)
if _, err := os.Stat(testlet_path); os.IsNotExist(err) {
log.Errorf("Testlet %s does not exist on this agent", itt.Tr.Testlet)
return errors.New("Error installing testrun - testlet doesn't exist on this agent.")
// Determine if this is a native testlet
testletPath, err := testing.GetTestletPath(itt.Tr.Testlet, itt.Config.LocalResources.OptDir)
if err != nil {
return err
}

// Run the testlet in check mode to verify that everything is okay to run this test
log.Debug("Running testlet in check mode: ", testlet_path)
cmd := exec.Command(testlet_path, "check")
log.Debug("Running testlet in check mode: ", testletPath)
cmd := exec.Command(testletPath, "check")

// Stdout buffer
cmdOutput := &bytes.Buffer{}
Expand All @@ -62,15 +60,15 @@ func (itt InstallTestRunTask) Run() error {

// This is probably the best cross-platform way to see if check mode passed.
if strings.Contains(string(cmdOutput.Bytes()), "Check mode PASSED") {
log.Debugf("Check mode for %s passed", testlet_path)
log.Debugf("Check mode for %s passed", testletPath)
} else {
log.Error("Testlet returned an error during check mode: ", string(cmdOutput.Bytes()))
return errors.New("Testlet returned an error during check mode")
}

// Insert testrun into agent cache
var ac = cache.NewAgentCache(itt.Config)
err := ac.InsertTestRun(itt.Tr)
err = ac.InsertTestRun(itt.Tr)
if err != nil {
log.Error(err)
return errors.New("Problem installing test run into agent cache")
Expand Down
68 changes: 0 additions & 68 deletions agent/testing/reporting.go

This file was deleted.

67 changes: 67 additions & 0 deletions agent/testing/testing.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
ToDD testing package

Contains infrastructure running testlets as well as maintaining
conformance for other native-Go testlet projects

Copyright 2016 Matt Oswalt. Use or modification of this
source code is governed by the license provided here:
https://github.com/Mierdin/todd/blob/master/LICENSE
*/

package testing

import (
"errors"
"fmt"
"os"

log "github.com/Sirupsen/logrus"
)

var (

// This map provides name redirection so that the native testlets can use names that don't
// conflict with existing system tools (i.e. using "toddping" instead of "ping") but users
// can still refer to the testlets using simple names.
//
// In short, users refer to the testlet by <key> and this map will redirect to the
// actual binary name <value>
nativeTestlets = map[string]string{
"ping": "toddping",
}
)

// Testlet defines what a testlet should look like if built in native
// go and compiled with the agent
type Testlet interface {

// Run is the "workflow" function for a testlet. All testing takes place here
// (or in a function called within)
Run(target string, args []string, timeLimit int) (metrics map[string]string, err error)
}
Copy link
Member

Choose a reason for hiding this comment

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

Having a "Base*" struct seems like an attempt to use inheritance. What does this add beyond the Testlet interface?

Copy link
Member Author

Choose a reason for hiding this comment

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

Nothing, now. This was another relic from the previous approach. Removed in upcoming patch


// GetTestletPath generates whatever path is needed to reach the given testlet
// It first determines if the referenced testlet is native or not - if it is native,
// then only the name needs to be returned (all native testlets must be in the path).
// If it is a custom testlet, then it will generate the full path to the testlet,
// ensure it is a valid path, and if so, return that full path back to the caller.
func GetTestletPath(testletName, optDir string) (string, error) {

if _, ok := nativeTestlets[testletName]; ok {
log.Debugf("%s is a native testlet", testletName)
return nativeTestlets[testletName], nil
}

log.Debugf("%s is a custom testlet", testletName)

// Generate path to testlet and make sure it exists.
testletPath := fmt.Sprintf("%s/assets/testlets/%s", optDir, testletName)
if _, err := os.Stat(testletPath); err != nil || os.IsNotExist(err) {
Copy link
Member

Choose a reason for hiding this comment

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

os.IsNotExist(err) will only be evaluated if err is nil, in which case os.IsNotExist will always return false.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, my intention was that regardless of the error, I wanted to treat it like the testlet didn't exist. However, that's fairly confusing.

I clarified this a bit by making the error more generic (and removing os.IsNotExist(err) in Mierdin@6f1db24 - stating in the error that there was simply a problem accessing the testlet

log.Errorf("Testlet %q does not exist on this agent", testletName)
return "", errors.New("Error installing testrun - testlet doesn't exist on this agent.")
}

return testletPath, nil

}
Loading