package
0.8.0
Repository: https://github.com/adrianwit/endly.git
Documentation: pkg.go.dev

# README

Execution service

The execution service is responsible for opening, managing terminal session, with the ability to send command and extract data. Service keeps tracking the session current directory commands, env variable setting, and will only issue SSH command if there is actual change.

Endly service action integration

Run the following command for exec service operation details:


endly -s=exec

endly -s=exec -a=run
endly -s=exec -a=extract
endly -s=exec -a=open
endly -s=exec -a=close

Service IdActionDescriptionRequestResponse
execopenopen SSH session on the target resource.OpenSessionRequestOpenSessionResponse
execcloseclose SSH sessionCloseSessionRequestCloseSessionResponse
execrunexecute basic commandsRunRequestRunResponse
execextractexecute commands with ability to extract data, define error or success stateExtractRequestRunResponse

RunRequest example

@run.json

{
  "Target": {
    "URL": "ssh://127.0.0.1/",
    "Credentials": "${env.HOME}/.secret/localhost.json"
  },
  "SuperUser":true,
  "Commands":["mkdir /tmp/app1"]
}

@run.yaml

target:
  url:  ssh://127.0.0.1/
  credentials: ${env.HOME}/.secret/localhost.json
commands:
  whoami
  ${cmd[0].stdout}:/root/?  mkdir -p /tmp/app
  ${cmd[0].stdout}:!/root/? mkdir ~/app
  echo cmd[0].stdout
  

ExtractRequest example

{
	"Target": {
	  "URL": "ssh://127.0.0.1/",
	  "Credentials": "${env.HOME}/.secret/localhost.json"
	},
	"SystemPaths": ["/opt/sdk/go/bin"],
	"Commands": [
	  {
		"Command": "go version",
		"Extraction": [
		  {
			"RegExpr": "go(\\d\\.\\d)",
			"Key": "Version"
		  }
		]
	  }
	]
}

SSH Session

In order to run any SSH command, service needs to open a session, it uses target.Credentials and secret service to connect the target host.

Opening session is an optional step, run or extract request will open session automatically.

By default session is open in non transient mode, which means once context.Close is called, session will be will be terminated. Otherwise caller is responsible for closing it.

    
        manager := endly.New()
        context := manager.NewContext(toolbox.NewContext())
        target := url.NewResource("ssh://127.0.0.1", "~/.secret/localhost.json")
        defer context.Close() // session closes as part of context.Close
        response, err := manager.Run(context, exec.NewOpenSessionRequest(target, []string{"/usr/local/bin"}, map[string]string{"M2_HOME":"/users/test/.m2/"},false, "/"))
        if err != nil {
            log.Fatal(err)
        }
        openResponse := response.(*exec.OpenSessionResponse)
        sessions :=context.TerminalSessions()
        assert.True(t,sessions.Has(openResponse.SessionID))
        log.Print(openResponse.SessionID)


Run vs Extract:

RunReuest provide a simple way to excute SSH command with conditional execution, it uses util.StdErrors as stdout errors. ExtractRequest has ability to fine tune SSH command execution with extraction data ability. Error matching in ExtractRequest does use any default value.

Run Commands

Command in RunRequest can represents one of the following:

  1. Simple command: i.e echo $HOME
  2. Conditional command: [criteria ?] command i.e. $stdout:/root/? echo 'hello root'",

    manager := endly.New()
    context := manager.NewContext(toolbox.NewContext())
    var target= url.NewResource("ssh://127.0.0.1", "localhost")
    var runRequest = exec.NewRunRequest(target, true, "whoami", "$stdout:/root/? echo 'hello root'")
    var runResponse = &exec.RunResponse{}
    err := endly.Run(context, runRequest, runResponse)

Run Command to Extract Data


    extractRequest := exec.NewExtractRequest(target,
		exec.DefaultOptions(),
		exec.NewExtractCommand(fmt.Sprintf("svn info"), "", nil, nil,
			endly.NewDataExtraction("origin", "^URL:[\\t\\s]+([^\\s]+)", false),
			endly.NewDataExtraction("revision", "Revision:\\s+([^\\s]+)", false)))
    manager := endly.New()
    context := manager.NewContext(toolbox.NewContext())
    var runResponse := &exec.RunResponse{}
    err := endly.Run(context, extractRequest, runResponse)
    if err != nil {
        log.Fatal(err)
    }
  			

Exec SSH Unit Testing

This module provide SSH session recording ability to later replay it during unit testing without actual SSH involvement.

Recroding SSH session

To record actual SSH session use exec.OpenRecorderContext helper method, the last parameters specify location where conversation is recorded, actual dump takes place when context is closed (defer context.Clode()). If you use sudo. any secret or credentials make sure that you rename it to *** before checking in any code so you can use var credentials, err = util.GetDummyCredential()

	manager := endly.New()
	target := url.NewResource("ssh://127.0.0.1", "~/.secret/localhost.json")
	context, err :=  exec.NewSSHRecodingContext(manager, target, "test/session/context")
	if err != nil {
		log.Fatal(err)
	}
	defer context.Close()

Replaying SSH session

In order to replay previously recoded SSH session use exec.GetReplayService helper method to create a test SSHService, use location of stored SSH conversation as parameter, then create context with exec.OpenTestContext

	manager := endly.New()
	var credentials, err = util.GetDummyCredential()
	if err != nil {
		log.Fatal(err)
	}
	target := url.NewResource("ssh://127.0.0.1", credentials)
	context, err := exec.NewSSHReplayContext(manager, target, "test/session/transient")
	if err != nil {
		log.Fatal(err)
	}
	response, err := manager.Run(context, exec.NewOpenSessionRequest(target, []string{"/usr/local/bin"}, map[string]string{"M2_HOME": "/users/test/.m2/"}, false, "/"))
    if err != nil {
        log.Fatal(err)
    }

# Functions

DefaultOptions creates a default execution options.
GetReplayService return replay service.
New creates a new execution service.
NewCommandLog creates a new command log.
NewExtractCommand creates a new extract command.
NewExtractRequest returns a new command request.
NewExtractRequestFromURL creates a new request from URL.
NewOpenSessionRequest creates a new session if transient flag is true, caller is responsible for closing session, otherwise session is closed as context is closed.
No description provided by the author
NewRunRequest creates a new request.
NewExtractRequestFromURL creates a new request from URL.
NewRunResponse creates a new RunResponse.
NewSdtinEvent crates a new execution start event value.
NewSSHMultiRecordingContext open multi recorded session.
OpenMultiSessionTestContext opens test context with multi SSH replay/mocks session.
NewSSHRecodingContext open recorder context (to capture SSH command).
NewSSHReplayContext opens test context with SSH commands to replay.
NewStdoutEvent crates a new execution start event value.
Os returns operating system for provide session.
TerminalSession returns Session for passed in target resource.
TerminalSessions returns system sessions.

# Constants

ServiceID represent system executor service id.
SudoCredentialKey represent obsucated password sudo credentials key (target.Credentials).

# Variables

No description provided by the author

# Structs

CloseSessionRequest closes session.
CloseSessionResponse closes session response.
Extracts represents an execution instructions.
ExtractRequest represents managed command request.
Log represents an executed command with Stdin, Stdout or Error.
OpenSessionRequest represents an open session request.
OpenSessionResponse represents a session id.
Options represents an execution options.
RunRequest represents a simple command.
RunResponse represents a command response with logged commands.
StdinEvent represents an execution event start.
StdoutEvent represents an execution event end.

# Type aliases

Command represents a command expression: [when criteria ?] command.