Add E2E tests for basic functionality and port launching to Go

This adds a new E2E test suite replacing the old log-parsing
based one. It also moves launching and controlling Smalltown VMs into
a Go package and command and exposes the '//:launch' alias.
The new E2E test suite covers basic conditions (IP assigned, Data
available) and Kubernetes Node, Deployment and StatefulSet tests.

Test Plan: This consists of E2E tests

X-Origin-Diff: phab/D544
GitOrigin-RevId: 7c624c667c849068bafa544a3a6c635d6d406e1c
diff --git a/core/internal/consensus/BUILD.bazel b/core/internal/consensus/BUILD.bazel
index c8b2f25..f0246f7 100644
--- a/core/internal/consensus/BUILD.bazel
+++ b/core/internal/consensus/BUILD.bazel
@@ -18,6 +18,7 @@
         "@io_etcd_go_etcd//pkg/types:go_default_library",
         "@io_etcd_go_etcd//proxy/grpcproxy/adapter:go_default_library",
         "@org_golang_x_sys//unix:go_default_library",
+        "@org_uber_go_atomic//:go_default_library",
         "@org_uber_go_zap//:go_default_library",
         "@org_uber_go_zap//zapcore:go_default_library",
     ],
diff --git a/core/internal/consensus/consensus.go b/core/internal/consensus/consensus.go
index 67bac1c..d401c1a 100644
--- a/core/internal/consensus/consensus.go
+++ b/core/internal/consensus/consensus.go
@@ -33,11 +33,6 @@
 	"strings"
 	"time"
 
-	"git.monogon.dev/source/nexantic.git/core/internal/common"
-	"git.monogon.dev/source/nexantic.git/core/internal/common/service"
-
-	"git.monogon.dev/source/nexantic.git/core/generated/api"
-
 	"github.com/pkg/errors"
 	"go.etcd.io/etcd/clientv3"
 	"go.etcd.io/etcd/clientv3/namespace"
@@ -45,10 +40,14 @@
 	"go.etcd.io/etcd/etcdserver/api/membership"
 	"go.etcd.io/etcd/pkg/types"
 	"go.etcd.io/etcd/proxy/grpcproxy/adapter"
+	"go.uber.org/atomic"
 	"go.uber.org/zap"
 	"go.uber.org/zap/zapcore"
 	"golang.org/x/sys/unix"
 
+	"git.monogon.dev/source/nexantic.git/core/generated/api"
+	"git.monogon.dev/source/nexantic.git/core/internal/common"
+	"git.monogon.dev/source/nexantic.git/core/internal/common/service"
 	"git.monogon.dev/source/nexantic.git/core/internal/consensus/ca"
 )
 
@@ -75,7 +74,7 @@
 
 		etcd  *embed.Etcd
 		kv    clientv3.KV
-		ready bool
+		ready atomic.Bool
 
 		// bootstrapCA and bootstrapCert cache the etcd cluster CA data during bootstrap.
 		bootstrapCA   *ca.CA
@@ -192,6 +191,7 @@
 	go func() {
 		s.Logger.Info("waiting for etcd to become ready")
 		<-s.etcd.Server.ReadyNotify()
+		s.ready.Store(true)
 		s.Logger.Info("etcd is now ready")
 	}()
 
@@ -432,7 +432,7 @@
 
 // IsReady returns whether etcd is ready and synced
 func (s *Service) IsReady() bool {
-	return s.ready
+	return s.ready.Load()
 }
 
 // AddMember adds a new etcd member to the cluster