diff --git a/clusterdef/fromshortstring.go b/clusterdef/fromshortstring.go index fd6ecf5..2596fe6 100644 --- a/clusterdef/fromshortstring.go +++ b/clusterdef/fromshortstring.go @@ -65,6 +65,26 @@ func FromShortString(shortStr string) (*Cluster, error) { FtsMemoryMB: 1024, }, }, nil + } else if defName == "columnar" { + return &Cluster{ + Columnar: true, + NodeGroups: []*NodeGroup{ + { + Count: 3, + Version: defVersion, + }, + }, + }, nil + } else if defName == "columnar-single" { + return &Cluster{ + Columnar: true, + NodeGroups: []*NodeGroup{ + { + Count: 1, + Version: defVersion, + }, + }, + }, nil } return nil, fmt.Errorf("unknown short string name `%s`", defName) diff --git a/cmd/list.go b/cmd/list.go index c8a9780..5e9a151 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -19,6 +19,7 @@ type ClusterListOutput []ClusterListOutput_Item type ClusterListOutput_Item struct { ID string `json:"id"` + Type string `json:"type"` State string `json:"state"` Expiry *time.Time `json:"expiry,omitempty"` Deployer string `json:"deployer"` @@ -26,10 +27,11 @@ type ClusterListOutput_Item struct { } type ClusterListOutput_Node struct { - ID string `json:"id"` - Name string `json:"name"` - IPAddress string `json:"ip_address"` - ResourceID string `json:"resource_id"` + ID string `json:"id"` + Name string `json:"name"` + IPAddress string `json:"ip_address"` + ResourceID string `json:"resource_id"` + IsClusterNode bool `json:"is_cluster_node"` } var listCmd = &cobra.Command{ @@ -88,14 +90,20 @@ var listCmd = &cobra.Command{ expiryStr = time.Until(cluster.GetExpiry()).Round(time.Second).String() } - fmt.Printf(" %s [State: %s, Timeout: %s, Deployer: %s]\n", + fmt.Printf(" %s [Type: %s, State: %s, Timeout: %s, Deployer: %s]\n", cluster.GetID(), + cluster.GetType(), cluster.GetState(), expiryStr, deployerName) for _, node := range cluster.GetNodes() { - fmt.Printf(" %-16s %-20s %-20s %s\n", - node.GetID(), + printId := node.GetID() + if !node.IsClusterNode() { + printId = "[UTIL] " + printId + } + + fmt.Printf(" %-40s %-20s %-20s %s\n", + printId, node.GetName(), node.GetIPAddress(), node.GetResourceID()) @@ -106,6 +114,7 @@ var listCmd = &cobra.Command{ for _, cluster := range clusters { clusterItem := ClusterListOutput_Item{ ID: cluster.Info.GetID(), + Type: string(cluster.Info.GetType()), State: cluster.Info.GetState(), Deployer: cluster.DeployerName, } @@ -117,10 +126,11 @@ var listCmd = &cobra.Command{ for _, node := range cluster.Info.GetNodes() { clusterItem.Nodes = append(clusterItem.Nodes, ClusterListOutput_Node{ - ID: node.GetID(), - Name: node.GetName(), - IPAddress: node.GetIPAddress(), - ResourceID: node.GetResourceID(), + ID: node.GetID(), + Name: node.GetName(), + IPAddress: node.GetIPAddress(), + ResourceID: node.GetResourceID(), + IsClusterNode: node.IsClusterNode(), }) } out = append(out, clusterItem) diff --git a/deployment/caodeploy/clusterinfo.go b/deployment/caodeploy/clusterinfo.go index 4c872f1..24520eb 100644 --- a/deployment/caodeploy/clusterinfo.go +++ b/deployment/caodeploy/clusterinfo.go @@ -14,10 +14,11 @@ type ClusterInfo struct { var _ (deployment.ClusterInfo) = (*ClusterInfo)(nil) -func (i ClusterInfo) GetID() string { return i.ClusterID } -func (i ClusterInfo) GetPurpose() string { return "" } -func (i ClusterInfo) GetExpiry() time.Time { return i.Expiry } -func (i ClusterInfo) GetState() string { return i.State } +func (i ClusterInfo) GetID() string { return i.ClusterID } +func (i ClusterInfo) GetType() deployment.ClusterType { return deployment.ClusterTypeServer } +func (i ClusterInfo) GetPurpose() string { return "" } +func (i ClusterInfo) GetExpiry() time.Time { return i.Expiry } +func (i ClusterInfo) GetState() string { return i.State } func (i ClusterInfo) GetNodes() []deployment.ClusterNodeInfo { return nil } diff --git a/deployment/clouddeploy/clusterinfo.go b/deployment/clouddeploy/clusterinfo.go index 2b848f3..f20ff18 100644 --- a/deployment/clouddeploy/clusterinfo.go +++ b/deployment/clouddeploy/clusterinfo.go @@ -17,10 +17,11 @@ type ClusterInfo struct { var _ (deployment.ClusterInfo) = (*ClusterInfo)(nil) -func (i ClusterInfo) GetID() string { return i.ClusterID } -func (i ClusterInfo) GetPurpose() string { return "" } -func (i ClusterInfo) GetExpiry() time.Time { return i.Expiry } -func (i ClusterInfo) GetState() string { return i.State } +func (i ClusterInfo) GetID() string { return i.ClusterID } +func (i ClusterInfo) GetType() deployment.ClusterType { return deployment.ClusterTypeServer } +func (i ClusterInfo) GetPurpose() string { return "" } +func (i ClusterInfo) GetExpiry() time.Time { return i.Expiry } +func (i ClusterInfo) GetState() string { return i.State } func (i ClusterInfo) GetNodes() []deployment.ClusterNodeInfo { return nil } diff --git a/deployment/deployer.go b/deployment/deployer.go index ddab703..7ea7ce7 100644 --- a/deployment/deployer.go +++ b/deployment/deployer.go @@ -7,8 +7,16 @@ import ( "github.com/couchbaselabs/cbdinocluster/clusterdef" ) +type ClusterType string + +const ( + ClusterTypeServer ClusterType = "server" + ClusterTypeColumnar ClusterType = "columnar" +) + type ClusterNodeInfo interface { GetID() string + IsClusterNode() bool GetResourceID() string GetName() string GetIPAddress() string @@ -16,6 +24,7 @@ type ClusterNodeInfo interface { type ClusterInfo interface { GetID() string + GetType() ClusterType GetPurpose() string GetExpiry() time.Time GetState() string diff --git a/deployment/dockerdeploy/clusterinfo.go b/deployment/dockerdeploy/clusterinfo.go index f2412e7..8c490d8 100644 --- a/deployment/dockerdeploy/clusterinfo.go +++ b/deployment/dockerdeploy/clusterinfo.go @@ -8,6 +8,7 @@ import ( type ClusterNodeInfo struct { NodeID string + IsNode bool Name string ResourceID string IPAddress string @@ -16,12 +17,14 @@ type ClusterNodeInfo struct { var _ (deployment.ClusterNodeInfo) = (*ClusterNodeInfo)(nil) func (i ClusterNodeInfo) GetID() string { return i.NodeID } +func (i ClusterNodeInfo) IsClusterNode() bool { return i.IsNode } func (i ClusterNodeInfo) GetName() string { return i.Name } func (i ClusterNodeInfo) GetResourceID() string { return i.ResourceID } func (i ClusterNodeInfo) GetIPAddress() string { return i.IPAddress } type ClusterInfo struct { ClusterID string + Type deployment.ClusterType Creator string Owner string Purpose string @@ -31,10 +34,11 @@ type ClusterInfo struct { var _ (deployment.ClusterInfo) = (*ClusterInfo)(nil) -func (i ClusterInfo) GetID() string { return i.ClusterID } -func (i ClusterInfo) GetPurpose() string { return i.Purpose } -func (i ClusterInfo) GetExpiry() time.Time { return i.Expiry } -func (i ClusterInfo) GetState() string { return "ready" } +func (i ClusterInfo) GetID() string { return i.ClusterID } +func (i ClusterInfo) GetType() deployment.ClusterType { return i.Type } +func (i ClusterInfo) GetPurpose() string { return i.Purpose } +func (i ClusterInfo) GetExpiry() time.Time { return i.Expiry } +func (i ClusterInfo) GetState() string { return "ready" } func (i ClusterInfo) GetNodes() []deployment.ClusterNodeInfo { var nodes []deployment.ClusterNodeInfo for _, node := range i.Nodes { diff --git a/deployment/dockerdeploy/controller.go b/deployment/dockerdeploy/controller.go index e113fcd..188406c 100644 --- a/deployment/dockerdeploy/controller.go +++ b/deployment/dockerdeploy/controller.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" "io" + "net/http" "time" "github.com/couchbaselabs/cbdinocluster/utils/clustercontrol" @@ -28,6 +29,7 @@ type Controller struct { type NodeInfo struct { ContainerID string + Type string NodeID string ClusterID string Name string @@ -41,6 +43,7 @@ type NodeInfo struct { func (c *Controller) parseContainerInfo(container types.Container) *NodeInfo { clusterID := container.Labels["com.couchbase.dyncluster.cluster_id"] + nodeType := container.Labels["com.couchbase.dyncluster.type"] nodeID := container.Labels["com.couchbase.dyncluster.node_id"] nodeName := container.Labels["com.couchbase.dyncluster.node_name"] creator := container.Labels["com.couchbase.dyncluster.creator"] @@ -57,8 +60,14 @@ func (c *Controller) parseContainerInfo(container types.Container) *NodeInfo { pickedNetwork = network } + // if the node type is unspecified, we default to server-node + if nodeType == "" { + nodeType = "server-node" + } + return &NodeInfo{ ContainerID: container.ID, + Type: nodeType, NodeID: nodeID, ClusterID: clusterID, Name: nodeName, @@ -182,12 +191,100 @@ func (c *Controller) ReadNodeState(ctx context.Context, containerID string) (*Do }, nil } +func (c *Controller) DeployS3MockNode(ctx context.Context, clusterID string, expiry time.Duration) (*NodeInfo, error) { + nodeID := "s3mock" + logger := c.Logger.With(zap.String("nodeId", nodeID)) + + logger.Debug("deploying s3mock node") + + containerName := "cbdynnode-s3-" + clusterID + + createResult, err := c.DockerCli.ContainerCreate(context.Background(), &container.Config{ + Image: "adobe/s3mock", + Labels: map[string]string{ + "com.couchbase.dyncluster.cluster_id": clusterID, + "com.couchbase.dyncluster.type": "s3mock", + "com.couchbase.dyncluster.purpose": "s3mock backing for columnar", + "com.couchbase.dyncluster.node_id": nodeID, + }, + // same effect as ntp + Volumes: map[string]struct{}{"/etc/localtime:/etc/localtime": {}}, + }, &container.HostConfig{ + AutoRemove: true, + NetworkMode: container.NetworkMode(c.NetworkName), + CapAdd: []string{"NET_ADMIN"}, + Resources: container.Resources{ + Ulimits: []*units.Ulimit{ + {Name: "nofile", Soft: 200000, Hard: 200000}, + }, + }, + }, nil, nil, containerName) + if err != nil { + return nil, errors.Wrap(err, "failed to create container") + } + + containerID := createResult.ID + + logger.Debug("container created, starting", zap.String("container", containerID)) + + err = c.DockerCli.ContainerStart(context.Background(), containerID, types.ContainerStartOptions{}) + if err != nil { + return nil, errors.Wrap(err, "failed to start container") + } + + expiryTime := time.Time{} + if expiry > 0 { + expiryTime = time.Now().Add(expiry) + } + + err = c.WriteNodeState(ctx, containerID, &DockerNodeState{ + Expiry: expiryTime, + }) + if err != nil { + return nil, errors.Wrap(err, "failed write node state") + } + + // Cheap hack for simpler parsing... + allNodes, err := c.ListNodes(ctx) + if err != nil { + return nil, errors.Wrap(err, "failed to list nodes") + } + + var node *NodeInfo + for _, allNode := range allNodes { + if allNode.ContainerID == containerID { + node = allNode + } + } + if node == nil { + return nil, errors.New("failed to find newly created container") + } + + logger.Debug("container has started, waiting for it to get ready", zap.String("address", node.IPAddress)) + + for { + resp, err := http.Get(fmt.Sprintf("http://%s:%d", node.IPAddress, 9090)) + if err != nil || resp.StatusCode != 200 { + logger.Debug("s3mock not ready yet", zap.Error(err)) + time.Sleep(100 * time.Millisecond) + continue + } + + break + } + + logger.Debug("container is ready!") + + return node, nil +} + type DeployNodeOptions struct { Purpose string Expiry time.Duration ClusterID string Image *ImageRef ImageServerVersion string + IsColumnar bool EnvVars map[string]string } @@ -204,10 +301,16 @@ func (c *Controller) DeployNode(ctx context.Context, def *DeployNodeOptions) (*N envVars = append(envVars, fmt.Sprintf("%s=%s", varName, varValue)) } + nodeType := "server-node" + if def.IsColumnar { + nodeType = "columnar-node" + } + createResult, err := c.DockerCli.ContainerCreate(context.Background(), &container.Config{ Image: def.Image.ImagePath, Labels: map[string]string{ "com.couchbase.dyncluster.cluster_id": def.ClusterID, + "com.couchbase.dyncluster.type": nodeType, "com.couchbase.dyncluster.purpose": def.Purpose, "com.couchbase.dyncluster.node_id": nodeID, "com.couchbase.dyncluster.initial_server_version": def.ImageServerVersion, diff --git a/deployment/dockerdeploy/deployer.go b/deployment/dockerdeploy/deployer.go index 769d251..775d415 100644 --- a/deployment/dockerdeploy/deployer.go +++ b/deployment/dockerdeploy/deployer.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "io" + "net/http" "os" "path" "strings" @@ -82,6 +83,7 @@ func (d *Deployer) listClusters(ctx context.Context) ([]*ClusterInfo, error) { } cluster := &ClusterInfo{ ClusterID: clusterID, + Type: deployment.ClusterTypeServer, } clusters = append(clusters, cluster) return cluster @@ -95,12 +97,24 @@ func (d *Deployer) listClusters(ctx context.Context) ([]*ClusterInfo, error) { if !node.Expiry.IsZero() && node.Expiry.After(cluster.Expiry) { cluster.Expiry = node.Expiry } + + isClusterNode := false + if node.Type == "server-node" || node.Type == "columnar-node" { + isClusterNode = true + } + cluster.Nodes = append(cluster.Nodes, &ClusterNodeInfo{ ResourceID: node.ContainerID[0:8] + "...", + IsNode: isClusterNode, NodeID: node.NodeID, Name: node.Name, IPAddress: node.IPAddress, }) + + // if any nodes are columnar nodes, the cluster is a columnar cluster + if node.Type == "columnar-node" { + cluster.Type = deployment.ClusterTypeColumnar + } } return clusters, nil @@ -119,7 +133,7 @@ func (d *Deployer) ListClusters(ctx context.Context) ([]deployment.ClusterInfo, return out, nil } -func (d *Deployer) getImagesForNodeGrps(ctx context.Context, nodeGrps []*clusterdef.NodeGroup) ([]*ImageRef, error) { +func (d *Deployer) getImagesForNodeGrps(ctx context.Context, nodeGrps []*clusterdef.NodeGroup, isColumnar bool) ([]*ImageRef, error) { nodeGrpDefs := make([]*ImageDef, len(nodeGrps)) nodeGrpImages := make([]*ImageRef, len(nodeGrps)) for nodeGrpIdx, nodeGrp := range nodeGrps { @@ -143,6 +157,7 @@ func (d *Deployer) getImagesForNodeGrps(ctx context.Context, nodeGrps []*cluster BuildNo: versionInfo.BuildNo, UseCommunityEdition: versionInfo.CommunityEdition, UseServerless: versionInfo.Serverless, + UseColumnar: isColumnar, } nodeGrpDefs[nodeGrpIdx] = imageDef @@ -169,11 +184,64 @@ func (d *Deployer) getImagesForNodeGrps(ctx context.Context, nodeGrps []*cluster } func (d *Deployer) NewCluster(ctx context.Context, def *clusterdef.Cluster) (deployment.ClusterInfo, error) { + if def.Columnar { + for _, nodeGrp := range def.NodeGroups { + if len(nodeGrp.Services) != 0 { + return nil, errors.New("columnar clusters cannot specify services") + } + + nodeGrp.Services = []clusterdef.Service{ + clusterdef.KvService, + clusterdef.AnalyticsService, + } + } + } + clusterID := uuid.NewString() + if def.Columnar { + d.logger.Info("deploying mock s3 for blob storage") + + d.logger.Debug("deploying s3mock container") + + node, err := d.controller.DeployS3MockNode(ctx, clusterID, def.Expiry) + if err != nil { + return nil, errors.Wrap(err, "failed to deploy s3mock node") + } + + d.logger.Debug("creating columnar bucket") + + bucketName := "columnar" + req, err := http.NewRequest( + "PUT", + fmt.Sprintf("http://%s:9090/%s/", node.IPAddress, bucketName), + nil) + if err != nil { + return nil, errors.Wrap(err, "failed to create columnar s3 bucket request") + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, errors.Wrap(err, "failed to create columnar s3 bucket") + } + if resp.StatusCode != 200 { + return nil, fmt.Errorf("non-200 status code when creating columnar s3 bucket (code: %d)", resp.StatusCode) + } + + d.logger.Info("s3 mock is ready") + + def.Docker.Analytics.BlobStorage = clusterdef.AnalyticsBlobStorageSettings{ + Region: "local", + Bucket: "columnar", + Scheme: "s3", + Endpoint: fmt.Sprintf("http://%s:9090", node.IPAddress), + AnonymousAuth: true, + } + } + d.logger.Info("gathering node images") - nodeGrpImages, err := d.getImagesForNodeGrps(ctx, def.NodeGroups) + nodeGrpImages, err := d.getImagesForNodeGrps(ctx, def.NodeGroups, def.Columnar) if err != nil { return nil, errors.Wrap(err, "failed to fetch images") } @@ -212,6 +280,7 @@ func (d *Deployer) NewCluster(ctx context.Context, def *clusterdef.Cluster) (dep ClusterID: clusterID, Image: image, ImageServerVersion: nodeGrp.Version, + IsColumnar: def.Columnar, Expiry: def.Expiry, EnvVars: nodeGrp.Docker.EnvVars, } @@ -428,10 +497,11 @@ type deployedNodeInfo struct { } type deployedClusterInfo struct { - ID string - Purpose string - Expiry time.Time - Nodes []*deployedNodeInfo + ID string + Purpose string + Expiry time.Time + Nodes []*deployedNodeInfo + IsColumnar bool } func (d *Deployer) getClusterInfo(ctx context.Context, clusterID string) (*deployedClusterInfo, error) { @@ -442,10 +512,15 @@ func (d *Deployer) getClusterInfo(ctx context.Context, clusterID string) (*deplo var purpose string var expiry time.Time + var isColumnar bool var nodeInfo []*deployedNodeInfo for _, node := range nodes { if node.ClusterID == clusterID { + if node.Type == "columnar-node" { + isColumnar = true + } + if node.Purpose != "" { purpose = node.Purpose } @@ -453,23 +528,30 @@ func (d *Deployer) getClusterInfo(ctx context.Context, clusterID string) (*deplo expiry = node.Expiry } - nodeCtrl := clustercontrol.NodeManager{ - Endpoint: fmt.Sprintf("http://%s:8091", node.IPAddress), - } - thisNodeInfo, err := nodeCtrl.Controller().GetLocalInfo(ctx) - if err != nil { - return nil, errors.Wrap(err, "failed to list a nodes services") - } + var otpNode string + var services []clusterdef.Service - services, err := clusterdef.NsServicesToServices(thisNodeInfo.Services) - if err != nil { - return nil, errors.Wrap(err, "failed to generate services list") + if node.Type == "server-node" || node.Type == "columnar-node" { + nodeCtrl := clustercontrol.NodeManager{ + Endpoint: fmt.Sprintf("http://%s:8091", node.IPAddress), + } + thisNodeInfo, err := nodeCtrl.Controller().GetLocalInfo(ctx) + if err != nil { + return nil, errors.Wrap(err, "failed to list a nodes services") + } + + services, err = clusterdef.NsServicesToServices(thisNodeInfo.Services) + if err != nil { + return nil, errors.Wrap(err, "failed to generate services list") + } + + otpNode = thisNodeInfo.OTPNode } nodeInfo = append(nodeInfo, &deployedNodeInfo{ ContainerID: node.ContainerID, IPAddress: node.IPAddress, - OTPNode: thisNodeInfo.OTPNode, + OTPNode: otpNode, Version: node.InitialServerVersion, Services: services, }) @@ -477,10 +559,11 @@ func (d *Deployer) getClusterInfo(ctx context.Context, clusterID string) (*deplo } return &deployedClusterInfo{ - ID: clusterID, - Purpose: purpose, - Expiry: expiry, - Nodes: nodeInfo, + ID: clusterID, + Purpose: purpose, + Expiry: expiry, + Nodes: nodeInfo, + IsColumnar: isColumnar, }, nil } @@ -547,7 +630,7 @@ func (d *Deployer) addRemoveNodes( d.logger.Info("gathering node images") - nodesToAddImages, err := d.getImagesForNodeGrps(ctx, nodesToAdd) + nodesToAddImages, err := d.getImagesForNodeGrps(ctx, nodesToAdd, clusterInfo.IsColumnar) if err != nil { return nil, errors.Wrap(err, "failed to fetch images") } @@ -564,6 +647,7 @@ func (d *Deployer) addRemoveNodes( ClusterID: clusterInfo.ID, Image: image, ImageServerVersion: nodeGrp.Version, + IsColumnar: clusterInfo.IsColumnar, Expiry: time.Until(clusterInfo.Expiry), EnvVars: nodeGrp.Docker.EnvVars, } @@ -843,6 +927,10 @@ func (d *Deployer) GetConnectInfo(ctx context.Context, clusterID string) (*deplo var mgmtAddr string var mgmtTlsAddr string for _, node := range thisCluster.Nodes { + if !node.IsClusterNode() { + continue + } + kvPort := 11210 kvTlsPort := 11207 mgmtPort := 8091 diff --git a/deployment/dockerdeploy/dockerhubimageprovider.go b/deployment/dockerdeploy/dockerhubimageprovider.go index 0072620..740e829 100644 --- a/deployment/dockerdeploy/dockerhubimageprovider.go +++ b/deployment/dockerdeploy/dockerhubimageprovider.go @@ -28,6 +28,9 @@ func (p *DockerHubImageProvider) GetImage(ctx context.Context, def *ImageDef) (* if def.UseServerless { return nil, errors.New("cannot use dockerhub for serverless releases") } + if def.UseColumnar { + return nil, errors.New("cannot use dockerhub for columnar releases") + } var serverVersion string if def.UseCommunityEdition { diff --git a/deployment/dockerdeploy/ghcrimageprovider.go b/deployment/dockerdeploy/ghcrimageprovider.go index 9a840de..ad45054 100644 --- a/deployment/dockerdeploy/ghcrimageprovider.go +++ b/deployment/dockerdeploy/ghcrimageprovider.go @@ -42,18 +42,31 @@ func (p *GhcrImageProvider) GetImage(ctx context.Context, def *ImageDef) (*Image return nil, errors.New("cannot use ghcr without credentials") } + if def.UseServerless { + return nil, errors.New("cannot use ghcr for serverless releases") + } + if def.BuildNo == 0 { return nil, errors.New("cannot use ghcr for ga releases") } serverVersion := fmt.Sprintf("%s-%d", def.Version, def.BuildNo) - if def.UseCommunityEdition { - serverVersion = "community-" + serverVersion - } - p.Logger.Debug("pulling image from ghcr") + var ghcrImagePath string + if !def.UseColumnar { + if def.UseCommunityEdition { + serverVersion = "community-" + serverVersion + } + + ghcrImagePath = fmt.Sprintf("ghcr.io/cb-vanilla/server:%s", serverVersion) + } else { + if def.UseCommunityEdition { + return nil, errors.New("cannot pull community edition of columnar") + } + + ghcrImagePath = fmt.Sprintf("ghcr.io/cb-vanilla/couchbase-columnar:%s", serverVersion) + } - ghcrImagePath := fmt.Sprintf("ghcr.io/cb-vanilla/server:%s", serverVersion) p.Logger.Debug("identified ghcr image to pull", zap.String("image", ghcrImagePath)) return MultiArchImagePuller{ diff --git a/deployment/dockerdeploy/imageprovider.go b/deployment/dockerdeploy/imageprovider.go index bb659c9..0a49500 100644 --- a/deployment/dockerdeploy/imageprovider.go +++ b/deployment/dockerdeploy/imageprovider.go @@ -12,6 +12,7 @@ type ImageDef struct { BuildNo int UseCommunityEdition bool UseServerless bool + UseColumnar bool } type ImageRef struct { @@ -49,5 +50,11 @@ func CompareImageDefs(a, b *ImageDef) int { return +1 } + if !a.UseColumnar && b.UseColumnar { + return -1 + } else if a.UseColumnar && !b.UseColumnar { + return +1 + } + return 0 } diff --git a/deployment/dockerdeploy/serverlessimageprovider.go b/deployment/dockerdeploy/serverlessimageprovider.go index 225f560..de2129f 100644 --- a/deployment/dockerdeploy/serverlessimageprovider.go +++ b/deployment/dockerdeploy/serverlessimageprovider.go @@ -33,6 +33,10 @@ func (p *ServerlessImageProvider) GetImage(ctx context.Context, def *ImageDef) ( return nil, errors.New("cannot use serverless provider for non-serverless") } + if def.UseColumnar { + return nil, errors.New("cannot use serverless provider for columnar images") + } + var serverVariant string if def.UseCommunityEdition { serverVariant = "community" diff --git a/deployment/localdeploy/clusterinfo.go b/deployment/localdeploy/clusterinfo.go index 0af4e00..5a1b043 100644 --- a/deployment/localdeploy/clusterinfo.go +++ b/deployment/localdeploy/clusterinfo.go @@ -12,6 +12,7 @@ type ClusterNodeInfo struct { var _ (deployment.ClusterNodeInfo) = (*ClusterNodeInfo)(nil) func (i ClusterNodeInfo) GetID() string { return "a" } +func (i ClusterNodeInfo) IsClusterNode() bool { return true } func (i ClusterNodeInfo) GetName() string { return "" } func (i ClusterNodeInfo) GetResourceID() string { return "" } func (i ClusterNodeInfo) GetIPAddress() string { return "127.0.0.1" } @@ -21,10 +22,11 @@ type ClusterInfo struct { var _ (deployment.ClusterInfo) = (*ClusterInfo)(nil) -func (i ClusterInfo) GetID() string { return "a" } -func (i ClusterInfo) GetPurpose() string { return "" } -func (i ClusterInfo) GetExpiry() time.Time { return time.Time{} } -func (i ClusterInfo) GetState() string { return "ready" } +func (i ClusterInfo) GetID() string { return "a" } +func (i ClusterInfo) GetType() deployment.ClusterType { return deployment.ClusterTypeServer } +func (i ClusterInfo) GetPurpose() string { return "" } +func (i ClusterInfo) GetExpiry() time.Time { return time.Time{} } +func (i ClusterInfo) GetState() string { return "ready" } func (i ClusterInfo) GetNodes() []deployment.ClusterNodeInfo { return []deployment.ClusterNodeInfo{ ClusterNodeInfo{}, diff --git a/examples/cloud-columnar.yaml b/examples/cloud-columnar.yaml deleted file mode 100644 index 0d8ba0f..0000000 --- a/examples/cloud-columnar.yaml +++ /dev/null @@ -1,10 +0,0 @@ -columnar: true -nodes: - - count: 1 - cloud: - cpu: 4 - memory: 32 -deployer: cloud -cloud: - cloud-provider: aws - region: us-west-2 \ No newline at end of file diff --git a/examples/columnar.yaml b/examples/columnar.yaml new file mode 100644 index 0000000..6c2bd35 --- /dev/null +++ b/examples/columnar.yaml @@ -0,0 +1,4 @@ +columnar: true +nodes: + - count: 3 + version: 1.0.0-2239 diff --git a/go.mod b/go.mod index 317c9d8..4942ef4 100644 --- a/go.mod +++ b/go.mod @@ -87,7 +87,7 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect - github.com/docker/go-units v0.5.0 // indirect + github.com/docker/go-units v0.5.0 github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v5 v5.0.0 // indirect github.com/golang/protobuf v1.5.3 // indirect