Unable to execute a command inside a docker container - sql

I am trying to spin up a Postgres container via the Docker Go SDK. I can get the container started, and I copy my SQL file into the container and verified the file is there.
I cannot run this file, which right now just contains CREATE TABLE tester;
Here is my Go code that I am trying to use:
package gosqlcontainer
import (
"archive/tar"
"bufio"
"bytes"
"context"
"fmt"
"io"
"log"
"os"
"os/exec"
"time"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
)
func StartContainer() string {
ctx := context.Background()
cli, err := client.NewClientWithOpts(client.WithAPIVersionNegotiation())
if err != nil {
panic(err)
}
imageName := "postgres"
out, err := cli.ImagePull(ctx, imageName, types.ImagePullOptions{})
if err != nil {
panic(err)
}
defer out.Close()
io.Copy(os.Stdout, out)
container, err := cli.ContainerCreate(ctx, &container.Config{
Image: imageName, Env: []string{"POSTGRES_PASSWORD=password"},
}, nil, nil, nil, "")
if err != nil {
panic(err)
}
if err := cli.ContainerStart(ctx, container.ID, types.ContainerStartOptions{}); err != nil {
panic(err)
}
tarFile := TarFile("test.sql")
if err = cli.CopyToContainer(ctx, container.ID, "/home/", tarFile, types.CopyToContainerOptions{AllowOverwriteDirWithFile: true}); err != nil {
fmt.Println("error copying to container", err)
}
time.Sleep(1 * time.Second)
execCommand, err := cli.ContainerExecCreate(ctx, container.ID, types.ExecConfig{AttachStdin: true, AttachStderr: true, AttachStdout: true, Cmd: []string{"psql", "-U postgres -f /home/test.sql"}})
if err != nil {
fmt.Println("exec err is", err)
}
if err := cli.ContainerExecStart(ctx, execCommand.ID, types.ExecStartCheck{}); err != nil {
fmt.Println("Err Start", err)
}
return container.ID
}
When I try to do this from CLI, I can run that file and verify that the DB is created. However, programmatically it does not work, and I do not see any errors returned.
The goal is for this to be a library I can reference to spin up a container, import data, and used for integration tests. I am currently calling it from a basic client locally, using go run main.go I am working on macOS Monterey v12.4

Related

how to launch my own browser version with selenium using go?

package main
import (
"fmt"
"time"
"github.com/tebeka/selenium"
"github.com/tebeka/selenium/chrome"
)
func main() {
// Run Chrome browser
service, err := selenium.NewChromeDriverService("./chromedriver", 4444)
if err != nil {
panic(err)
}
defer service.Stop()
caps := selenium.Capabilities{}
caps.AddChrome(chrome.Capabilities{Args: []string{
"window-size=1920x1080",
"--no-sandbox",
"--disable-dev-shm-usage",
"disable-gpu",
// "--headless", // comment out this line to see the browser
}})
driver, err := selenium.NewRemote(caps, "")
if err != nil {
panic(err)
}
driver.Get("https://google.com")
time.Sleep(50e+10)
The code above makes a new clear version of chrome browser. In my case I need to open my default one with my cookies and other data (no tabs needed).
I haven't found a method using Go programming language. I found a solution for a C# language (i guess) here it is
ChromeOptions options = new ChromeOptions(); options.setBinary("/path/to/other/chrome/binary");
but I'm noob and i don't know how to convert it to fit in my code.
Thanks for any help
UPDATE
I tryed this. But it doesn't work anyway :c
package main
import (
"fmt"
"time"
"github.com/tebeka/selenium"
"github.com/tebeka/selenium/chrome"
)
func main() {
// Run Chrome browser
service, err := selenium.NewChromeDriverService("./chromedriver", 4444)
if err != nil {
panic(err)
}
defer service.Stop()
caps := selenium.Capabilities{}
caps.AddChrome(chrome.Capabilities{
Path: "C:/Program Files/Google/Chrome/Application/chrome.exe",
Args: []string{
"window-size=1920x1080",
"--no-sandbox",
"--disable-dev-shm-usage",
"--disable-gpu",
"--user-data-dir=C:/Users/nikit/AppData/Local/Google/Chrome/User Data/Profile 2",
// "--headless", // comment out this line to see the browser
}})
driver, err := selenium.NewRemote(caps, "")
if err != nil {
panic(err)
}
driver.Get("https://point.wb.ru/login")
elem, _ := driver.FindElement(selenium.ByClassName, "opp-form")
if elem != nil {
fmt.Println("нашел!")
}
time.Sleep(time.Second * 100)
}

Go how to use cookiejar for multiple requests?

I'm trying to make a cli for a site that has csrf, needing the csrf token to be sent on headers and on a form.
I can't seem to understand net/http.Client or net/http/cookieJar
This its even good practice? There's a better way of doing csrf login on Go ?
Thx in advance ^v^
This its my code:
package main
import (
"fmt"
"log"
"net/http"
"net/http/cookiejar"
"net/url"
"strings"
"time"
)
var (
httpClient = &http.Client{}
)
func main() {
jar, err := cookiejar.New(nil)
if err != nil {
log.Fatal(err)
}
httpClient = &http.Client{
Timeout: 30 * time.Second,
Jar: jar,
}
requestURL := "https://example.com/"
res, err := httpClient.Get(requestURL)
if err != nil {
log.Fatal(err)
}
log.Println(res.Cookies())
// stdout: cookie as expected
u := &url.URL{}
u.Parse(requestURL)
log.Println(httpClient.Jar.Cookies(u))
// stdout: []
form := make(url.Values)
/* ... */
req, err := http.NewRequest(http.MethodPost, requestURL, strings.NewReader(form.Encode()))
if err != nil {
fmt.Printf("client: could not create request: %s\n", err)
}
res, err = httpClient.Do(req)
if err != nil {
log.Fatal(err)
}
fmt.Println(req)
// stdout: cookie as expected
}

How to properly register RabbitMQ exclusive-consumer

Summary
It seems pretty simple to implement an exclusive consumer in RabbitMQ. You just need to enable the exclusive flag while starting the consumption or that's what I thought. I tried this approach but for some reason, it's creating multiple exclusive consumers which actually contradicts with it's own definition.
Setup
I am using following setup -
Exchange: default
Queue: quorum, durable
Messages: durable
Here is the full code that I am using to register exclusive consumer -
package main
import (
"fmt"
amqp "github.com/rabbitmq/amqp091-go"
"sync"
"time"
)
type Config struct {
Schema string
Host string
Port string
Username string
Password string
Vhost string
}
type Rabbit struct {
config Config
connection *amqp.Connection
lock sync.Mutex
}
// NewRabbit returns a Rabbit instance.
func NewRabbit() *Rabbit {
// setup appropriate values
config := Config{
Host: "",
Username: "",
Password: "",
Port: "",
Vhost: "",
Schema: "",
}
return &Rabbit{
config: config,
}
}
// Connect connects to RabbitMQ server.
func (r *Rabbit) Connect() error {
r.lock.Lock()
defer r.lock.Unlock()
// Check if connection is already available
if r.connection == nil || r.connection.IsClosed() {
// Try connecting
con, err := amqp.DialConfig(fmt.Sprintf(
"%s://%s:%s#%s:%s/%s",
r.config.Schema,
r.config.Username,
r.config.Password,
r.config.Host,
r.config.Port,
r.config.Vhost,
), amqp.Config{})
if err != nil {
return err
}
r.connection = con
}
return nil
}
func (r *Rabbit) StartConsumer(queueName string) error {
chn, err := r.connection.Channel()
if err != nil {
return err
}
// Make sure we process 1 message at a time
if err := chn.Qos(1, 0, false); err != nil {
return err
}
_, err = chn.QueueDeclare(
queueName,
true,
false,
false,
false,
amqp.Table{"x-queue-type": "quorum"}) // This will ensure that the created queue is quorum-queue
if err != nil {
fmt.Printf("Error creating queue with name: %s, err: %s", queueName, err.Error())
return err
}
messages, err := chn.Consume(
queueName,
queueName+"-consumer",
false,
true,
false,
false,
nil,
)
if err != nil {
fmt.Printf("Unable to start consumer for webhook queue: %s, err: %s", queueName, err.Error())
return err
}
go func() {
// This for-loop will wait indefinitely or until channel is closed
for msg := range messages {
fmt.Printf("Message: %v", msg.Body)
if err = msg.Ack(false); err != nil {
fmt.Printf("Unable to acknowledge the message, err: %s", err.Error())
}
}
}()
return nil
}
Here is the main.go
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
)
func main() {
interrupt := make(chan os.Signal)
signal.Notify(interrupt, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
defer signal.Stop(interrupt)
rabbit := NewRabbit()
if err := rabbit.Connect(); err != nil {
fmt.Printf("Can't connect to RabbitMQ server, err: %s", err.Error())
} else {
fmt.Println("Successfully connected to RabbitMQ server")
}
err := rabbit.StartConsumer("test-queue")
if err != nil {
fmt.Printf("Error: %s", err.Error())
}
select {
case <-interrupt:
fmt.Println("Interrupt signal received")
break
}
fmt.Println("Application is about to close")
}
Here is go.mod
module ExclusiveRabbitMQConsumer
go 1.17
require github.com/rabbitmq/amqp091-go v1.3.4
And here is what I see after running 3 instances of this application -
RabbitMQ Management UI
All 3 consumers are shown as exclusive. The consumer tags are same however that doesn't matter according to RabbitMQ documentation.
I'm not sure what's wrong here.

How to resolve commit into branches?

I need to find all branches (tags) with a commit. On CLI using git command it's possible by using git branch --contains <commit> command.
How do to something like that using go-git library?
I tried to make a solution and got this:
func FindBranchesByCoommit(r *git.Repository, c *object.Commit) (branches []*plumbing.Reference, err error) {
brIt, err := r.Branches()
if err != nil {
return
}
defer brIt.Close()
if err := brIt.ForEach(func(ref *plumbing.Reference) error {
com, err := r.CommitObject(ref.Hash())
if err != nil {
return err
}
comIt, err := r.Log(&git.LogOptions{From: com.Hash})
if err != nil {
return err
}
defer comIt.Close()
for {
if com, err := comIt.Next(); err == nil {
if c.Hash == com.Hash {
branches = append(branches, ref)
break
}
} else if err == io.EOF {
break
} else {
return err
}
}
return nil
}); err != nil {
return nil, err
}
return
}

GO - Unknown error on executing a command via ssh connection

I'm trying to execute a command via session.Run() function over a ssh connection. So far I can successfully execute some commands but on others I keep getting the following error: "Process exited with: 1. Reason was: () exit status 1"
func (p *project) connect(config *ssh.ClientConfig) {
log.Printf("Trying connection...\n")
conn, err := ssh.Dial("tcp", fmt.Sprintf("%s:%s", p.hostname.name, p.port.name), config)
checkError("Failed to dial: ", err)
log.Printf("Connection established.\n")
for step := range p.typ.program.setup {
p.install(step, conn)
}
}
func (p *project) install(step int, conn *ssh.Client) {
session, err := conn.NewSession()
checkError("Failed to build session: ", err)
defer session.Close()
var stdoutBuf bytes.Buffer
session.Stdout = &stdoutBuf
log.Printf("Executing command: %s", p.typ.program.setup[step])
if err := session.Run(p.typ.program.setup[step]); err != nil {
log.Println(session.Stdout)
log.Fatal("Error on command execution", err.Error())
}
}
// That would be an example of a command which returns me an error
// "cd ~/www/www/ && git commit -m 'on the beginning was the commit'"
// That comes inside a slice on p.typ.program.setup accessed by the step(index).
The command output (session.Stdout) is the one i expect:
"# On branch master nothing to commit, working directory clean"
And just to note I already tried to execute the command directly on the console and it works just fine.
So, the code seems to be okay, the command ran on the remote but I still have an error no matter what.
Does anyone have a clue about why is that happening?
Thanks in advance.
Maybe my library will helps in your case: https://github.com/shagabutdinov/shell; it covers basic cases of running ssh commands in one session.
Try following:
handler := func(outputType int, message string) {
if(outputType == shell.Stdout) {
log.Println("stdout: ", message)
} else if(outputType == shell.Stdout) {
log.Println("stderr: ", message)
}
}
key, err := ssh.ParsePrivateKey([]byte(YOUR_PRIVATE_KEY))
if(err != nil) {
panic(err)
}
auth := []ssh.AuthMethod{ssh.PublicKeys(key)}
shell = shell.NewRemote(shell.RemoteConfig{
Host: "root#example.com:22",
Auth: auth,
})
if(err != nil) {
panic(err)
}
status, err := shell.Run("cd ~/www/www/", handler)
if(err != nil) {
panic(err)
}
status, err := shell.Run("git commit -m 'on the beginning was the commit'", handler)
if(err != nil) {
panic(err)
}
if(status == 0) {
console.log("command executed successfully")
} else {
console.log("command execution failed")
}