diff --git a/.github/workflows/vagrant-packet.yaml b/.github/workflows/vagrant-packet.yaml deleted file mode 100644 index 843b625c6..000000000 --- a/.github/workflows/vagrant-packet.yaml +++ /dev/null @@ -1,17 +0,0 @@ -name: Setup with Vagrant on Packet -on: - push: - pull_request: - types: [labeled] - -jobs: - vagrant-setup: - if: contains(github.event.pull_request.labels.*.name, 'ci-check/vagrant-setup') - runs-on: vagrant - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Vagrant Test - run: | - export VAGRANT_DEFAULT_PROVIDER="virtualbox" - go test --timeout 1h -v ./test/_vagrant diff --git a/test/_vagrant/vagrant.go b/test/_vagrant/vagrant.go deleted file mode 100644 index 5cf88f1b1..000000000 --- a/test/_vagrant/vagrant.go +++ /dev/null @@ -1,240 +0,0 @@ -package vagrant - -import ( - "bufio" - "bytes" - "context" - "fmt" - "io" - "io/ioutil" - "os" - "os/exec" - "strings" - "syscall" - - "golang.org/x/crypto/ssh" -) - -type Vagrant struct { - log func(string, ...interface{}) - VagrantBinPath string - Name string - Workdir string - provisioningProcess *os.Process - async bool - sshConn *ssh.Client - Stdout io.ReadWriter - Stderr io.ReadWriter -} - -type VagrantOpt func(*Vagrant) - -func WithStderr(s io.ReadWriter) VagrantOpt { - return func(v *Vagrant) { - v.Stderr = s - } -} - -func RunAsync() VagrantOpt { - return func(v *Vagrant) { - v.async = true - } -} - -func WithLogger(log func(string, ...interface{})) VagrantOpt { - return func(v *Vagrant) { - v.log = log - } -} - -func WithStdout(s io.ReadWriter) VagrantOpt { - return func(v *Vagrant) { - v.Stdout = s - } -} - -func WithWorkdir(workdir string) VagrantOpt { - return func(v *Vagrant) { - v.Workdir = workdir - } -} - -func WithMachineName(name string) VagrantOpt { - return func(v *Vagrant) { - v.Name = name - } -} - -func WithVagrantBinPath(path string) VagrantOpt { - return func(v *Vagrant) { - v.VagrantBinPath = path - } -} - -func (v *Vagrant) pipeOutput(ctx context.Context, name string, scanner *bufio.Scanner) { - for scanner.Scan() { - select { - case <-ctx.Done(): - return - default: - v.log("[pipeOutput %s] %s", name, scanner.Text()) - } - } -} - -func (v *Vagrant) execCmd(ctx context.Context, args ...string) (*exec.Cmd, error) { - cmd := exec.CommandContext(ctx, v.VagrantBinPath, args...) - cmd.Dir = v.Workdir - cmd.Stdout = v.Stdout - cmd.Stderr = v.Stderr - cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} - - stderrPipe, err := cmd.StderrPipe() - if err != nil { - return nil, fmt.Errorf("exec error: %v", err) - } - stdoutPipe, err := cmd.StdoutPipe() - if err != nil { - return nil, fmt.Errorf("exec error: %v", err) - } - - go v.pipeOutput(ctx, fmt.Sprintf("%s stderr", cmd.String()), bufio.NewScanner(stderrPipe)) - go v.pipeOutput(ctx, fmt.Sprintf("%s stdout", cmd.String()), bufio.NewScanner(stdoutPipe)) - - err = cmd.Start() - if err != nil { - return nil, fmt.Errorf("exec error: %v", err) - } - - v.log("executing cmd: %s pid=%d", cmd.String(), cmd.Process.Pid) - - return cmd, err -} - -func Up(ctx context.Context, opts ...VagrantOpt) (*Vagrant, error) { - const ( - defaultVagrantBin = "vagrant" - defaultName = "vagrant" - defaultWorkdir = "." - ) - v := &Vagrant{ - VagrantBinPath: defaultVagrantBin, - Name: defaultName, - Workdir: defaultWorkdir, - log: func(format string, args ...interface{}) { - fmt.Println(fmt.Sprintf(format, args)) - }, - } - for _, opt := range opts { - opt(v) - } - - cmd, err := v.execCmd(ctx, "up", "--provision", v.Name) - if err != nil { - return nil, err - } - - v.provisioningProcess = cmd.Process - - if v.async == false { - err = cmd.Wait() - if err != nil { - return nil, fmt.Errorf("exec error \"%s\": %v", err, cmd.String()) - } - } - return v, nil -} - -func (v *Vagrant) provision(ctx context.Context) error { - return nil -} - -func (v *Vagrant) Destroy(ctx context.Context) error { - if v.sshConn != nil { - v.sshConn.Close() - } - - // A destroy fails if there are any other process locking that particular - // machine. In our case a worker machine starts async because the - // provisioning never ends it hangs forever saying "impossible to connect - // via ssh" when the test succeed and the worker gets destroyed the - // provisioning process is still up and this prevents the worker to - // terminate. This procedures kills the provisioning - if v.provisioningProcess != nil { - err := v.provisioningProcess.Signal(syscall.Signal(0)) - if err == nil { - v.log( - "[Destroy %s]: killing provisioning process because it is still running. pid=%d", - v.Name, - v.provisioningProcess.Pid, - ) - err := syscall.Kill(-v.provisioningProcess.Pid, syscall.SIGKILL) - if err != nil { - v.log("error killing provisioning process: %s pid=%d", err, v.provisioningProcess.Pid) - } - } - } - - cmd, err := v.execCmd(ctx, "destroy", "--force", v.Name) - if err != nil { - return fmt.Errorf("exec error \"%s\": %v", err, cmd.String()) - } - err = cmd.Wait() - if err != nil { - return fmt.Errorf("exec error \"%s\": %v", err, cmd.String()) - } - return nil -} - -func (v *Vagrant) Exec(ctx context.Context, args ...string) ([]byte, error) { - if v.sshConn == nil { - signer, err := loadPrivateKey() - if err != nil { - return nil, err - } - - config := &ssh.ClientConfig{ - HostKeyCallback: ssh.InsecureIgnoreHostKey(), - User: "vagrant", - Auth: []ssh.AuthMethod{ssh.PublicKeys(signer), ssh.Password("vagrant")}, - } - - conn, err := ssh.Dial("tcp", "localhost:2222", config) - if err != nil { - return nil, fmt.Errorf("dial failed:%v", err) - } - - v.sshConn = conn - } - - session, err := v.sshConn.NewSession() - if err != nil { - return nil, err - } - - defer session.Close() - - v.log("[Exec %s] %s", v.Name, strings.Join(args, " ")) - - var stdoutBuf bytes.Buffer - session.Stdout = &stdoutBuf - session.Run(strings.Join(args, " ")) - - v.log("[Exec %s] %s Output:\n%s", v.Name, strings.Join(args, " "), stdoutBuf.String()) - - return stdoutBuf.Bytes(), nil -} - -func loadPrivateKey() (ssh.Signer, error) { - pemBytes, err := ioutil.ReadFile(os.Getenv("HOME") + "/.vagrant.d/insecure_private_key") - if err != nil { - return nil, err - } - - signer, err := ssh.ParsePrivateKey(pemBytes) - if err != nil { - return nil, err - } - - return signer, nil -} diff --git a/test/_vagrant/vagrant_test.go b/test/_vagrant/vagrant_test.go deleted file mode 100644 index 4ef2fcaf4..000000000 --- a/test/_vagrant/vagrant_test.go +++ /dev/null @@ -1,204 +0,0 @@ -package vagrant_test - -import ( - "context" - "encoding/json" - "net/http" - "os" - "testing" - "time" - - "github.com/tinkerbell/tink/client" - "github.com/tinkerbell/tink/pkg" - "github.com/tinkerbell/tink/protos/hardware" - "github.com/tinkerbell/tink/protos/template" - "github.com/tinkerbell/tink/protos/workflow" - vagrant "github.com/tinkerbell/tink/test/_vagrant" -) - -func TestVagrantSetupGuide(t *testing.T) { - ctx := context.Background() - - machine, err := vagrant.Up(ctx, - vagrant.WithLogger(t.Logf), - vagrant.WithMachineName("provisioner"), - vagrant.WithWorkdir("../../deploy/vagrant"), - ) - if err != nil { - t.Fatal(err) - } - - defer func() { - err := machine.Destroy(ctx) - if err != nil { - t.Error(err) - } - }() - - _, err = machine.Exec(ctx, "cd /vagrant/deploy && source ../envrc && docker-compose up -d") - if err != nil { - t.Fatal(err) - } - - _, err = machine.Exec(ctx, "docker pull hello-world") - if err != nil { - t.Fatal(err) - } - - _, err = machine.Exec(ctx, "docker tag hello-world 192.168.1.1/hello-world") - if err != nil { - t.Fatal(err) - } - - _, err = machine.Exec(ctx, "docker push 192.168.1.1/hello-world") - if err != nil { - t.Fatal(err) - } - - for ii := 0; ii < 5; ii++ { - resp, err := http.Get("http://localhost:42114/healthz") - if err != nil || resp.StatusCode != http.StatusOK { - if err != nil { - t.Logf("err tinkerbell healthcheck... retrying: %s", err) - } else { - t.Logf("err tinkerbell healthcheck... expected status code 200 got %d retrying", resp.StatusCode) - } - time.Sleep(10 * time.Second) - } - } - - t.Log("Tinkerbell is up and running") - - os.Setenv("TINKERBELL_CERT_URL", "http://127.0.0.1:42114/cert") - os.Setenv("TINKERBELL_GRPC_AUTHORITY", "127.0.0.1:42113") - client.Setup() - _, err = client.HardwareClient.All(ctx, &hardware.Empty{}) - if err != nil { - t.Fatal(err) - } - err = registerHardware(ctx) - if err != nil { - t.Fatal(err) - } - - templateID, err := registerTemplate(ctx) - if err != nil { - t.Fatal(err) - } - - t.Logf("templateID: %s", templateID) - - workflowID, err := createWorkflow(ctx, templateID) - if err != nil { - t.Fatal(err) - } - - t.Logf("WorkflowID: %s", workflowID) - - os.Setenv("VAGRANT_WORKER_GUI", "false") - worker, err := vagrant.Up(ctx, - vagrant.WithLogger(t.Logf), - vagrant.WithMachineName("worker"), - vagrant.WithWorkdir("../../deploy/vagrant"), - vagrant.RunAsync(), - ) - if err != nil { - t.Fatal(err) - } - - defer func() { - err := worker.Destroy(ctx) - if err != nil { - t.Error(err) - } - }() - - for iii := 0; iii < 30; iii++ { - events, err := client.WorkflowClient.ShowWorkflowEvents(ctx, &workflow.GetRequest{ - Id: workflowID, - }) - if err != nil { - t.Fatal(err) - } - for event, err := events.Recv(); err == nil && event != nil; event, err = events.Recv() { - if event.ActionName == "hello_world" && event.ActionStatus == workflow.ActionState_ACTION_STATE_SUCCESS { - t.Logf("event %s SUCCEEDED as expected", event.ActionName) - return - } - } - time.Sleep(10 * time.Second) - } - t.Fatal("Workflow never got to a complite state or it didn't make it on time (10m)") -} - -func createWorkflow(ctx context.Context, templateID string) (string, error) { - res, err := client.WorkflowClient.CreateWorkflow(ctx, &workflow.CreateRequest{ - Template: templateID, - Hardware: `{"device_1":"08:00:27:00:00:01"}`, - }) - if err != nil { - return "", err - } - return res.Id, nil -} - -func registerTemplate(ctx context.Context) (string, error) { - resp, err := client.TemplateClient.CreateTemplate(ctx, &template.WorkflowTemplate{ - Name: "hello-world", - Data: `version: "0.1" -name: hello_world_workflow -global_timeout: 600 -tasks: - - name: "hello world" - worker: "{{.device_1}}" - actions: - - name: "hello_world" - image: hello-world - timeout: 60`, - }) - if err != nil { - return "", err - } - - return resp.Id, nil -} - -func registerHardware(ctx context.Context) error { - data := []byte(`{ - "id": "ce2e62ed-826f-4485-a39f-a82bb74338e2", - "metadata": { - "facility": { - "facility_code": "onprem" - }, - "instance": {}, - "state": "" - }, - "network": { - "interfaces": [ - { - "dhcp": { - "arch": "x86_64", - "ip": { - "address": "192.168.1.5", - "gateway": "192.168.1.1", - "netmask": "255.255.255.248" - }, - "mac": "08:00:27:00:00:01", - "uefi": false - }, - "netboot": { - "allow_pxe": true, - "allow_workflow": true - } - } - ] - } -}`) - hw := pkg.HardwareWrapper{Hardware: &hardware.Hardware{}} - err := json.Unmarshal(data, &hw) - if err != nil { - return err - } - _, err = client.HardwareClient.Push(context.Background(), &hardware.PushRequest{Data: hw.Hardware}) - return err -}