Skip to content

Commit

Permalink
feat: initial client setup (#1)
Browse files Browse the repository at this point in the history
* feat: initial client setup

* chore: cleanup PHONY targets in Makefile

* chore: update rudder-go-kit version to 0.14.2

* chore: address several review comments

* Split workspace config model to multiple files
* Explicitly name model version in package
* Renamed SDK to Control Plane
* Refactored sample app for best practices
* Used url.URL to configure base URL for better error handling
  • Loading branch information
fxenik authored Aug 1, 2023
1 parent 0a75e7e commit 5638a16
Show file tree
Hide file tree
Showing 31 changed files with 1,541 additions and 14 deletions.
26 changes: 12 additions & 14 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
.DS_Store
.vscode
runtime.log
junit*.xml
**/*.test
.idea/*
*.out.*
*.out

# Dependency directories (remove the comment below to include it)
# vendor/
coverage.html
*.orig
**/gomock_reflect_*/*
ginkgo.report
.env
47 changes: 47 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
GO=go
LDFLAGS?=-s -w

.PHONY: default
default: lint

.PHONY: help
help: ## Show the available commands
@grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' ./Makefile | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

.PHONY: generate
generate: install-tools
$(GO) generate ./...

.PHONY: test
test: install-tools test-run ## Run all tests

.PHONY: test-run
test-run:
$(eval TEST_CMD = go test)
$(eval TEST_OPTIONS = -v -count 1 -race -coverprofile cover.out --timeout=15m)
ifdef package
$(TEST_CMD) $(TEST_OPTIONS) $(package)
else
$(TEST_CMD) $(TEST_OPTIONS) ./...
endif

.PHONY: coverage
coverage: test-run
go tool cover -html=cover.out -o coverage.html

.PHONY: test-with-coverage
test-with-coverage: test coverage

.PHONY: install-tools
install-tools:
go install github.com/golang/mock/mockgen@v1.6.0
go install mvdan.cc/gofumpt@latest

.PHONY: lint
lint: fmt ## Run linters on all go files
docker run --rm -v $(shell pwd):/app:ro -w /app golangci/golangci-lint:v1.51.1 bash -e -c \
'golangci-lint run -v --timeout 5m'

.PHONY: fmt
fmt: install-tools ## Formats all go files
gofumpt -l -w -extra .
76 changes: 76 additions & 0 deletions cmd/sampleapp/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package main

import (
"context"
"fmt"
"os"

cpsdk "github.com/rudderlabs/rudder-control-plane-sdk"
"github.com/rudderlabs/rudder-control-plane-sdk/identity"
"github.com/rudderlabs/rudder-go-kit/config"
"github.com/rudderlabs/rudder-go-kit/logger"
)

var log logger.Logger

func main() {
// setup a logger using the rudder-go-kit package
c := config.New()
loggerFactory := logger.NewFactory(c)
log = loggerFactory.NewLogger()

if err := run(); err != nil {
log.Fatalf("main error: %v", err)
}
}

// setupControlPlaneSDK creates a new SDK instance using the environment variables
func setupControlPlaneSDK() (*cpsdk.ControlPlane, error) {
apiUrl := os.Getenv("CPSDK_API_URL")
workspaceToken := os.Getenv("CPSDK_WORKSPACE_TOKEN")
namespace := os.Getenv("CPSDK_NAMESPACE")
hostedSecret := os.Getenv("CPSDK_HOSTED_SECRET")
adminUsername := os.Getenv("CPSDK_ADMIN_USERNAME")
adminPassword := os.Getenv("CPSDK_ADMIN_PASSWORD")

options := []cpsdk.Option{
cpsdk.WithBaseUrl(apiUrl),
cpsdk.WithLogger(log),
}

if namespace != "" {
options = append(options, cpsdk.WithNamespaceIdentity(namespace, hostedSecret))
} else {
options = append(options, cpsdk.WithWorkspaceIdentity(workspaceToken))
}

if adminUsername != "" || adminPassword != "" {
if adminUsername == "" || adminPassword == "" {
return nil, fmt.Errorf("both admin username and password must be provided")
}

adminCredentials := &identity.AdminCredentials{
AdminUsername: adminUsername,
AdminPassword: adminPassword,
}
options = append(options, cpsdk.WithAdminCredentials(adminCredentials))
}

return cpsdk.New(options...)
}

// run is the main function that uses the SDK
func run() error {
sdk, err := setupControlPlaneSDK()
if err != nil {
return fmt.Errorf("error setting up control plane sdk: %v", err)
}
defer sdk.Close()

_, err = sdk.Client.GetWorkspaceConfigs(context.Background())
if err != nil {
return fmt.Errorf("error getting workspace configs: %v", err)
}

return nil
}
115 changes: 115 additions & 0 deletions docs/overview.drawio
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<mxfile host="65bd71144e">
<diagram id="_XXg_SG4GZvzSHFKr3O1" name="Page-1">
<mxGraphModel dx="2261" dy="317" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1600" pageHeight="1200" background="#FFFFFF" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="17" value="access control plane admin functionalities using" style="edgeStyle=none;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;strokeColor=#000000;fontColor=#000000;labelBackgroundColor=#FFFFFF;" edge="1" parent="1" source="3" target="15">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="20" value="access control plane functionalities using" style="edgeStyle=none;html=1;strokeColor=#000000;fontColor=#000000;labelBackgroundColor=#FFFFFF;" edge="1" parent="1" source="3" target="4">
<mxGeometry x="-0.2495" y="-27" relative="1" as="geometry">
<mxPoint as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="38" value="reads cached workspace configs from" style="edgeStyle=none;html=1;strokeColor=#000000;fontColor=#000000;labelBackgroundColor=none;" edge="1" parent="1" source="3" target="28">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<object placeholders="1" c4Name="SDK" c4Type="Struct" c4Technology="SDK" c4Description="Entry point for Control Plane functionality" label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%: %c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="3">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;labelBackgroundColor=none;fillColor=#63BEF2;fontColor=#ffffff;align=center;arcSize=6;strokeColor=#2086C9;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
<mxGeometry x="1200" y="690" width="240" height="120" as="geometry"/>
</mxCell>
</object>
<mxCell id="18" value="is implemented by" style="edgeStyle=none;html=1;strokeColor=#000000;fontColor=#000000;labelBackgroundColor=#FFFFFF;" edge="1" parent="1" source="4" target="6">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="19" value="is implemented by" style="edgeStyle=none;html=1;strokeColor=#000000;fontColor=#000000;labelBackgroundColor=#FFFFFF;" edge="1" parent="1" source="4" target="5">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<object placeholders="1" c4Name="Client" c4Type="Interface" c4Technology="Client" c4Description="HTTP Client accessing common https://api.rudderstack.com API" label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%: %c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="4">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;labelBackgroundColor=none;fillColor=#63BEF2;fontColor=#ffffff;align=center;arcSize=6;strokeColor=#2086C9;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
<mxGeometry x="780" y="570" width="240" height="120" as="geometry"/>
</mxCell>
</object>
<mxCell id="22" value="makes HTTP API calls to" style="edgeStyle=none;html=1;strokeColor=#000000;labelBackgroundColor=#FFFFFF;fontColor=#000000;" edge="1" parent="1" source="5" target="21">
<mxGeometry x="0.0027" relative="1" as="geometry">
<mxPoint as="offset"/>
</mxGeometry>
</mxCell>
<object placeholders="1" c4Name="Workspace Client" c4Type="Struct" c4Technology="WorkspaceClient" c4Description="HTTP Client for single workspace operations" label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%: %c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="5">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;labelBackgroundColor=none;fillColor=#63BEF2;fontColor=#ffffff;align=center;arcSize=6;strokeColor=#2086C9;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
<mxGeometry x="380" y="490" width="240" height="120" as="geometry"/>
</mxCell>
</object>
<mxCell id="23" value="makes HTTP API calls to" style="edgeStyle=none;html=1;strokeColor=#000000;labelBackgroundColor=#FFFFFF;fontColor=#000000;" edge="1" parent="1" source="6" target="21">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<object placeholders="1" c4Name="Namespace Client" c4Type="Struct" c4Technology="NamespaceClient" c4Description="HTTP Client for namespace operations" label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%: %c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="6">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;labelBackgroundColor=none;fillColor=#63BEF2;fontColor=#ffffff;align=center;arcSize=6;strokeColor=#2086C9;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
<mxGeometry x="380" y="650" width="240" height="120" as="geometry"/>
</mxCell>
</object>
<mxCell id="24" value="makes HTTP API calls to" style="edgeStyle=none;html=1;strokeColor=#000000;labelBackgroundColor=#FFFFFF;fontColor=#000000;" edge="1" parent="1" source="15" target="21">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<object placeholders="1" c4Name="Admin Client" c4Type="Struct" c4Technology="AdminClient" c4Description="HTTP Client accessing https://api.rudderstack.com Admin API" label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%: %c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="15">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;labelBackgroundColor=none;fillColor=#63BEF2;fontColor=#ffffff;align=center;arcSize=6;strokeColor=#2086C9;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
<mxGeometry x="380" y="810" width="240" height="120" as="geometry"/>
</mxCell>
</object>
<object placeholders="1" c4Name="Control Plane HTTP API" c4Type="Software System" c4Description="https://api.rudderstack.com" label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#cccccc&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="21">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;labelBackgroundColor=none;fillColor=#1061B0;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0D5091;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
<mxGeometry x="-140" y="650" width="240" height="120" as="geometry"/>
</mxCell>
</object>
<mxCell id="26" value="uses to fetch workspce config" style="edgeStyle=none;html=1;strokeColor=#000000;labelBackgroundColor=#FFFFFF;fontColor=#000000;" edge="1" parent="1" source="25" target="4">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="35" value="notifies on workspace config changes" style="edgeStyle=none;html=1;strokeColor=#000000;fontColor=#000000;labelBackgroundColor=#FFFFFF;" edge="1" parent="1" source="25" target="34">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="41" value="&lt;font style=&quot;&quot; color=&quot;#000000&quot;&gt;updates workspace config cache&lt;/font&gt;" style="edgeStyle=none;html=1;strokeColor=#000000;labelBackgroundColor=#FFFFFF;" edge="1" parent="1" source="25" target="28">
<mxGeometry x="0.0083" relative="1" as="geometry">
<mxPoint as="offset"/>
</mxGeometry>
</mxCell>
<object placeholders="1" c4Name="Poller" c4Type="Struct" c4Technology="Poller" c4Description="Periodically polls workspace configs" label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%: %c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="25">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;labelBackgroundColor=none;fillColor=#63BEF2;fontColor=#ffffff;align=center;arcSize=6;strokeColor=#2086C9;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
<mxGeometry x="780" y="360" width="240" height="120" as="geometry"/>
</mxCell>
</object>
<object placeholders="1" c4Type="Postgres" c4Container="Container" c4Technology="Postgres" c4Description="Workspace config cache storage" label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Type%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Container%:&amp;nbsp;%c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#E6E6E6&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="27">
<mxCell style="shape=cylinder3;size=15;whiteSpace=wrap;html=1;boundedLbl=1;rounded=0;labelBackgroundColor=none;fillColor=#23A2D9;fontSize=12;fontColor=#ffffff;align=center;strokeColor=#0E7DAD;metaEdit=1;points=[[0.5,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.5,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];resizable=0;" vertex="1" parent="1">
<mxGeometry x="760" y="140" width="240" height="120" as="geometry"/>
</mxCell>
</object>
<mxCell id="33" value="persists copy of workspace config" style="edgeStyle=none;html=1;strokeColor=#000000;fontColor=#000000;labelBackgroundColor=#FFFFFF;" edge="1" parent="1" source="28" target="27">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<object placeholders="1" c4Name="Workspace Configs Cache" c4Type="Struct" c4Technology="WorkspaceConfigCache" c4Description="In-memory copy of latest workspace configs" label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%: %c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="28">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;labelBackgroundColor=none;fillColor=#63BEF2;fontColor=#ffffff;align=center;arcSize=6;strokeColor=#2086C9;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];" vertex="1" parent="1">
<mxGeometry x="1200" y="140" width="240" height="120" as="geometry"/>
</mxCell>
</object>
<mxCell id="37" value="subscribes to workspace config changes" style="edgeStyle=none;html=1;strokeColor=#000000;fontColor=#000000;labelBackgroundColor=#FFFFFF;" edge="1" parent="1" source="34" target="3">
<mxGeometry x="-0.0027" relative="1" as="geometry">
<mxPoint as="offset"/>
</mxGeometry>
</mxCell>
<object placeholders="1" c4Name="Workspace Config Subscriber" c4Type="Function" c4Description="A component that needs to monitor workspace config updates" label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#cccccc&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="34">
<mxCell style="html=1;fontSize=11;dashed=0;whiteSpace=wrap;fillColor=#6C6477;strokeColor=#4D4D4D;fontColor=#ffffff;shape=mxgraph.c4.person2;align=center;metaEdit=1;points=[[0.5,0,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0]];resizable=0;" vertex="1" parent="1">
<mxGeometry x="1770" y="330" width="200" height="180" as="geometry"/>
</mxCell>
</object>
<mxCell id="40" value="accesses control plane functionalities using" style="edgeStyle=none;html=1;strokeColor=#000000;fontColor=#000000;labelBackgroundColor=#FFFFFF;" edge="1" parent="1" source="39" target="3">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<object placeholders="1" c4Name="Control Plane Consumer" c4Type="Component" c4Description="A component that needs to use control plane functionalities" label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#cccccc&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="39">
<mxCell style="html=1;fontSize=11;dashed=0;whiteSpace=wrap;fillColor=#6C6477;strokeColor=#4D4D4D;fontColor=#ffffff;shape=mxgraph.c4.person2;align=center;metaEdit=1;points=[[0.5,0,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0]];resizable=0;" vertex="1" parent="1">
<mxGeometry x="1770" y="660" width="200" height="180" as="geometry"/>
</mxCell>
</object>
</root>
</mxGraphModel>
</diagram>
</mxfile>
1 change: 1 addition & 0 deletions docs/overview.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 5638a16

Please sign in to comment.