How to retrieve JobId from Jenkins - go

I'm doing a CLI in Go with gojenkins. I need to run a build and then retrieve the job information (because then I want to wait till finish), but id retrieved by BuildJob method is not the same that GetBuild needs.
func RunPipeline(config *config.Profile) {
jobName := "test_pipeline"
jk, err := getClient(config)
params := make(map[string]string)
id, err := jk.BuildJob(jobName, params)
if err != nil {
fmt.Println(err)
}
fmt.Printf("Build number: %d\n", id)
build, err := jk.GetBuild(jobName, id)
if err != nil {
fmt.Printf("Did not found build: %s\n", err)
}
fmt.Println(build)
}
Output:
Build number: 86
Did not found build: 404
<nil>
The last build id for that pipeline should be 37, but I got 86, can somoane helps me how to get that id? I didn't find anything on the lib documentation.

Finaly I've found this issue on github. BuildJob's id is the id on the queue. So this works for me.
func Pipeline(config *config.Profile, buildData BuildData) {
jobName := "test_pipeline"
jk, err := getClient(config)
if err != nil {
panic(err)
}
queueId, err := jk.BuildJob(jobName, buildData.toParams())
if err != nil {
fmt.Println(err)
}
task, err := jk.GetQueueItem(queueId)
if err != nil {
panic(err)
}
retry := 0
for retry < 60 {
if task.Raw.Executable.URL != "" {
break
}
time.Sleep(1 * time.Second)
task.Poll()
retry++
}
build, err := jk.GetBuild(jobName, task.Raw.Executable.Number)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", build.Raw)
}

Related

Calling opcua.Node.Attributes returns EOF error

I'm trying to get and return all the nodes of NodeClass Variable of my OPC UA Simulation Server starting at the root node and going down all folder nodes and object nodes that have childs. I tried to use browse-example of the gopcua repo but whenever the program gets to attrs, err := n.Attributes(...) for the second time, it returns an EOF error.
I tried to recreate a minimal example:
package main
import (
"context"
"fmt"
"log"
"github.com/gopcua/opcua"
"github.com/gopcua/opcua/id"
"github.com/gopcua/opcua/ua"
)
const (
endpoint string = "opc.tcp://<ServerAddress>"
rootNodeId string = "i=85"
)
func browse(c *opcua.Client, n *opcua.Node) error {
_, err := n.Attributes(ua.AttributeIDNodeClass, ua.AttributeIDDataType)
if err != nil {
return err
}
browseChildren := func(refType uint32) error {
refs, err := n.ReferencedNodes(refType, ua.BrowseDirectionForward, ua.NodeClassAll, true)
if err != nil {
return fmt.Errorf("references: %d: %s", refType, err)
}
fmt.Printf("found %d child refs\n", len(refs))
for _, rn := range refs {
err := browse(c, rn)
if err != nil {
return fmt.Errorf("browse children: %s", err)
}
fmt.Printf("Found a Node: %s\n", rn.ID.String())
}
return nil
}
if err := browseChildren(id.HasChild); err != nil {
return err
}
if err := browseChildren(id.Organizes); err != nil {
return err
}
return nil
}
func main() {
ctx := context.Background()
c := opcua.NewClient(endpoint)
if err := c.Connect(ctx); err != nil {
log.Fatal("Could not connect")
panic(err)
}
defer c.Close()
id, _ := ua.ParseNodeID(rootNodeId)
err := browse(c, c.Node(id))
if err != nil {
log.Fatal(err)
}
}
This is how the Prosys OPC UA Simulation Server looks like:
And this the output I get from the program:
found 0 child refs
found 5 child refs
2022/01/21 14:26:06 browse children: EOF
exit status 1
tl;dr
browseChildren := func(refType uint32) error {
refs, err := n.ReferencedNodes(refType, ua.BrowseDirectionForward, ua.NodeClassAll, true)
if err != nil {
return fmt.Errorf("references: %d: %s", refType, err)
}
fmt.Printf("found %d child refs\n", len(refs))
for _, rn := range refs {
refNodeID := ua.MustParseNodeID(rn.ID.String())
refNode := c.Node(refNodeID) // parse the referenced nodes before usage
err := browse(c, refNode)
if err != nil {
return fmt.Errorf("browse children: %s", err)
}
fmt.Printf("Found a Node: %s\n", refNode.ID.String())
}
return nil
}
Reason
The referenced nodes that are returned by n.ReferencedNodes have an invalid NodeIDType (64). The only supported NodeIDTypes are 0-5. Reparsing them gives them a proper NodeIDType. (Related Gitlab issue: https://github.com/gopcua/opcua/issues/550)

How to choose a valid case execution?

I use https://github.com/google/goexpect as my shell interaction, PPPoE dialing program, My operating system CentOS7, my dialing program rp-pppoe, For the first time, such as 1.
How do I write goexpect interactions when I dial?
I know where the problem is and I don't know how to solve it. When I create a dial with concurrency, the logic of the first interaction is different from that of the subsequent one. For example, the content of the second article is different from the content of the first article, and it adds a new question: (default ppp0) or enter 'n' if you Want to create a new one: , I saw that goexpect has an operation of ExpectSwitchCase, but I don't quite understand how to solve my problem with it. How to match one of the interaction logics and ignore other conditions.
The first time the interaction is performed
Welcome to the PPPoE client setup. First, I will run some checks on
your system to make sure the PPPoE client is installed properly...
LOGIN NAME
Enter your Login Name (default root): USER
When I execute the second interaction, How to use google/goexpect to match one in multiple conditions, and continue to perform the next step
Welcome to the PPPoE client setup. First, I will run some checks on
your system to make sure the PPPoE client is installed properly...
The following DSL config was found on your system:
Device: Name:
ppp0 DSLppp0
Please enter the device if you want to configure the present DSL config
(default ppp0) or enter 'n' if you want to create a new one:n
LOGIN NAME
Enter your Login Name: USER
My code, But it can't work properly
package shell
import (
"fmt"
expect "github.com/google/goexpect"
"github.com/google/goterm/term"
"regexp"
"time"
)
func R(user, password, dev string) error {
fmt.Println(term.Bluef("Telnet spawner example"))
to := 3 * time.Second
exec, _, err := expect.Spawn("/usr/sbin/pppoe-setup", to)
if err != nil {
return err
}
defer exec.Close()
r, rs, _, err := exec.ExpectSwitchCase([]expect.Caser{
&expect.Case{R: regexp.MustCompile(`Enter your Login Name \(default root\):`), S: user + "\n", T: expect.Next(), Rt: 0},
&expect.Case{R: regexp.MustCompile(`or enter 'n' if you want to create a new one:`), S: "n\n"},
}, to)
if err != nil {
return err
}
fmt.Println("r:rs:", r, rs)
ur, urs, err := exec.Expect(regexp.MustCompile(`Enter your Login Name`), to)
if err != nil {
return err
}
fmt.Println("ur:urs:", ur, urs)
if err := exec.Send(user + "\n"); err != nil {
fmt.Println("here03:", err.Error())
return err
}
dr, drs, err := exec.Expect(regexp.MustCompile(`\(default eth0\):`), to)
if err != nil {
fmt.Println("here04:", err.Error())
return err
}
fmt.Println(dr, drs)
if err := exec.Send(dev + "\n"); err != nil {
fmt.Println("here05:", err.Error())
return err
}
er, ers, err := exec.Expect(regexp.MustCompile(`Enter the demand value \(default no\):`), to)
if err != nil {
fmt.Println("here06:", err.Error())
return err
}
fmt.Println(er, ers)
if err := exec.Send("\n"); err != nil {
fmt.Println("here06x:", err.Error())
return err
}
if _, _, err := exec.Expect(regexp.MustCompile(`Enter the DNS information here:`), to); err != nil {
fmt.Println("here06x:", err.Error())
return err
}
if err := exec.Send("\n"); err != nil {
fmt.Println("here07:", err.Error())
return err
}
if _, _, err := exec.Expect(regexp.MustCompile(`Please enter your Password:`), to); err != nil {
fmt.Println("here08:", err.Error())
return err
}
if err := exec.Send(password + "\n"); err != nil {
fmt.Println("sendhere08:", err.Error())
return err
}
if _, _, err := exec.Expect(regexp.MustCompile(`Please re-enter your Password:`), to); err != nil {
fmt.Println("here0801:", err.Error())
return err
}
if err := exec.Send(password + "\n"); err != nil {
fmt.Println("sendhere0801:", err.Error())
return err
}
if _, _, err := exec.Expect(regexp.MustCompile(`normal user to start or stop DSL connection \(default yes\):`), to); err != nil {
fmt.Println("here09:", err.Error())
return err
}
if err := exec.Send("yes\n"); err != nil {
fmt.Println("here10:", err.Error())
return err
}
if _, _, err := exec.Expect(regexp.MustCompile(`Choose a type of firewall \(0-2\):`), to); err != nil {
fmt.Println("here11:", err.Error())
return err
}
if err := exec.Send("0\n"); err != nil {
fmt.Println("here12:", err.Error())
return err
}
if _, _, err := exec.Expect(regexp.MustCompile(`Please enter no or yes \(default no\):`), to); err != nil {
fmt.Println("here13:", err.Error())
return err
}
if err := exec.Send("yes\n"); err != nil {
fmt.Println("here14:", err.Error())
return err
}
fr, frs, err := exec.Expect(regexp.MustCompile(`Accept these settings and adjust configuration files \(y/n\)?`), to);
if err != nil {
fmt.Println("here15:", err.Error())
return err
}
fmt.Println(fr,frs)
if err := exec.Send("y\n"); err != nil {
fmt.Println("here16:", err.Error())
return err
}
return nil
}
This is the main file #Josh Chappelle
package main
import (
"fmt"
"github.com/seraphico/ppps/pkg/shell"
)
func main() {
err := shell.R("test01", "test01", "br3")
if err != nil {
fmt.Println(err.Error())
return
}
}
Thanks, I can fix it.
ro, _, _, err := exec.ExpectSwitchCase([]expect.Caser{
&expect.Case{R: regexp.MustCompile("if you want to create a new one:"), S: "n\n", T: expect.Next(), Rt: 1},
&expect.Case{R: regexp.MustCompile(`Enter your Login Name:`), S: user + "\n", Rt: 0},
&expect.Case{R: regexp.MustCompile(`Enter your Login Name \(default root\):`), S: user + "\n", Rt: 0},
}, to)
if err != nil {
return err
}
if if you want to create a new one:If the matching is unsuccessful, the join t status is next and set Rt 1.

Go SMB2 , reading and listing directory

I'm trying to list directory contents on a share from Linux to Windows using Go.
So far I've managed to Create/Remove new files inside a share with full Read/Write permissions.
Go module: https://godoc.org/github.com/hirochachacha/go-smb2#Client
Functions:
func connect_client(host string, share string, session map[string]string) *smb2.Client {
//Checks for a connection on port
conn, err := net.Dial("tcp", host+":445")
if err != nil {
panic(err)
}
//smb auth
d := &smb2.Dialer{
Initiator: &smb2.NTLMInitiator{
User: session["Username"],
Password: session["Password"],
Domain: session["Domain"],
},
}
//Returns a client session
client, err := d.Dial(conn)
if err != nil {
fmt.Println("Connection failed")
client.Logoff()
} else {
fmt.Println("Connection Succeeded")
}
return client
}
func check_write(host string, client *smb2.Client) {
file := "asdasdas.txt"
fs, err := client.Mount(host)
if err != nil {
fmt.Println(err)
os.Exit(0)
}
defer fs.Umount()
share := strings.Split(host, `\\`)
f, err := fs.Create(file)
if err != nil {
fmt.Println("You do not have write permissions on directory:%s ! \n", strings.Split(share[1], `\`)[1])
os.Exit(0)
}
defer fs.Remove(file)
defer f.Close()
fmt.Printf("You have write permissions to directory: %s \n", strings.Split(share[1], `\`)[1]))
}
func list_all(client *smb2.Client, host string) {
fs, err := client.Mount(host)
if err != nil {
fmt.Println(err)
os.Exit(0)
}
defer fs.Umount()
_, err = fs.Open(`Test.txt`)
if err != nil {
fmt.Println(err)
os.Exit(0)
}
}
func main() {
host, share, action, session := get_flags()
client := connect_client(host, share, session)
full_host := `\\` + host + `\` + share
//File create
if action == "check_write" {
check_write(full_host, client)
}
if action == "list_files" {
list_all(client, full_host)
}
}
In the function list_all() everything works, but when I am trying to access \\192.168.1.19\Sharing only..
When I input just a host with directory name it seas it can not list the directory path because it can not find the object specified.
I can't understand how I can get pointer used for *RemoteFile in order to use the functions:
f.Readdir()
f.Name()
etc....
So far I managed to use *RemoteFileSystem only for all other actions but I want to list all contents of the directory..
Help would be much appreciated!
Edit:
If it wasn't clear enough, in order to use functions like:
f.Readdir()
f.Name()
I need to get a pointer for *RemoteFile, this is my main issue
https://godoc.org/github.com/hirochachacha/go-smb2#RemoteFileSystem.Open
Use Open on a RemoteFileSystem and either a directory name, or empty string for the directory at the root of the filesystem.
e.g.
client, err := d.Dial(conn)
if err != nil {
return err
}
rfs, err := client.Mount("jrwren")
if err != nil {
return err
}
// cat the NOTES file.
f, err := rfs.Open("NOTES")
if err != nil {
return err
}
defer f.Close()
io.Copy(os.Stdout, f)
// List all the files
dir, err := rfs.Open("")
if err != nil {
return err
}
fis, err := dir.Readdir(10)
if err != nil {
return err
}
for i := range fis {
fmt.Println(fis[i].Name())
}
func list_all(client *smb2.Client, host string) {
fs, err := client.Mount(host)
if err != nil {
fmt.Println(err)
os.Exit(0)
}
dir, err := fs.Open("")
if err != nil {
fmt.Println(err)
os.Exit(0)
}
fis, err := dir.Readdir(-1)
if err != nil {
fmt.Println(err)
os.Exit(0)
}
for i := range fis {
fmt.Println(fis[i].Name())
}
}
This would be the answer thank you!

Purpose of a select statement with a single case in Go?

I'm reading the source code of MicroMDM, specifically the implementation of pollCommands (https://github.com/micromdm/micromdm/blob/5c70048c14592fc16c2107f1af1bf8e0d3a52e0b/platform/queue/queue.go#L223-L284):
func (db *Store) pollCommands(pubsub pubsub.PublishSubscriber) error {
commandEvents, err := pubsub.Subscribe(context.TODO(), "command-queue", command.CommandTopic)
if err != nil {
return errors.Wrapf(err,
"subscribing push to %s topic", command.CommandTopic)
}
go func() {
for {
select {
case event := <-commandEvents:
var ev command.Event
if err := command.UnmarshalEvent(event.Message, &ev); err != nil {
level.Info(db.logger).Log("msg", "unmarshal command event in queue", "err", err)
continue
}
cmd := new(DeviceCommand)
cmd.DeviceUDID = ev.DeviceUDID
byUDID, err := db.DeviceCommand(ev.DeviceUDID)
if err == nil && byUDID != nil {
cmd = byUDID
}
newPayload, err := plist.Marshal(ev.Payload)
if err != nil {
level.Info(db.logger).Log("msg", "marshal event payload", "err", err)
continue
}
newCmd := Command{
UUID: ev.Payload.CommandUUID,
Payload: newPayload,
}
cmd.Commands = append(cmd.Commands, newCmd)
if err := db.Save(cmd); err != nil {
level.Info(db.logger).Log("msg", "save command in db", "err", err)
continue
}
level.Info(db.logger).Log(
"msg", "queued event for device",
"device_udid", ev.DeviceUDID,
"command_uuid", ev.Payload.CommandUUID,
"request_type", ev.Payload.Command.RequestType,
)
cq := new(QueueCommandQueued)
cq.DeviceUDID = ev.DeviceUDID
cq.CommandUUID = ev.Payload.CommandUUID
msgBytes, err := MarshalQueuedCommand(cq)
if err != nil {
level.Info(db.logger).Log("msg", "marshal queued command", "err", err)
continue
}
if err := pubsub.Publish(context.TODO(), CommandQueuedTopic, msgBytes); err != nil {
level.Info(db.logger).Log("msg", "publish command to queued topic", "err", err)
}
}
}
}()
return nil
}
What puzzles me is why there is a select statement in the for loop with a single case. Would this code not be equivalent to
for {
event := <-commandEvents
var ev command.Event
...
}
It seems to me that the code could be simplified by doing away with the select statement?

Golang streams and readers

I am writing a simple script to get download unzip the tar.gz file and then remove it. Whenever I try to remove it I get an error:
The process cannot access the file because it is being used by another process.
I assume the error is in how I pass the file to the extractTarGz function, but I am not sure.
Here is the code:
package main
import (
"archive/tar"
"compress/gzip"
"io"
"log"
"os"
)
func main() {
f, err := os.Open("file.tar.gz")
if err != nil {
panic(err)
}
defer f.Close()
extractTarGz(f)
err = os.Remove("file.tar.gz")
}
func extractTarGz(gzipStream io.Reader) {
uncompressedStream, err := gzip.NewReader(gzipStream)
if err != nil {
log.Fatal("ExtractTarGz: NewReader failed")
}
tarReader := tar.NewReader(uncompressedStream)
for true {
header, err := tarReader.Next()
if err == io.EOF {
break
}
if err != nil {
log.Fatalf("ExtractTarGz: Next() failed: %s", err.Error())
}
switch header.Typeflag {
case tar.TypeDir:
if err := os.Mkdir(header.Name, 0755); err != nil {
log.Fatalf("ExtractTarGz: Mkdir() failed: %s", err.Error())
}
case tar.TypeReg:
outFile, err := os.Create(header.Name)
if err != nil {
log.Fatalf("ExtractTarGz: Create() failed: %s", err.Error())
}
defer outFile.Close()
if _, err := io.Copy(outFile, tarReader); err != nil {
log.Fatalf("ExtractTarGz: Copy() failed: %s", err.Error())
}
default:
log.Fatalf(
"ExtractTarGz: uknown type: %s in %s",
header.Typeflag,
header.Name)
}
}
}
You should first close the file, and then attempt to remove it. Since you close it using defer, that will / would be called after the os.Remove() call.
Try it like this:
name := "file.tar.gz"
defer func() {
if err = os.Remove(name); err != nil {
log.Printf("Failed to remove %s: %v", name, err)
}
}()
f, err := os.Open(name)
if err != nil {
panic(err)
}
defer f.Close()
extractTarGz(f)
Deferred functions are executed in LIFO (last-in-first-out) order, so first f.Close() will be called, and then the other which tries to remove the file. Quoting from Spec: Deferred statements:
...deferred functions are invoked immediately before the surrounding function returns, in the reverse order they were deferred.
f, err := os.Open("file.tar.gz")
if err != nil {
panic(err)
}
defer f.Close()
extractTarGz(f)
err = os.Remove("file.tar.gz")
At the very least, you need to close the file before you removeit.
err = f.Close()
if err != nil {
panic(err)
}
err = os.Remove("file.tar.gz")
defer f.Close() won't run until the end of the function.

Resources