├── VERSION ├── script ├── build ├── test ├── coverage ├── lint ├── test-integration └── env ├── vendor ├── github.com │ ├── spf13 │ │ ├── pflag │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ └── LICENSE │ │ └── cobra │ │ │ ├── command_notwin.go │ │ │ ├── .mailmap │ │ │ ├── command_win.go │ │ │ ├── .travis.yml │ │ │ └── .gitignore │ ├── mitchellh │ │ └── mapstructure │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── error.go │ │ │ └── README.md │ ├── olekukonko │ │ └── tablewriter │ │ │ ├── test.csv │ │ │ ├── .travis.yml │ │ │ ├── test_info.csv │ │ │ ├── LICENCE.md │ │ │ └── csv.go │ ├── hashicorp │ │ └── go-multierror │ │ │ ├── .travis.yml │ │ │ ├── flatten.go │ │ │ ├── format.go │ │ │ ├── Makefile │ │ │ ├── prefix.go │ │ │ ├── append.go │ │ │ └── multierror.go │ ├── stretchr │ │ └── testify │ │ │ ├── require │ │ │ ├── require_forward.go.tmpl │ │ │ ├── require.go.tmpl │ │ │ ├── requirements.go │ │ │ ├── forward_requirements.go │ │ │ └── doc.go │ │ │ ├── assert │ │ │ ├── assertion_forward.go.tmpl │ │ │ ├── errors.go │ │ │ ├── forward_assertions.go │ │ │ └── doc.go │ │ │ ├── suite │ │ │ └── interfaces.go │ │ │ └── LICENSE │ ├── mattn │ │ └── go-runewidth │ │ │ ├── runewidth_js.go │ │ │ ├── .travis.yml │ │ │ ├── runewidth_windows.go │ │ │ ├── README.mkd │ │ │ ├── LICENSE │ │ │ └── runewidth_posix.go │ ├── lusis │ │ └── outputter │ │ │ ├── .travis.yml │ │ │ ├── Gopkg.toml │ │ │ ├── errors.go │ │ │ └── output.go │ ├── shurcooL │ │ ├── vfsgen │ │ │ ├── .travis.yml │ │ │ ├── doc.go │ │ │ ├── stringwriter.go │ │ │ ├── CONTRIBUTING.md │ │ │ ├── commentwriter.go │ │ │ ├── LICENSE │ │ │ └── options.go │ │ └── httpfs │ │ │ ├── vfsutil │ │ │ ├── file.go │ │ │ └── vfsutil.go │ │ │ └── LICENSE │ ├── inconshreveable │ │ └── mousetrap │ │ │ ├── trap_others.go │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ └── trap_windows_1.4.go │ ├── davecgh │ │ └── go-spew │ │ │ ├── LICENSE │ │ │ └── spew │ │ │ └── bypasssafe.go │ └── pmezard │ │ └── go-difflib │ │ └── LICENSE ├── gopkg.in │ └── yaml.v2 │ │ ├── .travis.yml │ │ └── LICENSE.libyaml ├── golang.org │ └── x │ │ └── net │ │ ├── AUTHORS │ │ ├── CONTRIBUTORS │ │ ├── PATENTS │ │ └── LICENSE └── modules.txt ├── pkg ├── rundeck │ ├── responses │ │ ├── responder_test.go │ │ ├── testdata │ │ │ ├── failed.json │ │ │ ├── success.json │ │ │ ├── get_authenticated_user_roles.json │ │ │ ├── project_archive_import.json │ │ │ ├── config_item.json │ │ │ ├── project_archive_export_async.json │ │ │ ├── get_project_executions_metrics.json │ │ │ ├── user.json │ │ │ ├── job_option_upload.json │ │ │ ├── list_projects.json │ │ │ ├── error.json │ │ │ ├── project_scm_status_export.json │ │ │ ├── disable_scm_plugin_export.json │ │ │ ├── disable_scm_plugin_import.json │ │ │ ├── enable_scm_plugin_export.json │ │ │ ├── enable_scm_plugin_import.json │ │ │ ├── execution_adhoc.json │ │ │ ├── get_executions_metrics.json │ │ │ ├── get_job_scm_diff_export.json │ │ │ ├── project_scm_status_import.json │ │ │ ├── logstorage.json │ │ │ ├── get_project_scm_status_export.json │ │ │ ├── get_job_scm_status_import.json │ │ │ ├── get_project_scm_status_import.json │ │ │ ├── get_job_scm_action_input_fields_import.json │ │ │ ├── acl.json │ │ │ ├── get_job_scm_status_export.json │ │ │ ├── list_scm_plugins_export.json │ │ │ ├── list_scm_plugins_import.json │ │ │ ├── token.json │ │ │ ├── resource.json │ │ │ ├── key_metadata.json │ │ │ ├── job_metadata.json │ │ │ ├── execution_aborted.json │ │ │ ├── project.aclpolicy │ │ │ ├── job_info.json │ │ │ ├── jobs.json │ │ │ ├── failed_acl_validation.json │ │ │ ├── get_project_scm_action_input_fields_import.json │ │ │ ├── bulk_delete_executions.json │ │ │ ├── bulk_job_delete.json │ │ │ ├── project_archive_import_failed.json │ │ │ ├── upload_job_input_file.json │ │ │ ├── users.json │ │ │ ├── get_job_forecast.json │ │ │ ├── incomplete_logstorage_executions.json │ │ │ ├── execution_output.txt │ │ │ ├── bulk_toggle.json │ │ │ ├── execution_input_files.json │ │ │ ├── get_project_scm_config_export.json │ │ │ ├── get_project_scm_config_import.json │ │ │ ├── uploaded_job_input_files.json │ │ │ ├── foo.aclpolicy │ │ │ ├── job_definition.yaml │ │ │ ├── execution.json │ │ │ ├── tokens.json │ │ │ ├── imported_job.json │ │ │ ├── executions.json │ │ │ ├── get_job_scm_diff_import.json │ │ │ ├── list_keys.json │ │ │ ├── project_config.json │ │ │ ├── get_job_scm_action_input_fields_export.json │ │ │ ├── project_info.json │ │ │ └── systeminfo.json │ │ ├── job_definition_test.go │ │ ├── paging.go │ │ ├── errors.go │ │ ├── token_test.go │ │ ├── history_test.go │ │ ├── toggle_test.go │ │ ├── systeminfo_test.go │ │ ├── common_test.go │ │ ├── acl_test.go │ │ ├── keys_test.go │ │ ├── logstorage_test.go │ │ ├── user_test.go │ │ ├── versioned_response.go │ │ ├── common.go │ │ ├── helpers_test.go │ │ └── history.go │ ├── response_test.go │ ├── requests │ │ ├── bulk_toggle.go │ │ ├── user.go │ │ ├── token.go │ │ ├── project.go │ │ ├── common.go │ │ ├── job.go │ │ ├── scm.go │ │ ├── common_test.go │ │ └── job_test.go │ ├── version.go │ ├── system_info.go │ ├── helpers_test.go │ ├── system_info_test.go │ ├── history.go │ ├── error.go │ ├── keys.go │ ├── schedule_test.go │ ├── http_test.go │ └── history_test.go └── httpclient │ └── constants.go ├── docker ├── rundeckdb.mv.db ├── token.properties ├── realm.properties ├── gitrepo.sh ├── admin.aclpolicy ├── Dockerfile └── apitoken.aclpolicy ├── .gitignore ├── cmd ├── rundeck │ ├── main.go │ └── cmds │ │ ├── tokens.go │ │ ├── executions.go │ │ ├── http.go │ │ ├── token.go │ │ ├── jobs.go │ │ ├── log_storage.go │ │ ├── execution.go │ │ ├── job.go │ │ ├── policies.go │ │ ├── delete_job.go │ │ ├── delete_token.go │ │ ├── delete_project.go │ │ ├── scm.go │ │ ├── list.go │ │ ├── delete_system_acl_policy.go │ │ ├── resume_logstorage.go │ │ ├── delete_execution.go │ │ ├── helpers.go │ │ ├── root.go │ │ ├── export_job.go │ │ ├── get_system_acl_policy.go │ │ ├── helpers_test.go │ │ ├── get_execution_output.go │ │ ├── list_projects.go │ │ ├── list_jobs.go │ │ ├── get_project_config.go │ │ ├── get_job_opts.go │ │ ├── adhoc.go │ │ ├── list_users.go │ │ ├── delete_project_acl_policy.go │ │ ├── list_system_acl_policies.go │ │ ├── get_project.go │ │ ├── get_project_acl_policy.go │ │ ├── create_token.go │ │ ├── project.go │ │ ├── list_project_acl_policies.go │ │ ├── scm_setup.go │ │ ├── history.go │ │ ├── find_job_by_name.go │ │ ├── scm_enable_disable.go │ │ ├── toggle_execution.go │ │ ├── get_job.go │ │ ├── scm_list_plugins.go │ │ ├── get_execution.go │ │ ├── create_project.go │ │ ├── bulk_delete_executions.go │ │ ├── get_tokens.go │ │ ├── tail_execution_output.go │ │ ├── http_get.go │ │ └── scm_input_fields.go └── maketestdata │ └── main.go ├── TODO.md ├── .golangci.yml ├── LICENSE ├── Makefile ├── go.mod ├── .circleci └── config.yml └── RELEASENOTES.md /VERSION: -------------------------------------------------------------------------------- 1 | 20190430 2 | -------------------------------------------------------------------------------- /script/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | go build ./... 4 | -------------------------------------------------------------------------------- /vendor/github.com/spf13/pflag/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | 3 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/responder_test.go: -------------------------------------------------------------------------------- 1 | package responses 2 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/failed.json: -------------------------------------------------------------------------------- 1 | {"success":false} 2 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/success.json: -------------------------------------------------------------------------------- 1 | {"success":true} 2 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/get_authenticated_user_roles.json: -------------------------------------------------------------------------------- 1 | {"roles":["admin"]} 2 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/project_archive_import.json: -------------------------------------------------------------------------------- 1 | {"import_status":"successful"} -------------------------------------------------------------------------------- /docker/rundeckdb.mv.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lusis/go-rundeck/HEAD/docker/rundeckdb.mv.db -------------------------------------------------------------------------------- /docker/token.properties: -------------------------------------------------------------------------------- 1 | admin: yays72hw87aK2AfxWifTSdcMcY81GL1p,admin 2 | auser: jHpBIeJRkfVHfWlmiPRxXH2GSk2DF3wy,user 3 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/config_item.json: -------------------------------------------------------------------------------- 1 | { 2 | "key": "project.ssh-connect-timeout", 3 | "value": "0" 4 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env.local 2 | xmlfiles/ 3 | bin/ 4 | debug.test 5 | debug 6 | .vscode 7 | # I develop on windows sometimes yall 8 | *.exe -------------------------------------------------------------------------------- /vendor/github.com/mitchellh/mapstructure/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.8.1 5 | 6 | script: 7 | - go test 8 | -------------------------------------------------------------------------------- /vendor/github.com/spf13/cobra/command_notwin.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package cobra 4 | 5 | var preExecHookFn func(*Command) 6 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/project_archive_export_async.json: -------------------------------------------------------------------------------- 1 | { 2 | "token":"[TOKEN]", 3 | "ready":false, 4 | "percentage":75 5 | } -------------------------------------------------------------------------------- /vendor/github.com/olekukonko/tablewriter/test.csv: -------------------------------------------------------------------------------- 1 | first_name,last_name,ssn 2 | John,Barry,123456 3 | Kathy,Smith,687987 4 | Bob,McCornick,3979870 -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/get_project_executions_metrics.json: -------------------------------------------------------------------------------- 1 | {"duration":{"average":"0s","min":"0s","max":"0s"},"total":1,"status":{"failed":1}} 2 | -------------------------------------------------------------------------------- /script/test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -Eeuo pipefail 3 | # shellcheck disable=SC1091 4 | source script/env 5 | 6 | go test -short --race -v ./... 7 | 8 | 9 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/user.json: -------------------------------------------------------------------------------- 1 | { 2 | "login":"admin", 3 | "firstName":"Admin", 4 | "lastName":"McAdmin", 5 | "email":"admin@server.com" 6 | } -------------------------------------------------------------------------------- /script/coverage: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -Eeuo pipefail 3 | 4 | CI=${CI:-''} 5 | [ -n "$CI" ] && go get github.com/axw/gocov/gocov 6 | 7 | gocov test ./... | gocov report -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/job_option_upload.json: -------------------------------------------------------------------------------- 1 | { 2 | "total": 1, 3 | "options": { 4 | "myfile": "bb704988-6467-4613-b961-13014f6a55cb" 5 | } 6 | } -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.4 5 | - 1.5 6 | - 1.6 7 | - tip 8 | 9 | go_import_path: gopkg.in/yaml.v2 10 | -------------------------------------------------------------------------------- /cmd/rundeck/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/lusis/go-rundeck/cmd/rundeck/cmds" 5 | ) 6 | 7 | func main() { 8 | cmds.RootCommand() 9 | } 10 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/list_projects.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "url": "[API Href]", 4 | "name": "testproject", 5 | "description": "test project" 6 | } 7 | ] -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": true, 3 | "apiversion": 14, 4 | "errorCode": "api.error.api-version.unsupported", 5 | "message": "something blew up" 6 | } 7 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | - Build a test suite that actually launches rundeck for testing. A previous commit passed tests but failed real-world due to a bug in the setting of the `Accept` header. 2 | - Pagination 3 | -------------------------------------------------------------------------------- /vendor/github.com/olekukonko/tablewriter/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.1 5 | - 1.2 6 | - 1.3 7 | - 1.4 8 | - 1.5 9 | - 1.6 10 | - 1.7 11 | - 1.8 12 | - tip 13 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/project_scm_status_export.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": null, 3 | "integration": "export", 4 | "message": null, 5 | "project": "testproject", 6 | "synchState": "CLEAN" 7 | } 8 | -------------------------------------------------------------------------------- /vendor/github.com/hashicorp/go-multierror/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: go 4 | 5 | go: 6 | - 1.x 7 | 8 | branches: 9 | only: 10 | - master 11 | 12 | script: make test testrace 13 | -------------------------------------------------------------------------------- /vendor/github.com/olekukonko/tablewriter/test_info.csv: -------------------------------------------------------------------------------- 1 | Field,Type,Null,Key,Default,Extra 2 | user_id,smallint(5),NO,PRI,NULL,auto_increment 3 | username,varchar(10),NO,,NULL, 4 | password,varchar(100),NO,,NULL, -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/require/require_forward.go.tmpl: -------------------------------------------------------------------------------- 1 | {{.CommentWithoutT "a"}} 2 | func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) { 3 | {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) 4 | } 5 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/disable_scm_plugin_export.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "Plugin disabled for SCM export: git-export", 3 | "nextAction": null, 4 | "success": true, 5 | "validationErrors": null 6 | } 7 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/disable_scm_plugin_import.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "Plugin disabled for SCM import: git-import", 3 | "nextAction": null, 4 | "success": true, 5 | "validationErrors": null 6 | } 7 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/enable_scm_plugin_export.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "Plugin enabled for SCM export: git-export", 3 | "nextAction": null, 4 | "success": true, 5 | "validationErrors": null 6 | } 7 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/enable_scm_plugin_import.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "Plugin enabled for SCM import: git-import", 3 | "nextAction": null, 4 | "success": true, 5 | "validationErrors": null 6 | } 7 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/AUTHORS: -------------------------------------------------------------------------------- 1 | # This source code refers to The Go Authors for copyright purposes. 2 | # The master list of authors is in the main Go distribution, 3 | # visible at http://tip.golang.org/AUTHORS. 4 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This source code was written by the Go contributors. 2 | # The master list of contributors is in the main Go distribution, 3 | # visible at http://tip.golang.org/CONTRIBUTORS. 4 | -------------------------------------------------------------------------------- /pkg/rundeck/response_test.go: -------------------------------------------------------------------------------- 1 | package rundeck 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestErrorMessage(t *testing.T) { 8 | 9 | } 10 | 11 | func TestSuccessMessage(t *testing.T) { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /vendor/github.com/spf13/cobra/.mailmap: -------------------------------------------------------------------------------- 1 | Steve Francia 2 | Bjørn Erik Pedersen 3 | Fabiano Franz 4 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl: -------------------------------------------------------------------------------- 1 | {{.CommentWithoutT "a"}} 2 | func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool { 3 | return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) 4 | } 5 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/require/require.go.tmpl: -------------------------------------------------------------------------------- 1 | {{.Comment}} 2 | func {{.DocInfo.Name}}(t TestingT, {{.Params}}) { 3 | if !assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { 4 | t.FailNow() 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/execution_adhoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "Immediate execution scheduled (X)", 3 | "execution": { 4 | "id": 1, 5 | "href": "[API Href]", 6 | "permalink": "[GUI Href]" 7 | } 8 | } -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/get_executions_metrics.json: -------------------------------------------------------------------------------- 1 | {"duration":{ 2 | "average":"10s", 3 | "min":"0s", 4 | "max":"20s" 5 | }, 6 | "total":2, 7 | "status":{ 8 | "failed":2 9 | } 10 | } -------------------------------------------------------------------------------- /docker/realm.properties: -------------------------------------------------------------------------------- 1 | admin:admin,user,admin,architect,deploy,build 2 | auser:apassword,user 3 | #@jetty.user.deploy.name@:@jetty.user.deploy.password@,user,deploy 4 | #@jetty.user.build.name@:@jetty.user.build.password@,user,build 5 | 6 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/runewidth_js.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | 3 | package runewidth 4 | 5 | func IsEastAsian() bool { 6 | // TODO: Implement this for the web. Detect east asian in a compatible way, and return true. 7 | return false 8 | } 9 | -------------------------------------------------------------------------------- /pkg/rundeck/requests/bulk_toggle.go: -------------------------------------------------------------------------------- 1 | package requests 2 | 3 | // BulkToggleRequest represents a bulk toggle request body 4 | type BulkToggleRequest struct { 5 | IDs []string `json:"ids,omitempty"` 6 | IDList string `json:"idlist,omitempty"` 7 | } 8 | -------------------------------------------------------------------------------- /vendor/github.com/lusis/outputter/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.7.x 5 | - 1.8.x 6 | - 1.9.x 7 | - tip 8 | 9 | install: 10 | - echo "true" 11 | 12 | script: 13 | - script/lint 14 | - script/coverage 15 | - script/test -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/get_job_scm_diff_export.json: -------------------------------------------------------------------------------- 1 | { 2 | "commit": null, 3 | "diffContent": null, 4 | "id": "d1b9f2c1-d6a6-43ca-8e9f-85519d5a1323", 5 | "incomingCommit": null, 6 | "integration": "export", 7 | "project": "testproject" 8 | } 9 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/project_scm_status_import.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [ 3 | "import-all" 4 | ], 5 | "integration": "import", 6 | "message": "1 unimported file(s) found", 7 | "project": "testproject", 8 | "synchState": "IMPORT_NEEDED" 9 | } 10 | -------------------------------------------------------------------------------- /pkg/rundeck/requests/user.go: -------------------------------------------------------------------------------- 1 | package requests 2 | 3 | // UserInfo represents a user info request 4 | type UserInfo struct { 5 | FirstName string `json:"firstName,omitempty"` 6 | LastName string `json:"lastName,omitempty"` 7 | Email string `json:"email,omitempty"` 8 | } 9 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/logstorage.json: -------------------------------------------------------------------------------- 1 | { 2 | "enabled": true, 3 | "pluginName": "NAME", 4 | "succeededCount": 369, 5 | "failedCount": 0, 6 | "queuedCount": 0, 7 | "totalCount": 369, 8 | "incompleteCount": 0, 9 | "missingCount": 0 10 | } -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - tip 4 | before_install: 5 | - go get github.com/mattn/goveralls 6 | - go get golang.org/x/tools/cmd/cover 7 | script: 8 | - $HOME/gopath/bin/goveralls -repotoken lAKAWPzcGsD3A8yBX3BGGtRUdJ6CaGERL 9 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/get_project_scm_status_export.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [ 3 | "project-commit" 4 | ], 5 | "integration": "export", 6 | "message": "Some changes have not been committed", 7 | "project": "testproject", 8 | "synchState": "EXPORT_NEEDED" 9 | } 10 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | tests: false 3 | skip-dirs: 4 | - src 5 | - pkg/rundeck.v19 6 | linters: 7 | disable-all: true 8 | enable: 9 | - deadcode 10 | - errcheck 11 | - goconst 12 | - goimports 13 | - golint 14 | - gosimple 15 | - govet 16 | - ineffassign 17 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/tokens.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import "github.com/spf13/cobra" 4 | 5 | func tokensCommands() *cobra.Command { 6 | cmd := &cobra.Command{ 7 | Use: "tokens", 8 | Short: "operate on rundeck api tokens", 9 | } 10 | cmd.AddCommand(getTokensCommand()) 11 | return cmd 12 | } 13 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/get_job_scm_status_import.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [], 3 | "commit": null, 4 | "id": "6c66133e-03ed-48e3-aaa2-d2a646a4e47f", 5 | "integration": "import", 6 | "message": "Import Status: Not Tracked", 7 | "project": "testproject", 8 | "synchState": "UNKNOWN" 9 | } 10 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/get_project_scm_status_import.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [ 3 | "import-all" 4 | ], 5 | "integration": "import", 6 | "message": "1 unimported file(s) found, 1 tracked file(s) were deleted", 7 | "project": "testproject", 8 | "synchState": "IMPORT_NEEDED" 9 | } 10 | -------------------------------------------------------------------------------- /pkg/rundeck/requests/token.go: -------------------------------------------------------------------------------- 1 | package requests 2 | 3 | // TokenRequest represents a user and token 4 | // http://rundeck.org/docs/api/index.html#get-a-token 5 | type TokenRequest struct { 6 | User string `json:"user"` 7 | Roles string `json:"roles"` 8 | Duration string `json:"duration,omitempty"` 9 | } 10 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/get_job_scm_action_input_fields_import.json: -------------------------------------------------------------------------------- 1 | { 2 | "actionId": "import-all", 3 | "description": "Import the modifications to Rundeck", 4 | "exportItems": null, 5 | "fields": [], 6 | "importItems": [], 7 | "integration": "import", 8 | "title": "Import remote Changes" 9 | } 10 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/acl.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "", 3 | "type": "directory", 4 | "href": "[API Href]", 5 | "resources": [ 6 | { 7 | "path": "name.aclpolicy", 8 | "type": "file", 9 | "name": "name.aclpolicy", 10 | "href": "[API Href]" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/get_job_scm_status_export.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [ 3 | "job-commit" 4 | ], 5 | "commit": null, 6 | "id": "d1b9f2c1-d6a6-43ca-8e9f-85519d5a1323", 7 | "integration": "export", 8 | "message": "Created", 9 | "project": "testproject", 10 | "synchState": "CREATE_NEEDED" 11 | } 12 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/list_scm_plugins_export.json: -------------------------------------------------------------------------------- 1 | { 2 | "integration": "export", 3 | "plugins": [ 4 | { 5 | "configured": true, 6 | "description": "Export Jobs to a Git Repository", 7 | "enabled": true, 8 | "title": "Git Export", 9 | "type": "git-export" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/list_scm_plugins_import.json: -------------------------------------------------------------------------------- 1 | { 2 | "integration": "import", 3 | "plugins": [ 4 | { 5 | "configured": true, 6 | "description": "Import Jobs from a Git Repository", 7 | "enabled": true, 8 | "title": "Git Import", 9 | "type": "git-import" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/token.json: -------------------------------------------------------------------------------- 1 | { 2 | "user": "user3", 3 | "token": "VjkbX2zUAwnXjDIbRYFp824tF5X2N7W1", 4 | "id": "c13de457-c429-4476-9acd-e1c89e3c2928", 5 | "creator": "user3", 6 | "expiration": "2017-03-24T21:18:55Z", 7 | "roles": [ 8 | "USER_ACCOUNT" 9 | ], 10 | "expired": true 11 | } -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/require/requirements.go: -------------------------------------------------------------------------------- 1 | package require 2 | 3 | // TestingT is an interface wrapper around *testing.T 4 | type TestingT interface { 5 | Errorf(format string, args ...interface{}) 6 | FailNow() 7 | } 8 | 9 | //go:generate go run ../_codegen/main.go -output-package=require -template=require.go.tmpl 10 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/executions.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import "github.com/spf13/cobra" 4 | 5 | func executionsCommands() *cobra.Command { 6 | cmd := &cobra.Command{ 7 | Use: "executions", 8 | Short: "operate on rundeck multiple rundeck executions at once", 9 | } 10 | cmd.AddCommand(bulkDeleteExecutionsCommand()) 11 | return cmd 12 | } 13 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/resource.json: -------------------------------------------------------------------------------- 1 | { 2 | "node-0-fake":{ 3 | "nodename":"node-0-fake", 4 | "hostname":"nodehost-fake", 5 | "foo":"bar", 6 | "baz":"qux", 7 | "node-executor":"stub", 8 | "file-copier":"stub", 9 | "username":"nodeuser-fake", 10 | "tags":"stub" 11 | } 12 | } -------------------------------------------------------------------------------- /cmd/rundeck/cmds/http.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | ) 6 | 7 | func httpCommand() *cobra.Command { 8 | cmd := &cobra.Command{ 9 | Use: "http", 10 | Short: "perform authenticated http operations against a rundeck server. kinda like curl", 11 | } 12 | cmd.AddCommand(httpGetCommand()) 13 | return cmd 14 | } 15 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/token.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | ) 6 | 7 | func tokenCommand() *cobra.Command { 8 | cmd := &cobra.Command{ 9 | Use: "token", 10 | Short: "operate on an individual token in rundeck", 11 | } 12 | cmd.AddCommand(createTokenCommand()) 13 | cmd.AddCommand(deleteTokenCommand()) 14 | return cmd 15 | } 16 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/jobs.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import "github.com/spf13/cobra" 4 | 5 | func jobsCommands() *cobra.Command { 6 | cmd := &cobra.Command{ 7 | Use: "jobs", 8 | Short: "operate on rundeck multiple rundeck jobs at once", 9 | } 10 | cmd.AddCommand(bulkToggleExecutionsCommand()) 11 | cmd.AddCommand(bulkToggleScheduleCommand()) 12 | return cmd 13 | } 14 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/log_storage.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import "github.com/spf13/cobra" 4 | 5 | func logStorageCommand() *cobra.Command { 6 | cmd := &cobra.Command{ 7 | Use: "logstorage", 8 | Short: "operate on rundeck logstorage", 9 | } 10 | cmd.AddCommand(getLogStorageCommand()) 11 | cmd.AddCommand(resumeIncompleteLogStorageCommand()) 12 | return cmd 13 | } 14 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/key_metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "meta": { 3 | "Rundeck-key-type": "public", 4 | "Rundeck-content-size": "393", 5 | "Rundeck-content-type": "application/pgp-keys" 6 | }, 7 | "url": "http://dignan.local:4440/api/11/storage/keys/test1.pub", 8 | "name": "test1.pub", 9 | "type": "file", 10 | "path": "keys/test1.pub" 11 | } -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/job_metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "[UUID]", 3 | "name": "[name]", 4 | "group": "[group]", 5 | "project": "[project]", 6 | "description": "...", 7 | "href": "[API url]", 8 | "permalink": "[GUI url]", 9 | "scheduled": false, 10 | "scheduleEnabled": false, 11 | "enabled": true, 12 | "averageDuration": 1431975278220 13 | } -------------------------------------------------------------------------------- /vendor/github.com/spf13/pflag/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: go 4 | 5 | go: 6 | - 1.7.3 7 | - 1.8.1 8 | - tip 9 | 10 | matrix: 11 | allow_failures: 12 | - go: tip 13 | 14 | install: 15 | - go get github.com/golang/lint/golint 16 | - export PATH=$GOPATH/bin:$PATH 17 | - go install ./... 18 | 19 | script: 20 | - verify/all.sh -v 21 | - go test ./... 22 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/execution_aborted.json: -------------------------------------------------------------------------------- 1 | { 2 | "abort": { 3 | "status": "failed", 4 | "reason": "Job is not running" 5 | }, 6 | "execution": { 7 | "id": "565", 8 | "status": "succeeded", 9 | "href": "http://localhost:4440/api/21/execution/565", 10 | "permalink": "http://localhost:4440/project/testproject/execution/show/565" 11 | } 12 | } -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/project.aclpolicy: -------------------------------------------------------------------------------- 1 | 2 | description: auser access 3 | for: 4 | resource: 5 | - allow: '*' # allow read/create all kinds 6 | adhoc: 7 | - allow: '*' # allow read/running/killing adhoc jobs 8 | job: 9 | - allow: '*' # allow read/write/delete/run/kill of all jobs 10 | node: 11 | - allow: '*' # allow read/run for all nodes 12 | by: 13 | username: 'auser' 14 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/errors.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | // AnError is an error instance useful for testing. If the code does not care 8 | // about error specifics, and only needs to return the error for example, this 9 | // error should be used to make the test code more readable. 10 | var AnError = errors.New("assert.AnError general error for testing") 11 | -------------------------------------------------------------------------------- /pkg/rundeck/requests/project.go: -------------------------------------------------------------------------------- 1 | package requests 2 | 3 | // ProjectCreationRequest is the payload for creating a new project 4 | /* 5 | { 6 | "name":"fooproject3", 7 | "config":{ 8 | "somekey":"somevar", 9 | "anotherkey":"anothervar" 10 | } 11 | } 12 | */ 13 | type ProjectCreationRequest struct { 14 | Name string `json:"name"` 15 | Config *map[string]string `json:"config,omitempty"` 16 | } 17 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/job_info.json: -------------------------------------------------------------------------------- 1 | {"id":"d1b9f2c1-d6a6-43ca-8e9f-85519d5a1323","scheduled":false,"href":"http://localhost:4440/api/21/job/d1b9f2c1-d6a6-43ca-8e9f-85519d5a1323","averageDuration":120076,"scheduleEnabled":true,"enabled":true,"permalink":"http://localhost:4440/project/testproject/job/show/d1b9f2c1-d6a6-43ca-8e9f-85519d5a1323","name":"sleep-job","group":"test","description":"sleeps a while","project":"testproject"} -------------------------------------------------------------------------------- /vendor/github.com/spf13/cobra/command_win.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package cobra 4 | 5 | import ( 6 | "os" 7 | "time" 8 | 9 | "github.com/inconshreveable/mousetrap" 10 | ) 11 | 12 | var preExecHookFn = preExecHook 13 | 14 | func preExecHook(c *Command) { 15 | if MousetrapHelpText != "" && mousetrap.StartedByExplorer() { 16 | c.Print(MousetrapHelpText) 17 | time.Sleep(5 * time.Second) 18 | os.Exit(1) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /docker/gitrepo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This sets up some local git repos that can be used with the scm plugins 3 | cd /home 4 | git init --bare rundeck-export.git --shared=group 5 | git init --bare rundeck-import.git --shared=group 6 | cd rundeck-export.git 7 | git config receive.denyCurrentBranch ignore 8 | cd - 9 | cd rundeck-import.git 10 | git config receive.denyCurrentBranch ignore 11 | cd - 12 | chown -R rundeck:rundeck rundeck-*.git 13 | -------------------------------------------------------------------------------- /script/lint: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -Eeuo pipefail 3 | 4 | LINTVER="1.16.0" 5 | LINTCMD="golangci-lint" 6 | 7 | CI=${CI:-''} 8 | if [ -n "${CI}" ]; then 9 | curl -LO https://github.com/golangci/golangci-lint/releases/download/v${LINTVER}/golangci-lint-${LINTVER}-linux-amd64.tar.gz 10 | tar -zxvf golangci-lint-${LINTVER}-linux-amd64.tar.gz 11 | LINTCMD="./golangci-lint-1.16.0-linux-amd64/golangci-lint" 12 | fi 13 | 14 | ${LINTCMD} run -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/jobs.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "[UUID]", 4 | "name": "[name]", 5 | "group": "[group]", 6 | "project": "[project]", 7 | "description": "...", 8 | "href": "[API url]", 9 | "permalink": "[GUI url]", 10 | "scheduled": true, 11 | "scheduleEnabled": false, 12 | "enabled": true, 13 | "serverNodeUUID": "[UUID]", 14 | "serverOwned": true 15 | } 16 | ] -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/failed_acl_validation.json: -------------------------------------------------------------------------------- 1 | { 2 | "valid": false, 3 | "policies": [ 4 | { 5 | "policy": "file1.aclpolicy[1]", 6 | "errors": [ 7 | "reason...", 8 | "reason2..." 9 | ] 10 | }, 11 | 12 | { 13 | "policy": "file1.aclpolicy[2]", 14 | "errors": [ 15 | "reason...", 16 | "reason2..." 17 | ] 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/get_project_scm_action_input_fields_import.json: -------------------------------------------------------------------------------- 1 | { 2 | "actionId": "import-all", 3 | "description": "Import the modifications to Rundeck", 4 | "exportItems": null, 5 | "fields": [], 6 | "importItems": [ 7 | { 8 | "itemId": "import-test/new-sleep-job.yaml", 9 | "job": null, 10 | "tracked": false 11 | } 12 | ], 13 | "integration": "import", 14 | "title": "Import remote Changes" 15 | } 16 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/bulk_delete_executions.json: -------------------------------------------------------------------------------- 1 | { 2 | "failures": [ 3 | { 4 | "id": "82", 5 | "message": "Failed: 82" 6 | }, 7 | { 8 | "id": "83", 9 | "message": "Unauthorized: 83" 10 | }, 11 | { 12 | "id": "84", 13 | "message": "Not found: 84" 14 | } 15 | ], 16 | "failedCount": 3, 17 | "successCount": 2, 18 | "allsuccessful": false, 19 | "requestCount": 5 20 | } -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/bulk_job_delete.json: -------------------------------------------------------------------------------- 1 | { 2 | "requestCount": 2, 3 | "allsuccessful": false, 4 | "succeeded": [ 5 | { 6 | "id": "[UUID]", 7 | "message": "(success or failure message)" 8 | } 9 | ], 10 | "failed":[ 11 | { 12 | "id": "[UUID]", 13 | "errorCode": "(error code, see above)", 14 | "message": "(success or failure message)" 15 | } 16 | 17 | ] 18 | } -------------------------------------------------------------------------------- /pkg/rundeck/responses/job_definition_test.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | yaml "gopkg.in/yaml.v2" 8 | ) 9 | 10 | func TestJobYAMLResponse(t *testing.T) { 11 | obj := &JobYAMLResponse{} 12 | data, err := getAssetBytes(JobYAMLResponseTestFile) 13 | require.NoError(t, err) 14 | 15 | err = yaml.UnmarshalStrict(data, &obj) 16 | require.NoError(t, err) 17 | require.Implements(t, (*VersionedResponse)(nil), obj) 18 | } 19 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/paging.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | // PagingResponse represents paging data in a response 4 | type PagingResponse struct { 5 | Offset int `json:"offset"` 6 | Max int `json:"max"` 7 | Total int `json:"total"` 8 | Count int `json:"count"` 9 | } 10 | 11 | func (a PagingResponse) minVersion() int { return AbsoluteMinimumVersion } 12 | func (a PagingResponse) maxVersion() int { return CurrentVersion } 13 | func (a PagingResponse) deprecated() bool { return false } 14 | -------------------------------------------------------------------------------- /vendor/github.com/shurcooL/vfsgen/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: go 3 | go: 4 | - 1.x 5 | - master 6 | matrix: 7 | allow_failures: 8 | - go: master 9 | fast_finish: true 10 | install: 11 | - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step). 12 | script: 13 | - go get -t -v ./... 14 | - diff -u <(echo -n) <(gofmt -d -s .) 15 | - go tool vet . 16 | - go test -v -race ./... 17 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/forward_assertions.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | // Assertions provides assertion methods around the 4 | // TestingT interface. 5 | type Assertions struct { 6 | t TestingT 7 | } 8 | 9 | // New makes a new Assertions object for the specified TestingT. 10 | func New(t TestingT) *Assertions { 11 | return &Assertions{ 12 | t: t, 13 | } 14 | } 15 | 16 | //go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_forward.go.tmpl 17 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/require/forward_requirements.go: -------------------------------------------------------------------------------- 1 | package require 2 | 3 | // Assertions provides assertion methods around the 4 | // TestingT interface. 5 | type Assertions struct { 6 | t TestingT 7 | } 8 | 9 | // New makes a new Assertions object for the specified TestingT. 10 | func New(t TestingT) *Assertions { 11 | return &Assertions{ 12 | t: t, 13 | } 14 | } 15 | 16 | //go:generate go run ../_codegen/main.go -output-package=require -template=require_forward.go.tmpl 17 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/execution.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import "github.com/spf13/cobra" 4 | 5 | func executionCommands() *cobra.Command { 6 | cmd := &cobra.Command{ 7 | Use: "execution", 8 | Short: "operate on individual rundeck executions", 9 | } 10 | cmd.AddCommand(getExecutionCommand()) 11 | cmd.AddCommand(deleteExecutionCommand()) 12 | cmd.AddCommand(toggleExecutionCommand()) 13 | cmd.AddCommand(getExecutionOutputCommand()) 14 | cmd.AddCommand(tailExecutionOutputCommand()) 15 | return cmd 16 | } 17 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/job.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import "github.com/spf13/cobra" 4 | 5 | func jobCommands() *cobra.Command { 6 | cmd := &cobra.Command{ 7 | Use: "job", 8 | Short: "operate on individual rundeck jobs", 9 | } 10 | cmd.AddCommand(runJobCommand()) 11 | cmd.AddCommand(deleteJobCommand()) 12 | cmd.AddCommand(getJobCommand()) 13 | cmd.AddCommand(getJobOptsCommand()) 14 | cmd.AddCommand(exportJobCommand()) 15 | cmd.AddCommand(importJobCommand()) 16 | cmd.AddCommand(findJobByNameCommand()) 17 | return cmd 18 | } 19 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/policies.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import "github.com/spf13/cobra" 4 | 5 | func systemPoliciesCommands() *cobra.Command { 6 | cmd := &cobra.Command{ 7 | Use: "system-policy", 8 | Short: "operate on rundeck system acl policies", 9 | } 10 | cmd.AddCommand(getSystemACLPolicyCommand()) 11 | cmd.AddCommand(listSystemACLPoliciesCommand()) 12 | cmd.AddCommand(createSystemACLPolicyCommand()) 13 | cmd.AddCommand(updateSystemACLPolicyCommand()) 14 | cmd.AddCommand(deleteSystemACLPolicyCommand()) 15 | return cmd 16 | } 17 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/project_archive_import_failed.json: -------------------------------------------------------------------------------- 1 | { 2 | "import_status":"failed", 3 | "errors": [ 4 | "Job ABC could not be validated: ...", 5 | "Job XYZ could not be validated: ..." 6 | ], 7 | "execution_errors": [ 8 | "Execution 123 could not be imported: ...", 9 | "Execution 456 could not be imported: ..." 10 | ], 11 | "acl_errors": [ 12 | "file.aclpolicy could not be validated: ...", 13 | "file2.aclpolicy could not be validated: ..." 14 | ] 15 | } -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/upload_job_input_file.json: -------------------------------------------------------------------------------- 1 | { 2 | "dateCreated": "2017-02-24T19:10:33Z", 3 | "execId": 2741, 4 | "expirationDate": "2017-02-24T19:11:03Z", 5 | "fileName": null, 6 | "fileState": "deleted", 7 | "id": "f985864b-fa1b-4e09-af7a-4315e9908372", 8 | "jobId": "7b3fff59-7a2d-4a31-a5b2-dd26177c823c", 9 | "serverNodeUUID": "3425B691-7319-4EEE-8425-F053C628B4BA", 10 | "sha": "9284ed4fd7fe1346904656f329db6cc49c0e7ae5b8279bff37f96bc6eb59baad", 11 | "size": 12, 12 | "user": "admin" 13 | } -------------------------------------------------------------------------------- /vendor/github.com/shurcooL/vfsgen/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package vfsgen takes an http.FileSystem (likely at `go generate` time) and 3 | generates Go code that statically implements the provided http.FileSystem. 4 | 5 | Features: 6 | 7 | - Efficient generated code without unneccessary overhead. 8 | 9 | - Uses gzip compression internally (selectively, only for files that compress well). 10 | 11 | - Enables direct access to internal gzip compressed bytes via an optional interface. 12 | 13 | - Outputs `gofmt`ed Go code. 14 | */ 15 | package vfsgen 16 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/runewidth_windows.go: -------------------------------------------------------------------------------- 1 | package runewidth 2 | 3 | import ( 4 | "syscall" 5 | ) 6 | 7 | var ( 8 | kernel32 = syscall.NewLazyDLL("kernel32") 9 | procGetConsoleOutputCP = kernel32.NewProc("GetConsoleOutputCP") 10 | ) 11 | 12 | // IsEastAsian return true if the current locale is CJK 13 | func IsEastAsian() bool { 14 | r1, _, _ := procGetConsoleOutputCP.Call() 15 | if r1 == 0 { 16 | return false 17 | } 18 | 19 | switch int(r1) { 20 | case 932, 51932, 936, 949, 950: 21 | return true 22 | } 23 | 24 | return false 25 | } 26 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/delete_job.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/lusis/go-rundeck/pkg/cli" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func deleteJobFunc(cmd *cobra.Command, args []string) error { 9 | id := args[0] 10 | return cli.Client.DeleteJob(id) 11 | } 12 | 13 | func deleteJobCommand() *cobra.Command { 14 | cmd := &cobra.Command{ 15 | Use: "delete job-id", 16 | Short: "deletes a job on the rundeck server", 17 | Args: cobra.MinimumNArgs(1), 18 | RunE: deleteJobFunc, 19 | } 20 | rootCmd := cli.New(cmd) 21 | rootCmd.ResetFlags() 22 | return rootCmd 23 | } 24 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/users.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "login":"user", 3 | "firstName":"Name", 4 | "lastName":"LastName", 5 | "email":"user@server.com", 6 | "created": "2017-10-01T09:00:20Z", 7 | "updated": "2018-08-24T13:53:02Z", 8 | "lastJob": "2018-08-28T13:31:00Z", 9 | "tokens": 1 10 | }, 11 | { 12 | "login":"admin", 13 | "firstName":"Admin", 14 | "lastName":"Admin", 15 | "email":"admin@server.com", 16 | "created": "2016-07-17T18:42:00Z", 17 | "updated": "2018-08-24T13:53:00Z", 18 | "lastJob": "2018-08-28T13:31:00Z", 19 | "tokens": 6 20 | }] -------------------------------------------------------------------------------- /script/test-integration: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -Eeuo pipefail 3 | # shellcheck disable=SC1091 4 | source script/env 5 | 6 | CODEDIR=$(pwd) 7 | TESTCOMMAND="go test -v ./pkg/rundeck -run ^TestIntegration" 8 | CI=${CI:-''} 9 | if [ -n "$CI" ]; then 10 | docker run \ 11 | -e GOCACHE=/tmp \ 12 | -u "$(id -u):$(id -g)" \ 13 | -w /src \ 14 | -v "${CODEDIR}":/src \ 15 | --rm \ 16 | -i \ 17 | -t circleci/golang:1.12.4 \ 18 | go test -v -c -o rundeck.test ./pkg/rundeck 19 | ./rundeck.test -test.failfast -test.v 20 | else 21 | ${TESTCOMMAND} 22 | fi 23 | 24 | 25 | -------------------------------------------------------------------------------- /vendor/github.com/inconshreveable/mousetrap/trap_others.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package mousetrap 4 | 5 | // StartedByExplorer returns true if the program was invoked by the user 6 | // double-clicking on the executable from explorer.exe 7 | // 8 | // It is conservative and returns false if any of the internal calls fail. 9 | // It does not guarantee that the program was run from a terminal. It only can tell you 10 | // whether it was launched from explorer.exe 11 | // 12 | // On non-Windows platforms, it always returns false. 13 | func StartedByExplorer() bool { 14 | return false 15 | } 16 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/get_job_forecast.json: -------------------------------------------------------------------------------- 1 | { 2 | "href":"http://127.0.0.1:4440/api/31/job/b7361e0e-abed-4dcc-98d5-ec35189937c0", 3 | "id":"b7361e0e-abed-4dcc-98d5-ec35189937c0", 4 | "futureScheduledExecutions": [], 5 | "scheduleEnabled":true, 6 | "scheduled":false, 7 | "enabled":true, 8 | "permalink":"http://127.0.0.1:4440/project/TestSCMActionProjectExport-1556678173656898700/job/show/b7361e0e-abed-4dcc-98d5-ec35189937c0", 9 | "group":null, 10 | "description":"", 11 | "project":"TestSCMActionProjectExport-1556678173656898700", 12 | "name":"testjob" 13 | } 14 | -------------------------------------------------------------------------------- /pkg/httpclient/constants.go: -------------------------------------------------------------------------------- 1 | package httpclient 2 | 3 | import "errors" 4 | 5 | const ( 6 | // ContentTypeJSON is the mimetype for json 7 | ContentTypeJSON = "application/json" 8 | // ContentTypeXML is the mimetype for xml 9 | ContentTypeXML = "application/xml" 10 | // DefaultAccept is the default Accept mimetype for requests 11 | DefaultAccept = "*/*" 12 | ) 13 | 14 | var ( 15 | // ErrInvalidStatusCode is the error type returned when the user sets expected 16 | // status code with `ExpectStatus`, but it does not match 17 | ErrInvalidStatusCode = errors.New("response had an invalid status code") 18 | ) 19 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/incomplete_logstorage_executions.json: -------------------------------------------------------------------------------- 1 | { 2 | "total": 1, 3 | "max": 20, 4 | "offset": 0, 5 | "executions": [ 6 | { 7 | "id": 1, 8 | "project": "myProject", 9 | "href": "[API Href]", 10 | "permalink": "[GUI Href]", 11 | "storage": { 12 | "localFilesPresent": true, 13 | "incompleteFiletypes": "rdlog,state.json", 14 | "queued": true, 15 | "failed": true, 16 | "date": "2017-03-25T21:17:12Z" 17 | }, 18 | "errors": ["message","message..."] 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /cmd/rundeck/cmds/delete_token.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | cli "github.com/lusis/go-rundeck/pkg/cli" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func deleteTokenFunc(cmd *cobra.Command, args []string) error { 9 | id := args[0] 10 | return cli.Client.DeleteToken(id) 11 | } 12 | 13 | func deleteTokenCommand() *cobra.Command { 14 | cmd := &cobra.Command{ 15 | Use: "delete token-id", 16 | Short: "deletes an api token on the rundeck server", 17 | Args: cobra.MinimumNArgs(1), 18 | RunE: deleteTokenFunc, 19 | } 20 | 21 | rootCmd := cli.New(cmd) 22 | rootCmd.ResetFlags() 23 | return rootCmd 24 | } 25 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/execution_output.txt: -------------------------------------------------------------------------------- 1 | hello 2 | Failed: IOFailure: java.io.IOException: Cannot run program "for": error=2, No such file or directory 3 | Execution failed: 20 in project testproject: [Workflow result: , step failures: {4=Dispatch failed on 1 nodes: [localhost: IOFailure: java.io.IOException: Cannot run program "for": error=2, No such file or directory + {dataContext=MultiDataContextImpl(map={}, base=null)} ]}, Node failures: {localhost=[IOFailure: java.io.IOException: Cannot run program "for": error=2, No such file or directory + {dataContext=MultiDataContextImpl(map={}, base=null)} ]}, status: failed] 4 | -------------------------------------------------------------------------------- /cmd/maketestdata/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "os" 7 | "path/filepath" 8 | 9 | "github.com/shurcooL/vfsgen" 10 | ) 11 | 12 | func main() { 13 | var cwd, _ = os.Getwd() 14 | directories := []string{"responses"} 15 | for _, dir := range directories { 16 | testdata := http.Dir(filepath.Join(cwd, "pkg", "rundeck", dir, "testdata")) 17 | if err := vfsgen.Generate(testdata, vfsgen.Options{ 18 | Filename: "pkg/rundeck/" + dir + "/testdata.go", 19 | PackageName: dir, 20 | VariableName: "assets", 21 | }); err != nil { 22 | log.Fatalln(err) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/delete_project.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | cli "github.com/lusis/go-rundeck/pkg/cli" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func deleteProjectFunc(cmd *cobra.Command, args []string) error { 9 | id := args[0] 10 | return cli.Client.DeleteProject(id) 11 | } 12 | 13 | func deleteProjectCommand() *cobra.Command { 14 | cmd := &cobra.Command{ 15 | Use: "delete project-name", 16 | Short: "deletes a project on the rundeck server", 17 | Args: cobra.MinimumNArgs(1), 18 | RunE: deleteProjectFunc, 19 | } 20 | rootCmd := cli.New(cmd) 21 | rootCmd.ResetFlags() 22 | return rootCmd 23 | } 24 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/scm.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | ) 6 | 7 | var scmInputFieldsFullDescription bool 8 | var scmInputFieldsRequiredOnly bool 9 | var scmSetupParams []string 10 | 11 | func scmCommands() *cobra.Command { 12 | cmd := &cobra.Command{ 13 | Use: "scm", 14 | Short: "operate on rundeck scm plugins", 15 | } 16 | cmd.AddCommand(getSCMPluginInputFieldsCommand()) 17 | cmd.AddCommand(enableProjectSCMCommand()) 18 | cmd.AddCommand(disableProjectSCMCommand()) 19 | cmd.AddCommand(listProjectSCMPluginsCommand()) 20 | cmd.AddCommand(setupProjectSCMCommand()) 21 | return cmd 22 | } 23 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/bulk_toggle.json: -------------------------------------------------------------------------------- 1 | { 2 | "requestCount": 3, 3 | "enabled": false, 4 | "allsuccessful": false, 5 | "succeeded": [ 6 | { 7 | "id": "d1b9f2c1-d6a6-43ca-8e9f-85519d5a1323", 8 | "message": "Job Execution was disabled for: {{Job d1b9f2c1-d6a6-43ca-8e9f-85519d5a1323}}" 9 | } 10 | ], 11 | "failed": [ 12 | { 13 | "id": "abcdef", 14 | "errorCode": null, 15 | "message": null 16 | }, 17 | { 18 | "id": "abcdef", 19 | "errorCode": "failed", 20 | "message": "some message" 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /cmd/rundeck/cmds/list.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | ) 6 | 7 | func listProjectExecutionsCommand() *cobra.Command { 8 | cmd := getProjectExecutionsCommand() 9 | cmd.Use = "executions project-name [-r] [-m max]" 10 | return cmd 11 | } 12 | 13 | func listCommands() *cobra.Command { 14 | cmd := &cobra.Command{ 15 | Use: "list", 16 | Short: "list various things from the rundeck server", 17 | } 18 | cmd.AddCommand(listUsersCommand()) 19 | cmd.AddCommand(getJobsCommand()) 20 | cmd.AddCommand(listProjectsCommand()) 21 | cmd.AddCommand(listProjectExecutionsCommand()) 22 | return cmd 23 | } 24 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/execution_input_files.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | { 4 | "id": "382c7596-435b-4103-8781-6b32fbd629b2", 5 | "user": "admin", 6 | "fileState": "deleted", 7 | "sha": "9284ed4fd7fe1346904656f329db6cc49c0e7ae5b8279bff37f96bc6eb59baad", 8 | "jobId": "7b3fff59-7a2d-4a31-a5b2-dd26177c823c", 9 | "dateCreated": "2014-02-24T23:26:48Z", 10 | "serverNodeUUID": "3425B691-7319-4EEE-8425-F053C628B4BA", 11 | "fileName": null, 12 | "size": 12, 13 | "expirationDate": "2017-02-24T23:27:18Z", 14 | "execId": 2837 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /pkg/rundeck/responses/errors.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | // ErrorResponseTestFile is the test data for an ErrorResponse 4 | const ErrorResponseTestFile = "error.json" 5 | 6 | // ErrorResponse is the response for an api error 7 | type ErrorResponse struct { 8 | IsError bool `json:"error"` 9 | APIVersion int `json:"apiVersion"` 10 | ErrorCode string `json:"errorCode"` 11 | Message string `json:"message"` 12 | } 13 | 14 | func (a ErrorResponse) minVersion() int { return AbsoluteMinimumVersion } 15 | func (a ErrorResponse) maxVersion() int { return CurrentVersion } 16 | func (a ErrorResponse) deprecated() bool { return false } 17 | -------------------------------------------------------------------------------- /vendor/github.com/inconshreveable/mousetrap/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014 Alan Shreve 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /vendor/github.com/spf13/cobra/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | matrix: 4 | include: 5 | - go: 1.7.6 6 | - go: 1.8.3 7 | - go: tip 8 | allow_failures: 9 | - go: tip 10 | 11 | before_install: 12 | - mkdir -p bin 13 | - curl -Lso bin/shellcheck https://github.com/caarlos0/shellcheck-docker/releases/download/v0.4.3/shellcheck 14 | - chmod +x bin/shellcheck 15 | script: 16 | - PATH=$PATH:$PWD/bin go test -v ./... 17 | - go build 18 | - diff -u <(echo -n) <(gofmt -d -s .) 19 | - if [ -z $NOVET ]; then 20 | diff -u <(echo -n) <(go tool vet . 2>&1 | grep -vE 'ExampleCommand|bash_completions.*Fprint'); 21 | fi 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License, Version 2.0 2 | 3 | Copyright (c) 2016 John E. Vincent 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | -------------------------------------------------------------------------------- /pkg/rundeck/version.go: -------------------------------------------------------------------------------- 1 | package rundeck 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | 7 | "github.com/lusis/go-rundeck/pkg/rundeck/responses" 8 | ) 9 | 10 | func (c *Client) checkRequiredAPIVersion(r responses.VersionedResponse) error { 11 | reqVersion, err := strconv.Atoi(c.Config.APIVersion) 12 | if err != nil { 13 | return err 14 | } 15 | min := responses.GetMinVersionFor(r) 16 | max := responses.GetMaxVersionFor(r) 17 | if reqVersion >= min && reqVersion <= max { 18 | return nil 19 | } 20 | return fmt.Errorf("Requested API version (%d) does not meet the requirements for this api call (min: %d, max: %d)", 21 | reqVersion, min, max) 22 | } 23 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/delete_system_acl_policy.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/lusis/go-rundeck/pkg/cli" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func deleteSystemACLPolicyFunc(cmd *cobra.Command, args []string) error { 9 | policyName := args[0] 10 | return cli.Client.DeleteSystemACLPolicy(policyName) 11 | } 12 | 13 | func deleteSystemACLPolicyCommand() *cobra.Command { 14 | cmd := &cobra.Command{ 15 | Use: "delete policy-name", 16 | Short: "deletes a system acl policy", 17 | Args: cobra.MinimumNArgs(1), 18 | RunE: deleteSystemACLPolicyFunc, 19 | } 20 | rootCmd := cli.New(cmd) 21 | rootCmd.ResetFlags() 22 | return rootCmd 23 | } 24 | -------------------------------------------------------------------------------- /vendor/github.com/spf13/cobra/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | # Vim files https://github.com/github/gitignore/blob/master/Global/Vim.gitignore 23 | # swap 24 | [._]*.s[a-w][a-z] 25 | [._]s[a-w][a-z] 26 | # session 27 | Session.vim 28 | # temporary 29 | .netrwhist 30 | *~ 31 | # auto-generated tag files 32 | tags 33 | 34 | *.exe 35 | 36 | cobra.test 37 | -------------------------------------------------------------------------------- /vendor/github.com/shurcooL/httpfs/vfsutil/file.go: -------------------------------------------------------------------------------- 1 | package vfsutil 2 | 3 | import ( 4 | "net/http" 5 | "os" 6 | ) 7 | 8 | // File implements http.FileSystem using the native file system restricted to a 9 | // specific file served at root. 10 | // 11 | // While the FileSystem.Open method takes '/'-separated paths, a File's string 12 | // value is a filename on the native file system, not a URL, so it is separated 13 | // by filepath.Separator, which isn't necessarily '/'. 14 | type File string 15 | 16 | func (f File) Open(name string) (http.File, error) { 17 | if name != "/" { 18 | return nil, &os.PathError{Op: "open", Path: name, Err: os.ErrNotExist} 19 | } 20 | return os.Open(string(f)) 21 | } 22 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/get_project_scm_config_export.json: -------------------------------------------------------------------------------- 1 | { 2 | "config": { 3 | "url": "/home/rundeck-export.git/", 4 | "fetchAutomatically": "true", 5 | "dir": "/var/rundeck/projects/testproject/scm", 6 | "committerEmail": "${user.email}", 7 | "committerName": "${user.fullName}", 8 | "strictHostKeyChecking": "yes", 9 | "sshPrivateKeyPath": "", 10 | "branch": "master", 11 | "format": "yaml", 12 | "gitPasswordPath": "", 13 | "exportUuidBehavior": "preserve", 14 | "pathTemplate": "${job.group}${job.name}-${job.id}.${config.format}" 15 | }, 16 | "enabled": true, 17 | "integration": "export", 18 | "project": "testproject", 19 | "type": "git-export" 20 | } 21 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/resume_logstorage.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | 6 | cli "github.com/lusis/go-rundeck/pkg/cli" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | func resumeIncompleteLogStorageFunc(cmd *cobra.Command, args []string) error { 11 | data, err := cli.Client.ResumeIncompleteLogStorage() 12 | if err != nil { 13 | return err 14 | } 15 | fmt.Printf("%t\n", data) 16 | return nil 17 | } 18 | 19 | func resumeIncompleteLogStorageCommand() *cobra.Command { 20 | cmd := &cobra.Command{ 21 | Use: "resume", 22 | Short: "resumes incomplete log storage processing on the rundeck server", 23 | RunE: resumeIncompleteLogStorageFunc, 24 | } 25 | rootCmd := cli.New(cmd) 26 | return rootCmd 27 | } 28 | -------------------------------------------------------------------------------- /pkg/rundeck/requests/common.go: -------------------------------------------------------------------------------- 1 | package requests 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | // JSONTime is for custom marshal/unmarshal of rundeck datetime values 9 | type JSONTime struct { 10 | time.Time 11 | } 12 | 13 | var rdFormat = "2006-01-02T15:04:05-0700" 14 | 15 | // MarshalJSON converts a JSONTime to the format supported for rundeck requests 16 | // if empty, we specify the current time 17 | func (t *JSONTime) MarshalJSON() ([]byte, error) { 18 | var jsonTime string 19 | if !t.IsZero() { 20 | jsonTime = fmt.Sprintf("\"%s\"", t.Format(rdFormat)) 21 | return []byte(jsonTime), nil 22 | } 23 | jsonTime = fmt.Sprintf("\"%s\"", time.Now().Format(rdFormat)) 24 | return []byte(jsonTime), nil 25 | } 26 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/get_project_scm_config_import.json: -------------------------------------------------------------------------------- 1 | { 2 | "config": { 3 | "url": "/home/rundeck-import.git/", 4 | "fetchAutomatically": "true", 5 | "dir": "/var/rundeck/projects/testproject/scm", 6 | "_useFilePattern": "", 7 | "filePattern": ".*\\.yaml", 8 | "importUuidBehavior": "remove", 9 | "useFilePattern": "true", 10 | "strictHostKeyChecking": "yes", 11 | "sshPrivateKeyPath": "", 12 | "format": "yaml", 13 | "branch": "master", 14 | "gitPasswordPath": "", 15 | "pathTemplate": "${job.group}${job.name}-${job.id}.${config.format}" 16 | }, 17 | "enabled": true, 18 | "integration": "import", 19 | "project": "testproject", 20 | "type": "git-import" 21 | } 22 | -------------------------------------------------------------------------------- /vendor/github.com/hashicorp/go-multierror/flatten.go: -------------------------------------------------------------------------------- 1 | package multierror 2 | 3 | // Flatten flattens the given error, merging any *Errors together into 4 | // a single *Error. 5 | func Flatten(err error) error { 6 | // If it isn't an *Error, just return the error as-is 7 | if _, ok := err.(*Error); !ok { 8 | return err 9 | } 10 | 11 | // Otherwise, make the result and flatten away! 12 | flatErr := new(Error) 13 | flatten(err, flatErr) 14 | return flatErr 15 | } 16 | 17 | func flatten(err error, flatErr *Error) { 18 | switch err := err.(type) { 19 | case *Error: 20 | for _, e := range err.Errors { 21 | flatten(e, flatErr) 22 | } 23 | default: 24 | flatErr.Errors = append(flatErr.Errors, err) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/delete_execution.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "strconv" 5 | 6 | cli "github.com/lusis/go-rundeck/pkg/cli" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | func deleteExecutionFunc(cmd *cobra.Command, args []string) error { 11 | id := args[0] 12 | eID, err := strconv.Atoi(id) 13 | if err != nil { 14 | return err 15 | } 16 | return cli.Client.DeleteExecution(eID) 17 | } 18 | 19 | func deleteExecutionCommand() *cobra.Command { 20 | cmd := &cobra.Command{ 21 | Use: "delete execution-id", 22 | Short: "deletes an execution on the rundeck server", 23 | Args: cobra.MinimumNArgs(1), 24 | RunE: deleteExecutionFunc, 25 | } 26 | rootCmd := cli.New(cmd) 27 | rootCmd.ResetFlags() 28 | return rootCmd 29 | } 30 | -------------------------------------------------------------------------------- /vendor/github.com/shurcooL/vfsgen/stringwriter.go: -------------------------------------------------------------------------------- 1 | package vfsgen 2 | 3 | import ( 4 | "io" 5 | ) 6 | 7 | // stringWriter writes given bytes to underlying io.Writer as a Go interpreted string literal value, 8 | // not including double quotes. It tracks the total number of bytes written. 9 | type stringWriter struct { 10 | io.Writer 11 | N int64 // Total bytes written. 12 | } 13 | 14 | func (sw *stringWriter) Write(p []byte) (n int, err error) { 15 | const hex = "0123456789abcdef" 16 | buf := []byte{'\\', 'x', 0, 0} 17 | for _, b := range p { 18 | buf[2], buf[3] = hex[b/16], hex[b%16] 19 | _, err = sw.Writer.Write(buf) 20 | if err != nil { 21 | return n, err 22 | } 23 | n++ 24 | sw.N++ 25 | } 26 | return n, nil 27 | } 28 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/helpers.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | // ParseSliceKeyValue parses a cobra StringSlice into a map[string]string split on an = sign 9 | func ParseSliceKeyValue(s []string) (map[string]string, error) { 10 | res := map[string]string{} 11 | for _, o := range s { 12 | entry := strings.Split(o, "=") 13 | if len(entry) != 2 { 14 | return res, fmt.Errorf("error parsing entry: %s", o) 15 | } 16 | if entry[0] == "" { 17 | return res, fmt.Errorf("unable to parse key for value: %s", entry[1]) 18 | } 19 | if entry[1] == "" { 20 | return res, fmt.Errorf("unable to parse value for key: %s", entry[0]) 21 | } 22 | res[entry[0]] = entry[1] 23 | } 24 | return res, nil 25 | } 26 | -------------------------------------------------------------------------------- /pkg/rundeck/requests/job.go: -------------------------------------------------------------------------------- 1 | package requests 2 | 3 | /* 4 | { 5 | "argString":"...", 6 | "loglevel":"...", 7 | "asUser":"...", 8 | "filter":"...", 9 | "runAtTime":"...", 10 | "options": { 11 | "myopt1":"value", 12 | ... 13 | } 14 | } 15 | */ 16 | 17 | // RunJobRequest is the payload for running a job 18 | type RunJobRequest struct { 19 | ArgString string `json:"argString,omitempty"` 20 | LogLevel string `json:"loglevel,omitempty"` 21 | AsUser string `json:"asUser,omitempty"` 22 | Filter string `json:"filter,omitempty"` 23 | RunAtTime *JSONTime `json:"runAtTime,omitempty"` 24 | Options map[string]string `json:"options,omitempty"` 25 | } 26 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/uploaded_job_input_files.json: -------------------------------------------------------------------------------- 1 | { 2 | "paging": { 3 | "offset": 0, 4 | "max": 20, 5 | "total": 1, 6 | "count": 1 7 | }, 8 | "files": [ 9 | { 10 | "id": "023057ee-418f-4da7-9ae5-e065ac91eb5a", 11 | "user": "admin", 12 | "fileState": "temp", 13 | "sha": "9284ed4fd7fe1346904656f329db6cc49c0e7ae5b8279bff37f96bc6eb59baad", 14 | "jobId": "7b3fff59-7a2d-4a31-a5b2-dd26177c823c", 15 | "dateCreated": "2017-02-24T22:57:32Z", 16 | "serverNodeUUID": "3425B691-7319-4EEE-8425-F053C628B4BA", 17 | "fileName": null, 18 | "size": 12, 19 | "expirationDate": "2017-02-24T22:58:02Z", 20 | "execId": null 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /pkg/rundeck/responses/token_test.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/mitchellh/mapstructure" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestTokenResponse(t *testing.T) { 12 | obj := &TokenResponse{} 13 | data, err := getAssetBytes(TokenResponseTestFile) 14 | require.NoError(t, err) 15 | placeholder := make(map[string]interface{}) 16 | err = json.Unmarshal(data, &placeholder) 17 | require.NoError(t, err) 18 | config := newMSDecoderConfig() 19 | config.Result = obj 20 | decoder, err := mapstructure.NewDecoder(config) 21 | require.NoError(t, err) 22 | err = decoder.Decode(placeholder) 23 | require.NoError(t, err) 24 | require.Implements(t, (*VersionedResponse)(nil), obj) 25 | } 26 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/root.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | ) 6 | 7 | const enable = "enable" 8 | const disable = "disable" 9 | const adhoc = "" 10 | const nodescription = "" 11 | 12 | // RootCommand is the root of all commands 13 | func RootCommand() { 14 | cmd := &cobra.Command{ 15 | Use: "rundeck", 16 | Short: "Unified rundeck cli binary", 17 | } 18 | cmd.AddCommand(projectCommands(), 19 | adHocCommands(), 20 | listCommands(), 21 | systemPoliciesCommands(), 22 | jobCommands(), 23 | jobsCommands(), 24 | executionCommands(), 25 | executionsCommands(), 26 | tokenCommand(), 27 | tokensCommands(), 28 | httpCommand(), 29 | scmCommands(), 30 | logStorageCommand()) 31 | _ = cmd.Execute() 32 | } 33 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/history_test.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/mitchellh/mapstructure" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestHistoryResponse(t *testing.T) { 12 | obj := &HistoryResponse{} 13 | data, err := getAssetBytes(HistoryResponseTestFile) 14 | require.NoError(t, err) 15 | placeholder := make(map[string]interface{}) 16 | err = json.Unmarshal(data, &placeholder) 17 | require.NoError(t, err) 18 | config := newMSDecoderConfig() 19 | config.Result = obj 20 | decoder, err := mapstructure.NewDecoder(config) 21 | require.NoError(t, err) 22 | err = decoder.Decode(placeholder) 23 | require.NoError(t, err) 24 | require.Implements(t, (*VersionedResponse)(nil), obj) 25 | } 26 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/toggle_test.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/mitchellh/mapstructure" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestBulkToggleResponse(t *testing.T) { 12 | obj := &BulkToggleResponse{} 13 | data, err := getAssetBytes(BulkToggleResponseTestFile) 14 | require.NoError(t, err) 15 | placeholder := make(map[string]interface{}) 16 | err = json.Unmarshal(data, &placeholder) 17 | require.NoError(t, err) 18 | config := newMSDecoderConfig() 19 | config.Result = obj 20 | decoder, err := mapstructure.NewDecoder(config) 21 | require.NoError(t, err) 22 | err = decoder.Decode(placeholder) 23 | require.NoError(t, err) 24 | require.Implements(t, (*VersionedResponse)(nil), obj) 25 | } 26 | -------------------------------------------------------------------------------- /pkg/rundeck/requests/scm.go: -------------------------------------------------------------------------------- 1 | package requests 2 | 3 | // SetupSCMPluginRequest is the request body for calling setup scm plugin 4 | type SetupSCMPluginRequest struct { 5 | Config map[string]string `json:"config"` 6 | } 7 | 8 | // PerformSCMActionRequest is the request body for performing an scm action 9 | /* 10 | { 11 | "input":{ 12 | "message":"$commitMessage" 13 | }, 14 | "jobs":[ 15 | "$jobId" 16 | ], 17 | "items":[ 18 | "$itemId" 19 | ], 20 | "deleted":null 21 | } 22 | */ 23 | type PerformSCMActionRequest struct { 24 | Input map[string]string `json:"input"` 25 | Jobs []string `json:"jobs,omitempty"` 26 | Items []string `json:"items,omitempty"` 27 | Deleted []string `json:"deleted,omitempty"` 28 | } 29 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/systeminfo_test.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/mitchellh/mapstructure" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestSystemInfoResponse(t *testing.T) { 12 | obj := &SystemInfoResponse{} 13 | 14 | data, err := getAssetBytes(SystemInfoResponseTestFile) 15 | require.NoError(t, err) 16 | placeholder := make(map[string]interface{}) 17 | err = json.Unmarshal(data, &placeholder) 18 | require.NoError(t, err) 19 | config := newMSDecoderConfig() 20 | config.Result = obj 21 | decoder, err := mapstructure.NewDecoder(config) 22 | require.NoError(t, err) 23 | 24 | err = decoder.Decode(placeholder) 25 | require.NoError(t, err) 26 | require.Implements(t, (*VersionedResponse)(nil), obj) 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/hashicorp/go-multierror/format.go: -------------------------------------------------------------------------------- 1 | package multierror 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | // ErrorFormatFunc is a function callback that is called by Error to 9 | // turn the list of errors into a string. 10 | type ErrorFormatFunc func([]error) string 11 | 12 | // ListFormatFunc is a basic formatter that outputs the number of errors 13 | // that occurred along with a bullet point list of the errors. 14 | func ListFormatFunc(es []error) string { 15 | if len(es) == 1 { 16 | return fmt.Sprintf("1 error occurred:\n\n* %s", es[0]) 17 | } 18 | 19 | points := make([]string, len(es)) 20 | for i, err := range es { 21 | points[i] = fmt.Sprintf("* %s", err) 22 | } 23 | 24 | return fmt.Sprintf( 25 | "%d errors occurred:\n\n%s", 26 | len(es), strings.Join(points, "\n")) 27 | } 28 | -------------------------------------------------------------------------------- /pkg/rundeck/requests/common_test.go: -------------------------------------------------------------------------------- 1 | package requests 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "testing" 7 | "time" 8 | 9 | "github.com/stretchr/testify/require" 10 | ) 11 | 12 | type testTS struct { 13 | DateTime JSONTime `json:"datetime"` 14 | } 15 | 16 | func TestMarshalJSONTime(t *testing.T) { 17 | tstamp := time.Date(2016, time.November, 23, 12, 20, 55, 0, time.UTC) 18 | s := &testTS{ 19 | DateTime: JSONTime{tstamp}, 20 | } 21 | str := fmt.Sprintf(`{"datetime":"2016-11-23T12:20:55+0000"}`) 22 | res, resErr := json.Marshal(s) 23 | require.NoError(t, resErr) 24 | 25 | require.Equal(t, str, string(res)) 26 | } 27 | 28 | func TestMarshalJSONTimeNil(t *testing.T) { 29 | s := &testTS{} 30 | res, resErr := json.Marshal(s) 31 | require.NoError(t, resErr) 32 | require.NotEmpty(t, string(res)) 33 | } 34 | -------------------------------------------------------------------------------- /script/env: -------------------------------------------------------------------------------- 1 | PATH=test/libs/bats/bin:${PATH} 2 | VERSION=$(cat VERSION) 3 | BUILDUSER=${CIRCLE_USER:-$(whoami)} 4 | BUILDHOST=$HOSTNAME 5 | BUILDDATE=$(date +%Y%m%d-%H:%M:%S) 6 | GITSHA=${CIRCLE_SHA1:-$(git rev-parse HEAD)} 7 | GITBRANCH=${CIRCLE_BRANCH:-$(git rev-parse --abbrev-ref HEAD)} 8 | LD_FLAGS=("-s -X github.com/prometheus/common/version.Version=${VERSION} -X github.com/prometheus/common/version.Revision=${GITSHA} -X github.com/prometheus/common/version.Branch=${GITBRANCH} -X github.com/prometheus/common/version.BuildUser=${BUILDUSER}@${BUILDHOST} -X github.com/prometheus/common/version.BuildDate=${BUILDDATE}") 9 | BUILDTARGETS="linux/amd64 linux/386 darwin/amd64 darwin/386 windows/amd64 windows/386 freebsd/amd64 freebsd/386 openbsd/amd64 openbsd/386 netbsd/386 netbsd/amd64 dragonfly/amd64 linux/arm linux/arm64 freebsd/arm openbsd/arm netbsd/arm" -------------------------------------------------------------------------------- /pkg/rundeck/requests/job_test.go: -------------------------------------------------------------------------------- 1 | package requests 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "testing" 7 | "time" 8 | 9 | "github.com/stretchr/testify/require" 10 | ) 11 | 12 | func TestRunJobRequestMarshal(t *testing.T) { 13 | timeVal := "2018-01-03T11:44:23-0500" 14 | curTime, _ := time.Parse(rdFormat, timeVal) 15 | j := &RunJobRequest{ 16 | ArgString: "-opt 1", 17 | LogLevel: "DEBUG", 18 | AsUser: "user1", 19 | Filter: ".*", 20 | RunAtTime: &JSONTime{curTime}, 21 | Options: map[string]string{ 22 | "opt2": "val2", 23 | }, 24 | } 25 | res, err := json.Marshal(j) 26 | require.NoError(t, err) 27 | expected := fmt.Sprintf(`{"argString":"-opt 1","loglevel":"DEBUG","asUser":"user1","filter":".*","runAtTime":"%s","options":{"opt2":"val2"}}`, timeVal) 28 | require.Equal(t, expected, string(res)) 29 | } 30 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2012-2016 Dave Collins 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /vendor/github.com/shurcooL/vfsgen/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing 2 | ============ 3 | 4 | vfsgen is open source, thanks for considering contributing! 5 | 6 | Please note that vfsgen aims to be simple and minimalistic, with as little to configure as possible. If you'd like to remove or simplify code (while having tests continue to pass), fix bugs, or improve code (e.g., add missing error checking, etc.), PRs and issues are welcome. 7 | 8 | However, if you'd like to add new functionality that increases complexity or scope, please make an issue and discuss your proposal first. I'm unlikely to accept such changes outright. It might be that your request is already a part of other similar packages, or it might fit in their scope better. See [Comparison and Alternatives](https://github.com/shurcooL/vfsgen/tree/README-alternatives-and-comparison-section#comparison) sections. 9 | 10 | Thank you! 11 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/export_job.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/lusis/go-rundeck/pkg/cli" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | var exportJobFormat string 11 | 12 | func exportJobFunc(cmd *cobra.Command, args []string) error { 13 | jobid := args[0] 14 | 15 | res, err := cli.Client.ExportJob(jobid, exportJobFormat) 16 | if err != nil { 17 | return err 18 | } 19 | fmt.Println(string(res)) 20 | return nil 21 | } 22 | 23 | func exportJobCommand() *cobra.Command { 24 | cmd := &cobra.Command{ 25 | Use: "export jobid [-f format]", 26 | Short: "exports a job in the specified format", 27 | Args: cobra.MinimumNArgs(1), 28 | RunE: exportJobFunc, 29 | } 30 | 31 | rootCmd := cli.New(cmd) 32 | rootCmd.ResetFlags() 33 | rootCmd.Flags().StringVarP(&exportJobFormat, "job-format", "f", "yaml", "format to export job") 34 | return rootCmd 35 | } 36 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/get_system_acl_policy.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/lusis/go-rundeck/pkg/cli" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | func getSystemACLPolicyFunc(cmd *cobra.Command, args []string) error { 12 | policyName := args[0] 13 | if strings.HasSuffix(policyName, ".aclpolicy") { 14 | return fmt.Errorf("policy name should not end with .aclpolicy") 15 | } 16 | res, err := cli.Client.GetSystemACLPolicy(policyName) 17 | if err != nil { 18 | return err 19 | } 20 | fmt.Println(string(res)) 21 | return nil 22 | } 23 | 24 | func getSystemACLPolicyCommand() *cobra.Command { 25 | cmd := &cobra.Command{ 26 | Use: "get policy-name", 27 | Short: "gets a system acl policy", 28 | Args: cobra.MinimumNArgs(1), 29 | RunE: getSystemACLPolicyFunc, 30 | } 31 | rootCmd := cli.New(cmd) 32 | rootCmd.ResetFlags() 33 | return rootCmd 34 | } 35 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/helpers_test.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func TestParseGood(t *testing.T) { 10 | data := []string{"foo=bar", "qux=baz"} 11 | res, err := ParseSliceKeyValue(data) 12 | require.NoError(t, err) 13 | require.Len(t, res, 2) 14 | } 15 | 16 | func TestParseMissingKey(t *testing.T) { 17 | data := []string{"=bar", "qux=baz"} 18 | res, err := ParseSliceKeyValue(data) 19 | require.Error(t, err) 20 | require.Len(t, res, 0) 21 | } 22 | 23 | func TestParseMissingValue(t *testing.T) { 24 | data := []string{"foo=", "qux=baz"} 25 | res, err := ParseSliceKeyValue(data) 26 | require.Error(t, err) 27 | require.Len(t, res, 0) 28 | } 29 | 30 | func TestParseNoEqual(t *testing.T) { 31 | data := []string{"foo", "qux=baz"} 32 | res, err := ParseSliceKeyValue(data) 33 | require.Error(t, err) 34 | require.Len(t, res, 0) 35 | } 36 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/get_execution_output.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | 7 | cli "github.com/lusis/go-rundeck/pkg/cli" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | func getExecutionOutputFunc(cmd *cobra.Command, args []string) error { 12 | id := args[0] 13 | eID, eIDerr := strconv.Atoi(id) 14 | if eIDerr != nil { 15 | return eIDerr 16 | } 17 | data, err := cli.Client.GetExecutionOutput(eID) 18 | if err != nil { 19 | return err 20 | } 21 | for _, entry := range data.Entries { 22 | fmt.Println(entry.Log) 23 | } 24 | return nil 25 | } 26 | 27 | func getExecutionOutputCommand() *cobra.Command { 28 | cmd := &cobra.Command{ 29 | Use: "output execution-id", 30 | Short: "gets an execution's output from the rundeck server", 31 | Args: cobra.MinimumNArgs(1), 32 | RunE: getExecutionOutputFunc, 33 | } 34 | rootCmd := cli.New(cmd) 35 | rootCmd.ResetFlags() 36 | return rootCmd 37 | } 38 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/list_projects.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | cli "github.com/lusis/go-rundeck/pkg/cli" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func listProjectsFunc(cmd *cobra.Command, args []string) error { 9 | data, err := cli.Client.ListProjects() 10 | if err != nil { 11 | return err 12 | } 13 | 14 | cli.OutputFormatter.SetHeaders([]string{ 15 | "Name", 16 | "Description", 17 | "URL", 18 | }) 19 | 20 | for _, d := range data { 21 | if rowErr := cli.OutputFormatter.AddRow([]string{ 22 | d.Name, 23 | d.Description, 24 | d.URL, 25 | }); rowErr != nil { 26 | return rowErr 27 | } 28 | } 29 | cli.OutputFormatter.Draw() 30 | return nil 31 | } 32 | func listProjectsCommand() *cobra.Command { 33 | cmd := &cobra.Command{ 34 | Use: "projects", 35 | Short: "gets a list of projects from the rundeck server", 36 | RunE: listProjectsFunc, 37 | } 38 | rootCmd := cli.New(cmd) 39 | return rootCmd 40 | } 41 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/list_jobs.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/lusis/go-rundeck/pkg/cli" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func listJobsFunc(cmd *cobra.Command, args []string) error { 9 | projectid := args[0] 10 | data, err := cli.Client.ListJobs(projectid) 11 | if err != nil { 12 | return err 13 | } 14 | cli.OutputFormatter.SetHeaders([]string{"ID", "Name", "Description", "Group", "Project"}) 15 | for _, d := range data { 16 | if err := cli.OutputFormatter.AddRow([]string{d.ID, d.Name, d.Description, d.Group, d.Project}); err != nil { 17 | return err 18 | } 19 | } 20 | cli.OutputFormatter.Draw() 21 | return nil 22 | } 23 | 24 | func getJobsCommand() *cobra.Command { 25 | getJobsCmd := &cobra.Command{ 26 | Use: "jobs project-name", 27 | Short: "lists all jobs for a project", 28 | RunE: listJobsFunc, 29 | Args: cobra.MinimumNArgs(1), 30 | } 31 | cmd := cli.New(getJobsCmd) 32 | return cmd 33 | } 34 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/README.mkd: -------------------------------------------------------------------------------- 1 | go-runewidth 2 | ============ 3 | 4 | [![Build Status](https://travis-ci.org/mattn/go-runewidth.png?branch=master)](https://travis-ci.org/mattn/go-runewidth) 5 | [![Coverage Status](https://coveralls.io/repos/mattn/go-runewidth/badge.png?branch=HEAD)](https://coveralls.io/r/mattn/go-runewidth?branch=HEAD) 6 | [![GoDoc](https://godoc.org/github.com/mattn/go-runewidth?status.svg)](http://godoc.org/github.com/mattn/go-runewidth) 7 | [![Go Report Card](https://goreportcard.com/badge/github.com/mattn/go-runewidth)](https://goreportcard.com/report/github.com/mattn/go-runewidth) 8 | 9 | Provides functions to get fixed width of the character or string. 10 | 11 | Usage 12 | ----- 13 | 14 | ```go 15 | runewidth.StringWidth("つのだ☆HIRO") == 12 16 | ``` 17 | 18 | 19 | Author 20 | ------ 21 | 22 | Yasuhiro Matsumoto 23 | 24 | License 25 | ------- 26 | 27 | under the MIT License: http://mattn.mit-license.org/2013 28 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BINARIES := $(shell find cmd/ -maxdepth 1 -type d -name 'rundeck*' -exec sh -c 'echo $(basename {})' \;) 2 | BINLIST := $(subst src/,,$(BINARIES)) 3 | RUNDECK_DEB_VERSION := 3.0.21.20190424-1.201904242241 4 | #RUNDECK_DEB_VERSION := 3.0.9 5 | 6 | all: clean bindata test $(BINLIST) 7 | 8 | test: 9 | @script/test 10 | 11 | bindata: 12 | @CGO_ENABLED=0 go run ./cmd/maketestdata/main.go 13 | 14 | build-test-container: 15 | @cd docker; docker build --rm --build-arg RDECK_VER=$(RUNDECK_DEB_VERSION) -t go-rundeck-test:$(RUNDECK_DEB_VERSION) .; cd - 16 | 17 | run-test-container: 18 | @docker run -d -p 4440:4440 --name go-rundeck-test -t go-rundeck-test:$(RUNDECK_DEB_VERSION) 19 | 20 | stop-test-container: 21 | @docker stop go-rundeck-test 22 | @docker rm go-rundeck-test 23 | 24 | binaries: $(BINLIST) 25 | 26 | $(BINLIST): 27 | CGO_ENABLED=0 go install ./$@ 28 | 29 | clean: 30 | @rm -rf bin/ 31 | 32 | .PHONY: all clean bindata test $(BINLIST) 33 | -------------------------------------------------------------------------------- /docker/admin.aclpolicy: -------------------------------------------------------------------------------- 1 | description: Admin, all access. 2 | context: 3 | project: '.*' # all projects 4 | for: 5 | resource: 6 | - allow: '*' # allow read/create all kinds 7 | adhoc: 8 | - allow: '*' # allow read/running/killing adhoc jobs 9 | job: 10 | - allow: '*' # allow read/write/delete/run/kill of all jobs 11 | node: 12 | - allow: '*' # allow read/run for all nodes 13 | by: 14 | group: admin 15 | 16 | --- 17 | 18 | description: Admin, all access. 19 | context: 20 | application: 'rundeck' 21 | for: 22 | resource: 23 | - allow: '*' # allow create of projects 24 | project: 25 | - allow: '*' # allow view/admin of all projects 26 | project_acl: 27 | - allow: '*' # allow admin of all project-level ACL policies 28 | storage: 29 | - allow: '*' # allow read/create/update/delete for all /keys/* storage content 30 | system_acl: 31 | - allow: '*' # allow full access to the system 32 | by: 33 | group: admin 34 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/foo.aclpolicy: -------------------------------------------------------------------------------- 1 | 2 | description: Admin, all access. 3 | context: 4 | project: '.*' # all projects 5 | for: 6 | resource: 7 | - allow: '*' # allow read/create all kinds 8 | adhoc: 9 | - allow: '*' # allow read/running/killing adhoc jobs 10 | job: 11 | - allow: '*' # allow read/write/delete/run/kill of all jobs 12 | node: 13 | - allow: '*' # allow read/run for all nodes 14 | by: 15 | group: admin 16 | 17 | --- 18 | 19 | description: Admin, all access. 20 | context: 21 | application: 'rundeck' 22 | for: 23 | resource: 24 | - allow: '*' # allow create of projects 25 | project: 26 | - allow: '*' # allow view/admin of all projects 27 | project_acl: 28 | - allow: '*' # allow admin of all project-level ACL policies 29 | storage: 30 | - allow: '*' # allow read/create/update/delete for all /keys/* storage content 31 | system_acl: 32 | - allow: '*' # allow full access to the system 33 | by: 34 | group: admin -------------------------------------------------------------------------------- /vendor/github.com/inconshreveable/mousetrap/README.md: -------------------------------------------------------------------------------- 1 | # mousetrap 2 | 3 | mousetrap is a tiny library that answers a single question. 4 | 5 | On a Windows machine, was the process invoked by someone double clicking on 6 | the executable file while browsing in explorer? 7 | 8 | ### Motivation 9 | 10 | Windows developers unfamiliar with command line tools will often "double-click" 11 | the executable for a tool. Because most CLI tools print the help and then exit 12 | when invoked without arguments, this is often very frustrating for those users. 13 | 14 | mousetrap provides a way to detect these invocations so that you can provide 15 | more helpful behavior and instructions on how to run the CLI tool. To see what 16 | this looks like, both from an organizational and a technical perspective, see 17 | https://inconshreveable.com/09-09-2014/sweat-the-small-stuff/ 18 | 19 | ### The interface 20 | 21 | The library exposes a single interface: 22 | 23 | func StartedByExplorer() (bool) 24 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/get_project_config.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/lusis/go-rundeck/pkg/cli" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func getProjectConfigFunc(cmd *cobra.Command, args []string) error { 9 | projectName := args[0] 10 | data, err := cli.Client.GetProjectConfiguration(projectName) 11 | if err != nil { 12 | return err 13 | } 14 | cli.OutputFormatter.SetHeaders([]string{ 15 | "Name", 16 | "Value", 17 | }) 18 | for k, v := range data { 19 | if err := cli.OutputFormatter.AddRow([]string{ 20 | k, 21 | v}); err != nil { 22 | return err 23 | } 24 | } 25 | cli.OutputFormatter.Draw() 26 | return nil 27 | } 28 | 29 | func getProjectConfigCommand() *cobra.Command { 30 | cmd := &cobra.Command{ 31 | Use: "config project-name", 32 | Short: "gets a project's configuration from a rundeck server", 33 | Args: cobra.MinimumNArgs(1), 34 | RunE: getProjectConfigFunc, 35 | } 36 | rootCmd := cli.New(cmd) 37 | return rootCmd 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/suite/interfaces.go: -------------------------------------------------------------------------------- 1 | package suite 2 | 3 | import "testing" 4 | 5 | // TestingSuite can store and return the current *testing.T context 6 | // generated by 'go test'. 7 | type TestingSuite interface { 8 | T() *testing.T 9 | SetT(*testing.T) 10 | } 11 | 12 | // SetupAllSuite has a SetupSuite method, which will run before the 13 | // tests in the suite are run. 14 | type SetupAllSuite interface { 15 | SetupSuite() 16 | } 17 | 18 | // SetupTestSuite has a SetupTest method, which will run before each 19 | // test in the suite. 20 | type SetupTestSuite interface { 21 | SetupTest() 22 | } 23 | 24 | // TearDownAllSuite has a TearDownSuite method, which will run after 25 | // all the tests in the suite have been run. 26 | type TearDownAllSuite interface { 27 | TearDownSuite() 28 | } 29 | 30 | // TearDownTestSuite has a TearDownTest method, which will run after 31 | // each test in the suite. 32 | type TearDownTestSuite interface { 33 | TearDownTest() 34 | } 35 | -------------------------------------------------------------------------------- /vendor/github.com/hashicorp/go-multierror/Makefile: -------------------------------------------------------------------------------- 1 | TEST?=./... 2 | 3 | default: test 4 | 5 | # test runs the test suite and vets the code. 6 | test: generate 7 | @echo "==> Running tests..." 8 | @go list $(TEST) \ 9 | | grep -v "/vendor/" \ 10 | | xargs -n1 go test -timeout=60s -parallel=10 ${TESTARGS} 11 | 12 | # testrace runs the race checker 13 | testrace: generate 14 | @echo "==> Running tests (race)..." 15 | @go list $(TEST) \ 16 | | grep -v "/vendor/" \ 17 | | xargs -n1 go test -timeout=60s -race ${TESTARGS} 18 | 19 | # updatedeps installs all the dependencies needed to run and build. 20 | updatedeps: 21 | @sh -c "'${CURDIR}/scripts/deps.sh' '${NAME}'" 22 | 23 | # generate runs `go generate` to build the dynamically generated source files. 24 | generate: 25 | @echo "==> Generating..." 26 | @find . -type f -name '.DS_Store' -delete 27 | @go list ./... \ 28 | | grep -v "/vendor/" \ 29 | | xargs -n1 go generate 30 | 31 | .PHONY: default test testrace updatedeps generate 32 | -------------------------------------------------------------------------------- /vendor/github.com/hashicorp/go-multierror/prefix.go: -------------------------------------------------------------------------------- 1 | package multierror 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/hashicorp/errwrap" 7 | ) 8 | 9 | // Prefix is a helper function that will prefix some text 10 | // to the given error. If the error is a multierror.Error, then 11 | // it will be prefixed to each wrapped error. 12 | // 13 | // This is useful to use when appending multiple multierrors 14 | // together in order to give better scoping. 15 | func Prefix(err error, prefix string) error { 16 | if err == nil { 17 | return nil 18 | } 19 | 20 | format := fmt.Sprintf("%s {{err}}", prefix) 21 | switch err := err.(type) { 22 | case *Error: 23 | // Typed nils can reach here, so initialize if we are nil 24 | if err == nil { 25 | err = new(Error) 26 | } 27 | 28 | // Wrap each of the errors 29 | for i, e := range err.Errors { 30 | err.Errors[i] = errwrap.Wrapf(format, e) 31 | } 32 | 33 | return err 34 | default: 35 | return errwrap.Wrapf(format, err) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /pkg/rundeck/system_info.go: -------------------------------------------------------------------------------- 1 | package rundeck 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | multierror "github.com/hashicorp/go-multierror" 7 | responses "github.com/lusis/go-rundeck/pkg/rundeck/responses" 8 | ) 9 | 10 | // SystemInfo represents the rundeck server system info output 11 | type SystemInfo struct { 12 | responses.SystemInfoResponse 13 | } 14 | 15 | // GetSystemInfo gets system information from the rundeck server 16 | // http://rundeck.org/docs/api/index.html#system-info 17 | func (c *Client) GetSystemInfo() (*SystemInfo, error) { 18 | if err := c.checkRequiredAPIVersion(responses.SystemInfoResponse{}); err != nil { 19 | return nil, err 20 | } 21 | ls := SystemInfo{} 22 | data, err := c.httpGet("system/info", requestJSON(), requestExpects(200)) 23 | if err != nil { 24 | return nil, err 25 | } 26 | if jsonErr := json.Unmarshal(data, &ls); jsonErr != nil { 27 | return nil, &UnmarshalError{msg: multierror.Append(errDecoding, jsonErr).Error()} 28 | } 29 | return &ls, nil 30 | } 31 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/job_definition.yaml: -------------------------------------------------------------------------------- 1 | - description: sleeps a while 2 | executionEnabled: true 3 | group: test 4 | id: d1b9f2c1-d6a6-43ca-8e9f-85519d5a1323 5 | loglevel: INFO 6 | multipleExecutions: true 7 | name: sleep-job 8 | nodeFilterEditable: false 9 | options: 10 | - description: how long to sleep 11 | name: sleeptime 12 | regex: \d+ 13 | required: true 14 | value: '120' 15 | scheduleEnabled: true 16 | sequence: 17 | commands: 18 | - configuration: 19 | command: sleep ${option.sleeptime} 20 | nodeStep: true 21 | type: localexec 22 | - jobref: 23 | group: others/things 24 | name: another-job 25 | nodeStep: 'true' 26 | - configuration: 27 | export: exportvar 28 | group: vars 29 | value: snarf 30 | description: export global var 31 | nodeStep: false 32 | type: export-var 33 | keepgoing: false 34 | strategy: node-first 35 | uuid: d1b9f2c1-d6a6-43ca-8e9f-85519d5a1323 36 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/require/doc.go: -------------------------------------------------------------------------------- 1 | // Package require implements the same assertions as the `assert` package but 2 | // stops test execution when a test fails. 3 | // 4 | // Example Usage 5 | // 6 | // The following is a complete example using require in a standard test function: 7 | // import ( 8 | // "testing" 9 | // "github.com/stretchr/testify/require" 10 | // ) 11 | // 12 | // func TestSomething(t *testing.T) { 13 | // 14 | // var a string = "Hello" 15 | // var b string = "Hello" 16 | // 17 | // require.Equal(t, a, b, "The two words should be the same.") 18 | // 19 | // } 20 | // 21 | // Assertions 22 | // 23 | // The `require` package have same global functions as in the `assert` package, 24 | // but instead of returning a boolean result they call `t.FailNow()`. 25 | // 26 | // Every assertion function also takes an optional string message as the final argument, 27 | // allowing custom error messages to be appended to the message the assertion method outputs. 28 | package require 29 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/get_job_opts.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/lusis/go-rundeck/pkg/cli" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | func getJobOptsFunc(cmd *cobra.Command, args []string) error { 11 | jobid := args[0] 12 | data, err := cli.Client.GetJobOpts(jobid) 13 | if err != nil { 14 | return err 15 | } 16 | cli.OutputFormatter.SetHeaders([]string{ 17 | "Name", 18 | "Description", 19 | "Value", 20 | "Required?", 21 | "Regex", 22 | }) 23 | for _, d := range data { 24 | if err := cli.OutputFormatter.AddRow([]string{ 25 | d.Name, 26 | d.Description, 27 | d.Value, 28 | fmt.Sprintf("%t", d.Required), 29 | d.Regex}); err != nil { 30 | return err 31 | } 32 | } 33 | cli.OutputFormatter.Draw() 34 | return nil 35 | } 36 | 37 | func getJobOptsCommand() *cobra.Command { 38 | cmd := &cobra.Command{ 39 | Use: "opts job-id", 40 | Short: "gets a job's options from a rundeck server", 41 | Args: cobra.MinimumNArgs(1), 42 | RunE: getJobOptsFunc, 43 | } 44 | rootCmd := cli.New(cmd) 45 | return rootCmd 46 | } 47 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/adhoc.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import "github.com/spf13/cobra" 4 | 5 | var ( 6 | adHocAsUser string 7 | adHocFilter string 8 | adHocNodeThreadCount int 9 | adHocNodeKeepGoing bool 10 | adHocScriptInterpreter string 11 | adHocArgString string 12 | adHocArgsQuoted bool 13 | adHocFileExtension string 14 | ) 15 | 16 | func adHocCommands() *cobra.Command { 17 | cmd := &cobra.Command{ 18 | Use: "adhoc", 19 | Short: "run adhoc commands, scripts and scripts from urls against a project", 20 | } 21 | cmd.PersistentFlags().StringVar(&adHocAsUser, "as-user", "", "rundeck user to run as") 22 | cmd.PersistentFlags().StringVar(&adHocFilter, "filter", "", "rundeck filter to use") 23 | cmd.PersistentFlags().IntVar(&adHocNodeThreadCount, "thread-count", 1, "node thread count") 24 | cmd.PersistentFlags().BoolVar(&adHocNodeKeepGoing, "keep-going", false, "keep going on failure") 25 | cmd.AddCommand(runAdHocCmdCommand()) 26 | cmd.AddCommand(runAdHocScriptCommand()) 27 | cmd.AddCommand(runAdHocURLCommand()) 28 | return cmd 29 | } 30 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/execution.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 1, 3 | "href": "[url]", 4 | "permalink": "[url]", 5 | "status": "succeeded/failed/aborted/timedout/retried/other", 6 | "project": "[project]", 7 | "user": "[user]", 8 | "date-started": { 9 | "unixtime": 1431536339809, 10 | "date": "2015-05-13T16:58:59Z" 11 | }, 12 | "date-ended": { 13 | "unixtime": 1431536346423, 14 | "date": "2016-05-13T16:59:06Z" 15 | }, 16 | "job": { 17 | "id": "[uuid]", 18 | "href": "[url]", 19 | "permalink": "[url]", 20 | "averageDuration": 6094, 21 | "name": "[name]", 22 | "group": "[group]", 23 | "project": "[project]", 24 | "description": "[description]", 25 | "options": { 26 | "opt2": "a", 27 | "opt1": "testvalue" 28 | } 29 | }, 30 | "description": "echo hello there [... 5 steps]", 31 | "argstring": "-opt1 testvalue -opt2 a", 32 | "successfulNodes": [ 33 | "nodea","nodeb" 34 | ], 35 | "failedNodes": [ 36 | "nodec","noded" 37 | ] 38 | } -------------------------------------------------------------------------------- /vendor/github.com/shurcooL/vfsgen/commentwriter.go: -------------------------------------------------------------------------------- 1 | package vfsgen 2 | 3 | import "io" 4 | 5 | // commentWriter writes a Go comment to the underlying io.Writer, 6 | // using line comment form (//). 7 | type commentWriter struct { 8 | W io.Writer 9 | wroteSlashes bool // Wrote "//" at the beginning of the current line. 10 | } 11 | 12 | func (c *commentWriter) Write(p []byte) (int, error) { 13 | var n int 14 | for i, b := range p { 15 | if !c.wroteSlashes { 16 | s := "//" 17 | if b != '\n' { 18 | s = "// " 19 | } 20 | if _, err := io.WriteString(c.W, s); err != nil { 21 | return n, err 22 | } 23 | c.wroteSlashes = true 24 | } 25 | n0, err := c.W.Write(p[i : i+1]) 26 | n += n0 27 | if err != nil { 28 | return n, err 29 | } 30 | if b == '\n' { 31 | c.wroteSlashes = false 32 | } 33 | } 34 | return len(p), nil 35 | } 36 | 37 | func (c *commentWriter) Close() error { 38 | if !c.wroteSlashes { 39 | if _, err := io.WriteString(c.W, "//"); err != nil { 40 | return err 41 | } 42 | c.wroteSlashes = true 43 | } 44 | return nil 45 | } 46 | -------------------------------------------------------------------------------- /pkg/rundeck/helpers_test.go: -------------------------------------------------------------------------------- 1 | package rundeck 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "net/http/httptest" 7 | "net/url" 8 | ) 9 | 10 | func newTestRundeckClient(content []byte, contentType string, statusCode int) (*Client, *httptest.Server, error) { 11 | 12 | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 13 | w.WriteHeader(statusCode) 14 | w.Header().Set("Content-Type", contentType) 15 | fmt.Fprintf(w, string(content)) // nolint: errcheck 16 | })) 17 | 18 | transport := http.Transport{ 19 | Proxy: func(req *http.Request) (*url.URL, error) { 20 | return url.Parse(server.URL) 21 | }, 22 | } 23 | 24 | httpClient := http.Client{} 25 | httpClient.Transport = &transport 26 | conf := &ClientConfig{ 27 | BaseURL: "http://localhost:4440/", 28 | Token: "XXXXXXXXXXXXX", 29 | VerifySSL: false, 30 | AuthMethod: "token", 31 | APIVersion: MaxRundeckVersion, 32 | HTTPClient: &httpClient, 33 | } 34 | client, err := NewClient(conf) 35 | if err != nil { 36 | return nil, nil, err 37 | } 38 | return client, server, nil 39 | } 40 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/list_users.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/lusis/go-rundeck/pkg/cli" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | func listUsersFunc(cmd *cobra.Command, args []string) error { 11 | data, err := cli.Client.ListUsers() 12 | if err != nil { 13 | return err 14 | } 15 | cli.OutputFormatter.SetHeaders([]string{"Login", "First Name", "Last Name", "Email", "Created", "Updated", "Last Job", "Tokens"}) 16 | for _, d := range data { 17 | created, updated, lastjob := d.Created.Format(cli.TimeFormat), d.Updated.Format(cli.TimeFormat), d.LastJob.Format(cli.TimeFormat) 18 | if err := cli.OutputFormatter.AddRow([]string{d.Login, d.FirstName, d.LastName, d.Email, created, updated, lastjob, fmt.Sprintf("%d", d.Tokens)}); err != nil { 19 | return err 20 | } 21 | } 22 | cli.OutputFormatter.Draw() 23 | return nil 24 | } 25 | 26 | func listUsersCommand() *cobra.Command { 27 | cmd := &cobra.Command{ 28 | Use: "users", 29 | Short: "gets a list of users from the rundeck server", 30 | RunE: listUsersFunc, 31 | } 32 | rootCmd := cli.New(cmd) 33 | return rootCmd 34 | } 35 | -------------------------------------------------------------------------------- /vendor/github.com/lusis/outputter/Gopkg.toml: -------------------------------------------------------------------------------- 1 | 2 | # Gopkg.toml example 3 | # 4 | # Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md 5 | # for detailed Gopkg.toml documentation. 6 | # 7 | # required = ["github.com/user/thing/cmd/thing"] 8 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] 9 | # 10 | # [[constraint]] 11 | # name = "github.com/user/project" 12 | # version = "1.0.0" 13 | # 14 | # [[constraint]] 15 | # name = "github.com/user/project2" 16 | # branch = "dev" 17 | # source = "github.com/myfork/project2" 18 | # 19 | # [[override]] 20 | # name = "github.com/x/y" 21 | # version = "2.4.0" 22 | 23 | 24 | [[constraint]] 25 | name = "github.com/fatih/color" 26 | version = "1.5.0" 27 | 28 | [[constraint]] 29 | branch = "master" 30 | name = "github.com/olekukonko/tablewriter" 31 | 32 | [[constraint]] 33 | name = "github.com/spf13/cobra" 34 | version = "0.0.1" 35 | 36 | [[constraint]] 37 | name = "github.com/stretchr/testify" 38 | version = "1.1.4" 39 | 40 | [[constraint]] 41 | name = "gopkg.in/alecthomas/kingpin.v2" 42 | version = "2.2.5" 43 | -------------------------------------------------------------------------------- /vendor/github.com/shurcooL/httpfs/vfsutil/vfsutil.go: -------------------------------------------------------------------------------- 1 | // Package vfsutil implements some I/O utility functions for http.FileSystem. 2 | package vfsutil 3 | 4 | import ( 5 | "io/ioutil" 6 | "net/http" 7 | "os" 8 | ) 9 | 10 | // ReadDir reads the contents of the directory associated with file and 11 | // returns a slice of FileInfo values in directory order. 12 | func ReadDir(fs http.FileSystem, name string) ([]os.FileInfo, error) { 13 | f, err := fs.Open(name) 14 | if err != nil { 15 | return nil, err 16 | } 17 | defer f.Close() 18 | return f.Readdir(0) 19 | } 20 | 21 | // Stat returns the FileInfo structure describing file. 22 | func Stat(fs http.FileSystem, name string) (os.FileInfo, error) { 23 | f, err := fs.Open(name) 24 | if err != nil { 25 | return nil, err 26 | } 27 | defer f.Close() 28 | return f.Stat() 29 | } 30 | 31 | // ReadFile reads the file named by path from fs and returns the contents. 32 | func ReadFile(fs http.FileSystem, path string) ([]byte, error) { 33 | rc, err := fs.Open(path) 34 | if err != nil { 35 | return nil, err 36 | } 37 | defer rc.Close() 38 | return ioutil.ReadAll(rc) 39 | } 40 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/delete_project_acl_policy.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/lusis/go-rundeck/pkg/cli" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | var ( 12 | deleteProjectACLPolicyPolicyName string 13 | ) 14 | 15 | func deleteProjectACLPolicyFunc(cmd *cobra.Command, args []string) error { 16 | projectName := args[0] 17 | if strings.HasSuffix(deleteProjectACLPolicyPolicyName, ".aclpolicy") { 18 | return fmt.Errorf("policy name should not end with .aclpolicy") 19 | } 20 | return cli.Client.DeleteProjectACLPolicy(projectName, deleteProjectACLPolicyPolicyName) 21 | } 22 | 23 | func deleteProjectACLPolicyCommand() *cobra.Command { 24 | cmd := &cobra.Command{ 25 | Use: "delete project-name -p policy-name", 26 | Short: "deletes a project acl policy", 27 | Args: cobra.MinimumNArgs(1), 28 | RunE: deleteProjectACLPolicyFunc, 29 | } 30 | rootCmd := cli.New(cmd) 31 | rootCmd.ResetFlags() 32 | rootCmd.Flags().StringVarP(&deleteProjectACLPolicyPolicyName, "policy-name", "p", "", "policy name to get") 33 | _ = rootCmd.MarkFlagRequired("policy-name") 34 | return rootCmd 35 | } 36 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/list_system_acl_policies.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/lusis/go-rundeck/pkg/cli" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func listSystemACLPoliciesFunc(cmd *cobra.Command, args []string) error { 9 | policies, err := cli.Client.ListSystemACLPolicies() 10 | if err != nil { 11 | return err 12 | } 13 | cli.OutputFormatter.SetHeaders([]string{ 14 | "Name", 15 | "Path", 16 | "Type", 17 | "HRef", 18 | "Parent", 19 | "Parent Type", 20 | }) 21 | parent := "/" 22 | if policies.Path != "" { 23 | parent = policies.Path 24 | } 25 | for _, p := range policies.Resources { 26 | if err := cli.OutputFormatter.AddRow([]string{ 27 | p.Name, 28 | p.Path, 29 | p.Type, 30 | p.Href, 31 | parent, 32 | policies.Type, 33 | }); err != nil { 34 | return err 35 | } 36 | } 37 | cli.OutputFormatter.Draw() 38 | return nil 39 | } 40 | 41 | func listSystemACLPoliciesCommand() *cobra.Command { 42 | cmd := &cobra.Command{ 43 | Use: "list", 44 | Short: "lists system acl policies", 45 | RunE: listSystemACLPoliciesFunc, 46 | } 47 | rootCmd := cli.New(cmd) 48 | return rootCmd 49 | } 50 | -------------------------------------------------------------------------------- /vendor/github.com/olekukonko/tablewriter/LICENCE.md: -------------------------------------------------------------------------------- 1 | Copyright (C) 2014 by Oleku Konko 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /vendor/github.com/hashicorp/go-multierror/append.go: -------------------------------------------------------------------------------- 1 | package multierror 2 | 3 | // Append is a helper function that will append more errors 4 | // onto an Error in order to create a larger multi-error. 5 | // 6 | // If err is not a multierror.Error, then it will be turned into 7 | // one. If any of the errs are multierr.Error, they will be flattened 8 | // one level into err. 9 | func Append(err error, errs ...error) *Error { 10 | switch err := err.(type) { 11 | case *Error: 12 | // Typed nils can reach here, so initialize if we are nil 13 | if err == nil { 14 | err = new(Error) 15 | } 16 | 17 | // Go through each error and flatten 18 | for _, e := range errs { 19 | switch e := e.(type) { 20 | case *Error: 21 | if e != nil { 22 | err.Errors = append(err.Errors, e.Errors...) 23 | } 24 | default: 25 | if e != nil { 26 | err.Errors = append(err.Errors, e) 27 | } 28 | } 29 | } 30 | 31 | return err 32 | default: 33 | newErrs := make([]error, 0, len(errs)+1) 34 | if err != nil { 35 | newErrs = append(newErrs, err) 36 | } 37 | newErrs = append(newErrs, errs...) 38 | 39 | return Append(&Error{}, newErrs...) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /vendor/github.com/shurcooL/httpfs/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2015 Dmitri Shuralyov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/shurcooL/vfsgen/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2015 Dmitri Shuralyov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/get_project.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/lusis/go-rundeck/pkg/cli" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | func getProjectFunc(cmd *cobra.Command, args []string) error { 12 | projectName := args[0] 13 | data, err := cli.Client.GetProjectInfo(projectName) 14 | if err != nil { 15 | return err 16 | } 17 | cli.OutputFormatter.SetHeaders([]string{ 18 | "URL", 19 | "Name", 20 | "Description", 21 | "Config", 22 | }) 23 | var config []string 24 | for k, v := range data.Properties { 25 | config = append(config, fmt.Sprintf("%s - %s ", k, v)) 26 | } 27 | if rowErr := cli.OutputFormatter.AddRow([]string{ 28 | data.URL, 29 | data.Name, 30 | data.Description, 31 | strings.Join(config, "\n"), 32 | }); rowErr != nil { 33 | return rowErr 34 | } 35 | cli.OutputFormatter.Draw() 36 | return nil 37 | 38 | } 39 | 40 | func getProjectCommand() *cobra.Command { 41 | cmd := &cobra.Command{ 42 | Use: "get project-name", 43 | Short: "gets project info from the rundeck server", 44 | Args: cobra.MinimumNArgs(1), 45 | RunE: getProjectFunc, 46 | } 47 | rootCmd := cli.New(cmd) 48 | return rootCmd 49 | } 50 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/get_project_acl_policy.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/lusis/go-rundeck/pkg/cli" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | var ( 12 | getProjectACLPolicyPolicyName string 13 | ) 14 | 15 | func getProjectACLPolicyFunc(cmd *cobra.Command, args []string) error { 16 | projectName := args[0] 17 | if strings.HasSuffix(getProjectACLPolicyPolicyName, ".aclpolicy") { 18 | return fmt.Errorf("policy name should not end with .aclpolicy") 19 | } 20 | res, err := cli.Client.GetProjectACLPolicy(projectName, getProjectACLPolicyPolicyName) 21 | if err != nil { 22 | return err 23 | } 24 | fmt.Println(string(res)) 25 | return nil 26 | } 27 | 28 | func getProjectACLPolicyCommand() *cobra.Command { 29 | cmd := &cobra.Command{ 30 | Use: "get project-name -p policy-name", 31 | Short: "gets a project acl policy", 32 | Args: cobra.MinimumNArgs(1), 33 | RunE: getProjectACLPolicyFunc, 34 | } 35 | rootCmd := cli.New(cmd) 36 | rootCmd.ResetFlags() 37 | rootCmd.Flags().StringVarP(&getProjectACLPolicyPolicyName, "policy-name", "p", "", "policy name to get") 38 | _ = rootCmd.MarkFlagRequired("policy-name") 39 | return rootCmd 40 | } 41 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Yasuhiro Matsumoto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/create_token.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | cli "github.com/lusis/go-rundeck/pkg/cli" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | func createTokenFunc(cmd *cobra.Command, args []string) error { 12 | user := args[0] 13 | token, err := cli.Client.CreateToken(user) 14 | if err != nil { 15 | return err 16 | } 17 | cli.OutputFormatter.SetHeaders([]string{ 18 | "ID", 19 | "User", 20 | "Token", 21 | "Creator", 22 | "Expiration", 23 | "Roles", 24 | "Expired", 25 | }) 26 | rowErr := cli.OutputFormatter.AddRow([]string{ 27 | token.ID, 28 | token.User, 29 | token.Token, 30 | token.Creator, 31 | token.Expiration.String(), 32 | strings.Join(token.Roles, ", "), 33 | fmt.Sprintf("%t", token.Expired), 34 | }) 35 | if rowErr != nil { 36 | return rowErr 37 | } 38 | cli.OutputFormatter.Draw() 39 | return nil 40 | } 41 | 42 | func createTokenCommand() *cobra.Command { 43 | cmd := &cobra.Command{ 44 | Use: "create username", 45 | Short: "creates an api token in rundeck for the named user", 46 | Args: cobra.MinimumNArgs(1), 47 | RunE: createTokenFunc, 48 | } 49 | rootCmd := cli.New(cmd) 50 | return rootCmd 51 | } 52 | -------------------------------------------------------------------------------- /vendor/github.com/mitchellh/mapstructure/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Mitchell Hashimoto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/lusis/outputter/errors.go: -------------------------------------------------------------------------------- 1 | package outputter 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | // ErrorHeadersAlreadyAdded is an error for already having headers set 8 | var ErrorHeadersAlreadyAdded = errors.New("Headers already set. Cannot overwrite") 9 | 10 | // ErrorOutputAddRowNoHeaders is an error for not having yet called SetHeaders() 11 | var ErrorOutputAddRowNoHeaders = errors.New("Cannot AddRow with before calling SetHeaders") 12 | 13 | // ErrorOutputAddRowTooFewHeaders is an error for having fewer keys than values 14 | var ErrorOutputAddRowTooFewHeaders = errors.New("Cannot AddRow with more values than headers") 15 | 16 | // ErrorUnknownOutputter is an error for specifying an unknown ErrorUnknownFormatter 17 | var ErrorUnknownOutputter = errors.New("Unknown formatter specified") 18 | 19 | // ErrorInvalidOutputter is an error for specifying that a registered output isn't an Ouputter 20 | var ErrorInvalidOutputter = errors.New("Specified outputter is invalid") 21 | 22 | // ErrorCannotChangeWriter is an error for specifying that an output does not allow changing the writer after data is populated 23 | var ErrorCannotChangeWriter = errors.New("Must call SetWriter before any data is added") 24 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/project.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | ) 6 | 7 | func projectPoliciesCommands() *cobra.Command { 8 | cmd := &cobra.Command{ 9 | Use: "policy", 10 | Short: "operate on rundeck project acl policies", 11 | } 12 | cmd.AddCommand(getProjectACLPolicyCommand()) 13 | cmd.AddCommand(deleteProjectACLPolicyCommand()) 14 | cmd.AddCommand(updateProjectACLPolicyCommand()) 15 | cmd.AddCommand(createProjectACLPolicyCommand()) 16 | cmd.AddCommand(deleteProjectACLPolicyCommand()) 17 | cmd.AddCommand(listProjectACLPoliciesCommand()) 18 | return cmd 19 | } 20 | 21 | func projectCommands() *cobra.Command { 22 | cmd := &cobra.Command{ 23 | Use: "project", 24 | Short: "operate on a rundeck project", 25 | } 26 | cmd.AddCommand(getProjectCommand()) 27 | cmd.AddCommand(deleteProjectCommand()) 28 | cmd.AddCommand(createProjectCommand()) 29 | cmd.AddCommand(getJobsCommand()) 30 | cmd.AddCommand(projectExecutionsCommand()) 31 | cmd.AddCommand(projectHistoryCommand()) 32 | cmd.AddCommand(getProjectConfigCommand()) 33 | cmd.AddCommand(exportProjectCommand()) 34 | cmd.AddCommand(projectPoliciesCommands()) 35 | cmd.AddCommand(scmCommands()) 36 | return cmd 37 | } 38 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/list_project_acl_policies.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/lusis/go-rundeck/pkg/cli" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func listProjectACLPoliciesFunc(cmd *cobra.Command, args []string) error { 9 | projectName := args[0] 10 | policies, err := cli.Client.ListProjectACLPolicies(projectName) 11 | if err != nil { 12 | return err 13 | } 14 | cli.OutputFormatter.SetHeaders([]string{ 15 | "Name", 16 | "Path", 17 | "Type", 18 | "HRef", 19 | "Parent", 20 | "Parent Type", 21 | }) 22 | parent := "/" 23 | if policies.Path != "" { 24 | parent = policies.Path 25 | } 26 | for _, p := range policies.Resources { 27 | if err := cli.OutputFormatter.AddRow([]string{ 28 | p.Name, 29 | p.Path, 30 | p.Type, 31 | p.Href, 32 | parent, 33 | policies.Type, 34 | }); err != nil { 35 | return err 36 | } 37 | } 38 | cli.OutputFormatter.Draw() 39 | return nil 40 | } 41 | 42 | func listProjectACLPoliciesCommand() *cobra.Command { 43 | cmd := &cobra.Command{ 44 | Use: "list", 45 | Short: "lists system acl policies", 46 | Args: cobra.MinimumNArgs(1), 47 | RunE: listProjectACLPoliciesFunc, 48 | } 49 | rootCmd := cli.New(cmd) 50 | return rootCmd 51 | } 52 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/common_test.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | import ( 4 | "encoding/json" 5 | "io/ioutil" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | type testTS struct { 12 | DateTime *JSONTime `json:"datetime"` 13 | } 14 | 15 | type testDuration struct { 16 | Duration *JSONDuration `json:"duration"` 17 | } 18 | 19 | func TestUnmarshal(t *testing.T) { 20 | str := `{"datetime":"2015-05-13T16:58:59Z"}` 21 | obj := &testTS{} 22 | err := json.Unmarshal([]byte(str), &obj) 23 | require.NoError(t, err) 24 | require.Equal(t, 2015, obj.DateTime.Year()) 25 | } 26 | 27 | func TestUnmarshalNil(t *testing.T) { 28 | str := `{"datetime":null}` 29 | obj := &testTS{} 30 | err := json.Unmarshal([]byte(str), &obj) 31 | require.NoError(t, err) 32 | } 33 | 34 | func getAssetBytes(fileName string) ([]byte, error) { 35 | data, err := assets.Open(fileName) 36 | if err != nil { 37 | return nil, err 38 | } 39 | return ioutil.ReadAll(data) 40 | } 41 | 42 | func TestUnmarshalJSONDuration(t *testing.T) { 43 | str := `{"duration": "1h"}` 44 | obj := &testDuration{} 45 | err := json.Unmarshal([]byte(str), &obj) 46 | require.NoError(t, err) 47 | require.Equal(t, float64(3600), obj.Duration.Seconds()) 48 | } 49 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/tokens.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "user": "user3", 4 | "id": "ece75ac8-2791-442e-b179-a9907d83fd05", 5 | "creator": "user3", 6 | "expiration": "2017-03-25T21:16:50Z", 7 | "roles": [ 8 | "DEV_99", 9 | "FEDCD25B-C945-48D3-9821-A10D44535EA4" 10 | ], 11 | "expired": false 12 | }, 13 | { 14 | "user": "user3", 15 | "id": "abcb096f-cef4-451a-bd2b-43284a3ff2ad", 16 | "creator": "user3", 17 | "expiration": "2017-03-25T21:17:12Z", 18 | "roles": [ 19 | "SVC_XYZ", 20 | "devops", 21 | "user3" 22 | ], 23 | "expired": false 24 | }, 25 | { 26 | "user": "user3", 27 | "id": "a99bd86d-0125-4eaa-9b16-caded4485476", 28 | "creator": "user3", 29 | "expiration": "2018-03-24T21:17:26Z", 30 | "roles": [ 31 | "user", 32 | "FEDCD25B-C945-48D3-9821-A10D44535EA4" 33 | ], 34 | "expired": false 35 | }, 36 | { 37 | "user": "user3", 38 | "id": "c13de457-c429-4476-9acd-e1c89e3c2928", 39 | "creator": "user3", 40 | "expiration": "2017-03-24T21:18:55Z", 41 | "roles": [ 42 | "USER_ACCOUNT" 43 | ], 44 | "expired": true 45 | } 46 | ] -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell 2 | 3 | Please consider promoting this project if you find it useful. 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the "Software"), to deal in the Software without restriction, 8 | including without limitation the rights to use, copy, modify, merge, 9 | publish, distribute, sublicense, and/or sell copies of the Software, 10 | and to permit persons to whom the Software is furnished to do so, 11 | subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included 14 | in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 20 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 21 | OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 22 | OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /vendor/github.com/mitchellh/mapstructure/error.go: -------------------------------------------------------------------------------- 1 | package mapstructure 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "sort" 7 | "strings" 8 | ) 9 | 10 | // Error implements the error interface and can represents multiple 11 | // errors that occur in the course of a single decode. 12 | type Error struct { 13 | Errors []string 14 | } 15 | 16 | func (e *Error) Error() string { 17 | points := make([]string, len(e.Errors)) 18 | for i, err := range e.Errors { 19 | points[i] = fmt.Sprintf("* %s", err) 20 | } 21 | 22 | sort.Strings(points) 23 | return fmt.Sprintf( 24 | "%d error(s) decoding:\n\n%s", 25 | len(e.Errors), strings.Join(points, "\n")) 26 | } 27 | 28 | // WrappedErrors implements the errwrap.Wrapper interface to make this 29 | // return value more useful with the errwrap and go-multierror libraries. 30 | func (e *Error) WrappedErrors() []error { 31 | if e == nil { 32 | return nil 33 | } 34 | 35 | result := make([]error, len(e.Errors)) 36 | for i, e := range e.Errors { 37 | result[i] = errors.New(e) 38 | } 39 | 40 | return result 41 | } 42 | 43 | func appendErrors(errors []string, err error) []string { 44 | switch e := err.(type) { 45 | case *Error: 46 | return append(errors, e.Errors...) 47 | default: 48 | return append(errors, e.Error()) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/scm_setup.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/lusis/go-rundeck/pkg/cli" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func setupProjectSCMFunc(cmd *cobra.Command, args []string) error { 9 | projectName := args[0] 10 | integration := args[1] 11 | pluginType := args[2] 12 | 13 | params, paramsErr := ParseSliceKeyValue(scmSetupParams) 14 | if paramsErr != nil { 15 | return paramsErr 16 | } 17 | _, err := cli.Client.SetupSCMPluginForProject(projectName, integration, pluginType, params) 18 | return err 19 | } 20 | func setupProjectSCMCommand() *cobra.Command { 21 | cmd := &cobra.Command{ 22 | Use: "setup project-name integration plugin-type -o setting=value [-o setting=value]", 23 | Short: "sets up scm integration for a rundeck project", 24 | Example: "setup fooprj import git-import -o dir=/var/tmp/fooprj -o url=/home/rundeck-import.git/ -o pathTemplate=\\${job.group}\\${job.name}-\\${job.id}.\\${config.format} -o branch=master -o format=yaml -o strictHostKeyChecking=no", 25 | Args: cobra.MinimumNArgs(3), 26 | RunE: setupProjectSCMFunc, 27 | } 28 | 29 | rootCmd := cli.New(cmd) 30 | rootCmd.Flags().StringSliceVarP(&scmSetupParams, "option", "o", []string{}, "repeatable list of key/value options in the format of key=value") 31 | return rootCmd 32 | } 33 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/acl_test.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/mitchellh/mapstructure" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestACLReponses(t *testing.T) { 12 | testCases := []struct{ 13 | name string 14 | placeholder interface{} 15 | obj interface{} 16 | testfile string 17 | }{ 18 | { 19 | name: "ACLResponse", 20 | placeholder: make(map[string]interface{}), 21 | obj: &ACLResponse{}, 22 | testfile: ACLResponseTestFile, 23 | }, 24 | { 25 | name: "FailedACLValidationResponse", 26 | placeholder: make(map[string]interface{}), 27 | obj: &FailedACLValidationResponse{}, 28 | testfile: FailedACLValidationResponseTestFile, 29 | }, 30 | } 31 | for _, tc := range testCases { 32 | t.Run(tc.name, func(t *testing.T) { 33 | data, err := getAssetBytes(tc.testfile) 34 | require.NoError(t, err) 35 | err = json.Unmarshal(data, &tc.placeholder) 36 | require.NoError(t, err) 37 | config := newMSDecoderConfig() 38 | config.Result = tc.obj 39 | decoder, err := mapstructure.NewDecoder(config) 40 | require.NoError(t, err) 41 | err = decoder.Decode(tc.placeholder) 42 | require.NoError(t, err) 43 | require.Implements(t, (*VersionedResponse)(nil), tc.obj) 44 | }) 45 | } 46 | } -------------------------------------------------------------------------------- /pkg/rundeck/responses/keys_test.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/mitchellh/mapstructure" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestKeysReponses(t *testing.T) { 12 | testCases := []struct{ 13 | name string 14 | placeholder interface{} 15 | obj interface{} 16 | testfile string 17 | }{ 18 | { 19 | name: "ListKeysResourceResponse", 20 | placeholder: make(map[string]interface{}), 21 | obj: &ListKeysResourceResponse{}, 22 | testfile: ListKeysResourceResponseTestFile, 23 | }, 24 | { 25 | name: "ListKeysResponse", 26 | placeholder: make(map[string]interface{}), 27 | obj: &ListKeysResponse{}, 28 | testfile: ListKeysResponseTestFile, 29 | }, 30 | } 31 | for _, tc := range testCases { 32 | t.Run(tc.name, func(t *testing.T) { 33 | data, err := getAssetBytes(tc.testfile) 34 | require.NoError(t, err) 35 | err = json.Unmarshal(data, &tc.placeholder) 36 | require.NoError(t, err) 37 | config := newMSDecoderConfig() 38 | config.Result = tc.obj 39 | decoder, err := mapstructure.NewDecoder(config) 40 | require.NoError(t, err) 41 | err = decoder.Decode(tc.placeholder) 42 | require.NoError(t, err) 43 | require.Implements(t, (*VersionedResponse)(nil), tc.obj) 44 | }) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /pkg/rundeck/system_info_test.go: -------------------------------------------------------------------------------- 1 | package rundeck 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/lusis/go-rundeck/pkg/rundeck/responses" 7 | 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestGetSystemInfo(t *testing.T) { 12 | jsonfile, err := responses.GetTestData(responses.SystemInfoResponseTestFile) 13 | if err != nil { 14 | t.Fatalf(err.Error()) 15 | } 16 | 17 | client, server, cErr := newTestRundeckClient(jsonfile, "application/json", 200) 18 | defer server.Close() 19 | if cErr != nil { 20 | t.Fatalf(cErr.Error()) 21 | } 22 | 23 | s, err := client.GetSystemInfo() 24 | require.NoError(t, err) 25 | require.NotNil(t, s) 26 | } 27 | 28 | func TestGetSystemJSONError(t *testing.T) { 29 | client, server, cErr := newTestRundeckClient([]byte(""), "application/json", 200) 30 | defer server.Close() 31 | if cErr != nil { 32 | t.Fatalf(cErr.Error()) 33 | } 34 | 35 | s, err := client.GetSystemInfo() 36 | require.Error(t, err) 37 | require.Nil(t, s) 38 | } 39 | 40 | func TestGetSystemInvalidStatus(t *testing.T) { 41 | client, server, cErr := newTestRundeckClient([]byte(""), "application/json", 500) 42 | defer server.Close() 43 | if cErr != nil { 44 | t.Fatalf(cErr.Error()) 45 | } 46 | 47 | s, err := client.GetSystemInfo() 48 | require.Error(t, err) 49 | require.Nil(t, s) 50 | } 51 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/logstorage_test.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/mitchellh/mapstructure" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestLogStorageReponses(t *testing.T) { 12 | testCases := []struct{ 13 | name string 14 | placeholder interface{} 15 | obj interface{} 16 | testfile string 17 | }{ 18 | { 19 | name: "LogStorageResponse", 20 | placeholder: make(map[string]interface{}), 21 | obj: &LogStorageResponse{}, 22 | testfile: LogStorageResponseTestFile, 23 | }, 24 | { 25 | name: "IncompleteLogStorageExecutionResponse", 26 | placeholder: make(map[string]interface{}), 27 | obj: &IncompleteLogStorageResponse{}, 28 | testfile: IncompleteLogStorageResponseTestFile, 29 | }, 30 | } 31 | for _, tc := range testCases { 32 | t.Run(tc.name, func(t *testing.T) { 33 | data, err := getAssetBytes(tc.testfile) 34 | require.NoError(t, err) 35 | err = json.Unmarshal(data, &tc.placeholder) 36 | require.NoError(t, err) 37 | config := newMSDecoderConfig() 38 | config.Result = tc.obj 39 | decoder, err := mapstructure.NewDecoder(config) 40 | require.NoError(t, err) 41 | err = decoder.Decode(tc.placeholder) 42 | require.NoError(t, err) 43 | require.Implements(t, (*VersionedResponse)(nil), tc.obj) 44 | }) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/history.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/lusis/go-rundeck/pkg/cli" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | func projectHistoryFunc(cmd *cobra.Command, args []string) error { 11 | projectid := args[0] 12 | data, err := cli.Client.ListHistory(projectid) 13 | if err != nil { 14 | return err 15 | } 16 | cli.OutputFormatter.SetHeaders([]string{ 17 | "Title", 18 | "Status", 19 | "Summary", 20 | "Start Time", 21 | "End Time", 22 | "S/F/T", 23 | "Execution", 24 | "User", 25 | "Project", 26 | }) 27 | for _, d := range data.Events { 28 | if rowErr := cli.OutputFormatter.AddRow([]string{ 29 | d.Title, 30 | d.Status, 31 | d.Summary, 32 | d.DateStarted.String(), 33 | d.DateEnded.String(), 34 | fmt.Sprintf("%d/%d/%d", d.NodeSummary.Succeeded, d.NodeSummary.Failed, d.NodeSummary.Total), 35 | d.Execution.ID, 36 | d.User, 37 | d.Project, 38 | }); rowErr != nil { 39 | return rowErr 40 | } 41 | } 42 | 43 | cli.OutputFormatter.Draw() 44 | return nil 45 | } 46 | func projectHistoryCommand() *cobra.Command { 47 | cmd := &cobra.Command{ 48 | Use: "history project-name", 49 | Short: "gets project history from the rundeck server", 50 | Args: cobra.MinimumNArgs(1), 51 | RunE: projectHistoryFunc, 52 | } 53 | rootCmd := cli.New(cmd) 54 | return rootCmd 55 | } 56 | -------------------------------------------------------------------------------- /pkg/rundeck/history.go: -------------------------------------------------------------------------------- 1 | package rundeck 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | multierror "github.com/hashicorp/go-multierror" 7 | httpclient "github.com/lusis/go-rundeck/pkg/httpclient" 8 | responses "github.com/lusis/go-rundeck/pkg/rundeck/responses" 9 | ) 10 | 11 | // History represents a project history 12 | type History struct { 13 | responses.HistoryResponse 14 | } 15 | 16 | // ListHistory returns the history for a project 17 | // http://rundeck.org/docs/api/index.html#listing-history 18 | func (c *Client) ListHistory(project string, opts ...map[string]string) (*History, error) { 19 | if err := c.checkRequiredAPIVersion(responses.HistoryResponse{}); err != nil { 20 | return nil, err 21 | } 22 | u := make(map[string]string) 23 | for _, opt := range opts { 24 | for k, v := range opt { 25 | u[k] = v 26 | } 27 | } 28 | data := &History{} 29 | options := []httpclient.RequestOption{ 30 | accept("application/json"), 31 | contentType("application/x-www-form-urlencoded"), 32 | queryParams(u), 33 | requestExpects(200), 34 | } 35 | res, err := c.httpGet("project/"+project+"/history", options...) 36 | if err != nil { 37 | return nil, err 38 | } 39 | if jsonErr := json.Unmarshal(res, data); jsonErr != nil { 40 | return nil, &UnmarshalError{msg: multierror.Append(errDecoding, jsonErr).Error()} 41 | } 42 | return data, nil 43 | } 44 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:stretch 2 | LABEL authors="John E. Vincent " 3 | ENV DEBIAN_FRONTEND noninteractive 4 | ARG RDECK_VER 5 | EXPOSE 4440:4440 6 | 7 | RUN apt-get update 8 | RUN apt-get install -yq openssh-client curl uuid-runtime python3 git gnupg2 apt-transport-https 9 | 10 | RUN echo "deb https://rundeck.bintray.com/rundeck-deb /" | tee -a /etc/apt/sources.list.d/rundeck.list 11 | RUN curl 'https://bintray.com/user/downloadSubjectPublicKey?username=bintray' | apt-key add - 12 | RUN apt-get update 13 | RUN apt-get install -yq rundeck=${RDECK_VER} 14 | 15 | ADD rundeckd.init /etc/init.d/rundeckd 16 | ADD admin.aclpolicy /etc/rundeck/admin.aclpolicy 17 | ADD apitoken.aclpolicy /etc/rundeck/apitoken.aclpolicy 18 | ADD realm.properties /etc/rundeck/realm.properties 19 | ADD token.properties /etc/rundeck/token.properties 20 | RUN sed -ie "s/-Dserver.http.port/-Dfile.encoding=UTF-8 -Dserver.http.port/g" /etc/rundeck/profile 21 | RUN sed -ie "s/grails.serverURL=http:\/\/localhost:4440/grails.serverURL=http:\/\/127.0.0.1:4440/g" /etc/rundeck/rundeck-config.properties 22 | RUN echo "rundeck.tokens.file=/etc/rundeck/token.properties" >> /etc/rundeck/framework.properties 23 | ADD gitrepo.sh /gitrepo.sh 24 | RUN chmod +x /gitrepo.sh 25 | RUN /gitrepo.sh 26 | RUN chmod +x /etc/init.d/rundeckd 27 | 28 | CMD /etc/init.d/rundeckd foreground 29 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/find_job_by_name.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/lusis/go-rundeck/pkg/cli" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | func findJobByNameFunc(cmd *cobra.Command, args []string) error { 11 | jobname := args[0] 12 | 13 | res, err := cli.Client.FindJobByName(jobname) 14 | if err != nil { 15 | return err 16 | } 17 | cli.OutputFormatter.SetHeaders([]string{ 18 | "ID", 19 | "Name", 20 | "Project", 21 | "Description", 22 | "Group", 23 | "Scheduled?", 24 | "Schedule Enabled?", 25 | "Enabled?", 26 | "Average Duration", 27 | }) 28 | for _, data := range res { 29 | if rowErr := cli.OutputFormatter.AddRow([]string{ 30 | data.ID, 31 | data.Name, 32 | data.Project, 33 | data.Description, 34 | data.Group, 35 | fmt.Sprintf("%t", data.Scheduled), 36 | fmt.Sprintf("%t", data.ScheduleEnabled), 37 | fmt.Sprintf("%t", data.Enabled), 38 | fmt.Sprintf("%d", data.AverageDuration), 39 | }); rowErr != nil { 40 | return rowErr 41 | } 42 | } 43 | cli.OutputFormatter.Draw() 44 | return nil 45 | } 46 | 47 | func findJobByNameCommand() *cobra.Command { 48 | cmd := &cobra.Command{ 49 | Use: "find job-name", 50 | Short: "finds a project's job by name", 51 | Args: cobra.MinimumNArgs(1), 52 | RunE: findJobByNameFunc, 53 | } 54 | rootCmd := cli.New(cmd) 55 | return rootCmd 56 | } 57 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/scm_enable_disable.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "github.com/lusis/go-rundeck/pkg/cli" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func enableProjectSCMFunc(cmd *cobra.Command, args []string) error { 9 | projectName := args[0] 10 | integration := args[1] 11 | pluginType := args[2] 12 | return cli.Client.EnableSCMPluginForProject(projectName, integration, pluginType) 13 | } 14 | 15 | func disableProjectSCMFunc(cmd *cobra.Command, args []string) error { 16 | projectName := args[0] 17 | integration := args[1] 18 | pluginType := args[2] 19 | return cli.Client.DisableSCMPluginForProject(projectName, integration, pluginType) 20 | } 21 | 22 | func enableProjectSCMCommand() *cobra.Command { 23 | cmd := &cobra.Command{ 24 | Use: "enable integration plugin-type", 25 | Short: "enables a project's scm configuration", 26 | Args: cobra.MinimumNArgs(3), 27 | RunE: enableProjectSCMFunc, 28 | } 29 | rootCmd := cli.New(cmd) 30 | rootCmd.ResetFlags() 31 | return rootCmd 32 | } 33 | 34 | func disableProjectSCMCommand() *cobra.Command { 35 | cmd := &cobra.Command{ 36 | Use: "disable project-name integration plugin-type", 37 | Short: "disables a project's scm configuration", 38 | Args: cobra.MinimumNArgs(3), 39 | RunE: disableProjectSCMFunc, 40 | } 41 | rootCmd := cli.New(cmd) 42 | rootCmd.ResetFlags() 43 | return rootCmd 44 | } 45 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/toggle_execution.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "errors" 5 | "strconv" 6 | 7 | "github.com/lusis/go-rundeck/pkg/cli" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | func toggleExecutionFunc(cmd *cobra.Command, args []string) error { 12 | action := args[1] 13 | switch action { 14 | case enable: 15 | return enableExecutionFunc(cmd, args) 16 | case disable: 17 | return disableExecutionFunc(cmd, args) 18 | default: 19 | return errors.New("action must be one of 'enable' or 'disable'") 20 | } 21 | } 22 | 23 | func disableExecutionFunc(cmd *cobra.Command, args []string) error { 24 | id := args[0] 25 | i, iErr := strconv.Atoi(id) 26 | if iErr != nil { 27 | return iErr 28 | } 29 | _, err := cli.Client.DisableExecution(i) 30 | return err 31 | 32 | } 33 | 34 | func enableExecutionFunc(cmd *cobra.Command, args []string) error { 35 | id := args[0] 36 | i, iErr := strconv.Atoi(id) 37 | if iErr != nil { 38 | return iErr 39 | } 40 | _, err := cli.Client.EnableExecution(i) 41 | return err 42 | 43 | } 44 | 45 | func toggleExecutionCommand() *cobra.Command { 46 | cmd := &cobra.Command{ 47 | Use: "toggle job-id [enable|disable]", 48 | Short: "enables or disables an execution on the rundeck server", 49 | Args: cobra.MinimumNArgs(2), 50 | RunE: toggleExecutionFunc, 51 | } 52 | rootCmd := cli.New(cmd) 53 | rootCmd.ResetFlags() 54 | return rootCmd 55 | } 56 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/get_job.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/lusis/go-rundeck/pkg/cli" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | func getJobFunc(cmd *cobra.Command, args []string) error { 11 | jobid := args[0] 12 | data, err := cli.Client.GetJobMetaData(jobid) 13 | if err != nil { 14 | return err 15 | } 16 | cli.OutputFormatter.SetHeaders([]string{ 17 | "ID", 18 | "Name", 19 | "Description", 20 | "Group", 21 | "Scheduled?", 22 | "Schedule Enabled?", 23 | "Enabled?", 24 | "Average Duration", 25 | }) 26 | description := "" 27 | if data.Description != "" { 28 | description = data.Description 29 | } 30 | group := "" 31 | if data.Group != "" { 32 | group = data.Group 33 | } 34 | if rowErr := cli.OutputFormatter.AddRow([]string{ 35 | data.ID, 36 | data.Name, 37 | description, 38 | group, 39 | fmt.Sprintf("%t", data.Scheduled), 40 | fmt.Sprintf("%t", data.ScheduleEnabled), 41 | fmt.Sprintf("%t", data.Enabled), 42 | fmt.Sprintf("%d", data.AverageDuration), 43 | }); rowErr != nil { 44 | return rowErr 45 | } 46 | cli.OutputFormatter.Draw() 47 | return nil 48 | } 49 | 50 | func getJobCommand() *cobra.Command { 51 | cmd := &cobra.Command{ 52 | Use: "get job-id", 53 | Short: "gets job metadata from a rundeck server", 54 | Args: cobra.MinimumNArgs(1), 55 | RunE: getJobFunc, 56 | } 57 | rootCmd := cli.New(cmd) 58 | return rootCmd 59 | } 60 | -------------------------------------------------------------------------------- /vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | // +build go1.4 3 | 4 | package mousetrap 5 | 6 | import ( 7 | "os" 8 | "syscall" 9 | "unsafe" 10 | ) 11 | 12 | func getProcessEntry(pid int) (*syscall.ProcessEntry32, error) { 13 | snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0) 14 | if err != nil { 15 | return nil, err 16 | } 17 | defer syscall.CloseHandle(snapshot) 18 | var procEntry syscall.ProcessEntry32 19 | procEntry.Size = uint32(unsafe.Sizeof(procEntry)) 20 | if err = syscall.Process32First(snapshot, &procEntry); err != nil { 21 | return nil, err 22 | } 23 | for { 24 | if procEntry.ProcessID == uint32(pid) { 25 | return &procEntry, nil 26 | } 27 | err = syscall.Process32Next(snapshot, &procEntry) 28 | if err != nil { 29 | return nil, err 30 | } 31 | } 32 | } 33 | 34 | // StartedByExplorer returns true if the program was invoked by the user double-clicking 35 | // on the executable from explorer.exe 36 | // 37 | // It is conservative and returns false if any of the internal calls fail. 38 | // It does not guarantee that the program was run from a terminal. It only can tell you 39 | // whether it was launched from explorer.exe 40 | func StartedByExplorer() bool { 41 | pe, err := getProcessEntry(os.Getppid()) 42 | if err != nil { 43 | return false 44 | } 45 | return "explorer.exe" == syscall.UTF16ToString(pe.ExeFile[:]) 46 | } 47 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/imported_job.json: -------------------------------------------------------------------------------- 1 | { 2 | "succeeded": [ 3 | { 4 | "index": 1, 5 | "href": "http://madmartigan.local:4440/api/14/job/3b6c19f6-41ee-475f-8fd0-8f1a26f27a9a", 6 | "id": "3b6c19f6-41ee-475f-8fd0-8f1a26f27a9a", 7 | "name": "good", 8 | "group": "app2/dev", 9 | "project": "test", 10 | "permalink": "http://madmartigan.local:4440/job/show/3b6c19f6-41ee-475f-8fd0-8f1a26f27a9a" 11 | } 12 | ], 13 | "failed": [ 14 | { 15 | "index": 2, 16 | "href": "http://madmartigan.local:4440/api/14/job/3b6c19f6-41ee-475f-8fd0-8f1a26f27a9a", 17 | "id": "3b6c19f6-41ee-475f-8fd0-8f1a26f27a9a", 18 | "name": "bad", 19 | "group": "app2/dev", 20 | "project": "test", 21 | "permalink": "http://madmartigan.local:4440/job/show/3b6c19f6-41ee-475f-8fd0-8f1a26f27a9a" 22 | } 23 | ], 24 | "skipped": [ 25 | { 26 | "index": 3, 27 | "href": "http://madmartigan.local:4440/api/14/job/3b6c19f6-41ee-475f-8fd0-8f1a26f27a9a", 28 | "id": "3b6c19f6-41ee-475f-8fd0-8f1a26f27a9a", 29 | "name": "skipped", 30 | "group": "app2/dev", 31 | "project": "test", 32 | "permalink": "http://madmartigan.local:4440/job/show/3b6c19f6-41ee-475f-8fd0-8f1a26f27a9a" 33 | } 34 | ] 35 | } -------------------------------------------------------------------------------- /docker/apitoken.aclpolicy: -------------------------------------------------------------------------------- 1 | description: API project level access control 2 | context: 3 | project: '.*' # all projects 4 | for: 5 | resource: 6 | - equals: 7 | kind: job 8 | allow: [create,delete] # allow create and delete jobs 9 | - equals: 10 | kind: node 11 | allow: [read,create,update,refresh] # allow refresh node sources 12 | - equals: 13 | kind: event 14 | allow: [read,create] # allow read/create events 15 | - equals: 16 | kind: system_acl 17 | allow: [read] 18 | adhoc: 19 | - allow: [read,run,kill] # allow running/killing adhoc jobs and read output 20 | job: 21 | - allow: [create,read,update,delete,run,kill] # allow create/read/write/delete/run/kill of all jobs 22 | node: 23 | - allow: [read,run] # allow read/run for all nodes 24 | by: 25 | group: api_token_group 26 | 27 | --- 28 | 29 | description: API Application level access control 30 | context: 31 | application: 'rundeck' 32 | for: 33 | resource: 34 | - equals: 35 | kind: system 36 | allow: [read] # allow read of system info 37 | - equals: 38 | kind: system_acl 39 | allow: [read] 40 | project: 41 | - match: 42 | name: '.*' 43 | allow: [read,create] # allow view of all projects 44 | storage: 45 | - match: 46 | path: '(keys|keys/.*)' 47 | allow: '*' # allow all access to manage stored keys 48 | by: 49 | group: api_token_group 50 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/LICENSE.libyaml: -------------------------------------------------------------------------------- 1 | The following files were ported to Go from C files of libyaml, and thus 2 | are still covered by their original copyright and license: 3 | 4 | apic.go 5 | emitterc.go 6 | parserc.go 7 | readerc.go 8 | scannerc.go 9 | writerc.go 10 | yamlh.go 11 | yamlprivateh.go 12 | 13 | Copyright (c) 2006 Kirill Simonov 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy of 16 | this software and associated documentation files (the "Software"), to deal in 17 | the Software without restriction, including without limitation the rights to 18 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 19 | of the Software, and to permit persons to whom the Software is furnished to do 20 | so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in all 23 | copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/lusis/go-rundeck 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/davecgh/go-spew v1.1.1 // indirect 7 | github.com/fatih/color v1.7.0 // indirect 8 | github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce // indirect 9 | github.com/hashicorp/go-multierror v0.0.0-20171204182908-b7773ae21874 10 | github.com/inconshreveable/mousetrap v1.0.0 // indirect 11 | github.com/kr/pretty v0.1.0 // indirect 12 | github.com/lusis/outputter v0.0.0-20171130132426-5a3b464a163f 13 | github.com/mattn/go-colorable v0.1.1 // indirect 14 | github.com/mattn/go-isatty v0.0.7 // indirect 15 | github.com/mattn/go-runewidth v0.0.2 // indirect 16 | github.com/mitchellh/mapstructure v0.0.0-20171017171808-06020f85339e 17 | github.com/olekukonko/tablewriter v0.0.0-20171203151007-65fec0d89a57 // indirect 18 | github.com/pmezard/go-difflib v1.0.0 // indirect 19 | github.com/shurcooL/httpfs v0.0.0-20181222201310-74dc9339e414 // indirect 20 | github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd 21 | github.com/spf13/cobra v0.0.1 22 | github.com/spf13/pflag v1.0.0 // indirect 23 | github.com/stretchr/testify v1.1.4 24 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 25 | golang.org/x/sys v0.0.0-20190412213103-97732733099d // indirect 26 | golang.org/x/tools v0.0.0-20190430194229-2d28432af7a5 // indirect 27 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect 28 | gopkg.in/yaml.v2 v2.0.0-20171116090243-287cf08546ab 29 | ) 30 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/scm_list_plugins.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/lusis/go-rundeck/pkg/cli" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | func listProjectSCMPluginsFunc(cmd *cobra.Command, args []string) error { 11 | projectName := args[0] 12 | data, err := cli.Client.ListSCMPlugins(projectName) 13 | if err != nil { 14 | return err 15 | } 16 | cli.OutputFormatter.SetHeaders([]string{ 17 | "Title", 18 | "Description", 19 | "Enabled?", 20 | "Configured?", 21 | "Type", 22 | }) 23 | for _, p := range data.Import { 24 | if rowErr := cli.OutputFormatter.AddRow([]string{ 25 | p.Title, 26 | p.Description, 27 | fmt.Sprintf("%t", p.Enabled), 28 | fmt.Sprintf("%t", p.Configured), 29 | p.Type, 30 | }); rowErr != nil { 31 | return err 32 | } 33 | } 34 | for _, p := range data.Export { 35 | if rowErr := cli.OutputFormatter.AddRow([]string{ 36 | p.Title, 37 | p.Description, 38 | fmt.Sprintf("%t", p.Enabled), 39 | fmt.Sprintf("%t", p.Configured), 40 | p.Type, 41 | }); rowErr != nil { 42 | return err 43 | } 44 | } 45 | cli.OutputFormatter.Draw() 46 | return nil 47 | } 48 | 49 | func listProjectSCMPluginsCommand() *cobra.Command { 50 | cmd := &cobra.Command{ 51 | Use: "list-plugins project-name", 52 | Short: "lists a project's scm plugins", 53 | Args: cobra.MinimumNArgs(1), 54 | RunE: listProjectSCMPluginsFunc, 55 | } 56 | rootCmd := cli.New(cmd) 57 | return rootCmd 58 | } 59 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/get_execution.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | 7 | cli "github.com/lusis/go-rundeck/pkg/cli" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | func getExecutionFunc(cmd *cobra.Command, args []string) error { 12 | id := args[0] 13 | eID, eIDerr := strconv.Atoi(id) 14 | if eIDerr != nil { 15 | return eIDerr 16 | } 17 | data, err := cli.Client.GetExecutionInfo(eID) 18 | if err != nil { 19 | return err 20 | } 21 | cli.OutputFormatter.SetHeaders([]string{ 22 | "ID", 23 | "User", 24 | "Status", 25 | "Start Date", 26 | "End Date", 27 | "Args", 28 | "Server UUID", 29 | "Custom Status", 30 | }) 31 | var dateEnded string 32 | if data.DateEnded.Date == nil { 33 | dateEnded = "running" // nolint: goconst 34 | } else { 35 | dateEnded = data.DateEnded.Date.String() 36 | } 37 | if rowErr := cli.OutputFormatter.AddRow([]string{ 38 | fmt.Sprintf("%d", data.ID), 39 | data.User, 40 | data.Status, 41 | data.DateStarted.Date.String(), 42 | dateEnded, 43 | data.ArgString, 44 | data.ServerUUID, 45 | data.CustomStatus, 46 | }); rowErr != nil { 47 | return rowErr 48 | } 49 | 50 | cli.OutputFormatter.Draw() 51 | return nil 52 | } 53 | func getExecutionCommand() *cobra.Command { 54 | cmd := &cobra.Command{ 55 | Use: "get execution-id", 56 | Short: "gets an execution from the rundeck server", 57 | Args: cobra.MinimumNArgs(1), 58 | RunE: getExecutionFunc, 59 | } 60 | rootCmd := cli.New(cmd) 61 | return rootCmd 62 | } 63 | -------------------------------------------------------------------------------- /pkg/rundeck/error.go: -------------------------------------------------------------------------------- 1 | package rundeck 2 | 3 | // UnmarshalError is a custom error type for decoding errors 4 | type UnmarshalError struct { 5 | msg string 6 | } 7 | 8 | // Error returns the error message 9 | func (e *UnmarshalError) Error() string { 10 | return e.msg 11 | } 12 | 13 | // MarshalError is a custom error type for decoding errors 14 | type MarshalError struct { 15 | msg string 16 | } 17 | 18 | // Error returns the error message 19 | func (e *MarshalError) Error() string { 20 | return e.msg 21 | } 22 | 23 | // OptionError is a custom error type for option errors 24 | type OptionError struct { 25 | msg string 26 | } 27 | 28 | // Error returns the error message 29 | func (e *OptionError) Error() string { 30 | return e.msg 31 | } 32 | 33 | // PolicyValidationError is a custom error type for policy validation errors 34 | type PolicyValidationError struct { 35 | msg string 36 | } 37 | 38 | // Error returns the error message 39 | func (e *PolicyValidationError) Error() string { 40 | return e.msg 41 | } 42 | 43 | // AuthError is a custom error type for decoding errors 44 | type AuthError struct { 45 | msg string 46 | } 47 | 48 | // Error returns the error message 49 | func (e *AuthError) Error() string { 50 | return e.msg 51 | } 52 | 53 | // SCMValidationError is a custom error type for scm validation errors 54 | type SCMValidationError struct { 55 | msg string 56 | } 57 | 58 | // Error returns the error message 59 | func (e *SCMValidationError) Error() string { 60 | return e.msg 61 | } 62 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/executions.json: -------------------------------------------------------------------------------- 1 | { 2 | "paging": { 3 | "count": 2, 4 | "total": 2, 5 | "offset": 0, 6 | "max": 20 7 | }, 8 | "executions": [ 9 | { 10 | "id": 387, 11 | "href": "[API url]", 12 | "permalink": "[GUI url]", 13 | "status": "[status]", 14 | "customStatus": "[string]", 15 | "project": "test", 16 | "user": "[user]", 17 | "serverUUID":"[UUID]", 18 | "date-started": { 19 | "unixtime": 1431536339809, 20 | "date": "2015-05-13T16:58:59Z" 21 | }, 22 | "date-ended": { 23 | "unixtime": 1431536346423, 24 | "date": "2016-05-13T16:59:06Z" 25 | }, 26 | "job": { 27 | "id": "7400ff98-31c4-4834-ba3d-aee9646e867f", 28 | "averageDuration": 6094, 29 | "name": "test job", 30 | "group": "api-test/job-run-steps", 31 | "project": "test", 32 | "description": "", 33 | "href": "[API url]", 34 | "permalink": "[GUI url]", 35 | "options": { 36 | "opt2": "a", 37 | "opt1": "testvalue" 38 | } 39 | }, 40 | "description": "echo hello there [... 5 steps]", 41 | "argstring": "-opt1 testvalue -opt2 a", 42 | "successfulNodes": [ 43 | "madmartigan.local" 44 | ], 45 | "failedNodes": [ 46 | "nodec","noded" 47 | ] 48 | } 49 | ] 50 | } 51 | 52 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/user_test.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | import ( 4 | "encoding/json" 5 | "testing" 6 | 7 | "github.com/mitchellh/mapstructure" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestUserReponses(t *testing.T) { 12 | testCases := []struct{ 13 | name string 14 | placeholder interface{} 15 | obj interface{} 16 | testfile string 17 | }{ 18 | { 19 | name: "UserProfileResponse", 20 | placeholder: make(map[string]interface{}), 21 | obj: &UserProfileResponse{}, 22 | testfile: UserProfileResponseTestFile, 23 | }, 24 | { 25 | name: "UsersInfoResponse", 26 | placeholder: make([]map[string]interface{}, 1, 1), 27 | obj: &ListUsersResponse{}, 28 | testfile: ListUsersResponseTestFile, 29 | }, 30 | { 31 | name: "AuthenticatedUserRolesResponse", 32 | placeholder: make(map[string]interface{}), 33 | obj: &AuthenticatedUserRoles{}, 34 | testfile: AuthenticatedUserRolesTestFile, 35 | }, 36 | } 37 | for _, tc := range testCases { 38 | t.Run(tc.name, func(t *testing.T) { 39 | data, err := getAssetBytes(tc.testfile) 40 | require.NoError(t, err) 41 | err = json.Unmarshal(data, &tc.placeholder) 42 | require.NoError(t, err) 43 | config := newMSDecoderConfig() 44 | config.Result = tc.obj 45 | decoder, err := mapstructure.NewDecoder(config) 46 | require.NoError(t, err) 47 | err = decoder.Decode(tc.placeholder) 48 | require.NoError(t, err) 49 | require.Implements(t, (*VersionedResponse)(nil), tc.obj) 50 | }) 51 | } 52 | } -------------------------------------------------------------------------------- /vendor/github.com/hashicorp/go-multierror/multierror.go: -------------------------------------------------------------------------------- 1 | package multierror 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // Error is an error type to track multiple errors. This is used to 8 | // accumulate errors in cases and return them as a single "error". 9 | type Error struct { 10 | Errors []error 11 | ErrorFormat ErrorFormatFunc 12 | } 13 | 14 | func (e *Error) Error() string { 15 | fn := e.ErrorFormat 16 | if fn == nil { 17 | fn = ListFormatFunc 18 | } 19 | 20 | return fn(e.Errors) 21 | } 22 | 23 | // ErrorOrNil returns an error interface if this Error represents 24 | // a list of errors, or returns nil if the list of errors is empty. This 25 | // function is useful at the end of accumulation to make sure that the value 26 | // returned represents the existence of errors. 27 | func (e *Error) ErrorOrNil() error { 28 | if e == nil { 29 | return nil 30 | } 31 | if len(e.Errors) == 0 { 32 | return nil 33 | } 34 | 35 | return e 36 | } 37 | 38 | func (e *Error) GoString() string { 39 | return fmt.Sprintf("*%#v", *e) 40 | } 41 | 42 | // WrappedErrors returns the list of errors that this Error is wrapping. 43 | // It is an implementation of the errwrap.Wrapper interface so that 44 | // multierror.Error can be used with that library. 45 | // 46 | // This method is not safe to be called concurrently and is no different 47 | // than accessing the Errors field directly. It is implemented only to 48 | // satisfy the errwrap.Wrapper interface. 49 | func (e *Error) WrappedErrors() []error { 50 | return e.Errors 51 | } 52 | -------------------------------------------------------------------------------- /vendor/modules.txt: -------------------------------------------------------------------------------- 1 | # github.com/davecgh/go-spew v1.1.1 2 | github.com/davecgh/go-spew/spew 3 | # github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce 4 | github.com/hashicorp/errwrap 5 | # github.com/hashicorp/go-multierror v0.0.0-20171204182908-b7773ae21874 6 | github.com/hashicorp/go-multierror 7 | # github.com/inconshreveable/mousetrap v1.0.0 8 | github.com/inconshreveable/mousetrap 9 | # github.com/lusis/outputter v0.0.0-20171130132426-5a3b464a163f 10 | github.com/lusis/outputter 11 | # github.com/mattn/go-runewidth v0.0.2 12 | github.com/mattn/go-runewidth 13 | # github.com/mitchellh/mapstructure v0.0.0-20171017171808-06020f85339e 14 | github.com/mitchellh/mapstructure 15 | # github.com/olekukonko/tablewriter v0.0.0-20171203151007-65fec0d89a57 16 | github.com/olekukonko/tablewriter 17 | # github.com/pmezard/go-difflib v1.0.0 18 | github.com/pmezard/go-difflib/difflib 19 | # github.com/shurcooL/httpfs v0.0.0-20181222201310-74dc9339e414 20 | github.com/shurcooL/httpfs/vfsutil 21 | # github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd 22 | github.com/shurcooL/vfsgen 23 | # github.com/spf13/cobra v0.0.1 24 | github.com/spf13/cobra 25 | # github.com/spf13/pflag v1.0.0 26 | github.com/spf13/pflag 27 | # github.com/stretchr/testify v1.1.4 28 | github.com/stretchr/testify/require 29 | github.com/stretchr/testify/suite 30 | github.com/stretchr/testify/assert 31 | # golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 32 | golang.org/x/net/publicsuffix 33 | # gopkg.in/yaml.v2 v2.0.0-20171116090243-287cf08546ab 34 | gopkg.in/yaml.v2 35 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/get_job_scm_diff_import.json: -------------------------------------------------------------------------------- 1 | { 2 | "commit": { 3 | "author": "rundeck", 4 | "commitId": "5e773481877684a9d48643bf89c28aabe4f88763", 5 | "date": "2018-01-08T19:28:26Z", 6 | "info": { 7 | "date": "2018-01-08T19:28:26Z", 8 | "authorEmail": "rundeck@rundeck", 9 | "authorName": "rundeck", 10 | "commitId6": "5e7734", 11 | "commitId": "5e773481877684a9d48643bf89c28aabe4f88763", 12 | "authorTime": "2018-01-08T19:28:26Z", 13 | "authorTimeZone": "GMT+00:00", 14 | "message": "initial commit" 15 | }, 16 | "message": "initial commit" 17 | }, 18 | "diffContent": "@@ -1,5 +1,5 @@\n - description: sleeps a while\n- executionEnabled: true\n+ executionEnabled: false\n group: test\n loglevel: INFO\n multipleExecutions: true\n", 19 | "id": "6c66133e-03ed-48e3-aaa2-d2a646a4e47f", 20 | "incomingCommit": { 21 | "author": "rundeck", 22 | "commitId": "5e773481877684a9d48643bf89c28aabe4f88763", 23 | "date": "2018-01-08T19:28:26Z", 24 | "info": { 25 | "date": "2018-01-08T19:28:26Z", 26 | "authorEmail": "rundeck@rundeck", 27 | "authorName": "rundeck", 28 | "commitId6": "5e7734", 29 | "commitId": "5e773481877684a9d48643bf89c28aabe4f88763", 30 | "authorTime": "2018-01-08T19:28:26Z", 31 | "authorTimeZone": "GMT+00:00", 32 | "message": "initial commit" 33 | }, 34 | "message": "initial commit" 35 | }, 36 | "integration": "import", 37 | "project": "testproject" 38 | } 39 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/create_project.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/lusis/go-rundeck/pkg/cli" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | var ( 12 | createProjectOptions []string 13 | createProjectCmd = &cobra.Command{ 14 | Use: "create project-name [-o foo=bar]", 15 | Short: "creates a rundeck project", 16 | RunE: createProjectFunc, 17 | Args: cobra.MinimumNArgs(1), 18 | } 19 | ) 20 | 21 | func createProjectFunc(cmd *cobra.Command, args []string) error { 22 | projectName := args[0] 23 | params, paramErr := cli.BuildParams(createProjectOptions) 24 | if paramErr != nil { 25 | return paramErr 26 | } 27 | data, err := cli.Client.CreateProject(projectName, params) 28 | if err != nil { 29 | return err 30 | } 31 | cli.OutputFormatter.SetHeaders([]string{ 32 | "URL", 33 | "Name", 34 | "Description", 35 | "Config", 36 | }) 37 | var config []string 38 | for k, v := range data.Properties { 39 | config = append(config, fmt.Sprintf("%s - %s ", k, v)) 40 | } 41 | if rowErr := cli.OutputFormatter.AddRow([]string{ 42 | data.URL, 43 | data.Name, 44 | data.Description, 45 | strings.Join(config, "\n"), 46 | }); rowErr != nil { 47 | return rowErr 48 | } 49 | cli.OutputFormatter.Draw() 50 | return nil 51 | } 52 | 53 | func createProjectCommand() *cobra.Command { 54 | cmd := cli.New(createProjectCmd) 55 | cmd.Flags().StringSliceVarP(&createProjectOptions, "options", "o", []string{}, "custom options to pass in format of name=value. Can specify multiple times") 56 | return cmd 57 | } 58 | -------------------------------------------------------------------------------- /vendor/github.com/pmezard/go-difflib/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Patrick Mezard 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | The names of its contributors may not be used to endorse or promote 14 | products derived from this software without specific prior written 15 | permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 18 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 20 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 23 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/list_keys.json: -------------------------------------------------------------------------------- 1 | { 2 | "resources": [ 3 | { 4 | "meta": { 5 | "Rundeck-key-type": "private", 6 | "Rundeck-content-mask": "content", 7 | "Rundeck-content-size": "1679", 8 | "Rundeck-content-type": "application/octet-stream" 9 | }, 10 | "url": "http://dignan.local:4440/api/11/storage/keys/test1.pem", 11 | "name": "test1.pem", 12 | "type": "file", 13 | "path": "keys/test1.pem" 14 | }, 15 | { 16 | "url": "http://dignan.local:4440/api/11/storage/keys/subdir", 17 | "type": "directory", 18 | "path": "keys/subdir" 19 | }, 20 | { 21 | "meta": { 22 | "Rundeck-key-type": "public", 23 | "Rundeck-content-size": "640198", 24 | "Rundeck-content-type": "application/pgp-keys" 25 | }, 26 | "url": "http://dignan.local:4440/api/11/storage/keys/monkey1.pub", 27 | "name": "monkey1.pub", 28 | "type": "file", 29 | "path": "keys/monkey1.pub" 30 | }, 31 | { 32 | "meta": { 33 | "Rundeck-key-type": "public", 34 | "Rundeck-content-size": "393", 35 | "Rundeck-content-type": "application/pgp-keys" 36 | }, 37 | "url": "http://dignan.local:4440/api/11/storage/keys/test1.pub", 38 | "name": "test1.pub", 39 | "type": "file", 40 | "path": "keys/test1.pub" 41 | } 42 | ], 43 | "url": "http://dignan.local:4440/api/11/storage/keys", 44 | "type": "directory", 45 | "path": "keys" 46 | } -------------------------------------------------------------------------------- /vendor/github.com/olekukonko/tablewriter/csv.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Oleku Konko All rights reserved. 2 | // Use of this source code is governed by a MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | // This module is a Table Writer API for the Go Programming Language. 6 | // The protocols were written in pure Go and works on windows and unix systems 7 | 8 | package tablewriter 9 | 10 | import ( 11 | "encoding/csv" 12 | "io" 13 | "os" 14 | ) 15 | 16 | // Start A new table by importing from a CSV file 17 | // Takes io.Writer and csv File name 18 | func NewCSV(writer io.Writer, fileName string, hasHeader bool) (*Table, error) { 19 | file, err := os.Open(fileName) 20 | if err != nil { 21 | return &Table{}, err 22 | } 23 | defer file.Close() 24 | csvReader := csv.NewReader(file) 25 | t, err := NewCSVReader(writer, csvReader, hasHeader) 26 | return t, err 27 | } 28 | 29 | // Start a New Table Writer with csv.Reader 30 | // This enables customisation such as reader.Comma = ';' 31 | // See http://golang.org/src/pkg/encoding/csv/reader.go?s=3213:3671#L94 32 | func NewCSVReader(writer io.Writer, csvReader *csv.Reader, hasHeader bool) (*Table, error) { 33 | t := NewWriter(writer) 34 | if hasHeader { 35 | // Read the first row 36 | headers, err := csvReader.Read() 37 | if err != nil { 38 | return &Table{}, err 39 | } 40 | t.SetHeader(headers) 41 | } 42 | for { 43 | record, err := csvReader.Read() 44 | if err == io.EOF { 45 | break 46 | } else if err != nil { 47 | return &Table{}, err 48 | } 49 | t.Append(record) 50 | } 51 | return t, nil 52 | } 53 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/bulk_delete_executions.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "strconv" 7 | "strings" 8 | 9 | "github.com/lusis/go-rundeck/pkg/cli" 10 | "github.com/spf13/cobra" 11 | ) 12 | 13 | var ( 14 | bulkDeleteExecutionIDs = []int{} 15 | ) 16 | 17 | func bulkDeleteExecutionsFunc(cmd *cobra.Command, args []string) error { 18 | if len(bulkDeleteExecutionIDs) == 0 { 19 | return errors.New("at least one id is required") 20 | } 21 | res, err := cli.Client.BulkDeleteExecutions(bulkDeleteExecutionIDs...) 22 | if err != nil { 23 | return err 24 | } 25 | cli.OutputFormatter.SetHeaders([]string{ 26 | "Successful", 27 | "Failed", 28 | "Errors", 29 | }) 30 | var failureResults []string 31 | if res.FailedCount != 0 { 32 | for _, f := range res.Failures { 33 | failureResults = append(failureResults, fmt.Sprintf("%s: %s", f.ID, f.Message)) 34 | } 35 | } 36 | if rowErr := cli.OutputFormatter.AddRow([]string{ 37 | strconv.Itoa(res.SuccessCount), 38 | strconv.Itoa(res.FailedCount), 39 | strings.Join(failureResults, "\n"), 40 | }); rowErr != nil { 41 | return rowErr 42 | } 43 | cli.OutputFormatter.Draw() 44 | return nil 45 | 46 | } 47 | 48 | func bulkDeleteExecutionsCommand() *cobra.Command { 49 | cmd := &cobra.Command{ 50 | Use: "delete -i [execution-id][,execution-id]", 51 | Short: "Bulk deletes executions from a rundeck server", 52 | RunE: bulkDeleteExecutionsFunc, 53 | } 54 | rootCmd := cli.New(cmd) 55 | rootCmd.Flags().IntSliceVarP(&bulkDeleteExecutionIDs, "ids", "i", nil, "list of execution ids") 56 | 57 | return rootCmd 58 | } 59 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/doc.go: -------------------------------------------------------------------------------- 1 | // Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. 2 | // 3 | // Example Usage 4 | // 5 | // The following is a complete example using assert in a standard test function: 6 | // import ( 7 | // "testing" 8 | // "github.com/stretchr/testify/assert" 9 | // ) 10 | // 11 | // func TestSomething(t *testing.T) { 12 | // 13 | // var a string = "Hello" 14 | // var b string = "Hello" 15 | // 16 | // assert.Equal(t, a, b, "The two words should be the same.") 17 | // 18 | // } 19 | // 20 | // if you assert many times, use the format below: 21 | // 22 | // import ( 23 | // "testing" 24 | // "github.com/stretchr/testify/assert" 25 | // ) 26 | // 27 | // func TestSomething(t *testing.T) { 28 | // assert := assert.New(t) 29 | // 30 | // var a string = "Hello" 31 | // var b string = "Hello" 32 | // 33 | // assert.Equal(a, b, "The two words should be the same.") 34 | // } 35 | // 36 | // Assertions 37 | // 38 | // Assertions allow you to easily write test code, and are global funcs in the `assert` package. 39 | // All assertion functions take, as the first argument, the `*testing.T` object provided by the 40 | // testing framework. This allows the assertion funcs to write the failings and other details to 41 | // the correct place. 42 | // 43 | // Every assertion function also takes an optional string message as the final argument, 44 | // allowing custom error messages to be appended to the message the assertion method outputs. 45 | package assert 46 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/versioned_response.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | // VersionedResponse is an interface for a Rundeck Response that supports versioning information 4 | type VersionedResponse interface { 5 | minVersion() int 6 | maxVersion() int 7 | deprecated() bool 8 | } 9 | 10 | // AbsoluteMinimumVersion is the absolute minimum version this library will support 11 | // We set this to `14` as that was the first version of the rundeck API to support JSON 12 | const AbsoluteMinimumVersion = 14 13 | 14 | // CurrentVersion is the current version of the API that this library is tested against 15 | const CurrentVersion = 31 16 | 17 | // GetMinVersionFor gets the minimum api version required for a response 18 | func GetMinVersionFor(a VersionedResponse) int { return a.minVersion() } 19 | 20 | // GetMaxVersionFor gets the maximum api version required for a response 21 | func GetMaxVersionFor(a VersionedResponse) int { return a.maxVersion() } 22 | 23 | // IsDeprecated indicates if a response is deprecated or not 24 | func IsDeprecated(a VersionedResponse) bool { return a.deprecated() } 25 | 26 | // GenericVersionedResponse is for version checking 27 | // Some operations don't have a response (think DELETE or PUT) 28 | // but we still want to do a version check on ALL functions anyway 29 | // This response simply responds to that 30 | type GenericVersionedResponse struct{} 31 | 32 | func (g GenericVersionedResponse) minVersion() int { return AbsoluteMinimumVersion } 33 | func (g GenericVersionedResponse) maxVersion() int { return CurrentVersion } 34 | func (g GenericVersionedResponse) deprecated() bool { return false } 35 | -------------------------------------------------------------------------------- /vendor/github.com/shurcooL/vfsgen/options.go: -------------------------------------------------------------------------------- 1 | package vfsgen 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | // Options for vfsgen code generation. 9 | type Options struct { 10 | // Filename of the generated Go code output (including extension). 11 | // If left empty, it defaults to "{{toLower .VariableName}}_vfsdata.go". 12 | Filename string 13 | 14 | // PackageName is the name of the package in the generated code. 15 | // If left empty, it defaults to "main". 16 | PackageName string 17 | 18 | // BuildTags are the optional build tags in the generated code. 19 | // The build tags syntax is specified by the go tool. 20 | BuildTags string 21 | 22 | // VariableName is the name of the http.FileSystem variable in the generated code. 23 | // If left empty, it defaults to "assets". 24 | VariableName string 25 | 26 | // VariableComment is the comment of the http.FileSystem variable in the generated code. 27 | // If left empty, it defaults to "{{.VariableName}} statically implements the virtual filesystem provided to vfsgen.". 28 | VariableComment string 29 | } 30 | 31 | // fillMissing sets default values for mandatory options that are left empty. 32 | func (opt *Options) fillMissing() { 33 | if opt.PackageName == "" { 34 | opt.PackageName = "main" 35 | } 36 | if opt.VariableName == "" { 37 | opt.VariableName = "assets" 38 | } 39 | if opt.Filename == "" { 40 | opt.Filename = fmt.Sprintf("%s_vfsdata.go", strings.ToLower(opt.VariableName)) 41 | } 42 | if opt.VariableComment == "" { 43 | opt.VariableComment = fmt.Sprintf("%s statically implements the virtual filesystem provided to vfsgen.", opt.VariableName) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/common.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | import ( 4 | "errors" 5 | "io/ioutil" 6 | "strings" 7 | "time" 8 | ) 9 | 10 | // JSONTime is for custom marshal/unmarshal of rundeck datetime values 11 | type JSONTime struct { 12 | time.Time 13 | } 14 | 15 | // JSONDuration is for custom marshal/unmarshal of duration strings 16 | type JSONDuration struct { 17 | time.Duration 18 | } 19 | 20 | const rdTime = "2006-01-02T15:04:05Z" 21 | 22 | // UnmarshalJSON parses the rundeck datetime format 23 | func (t *JSONTime) UnmarshalJSON(data []byte) error { 24 | if t == nil { 25 | return errors.New("JSONTime: Unmarshal on nil pointer") 26 | } 27 | s := strings.Trim(string(data), "\"") 28 | if s == "null" { 29 | t.Time = time.Time{} 30 | return nil 31 | } 32 | tempTime, tErr := time.Parse(rdTime, s) 33 | if tErr != nil { 34 | return errors.New("JSONTime: " + tErr.Error()) 35 | } 36 | t.Time = tempTime 37 | return nil 38 | } 39 | 40 | // UnmarshalJSON parses a string into a Duration 41 | func (d *JSONDuration) UnmarshalJSON(data []byte) error { 42 | if d == nil { 43 | return errors.New("JSONDuration: Unmarshal on nil pointer") 44 | } 45 | s := strings.Trim(string(data), "\"") 46 | if s == "null" { 47 | return nil 48 | } 49 | dur, err := time.ParseDuration(string(s)) 50 | if err != nil { 51 | return err 52 | } 53 | d.Duration = dur 54 | return nil 55 | } 56 | 57 | // GetTestData returns the contents of testdata/fileName as a []byte 58 | func GetTestData(fileName string) ([]byte, error) { 59 | data, err := assets.Open(fileName) 60 | if err != nil { 61 | return nil, err 62 | } 63 | return ioutil.ReadAll(data) 64 | } 65 | -------------------------------------------------------------------------------- /vendor/github.com/spf13/pflag/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Alex Ogier. All rights reserved. 2 | Copyright (c) 2012 The Go Authors. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following disclaimer 12 | in the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of Google Inc. nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/get_tokens.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/lusis/go-rundeck/pkg/cli" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | var ( 12 | getTokensCmd = &cobra.Command{ 13 | Use: "get username", 14 | Short: "gets all tokens for the specified username", 15 | RunE: getTokensFunc, 16 | Args: cobra.MinimumNArgs(1), 17 | } 18 | ) 19 | 20 | func getTokensFunc(cmd *cobra.Command, args []string) error { 21 | userid := args[0] 22 | cli.OutputFormatter.SetHeaders([]string{ 23 | "ID", 24 | "User", 25 | "Creator", 26 | "Expiration", 27 | "Expired?", 28 | "Roles", 29 | }) 30 | if userid == "" { 31 | data, err := cli.Client.ListTokens() 32 | if err != nil { 33 | return err 34 | } 35 | 36 | for _, d := range data { 37 | if rowErr := cli.OutputFormatter.AddRow([]string{ 38 | d.ID, 39 | d.User, 40 | d.Creator, 41 | d.Expiration.String(), 42 | fmt.Sprintf("%t", d.Expired), 43 | strings.Join(d.Roles, ","), 44 | }); rowErr != nil { 45 | return rowErr 46 | } 47 | } 48 | } else { 49 | data, err := cli.Client.ListTokensForUser(userid) 50 | if err != nil { 51 | return err 52 | } 53 | for _, d := range data { 54 | if rowErr := cli.OutputFormatter.AddRow([]string{ 55 | d.ID, 56 | d.User, 57 | d.Creator, 58 | d.Expiration.String(), 59 | fmt.Sprintf("%t", d.Expired), 60 | strings.Join(d.Roles, ","), 61 | }); rowErr != nil { 62 | return rowErr 63 | } 64 | } 65 | } 66 | cli.OutputFormatter.Draw() 67 | return nil 68 | } 69 | func getTokensCommand() *cobra.Command { 70 | cmd := cli.New(getTokensCmd) 71 | return cmd 72 | } 73 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/helpers_test.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | import ( 4 | "io/ioutil" 5 | "os" 6 | "reflect" 7 | "time" 8 | 9 | "github.com/mitchellh/mapstructure" 10 | ) 11 | 12 | func testReadJSON(filename string) ([]byte, error) { 13 | file, err := os.Open(filename) 14 | if err != nil { 15 | return nil, err 16 | } 17 | defer func() { _ = file.Close() }() 18 | return ioutil.ReadAll(file) 19 | } 20 | 21 | // newMSDecoderConfig returns a new mapstructure.DecoderConfig we can use for strict validation 22 | // in testing 23 | func newMSDecoderConfig() *mapstructure.DecoderConfig { 24 | // This converts our custom JSONTime/JSONDuration properly 25 | jsonTimeHook := func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) { 26 | // we only work on strings 27 | if f.Kind() != reflect.String { 28 | return data, nil 29 | } 30 | 31 | // first we check if it's a JSONTime 32 | if t == reflect.TypeOf(&JSONTime{time.Time{}}) { 33 | // Convert it by parsing 34 | tTime, err := time.Parse(rdTime, data.(string)) 35 | if err != nil { 36 | return nil, err 37 | } 38 | return JSONTime{tTime}, nil 39 | } 40 | 41 | // Next we check if it's a JSONDuration 42 | sampleDuration, _ := time.ParseDuration("1s") 43 | if t == reflect.TypeOf(&JSONDuration{sampleDuration}) { 44 | dur, err := time.ParseDuration(data.(string)) 45 | if err != nil { return nil, err} 46 | return JSONDuration{dur}, nil 47 | } 48 | 49 | return data, nil 50 | } 51 | return &mapstructure.DecoderConfig{ 52 | ErrorUnused: true, 53 | WeaklyTypedInput: false, 54 | TagName: "json", 55 | DecodeHook: jsonTimeHook, 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/project_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "resources.source.3.type": "file", 3 | "project.jobs.gui.groupExpandLevel": "1", 4 | "project.ssh-authentication": "privateKey", 5 | "project.gui.motd.display": "projectHome", 6 | "resources.source.3.config.generateFileAutomatically": "true", 7 | "resources.source.2.config.timeout": "30", 8 | "resources.source.3.config.includeServerNode": "true", 9 | "service.FileCopier.default.provider": "stub", 10 | "resources.source.1.config.count": "10", 11 | "project.nodeCache.delay": "30", 12 | "project.nodeCache.enabled": "false", 13 | "project.gui.readme.display": "projectHome", 14 | "project.disable.executions": "false", 15 | "project.ssh-command-timeout": "0", 16 | "project.description": "test project", 17 | "project.ssh-keypath": "/var/lib/rundeck/.ssh/id_rsa", 18 | "resources.source.1.config.prefix": "node", 19 | "resources.source.1.config.attrs": "foo=bar,baz=qux", 20 | "resources.source.1.config.tags": "stub", 21 | "service.NodeExecutor.default.provider": "stub", 22 | "project.name": "testproject", 23 | "resources.source.3.config.format": "resourcejson", 24 | "project.disable.schedule": "false", 25 | "project.ssh-connect-timeout": "0", 26 | "resources.source.1.type": "stub", 27 | "resources.source.3.config.file": "/tmp/file.json", 28 | "resources.source.3.config.requireFileExists": "false", 29 | "resources.source.3.config.writeable": "true", 30 | "resources.source.2.config.url": "http://localhost", 31 | "resources.source.1.config.delay": "0", 32 | "resources.source.1.config.suffix": "-fake", 33 | "resources.source.2.type": "url", 34 | "resources.source.2.config.cache": "true" 35 | } 36 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | jobs: 3 | test: 4 | environment: 5 | TEST_RESULTS: /tmp/test-results 6 | docker: 7 | - image: circleci/golang:1.12.4 8 | steps: 9 | - checkout 10 | - run: mkdir -p ${TEST_RESULTS} 11 | - run: go get github.com/jstemmer/go-junit-report 12 | - run: 13 | name: lint 14 | command: script/lint 15 | - run: 16 | name: coverage 17 | command: script/coverage 18 | build_binaries: 19 | docker: 20 | - image: circleci/golang:1.12.4 21 | steps: 22 | - checkout 23 | - run: make binaries 24 | integration_tests: 25 | machine: 26 | enabled: true 27 | steps: 28 | - checkout 29 | - run: 30 | name: build docker image 31 | command: make build-test-container 32 | - run: 33 | name: run test container 34 | command: make run-test-container 35 | - run: 36 | name: wait for container 37 | command: sleep 30 38 | - run: 39 | name: run integration tests 40 | command: script/test-integration 41 | - run: 42 | name: stop test container 43 | command: make stop-test-container 44 | workflows: 45 | version: 2 46 | build_and_test: 47 | jobs: 48 | - test: 49 | filters: 50 | tags: 51 | only: /.*/ 52 | - build_binaries: 53 | filters: 54 | tags: 55 | only: /.*/ 56 | requires: 57 | - test 58 | - integration_tests: 59 | filters: 60 | tags: 61 | only: /.*/ 62 | requires: 63 | - test 64 | -------------------------------------------------------------------------------- /RELEASENOTES.md: -------------------------------------------------------------------------------- 1 | # v13 2 | - Added support for username/password auth as non-admins cannot use api tokens. Precendence order is as follows: 3 | - If `RUNDECK_TOKEN` is set, that will be used 4 | - If `RUNDECK_TOKEN` is not set, `RUNDECK_USERNAME`/`RUNDECK_PASSWORD` are required. 5 | - Every request will attempt to reauthenticate with the rundeck server when username/password auth is being used 6 | 7 | ## Core API 8 | - Changed API for `client.` (i.e. `GET`,`PUT`,`POST`,`DELETE`) to be more flexible in the fact of rundeck API changes 9 | 10 | Instead of passing the struct you want the XML unmarshaled into to each function, you are now required to pass in a pointer to a `[]byte` and handle unmarshalling yourself. 11 | 12 | - Removed the `client.RawGet` function as it's no longer neccessary 13 | - Changed `ListExecutions`/DeleteAllExecutionsFor` to `ListProjectExecutions`/`DeleteAllExecutionsForProject`. See reasoning under bundled utilities changes. 14 | ## Bundled utilities 15 | - Updated bundled utilities to use `v13` of the Rundeck API. There was only a single change between `v12` and `v13`: 16 | 17 | ``` 18 | Version 13: 19 | 20 | New endpoints 21 | /api/13/project/[PROJECT]/readme.md and /api/13/project/[PROJECT]/motd.md 22 | Project Readme File (GET, PUT, DELETE) 23 | ``` 24 | 25 | which did not impact existing functionality. 26 | 27 | - Renamed `rundeck-list-executions` to `rundeck-list-project-executions` as there are actually two execution list scopes that can be used in the Rundeck API 28 | - Renamed `rundeck-delete-executions-for` to `rundeck-delete-executions-for-project` 29 | - Some arguments to bins MAY have changed as I migrated from a basic argv approach to using kingpin. 30 | 31 | # v12 32 | Initial release 33 | -------------------------------------------------------------------------------- /pkg/rundeck/keys.go: -------------------------------------------------------------------------------- 1 | package rundeck 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/lusis/go-rundeck/pkg/rundeck/responses" 7 | ) 8 | 9 | // UploadKey stores keys on the rundeck server 10 | // http://rundeck.org/docs/api/index.html#upload-keys 11 | func (c *Client) UploadKey() error { 12 | if err := c.checkRequiredAPIVersion(responses.GenericVersionedResponse{}); err != nil { 13 | return err 14 | } 15 | return fmt.Errorf("not yet implemented") 16 | } 17 | 18 | // ListKeys lists key resources 19 | // http://rundeck.org/docs/api/index.html#list-keys 20 | func (c *Client) ListKeys() error { 21 | if err := c.checkRequiredAPIVersion(responses.ListKeysResponse{}); err != nil { 22 | return err 23 | } 24 | return fmt.Errorf("not yet implemented") 25 | } 26 | 27 | // GetKeyMetaData returns the metadata about a stored key 28 | // http://rundeck.org/docs/api/index.html#get-key-metadata 29 | func (c *Client) GetKeyMetaData() error { 30 | if err := c.checkRequiredAPIVersion(responses.KeyMetaResponse{}); err != nil { 31 | return err 32 | } 33 | return fmt.Errorf("not yet implemented") 34 | } 35 | 36 | // GetKeyContents provides the public key content 37 | // http://rundeck.org/docs/api/index.html#get-key-contents 38 | func (c *Client) GetKeyContents() error { 39 | if err := c.checkRequiredAPIVersion(responses.GenericVersionedResponse{}); err != nil { 40 | return err 41 | } 42 | return fmt.Errorf("not yet implemented") 43 | } 44 | 45 | // DeleteKey deletes a key 46 | // http://rundeck.org/docs/api/index.html#delete-keys 47 | func (c *Client) DeleteKey() error { 48 | if err := c.checkRequiredAPIVersion(responses.GenericVersionedResponse{}); err != nil { 49 | return err 50 | } 51 | return fmt.Errorf("not yet implemented") 52 | } 53 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/get_job_scm_action_input_fields_export.json: -------------------------------------------------------------------------------- 1 | { 2 | "actionId": "project-commit", 3 | "description": "Commit changes to local git repo.", 4 | "exportItems": [ 5 | { 6 | "deleted": false, 7 | "itemId": "test/sleep-job-d1b9f2c1-d6a6-43ca-8e9f-85519d5a1323.yaml", 8 | "job": { 9 | "groupPath": "test", 10 | "jobId": "d1b9f2c1-d6a6-43ca-8e9f-85519d5a1323", 11 | "jobName": "sleep-job" 12 | }, 13 | "originalId": null, 14 | "renamed": false 15 | } 16 | ], 17 | "fields": [ 18 | { 19 | "defaultValue": null, 20 | "description": "Enter a commit message. Committing to branch: `master`", 21 | "name": "message", 22 | "renderingOptions": { 23 | "displayType": "MULTI_LINE" 24 | }, 25 | "required": true, 26 | "scope": null, 27 | "title": "Commit Message", 28 | "type": "String", 29 | "values": null 30 | }, 31 | { 32 | "defaultValue": null, 33 | "description": "Enter a tag name to include, will be pushed with the branch.", 34 | "name": "tagName", 35 | "renderingOptions": {}, 36 | "required": false, 37 | "scope": null, 38 | "title": "Tag", 39 | "type": "String", 40 | "values": null 41 | }, 42 | { 43 | "defaultValue": null, 44 | "description": "Check to push to the remote", 45 | "name": "push", 46 | "renderingOptions": {}, 47 | "required": false, 48 | "scope": null, 49 | "title": "Push Remotely?", 50 | "type": "Boolean", 51 | "values": null 52 | } 53 | ], 54 | "importItems": null, 55 | "integration": "export", 56 | "title": "Commit Changes to Git" 57 | } 58 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/tail_execution_output.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "bufio" 5 | "os" 6 | "strconv" 7 | "time" 8 | 9 | "github.com/lusis/go-rundeck/pkg/cli" 10 | "github.com/spf13/cobra" 11 | ) 12 | 13 | var tailPollInterval int 14 | 15 | func getOutput(eID int, offset string, w *bufio.Writer) error { 16 | wait := time.Duration(tailPollInterval) 17 | time.Sleep(wait * time.Second) 18 | iOffset, iOffsetErr := strconv.Atoi(offset) 19 | if iOffsetErr != nil { 20 | return iOffsetErr 21 | } 22 | data, err := cli.Client.GetExecutionOutputWithOffset(eID, iOffset) 23 | if err != nil { 24 | return err 25 | } 26 | for _, entry := range data.Entries { 27 | _, err := w.WriteString(entry.Log + "\n") 28 | if err != nil { 29 | return err 30 | } 31 | 32 | flushErr := w.Flush() 33 | if flushErr != nil { 34 | return flushErr 35 | } 36 | } 37 | 38 | if data.ExecCompleted { 39 | return nil 40 | } 41 | 42 | return getOutput(eID, data.Offset, w) 43 | } 44 | 45 | func tailExecutionOutputFunc(cmd *cobra.Command, args []string) error { 46 | id := args[0] 47 | eID, eIDerr := strconv.Atoi(id) 48 | if eIDerr != nil { 49 | return eIDerr 50 | } 51 | w := bufio.NewWriter(os.Stdout) 52 | return getOutput(eID, "0", w) 53 | } 54 | 55 | func tailExecutionOutputCommand() *cobra.Command { 56 | cmd := &cobra.Command{ 57 | Use: "tail execution-id [-i poll-interval]", 58 | Short: "tails an execution's output from the rundeck server", 59 | Args: cobra.MinimumNArgs(1), 60 | RunE: tailExecutionOutputFunc, 61 | } 62 | rootCmd := cli.New(cmd) 63 | rootCmd.ResetFlags() 64 | rootCmd.Flags().IntVarP(&tailPollInterval, "interval", "i", 2, "interval to poll for more log data in seconds") 65 | return rootCmd 66 | } 67 | -------------------------------------------------------------------------------- /pkg/rundeck/schedule_test.go: -------------------------------------------------------------------------------- 1 | package rundeck 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/lusis/go-rundeck/pkg/rundeck/responses" 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func TestEnableSchedule(t *testing.T) { 11 | client, server, cErr := newTestRundeckClient([]byte(`{"success":true}`), "application/json", 200) 12 | defer server.Close() 13 | if cErr != nil { 14 | t.Fatalf(cErr.Error()) 15 | } 16 | 17 | res, err := client.EnableSchedule("1") 18 | require.NoError(t, err) 19 | require.True(t, res) 20 | } 21 | 22 | func TestDisableSchedule(t *testing.T) { 23 | client, server, cErr := newTestRundeckClient([]byte(`{"success":true}`), "application/json", 200) 24 | defer server.Close() 25 | if cErr != nil { 26 | t.Fatalf(cErr.Error()) 27 | } 28 | 29 | res, err := client.DisableSchedule("1") 30 | require.NoError(t, err) 31 | require.True(t, res) 32 | } 33 | func TestBulkEnableSchedule(t *testing.T) { 34 | jsonfile, err := responses.GetTestData(responses.BulkToggleResponseTestFile) 35 | if err != nil { 36 | t.Fatalf(err.Error()) 37 | } 38 | 39 | client, server, _ := newTestRundeckClient(jsonfile, "application/json", 200) 40 | defer server.Close() 41 | obj, cErr := client.BulkEnableSchedule("a", "b", "c") 42 | require.NoError(t, cErr) 43 | require.NotNil(t, obj) 44 | } 45 | 46 | func TestBulkDisableSchedule(t *testing.T) { 47 | jsonfile, err := responses.GetTestData(responses.BulkToggleResponseTestFile) 48 | if err != nil { 49 | t.Fatalf(err.Error()) 50 | } 51 | 52 | client, server, _ := newTestRundeckClient(jsonfile, "application/json", 200) 53 | defer server.Close() 54 | obj, cErr := client.BulkDisableSchedule("a", "b", "c") 55 | require.NoError(t, cErr) 56 | require.NotNil(t, obj) 57 | } 58 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/runewidth_posix.go: -------------------------------------------------------------------------------- 1 | // +build !windows,!js 2 | 3 | package runewidth 4 | 5 | import ( 6 | "os" 7 | "regexp" 8 | "strings" 9 | ) 10 | 11 | var reLoc = regexp.MustCompile(`^[a-z][a-z][a-z]?(?:_[A-Z][A-Z])?\.(.+)`) 12 | 13 | var mblenTable = map[string]int{ 14 | "utf-8": 6, 15 | "utf8": 6, 16 | "jis": 8, 17 | "eucjp": 3, 18 | "euckr": 2, 19 | "euccn": 2, 20 | "sjis": 2, 21 | "cp932": 2, 22 | "cp51932": 2, 23 | "cp936": 2, 24 | "cp949": 2, 25 | "cp950": 2, 26 | "big5": 2, 27 | "gbk": 2, 28 | "gb2312": 2, 29 | } 30 | 31 | func isEastAsian(locale string) bool { 32 | charset := strings.ToLower(locale) 33 | r := reLoc.FindStringSubmatch(locale) 34 | if len(r) == 2 { 35 | charset = strings.ToLower(r[1]) 36 | } 37 | 38 | if strings.HasSuffix(charset, "@cjk_narrow") { 39 | return false 40 | } 41 | 42 | for pos, b := range []byte(charset) { 43 | if b == '@' { 44 | charset = charset[:pos] 45 | break 46 | } 47 | } 48 | max := 1 49 | if m, ok := mblenTable[charset]; ok { 50 | max = m 51 | } 52 | if max > 1 && (charset[0] != 'u' || 53 | strings.HasPrefix(locale, "ja") || 54 | strings.HasPrefix(locale, "ko") || 55 | strings.HasPrefix(locale, "zh")) { 56 | return true 57 | } 58 | return false 59 | } 60 | 61 | // IsEastAsian return true if the current locale is CJK 62 | func IsEastAsian() bool { 63 | locale := os.Getenv("LC_CTYPE") 64 | if locale == "" { 65 | locale = os.Getenv("LANG") 66 | } 67 | 68 | // ignore C locale 69 | if locale == "POSIX" || locale == "C" { 70 | return false 71 | } 72 | if len(locale) > 1 && locale[0] == 'C' && (locale[1] == '.' || locale[1] == '-') { 73 | return false 74 | } 75 | 76 | return isEastAsian(locale) 77 | } 78 | -------------------------------------------------------------------------------- /vendor/github.com/mitchellh/mapstructure/README.md: -------------------------------------------------------------------------------- 1 | # mapstructure 2 | 3 | mapstructure is a Go library for decoding generic map values to structures 4 | and vice versa, while providing helpful error handling. 5 | 6 | This library is most useful when decoding values from some data stream (JSON, 7 | Gob, etc.) where you don't _quite_ know the structure of the underlying data 8 | until you read a part of it. You can therefore read a `map[string]interface{}` 9 | and use this library to decode it into the proper underlying native Go 10 | structure. 11 | 12 | ## Installation 13 | 14 | Standard `go get`: 15 | 16 | ``` 17 | $ go get github.com/mitchellh/mapstructure 18 | ``` 19 | 20 | ## Usage & Example 21 | 22 | For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/mapstructure). 23 | 24 | The `Decode` function has examples associated with it there. 25 | 26 | ## But Why?! 27 | 28 | Go offers fantastic standard libraries for decoding formats such as JSON. 29 | The standard method is to have a struct pre-created, and populate that struct 30 | from the bytes of the encoded format. This is great, but the problem is if 31 | you have configuration or an encoding that changes slightly depending on 32 | specific fields. For example, consider this JSON: 33 | 34 | ```json 35 | { 36 | "type": "person", 37 | "name": "Mitchell" 38 | } 39 | ``` 40 | 41 | Perhaps we can't populate a specific structure without first reading 42 | the "type" field from the JSON. We could always do two passes over the 43 | decoding of the JSON (reading the "type" first, and the rest later). 44 | However, it is much simpler to just decode this into a `map[string]interface{}` 45 | structure, read the "type" key, then use something like this library 46 | to decode it into the proper structure. 47 | -------------------------------------------------------------------------------- /vendor/github.com/lusis/outputter/output.go: -------------------------------------------------------------------------------- 1 | package outputter 2 | 3 | import ( 4 | "io" 5 | "sync" 6 | ) 7 | 8 | var defaultOutput = "tabular" 9 | 10 | // OutputRegistry is a registry of all known outputter types 11 | type OutputRegistry struct { 12 | Outputs map[string]OutputCtr 13 | sync.RWMutex 14 | } 15 | 16 | var registry = &OutputRegistry{Outputs: make(map[string]OutputCtr)} 17 | 18 | // OutputCtr returns a func that creates an Outputter 19 | type OutputCtr func() Outputter 20 | 21 | // RegisterOutput adds an Outputter to the registry 22 | func RegisterOutput(name string, factory OutputCtr) { 23 | if _, exists := registry.Outputs[name]; !exists { 24 | registry.Outputs[name] = factory 25 | } 26 | } 27 | 28 | // Outputter is an interface for multiple ways to draw data to the console 29 | type Outputter interface { 30 | Draw() 31 | SetHeaders([]string) 32 | AddRow([]string) error 33 | ColorSupport() bool 34 | SetPretty() 35 | SetWriter(io.Writer) error 36 | } 37 | 38 | // GetDefaultOutputter returns the default output outputters 39 | func GetDefaultOutputter() Outputter { 40 | f, _ := NewOutputter(defaultOutput) 41 | return f 42 | } 43 | 44 | // GetOutputters returns a list of all supported outputters 45 | func GetOutputters() []string { 46 | var o []string 47 | for name := range registry.Outputs { 48 | o = append(o, name) 49 | } 50 | return o 51 | } 52 | 53 | // NewOutputter returns a new outputter of the specified type 54 | func NewOutputter(outputFormat string) (Outputter, error) { 55 | if _, exists := registry.Outputs[outputFormat]; !exists { 56 | return nil, ErrorUnknownOutputter 57 | } 58 | factory, ok := registry.Outputs[outputFormat] 59 | if !ok { 60 | return nil, ErrorInvalidOutputter 61 | } 62 | o := factory() 63 | return o, nil 64 | } 65 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/project_info.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "[API Href]", 3 | "name": "testproject", 4 | "description": "test project", 5 | "config": { 6 | "resources.source.3.type": "file", 7 | "project.jobs.gui.groupExpandLevel": "1", 8 | "project.ssh-authentication": "privateKey", 9 | "project.gui.motd.display": "projectHome", 10 | "resources.source.3.config.generateFileAutomatically": "true", 11 | "resources.source.2.config.timeout": "30", 12 | "resources.source.3.config.includeServerNode": "true", 13 | "service.FileCopier.default.provider": "stub", 14 | "resources.source.1.config.count": "10", 15 | "project.nodeCache.delay": "30", 16 | "project.nodeCache.enabled": "false", 17 | "project.gui.readme.display": "projectHome", 18 | "project.disable.executions": "false", 19 | "project.ssh-command-timeout": "0", 20 | "project.description": "test project", 21 | "project.ssh-keypath": "/var/lib/rundeck/.ssh/id_rsa", 22 | "resources.source.1.config.prefix": "node", 23 | "resources.source.1.config.tags": "stub", 24 | "service.NodeExecutor.default.provider": "stub", 25 | "project.name": "testproject", 26 | "resources.source.3.config.format": "resourcejson", 27 | "project.disable.schedule": "false", 28 | "project.ssh-connect-timeout": "0", 29 | "resources.source.1.type": "stub", 30 | "resources.source.3.config.file": "/tmp/file.json", 31 | "resources.source.3.config.requireFileExists": "false", 32 | "resources.source.3.config.writeable": "true", 33 | "resources.source.2.config.url": "http://localhost", 34 | "resources.source.1.config.delay": "0", 35 | "resources.source.1.config.suffix": "fake", 36 | "resources.source.2.type": "url", 37 | "resources.source.2.config.cache": "true" 38 | } 39 | } -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/spew/bypasssafe.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2016 Dave Collins 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | // NOTE: Due to the following build constraints, this file will only be compiled 16 | // when the code is running on Google App Engine, compiled by GopherJS, or 17 | // "-tags safe" is added to the go build command line. The "disableunsafe" 18 | // tag is deprecated and thus should not be used. 19 | // +build js appengine safe disableunsafe !go1.4 20 | 21 | package spew 22 | 23 | import "reflect" 24 | 25 | const ( 26 | // UnsafeDisabled is a build-time constant which specifies whether or 27 | // not access to the unsafe package is available. 28 | UnsafeDisabled = true 29 | ) 30 | 31 | // unsafeReflectValue typically converts the passed reflect.Value into a one 32 | // that bypasses the typical safety restrictions preventing access to 33 | // unaddressable and unexported data. However, doing this relies on access to 34 | // the unsafe package. This is a stub version which simply returns the passed 35 | // reflect.Value when the unsafe package is not available. 36 | func unsafeReflectValue(v reflect.Value) reflect.Value { 37 | return v 38 | } 39 | -------------------------------------------------------------------------------- /cmd/rundeck/cmds/http_get.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | 6 | cli "github.com/lusis/go-rundeck/pkg/cli" 7 | httpclient "github.com/lusis/go-rundeck/pkg/httpclient" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | var ( 12 | httpGetQueryParameters []string 13 | httpGetContentType string 14 | ) 15 | 16 | var helpLong = ` 17 | "rundeck http get" allows you to perform authenticated http get requests against the rundeck api. 18 | Examples: 19 | 20 | # rundeck http get system/acl/ 21 | # rundeck http get job/XXXXXXX/executions -q max=1 22 | # rundeck http get job/XXXXXXX/executions -q max=1 -q status=failed 23 | # rundeck http get execution/29 -c application/xml 24 | 25 | This tool is used to generate test response data for this library itself. 26 | ` 27 | 28 | func httpGetFunc(cmd *cobra.Command, args []string) error { 29 | path := args[0] 30 | params, paramErr := cli.BuildParams(httpGetQueryParameters) 31 | if paramErr != nil { 32 | return paramErr 33 | } 34 | res, err := cli.Client.Get(path, httpclient.QueryParams(params), httpclient.Accept(httpGetContentType)) 35 | if err != nil { 36 | return err 37 | } 38 | fmt.Println(string(res)) 39 | return nil 40 | } 41 | 42 | func httpGetCommand() *cobra.Command { 43 | cmd := &cobra.Command{ 44 | Use: "get path [-q foo=bar] [-c application/json]", 45 | Short: "performs an authenticated http get against the rundeck api", 46 | Long: helpLong, 47 | RunE: httpGetFunc, 48 | Args: cobra.MinimumNArgs(1), 49 | } 50 | rootCmd := cli.New(cmd) 51 | rootCmd.ResetFlags() // remove the global --output-format flag inherited from cli.New() 52 | rootCmd.Flags().StringSliceVarP(&httpGetQueryParameters, "query-param", "q", []string{}, "custom query params to pass in format of name=value. Can specify multiple times") 53 | rootCmd.Flags().StringVarP(&httpGetContentType, "content-type", "c", "application/json", "content-type to return") 54 | 55 | return rootCmd 56 | } 57 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/testdata/systeminfo.json: -------------------------------------------------------------------------------- 1 | { 2 | "system": { 3 | "timestamp": { 4 | "epoch": 1431975278220, 5 | "unit": "ms", 6 | "datetime": "2015-05-18T18:54:38Z" 7 | }, 8 | "rundeck": { 9 | "version": "2.5.2-SNAPSHOT", 10 | "build": "2.5.2-0-SNAPSHOT", 11 | "node": "madmartigan.local", 12 | "base": "/Users/greg/rundeck25", 13 | "apiversion": 14, 14 | "serverUUID": null 15 | }, 16 | "executions":{ 17 | "active":true, 18 | "executionMode":"active" 19 | }, 20 | "os": { 21 | "arch": "x86_64", 22 | "name": "Mac OS X", 23 | "version": "10.10.3" 24 | }, 25 | "jvm": { 26 | "name": "Java HotSpot(TM) 64-Bit Server VM", 27 | "vendor": "Oracle Corporation", 28 | "version": "1.7.0_71", 29 | "implementationVersion": "24.71-b01" 30 | }, 31 | "stats": { 32 | "uptime": { 33 | "duration": 546776, 34 | "unit": "ms", 35 | "since": { 36 | "epoch": 1431974731444, 37 | "unit": "ms", 38 | "datetime": "2015-05-18T18:45:31Z" 39 | } 40 | }, 41 | "cpu": { 42 | "loadAverage": { 43 | "unit": "percent", 44 | "average": 2.689453125 45 | }, 46 | "processors": 8 47 | }, 48 | "memory": { 49 | "unit": "byte", 50 | "max": 716177408, 51 | "free": 138606040, 52 | "total": 527958016 53 | }, 54 | "scheduler": { 55 | "running": 0, 56 | "threadPoolSize": 10 57 | }, 58 | "threads": { 59 | "active": 35 60 | } 61 | }, 62 | "metrics": { 63 | "href": "http://madmartigan.local:4440/metrics/metrics?pretty=true", 64 | "contentType": "text/json" 65 | }, 66 | "threadDump": { 67 | "href": "http://madmartigan.local:4440/metrics/threads", 68 | "contentType": "text/plain" 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /cmd/rundeck/cmds/scm_input_fields.go: -------------------------------------------------------------------------------- 1 | package cmds 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/lusis/go-rundeck/pkg/cli" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | func getSCMPluginInputFieldsFunc(cmd *cobra.Command, args []string) error { 12 | projectName := args[0] 13 | integration := args[1] 14 | pluginType := args[2] 15 | data, err := cli.Client.GetProjectSCMPluginInputFields(projectName, integration, pluginType) 16 | if err != nil { 17 | return err 18 | } 19 | cli.OutputFormatter.SetHeaders([]string{ 20 | "Name", 21 | "Title", 22 | "Type", 23 | "Default Value", 24 | "Description", 25 | "Required?", 26 | "Values", 27 | }) 28 | for _, p := range data.Fields { 29 | if scmInputFieldsRequiredOnly { 30 | if !p.Required { 31 | continue 32 | } 33 | } 34 | // by default we only want the first line of the description 35 | desc := strings.Split(p.Description, "\n")[0] 36 | 37 | if scmInputFieldsFullDescription { 38 | desc = p.Description 39 | } 40 | if rowErr := cli.OutputFormatter.AddRow([]string{ 41 | p.Name, 42 | p.Title, 43 | p.Type, 44 | p.DefaultValue, 45 | desc, 46 | fmt.Sprintf("%t", p.Required), 47 | strings.Join(p.Values, ","), 48 | }); rowErr != nil { 49 | return err 50 | } 51 | } 52 | cli.OutputFormatter.Draw() 53 | return nil 54 | } 55 | 56 | func getSCMPluginInputFieldsCommand() *cobra.Command { 57 | cmd := &cobra.Command{ 58 | Use: "input-fields project-name integration type [--full-description] [--required-only]", 59 | Short: "lists the input fields for a given SCM plugin", 60 | Args: cobra.MinimumNArgs(3), 61 | RunE: getSCMPluginInputFieldsFunc, 62 | } 63 | rootCmd := cli.New(cmd) 64 | rootCmd.Flags().BoolVar(&scmInputFieldsFullDescription, "full-description", false, "Show full field description") 65 | rootCmd.Flags().BoolVarP(&scmInputFieldsRequiredOnly, "required-only", "r", false, "Show only required fields") 66 | return rootCmd 67 | } 68 | -------------------------------------------------------------------------------- /pkg/rundeck/responses/history.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | // HistoryResponseTestFile is the test data for a HistoryResponse 4 | const HistoryResponseTestFile = "history.json" 5 | 6 | // HistoryResponse represents a project history response 7 | // http://rundeck.org/docs/api/index.html#listing-history 8 | type HistoryResponse struct { 9 | Paging *PagingResponse `json:"paging"` 10 | Events []*HistoryEventResponse `json:"events"` 11 | } 12 | 13 | func (a HistoryResponse) minVersion() int { return AbsoluteMinimumVersion } 14 | func (a HistoryResponse) maxVersion() int { return CurrentVersion } 15 | func (a HistoryResponse) deprecated() bool { return false } 16 | 17 | // HistoryEventResponse represents an individual event in a history response 18 | type HistoryEventResponse struct { 19 | StartTime int `json:"starttime"` 20 | EndTime int `json:"endtime"` 21 | DateStarted *JSONTime `json:"date-started"` 22 | DateEnded *JSONTime `json:"date-ended"` 23 | Title string `json:"title"` 24 | Status string `json:"status"` 25 | StatusString string `json:"statusString"` 26 | Job *struct { 27 | ID string `json:"id"` 28 | HRef string `json:"href"` 29 | Permalink string `json:"permalink"` 30 | } `json:"job,omitempty"` 31 | Summary string `json:"summary"` 32 | NodeSummary *struct { 33 | Succeeded int `json:"succeeded"` 34 | Failed int `json:"failed"` 35 | Total int `json:"total"` 36 | } `json:"node-summary"` 37 | User string `json:"user"` 38 | Project string `json:"project"` 39 | Execution *struct { 40 | ID string `json:"id"` 41 | HRef string `json:"href"` 42 | Permalink string `json:"permalink"` 43 | } `json:"execution"` 44 | } 45 | 46 | func (a HistoryEventResponse) minVersion() int { return AbsoluteMinimumVersion } 47 | func (a HistoryEventResponse) maxVersion() int { return CurrentVersion } 48 | func (a HistoryEventResponse) deprecated() bool { return false } 49 | -------------------------------------------------------------------------------- /pkg/rundeck/http_test.go: -------------------------------------------------------------------------------- 1 | package rundeck 2 | 3 | import ( 4 | "testing" 5 | 6 | httpclient "github.com/lusis/go-rundeck/pkg/httpclient" 7 | "github.com/lusis/go-rundeck/pkg/rundeck/responses" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestHTTP404(t *testing.T) { 12 | client, server, _ := newTestRundeckClient([]byte("hello"), "application/json", 404) 13 | defer server.Close() 14 | funcs := map[string]func(string, ...httpclient.RequestOption) ([]byte, error){ 15 | "get": client.httpGet, 16 | "put": client.httpPut, 17 | "post": client.httpPost, 18 | } 19 | for n, f := range funcs { 20 | res, err := f("/", requestExpects(200)) 21 | require.Nil(t, res, n+" body should be nil") 22 | require.Error(t, err, n+" should return an error") 23 | require.IsType(t, ErrMissingResource, err, n+" should return ErrMissingResource") 24 | } 25 | _, err := client.httpDelete("/f", requestExpects(204)) 26 | require.Error(t, err, "delete should return an error") 27 | require.IsType(t, ErrMissingResource, err, "delete should return ErrMissingResource") 28 | } 29 | 30 | func TestRDErrorResponse(t *testing.T) { 31 | jsonfile, err := responses.GetTestData(responses.ErrorResponseTestFile) 32 | if err != nil { 33 | t.Fatalf(err.Error()) 34 | } 35 | 36 | client, server, _ := newTestRundeckClient(jsonfile, "application/json", 500) 37 | defer server.Close() 38 | funcs := map[string]func(string, ...httpclient.RequestOption) ([]byte, error){ 39 | "get": client.httpGet, 40 | "put": client.httpPut, 41 | "post": client.httpPost, 42 | } 43 | for n, f := range funcs { 44 | res, reserr := f("/", requestExpects(200)) 45 | require.Nil(t, res, n+" body should be nil") 46 | require.Error(t, reserr, n+" should return an error") 47 | require.Equal(t, "something blew up", reserr.Error()) 48 | } 49 | _, reserr := client.httpDelete("/f", requestExpects(204)) 50 | require.Error(t, reserr, "delete should return an error") 51 | require.Equal(t, "something blew up", reserr.Error()) 52 | } 53 | -------------------------------------------------------------------------------- /pkg/rundeck/history_test.go: -------------------------------------------------------------------------------- 1 | package rundeck 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/lusis/go-rundeck/pkg/rundeck/responses" 7 | 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestGetHistory(t *testing.T) { 12 | jsonfile, err := responses.GetTestData(responses.HistoryResponseTestFile) 13 | if err != nil { 14 | t.Fatalf(err.Error()) 15 | } 16 | 17 | client, server, cErr := newTestRundeckClient(jsonfile, "application/json", 200) 18 | defer server.Close() 19 | if cErr != nil { 20 | t.Fatalf(cErr.Error()) 21 | } 22 | obj, cErr := client.ListHistory("testproject", nil) 23 | require.NoError(t, cErr) 24 | require.NotNil(t, obj) 25 | } 26 | 27 | func TestGetHistoryNotFound(t *testing.T) { 28 | jsonfile, err := responses.GetTestData(responses.HistoryResponseTestFile) 29 | if err != nil { 30 | t.Fatalf(err.Error()) 31 | } 32 | 33 | client, server, cErr := newTestRundeckClient(jsonfile, "application/json", 404) 34 | defer server.Close() 35 | if cErr != nil { 36 | t.Fatalf(cErr.Error()) 37 | } 38 | obj, oErr := client.ListHistory("testproject", nil) 39 | require.Error(t, oErr) 40 | require.Nil(t, obj) 41 | } 42 | 43 | func TestGetHistoryDecodeError(t *testing.T) { 44 | client, server, cErr := newTestRundeckClient([]byte(""), "application/json", 200) 45 | defer server.Close() 46 | if cErr != nil { 47 | t.Fatalf(cErr.Error()) 48 | } 49 | obj, oErr := client.ListHistory("testproject", nil) 50 | require.Error(t, oErr) 51 | require.Nil(t, obj) 52 | } 53 | 54 | func TestGetHistoryOptions(t *testing.T) { 55 | jsonfile, err := responses.GetTestData(responses.HistoryResponseTestFile) 56 | if err != nil { 57 | t.Fatalf(err.Error()) 58 | } 59 | 60 | client, server, cErr := newTestRundeckClient(jsonfile, "application/json", 200) 61 | defer server.Close() 62 | if cErr != nil { 63 | t.Fatalf(cErr.Error()) 64 | } 65 | obj, cErr := client.ListHistory("testproject", map[string]string{"foo": "bar"}) 66 | 67 | require.NoError(t, cErr) 68 | require.NotNil(t, obj) 69 | } 70 | --------------------------------------------------------------------------------