Skip to content

Commit fd7c979

Browse files
authored
feat: Go SDK integration tests and CI (#988)
1 parent a4f1dec commit fd7c979

File tree

2 files changed

+321
-3
lines changed

2 files changed

+321
-3
lines changed

.github/workflows/go-ci.yml

+138-3
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,20 @@ on:
1313
workflow_dispatch:
1414

1515
env:
16+
LOOKERSDK_BASE_URL: https://localhost:20000
17+
LOOKERSDK_VERIFY_SSL: false
1618
JUNIT_OUTPUT_DIR: results
1719
JUNIT_ARTIFACT_DIR: gosdk-test-results
1820

1921
jobs:
2022
unit:
2123
name: Unit - ${{ matrix.os }} / Go ${{ matrix.go-version }}
2224
env:
23-
GO_JUNIT_OUTPUT_NAME: ${{ matrix.os }}.gosdkunitresult${{ matrix.go-version }}.xml
25+
GO_JUNIT_OUTPUT_NAME: ${{ matrix.os }}.gounit.${{ matrix.go-version }}.xml
2426
runs-on: ${{ matrix.os }}-latest
27+
defaults:
28+
run:
29+
shell: bash
2530

2631
strategy:
2732
matrix:
@@ -44,7 +49,7 @@ jobs:
4449
go-version: ${{ matrix.go-version }}
4550

4651
- name: Install dependencies
47-
run: go get -u github.com/jstemmer/go-junit-report
52+
run: go install github.com/jstemmer/go-junit-report@latest
4853

4954
- name: Run unit tests
5055
run: |
@@ -59,8 +64,138 @@ jobs:
5964
name: ${{ env.JUNIT_ARTIFACT_DIR }}
6065
path: ${{ env.JUNIT_OUTPUT_DIR }}
6166

62-
publish-test-results:
67+
integration:
6368
needs: unit
69+
name: Integration - ${{ matrix.os }} / Looker.${{ matrix.looker }}
70+
env:
71+
GO_JUNIT_OUTPUT_NAME: ${{ matrix.os }}.Looker-${{ matrix.looker }}.gointegration.xml
72+
runs-on: ${{ matrix.os }}-latest
73+
defaults:
74+
run:
75+
shell: bash
76+
77+
strategy:
78+
matrix:
79+
os:
80+
- ubuntu
81+
looker:
82+
- '21_18'
83+
- '21_20'
84+
- '22_0'
85+
# TODO uncomment `include:` when either macos or windows works to satisfaction.
86+
#include:
87+
# TODO: macos matrix leg is functional but it takes ~20 minutes (compared
88+
# to ~4 minutes for ubuntu) because docker install takes ~5 minutes
89+
# and docker pull takes ~10 minutes. We can probably figure out how to
90+
# cache the docker install but hopefully github will soon have docker
91+
# available pre-installed on macos so not worth the effort now.
92+
# Regarding docker pull ... it would be nice if there's a way to cache
93+
# only some layers of the image on the runner but we don't want to cache
94+
# the final layer(s) with Looker IP. This would speed up docker pull on
95+
# all OSs.
96+
#- os: macos
97+
# python-version: 3.9
98+
# looker: '7_20'
99+
# TODO: currently can't run linux containers on windows.
100+
# Pending new windows server version
101+
# https://github.com/actions/virtual-environments/issues/1143#issuecomment-698797524
102+
#- os: windows
103+
# python-version: 3.9
104+
# looker: '7_20'
105+
steps:
106+
- name: Repo Checkout
107+
uses: actions/checkout@v2
108+
109+
- name: Set up Cloud SDK
110+
uses: google-github-actions/[email protected]
111+
with:
112+
project_id: ${{ secrets.GCP_PROJECT_ID }}
113+
service_account_key: ${{ secrets.GCP_AR_READER_SA_KEY }}
114+
export_default_credentials: true
115+
116+
- name: Authenticate Artifact Repository
117+
run: gcloud auth configure-docker us-west1-docker.pkg.dev --quiet
118+
119+
- name: Install docker on macos
120+
if: ${{ matrix.os == 'macos' }}
121+
uses: docker-practice/actions-setup-docker@v1
122+
with:
123+
docker_channel: stable
124+
docker_buildx: false
125+
docker_cli_experimental: disabled
126+
127+
- name: Bump docker for mac memory
128+
if: ${{ matrix.os == 'macos' }}
129+
run: |
130+
osascript -e 'quit app "Docker"'
131+
sed -i'.original' -e's/ "memoryMiB" : 2048/ "memoryMiB" : 8192/' ~/Library/Group\ Containers/group.com.docker/settings.json
132+
open -g /Applications/Docker.app
133+
# re-run docker startup logic from docker-practice/actions-setup-docker action
134+
sleep 60
135+
i=0
136+
while ! docker system info &>/dev/null; do
137+
(( i++ == 0 )) && printf %s '-- Waiting for Docker to finish starting up...' || printf '.'
138+
sleep 1
139+
done
140+
(( i )) && printf '\n'
141+
echo "-- Docker is ready."
142+
143+
- name: Pull and run Looker docker image
144+
# TODO: can we cache some layers of the image for faster download?
145+
# we probably don't want to cache the final image for IP security...
146+
run: |
147+
docker pull --quiet us-west1-docker.pkg.dev/cloud-looker-sdk-codegen-cicd/looker/${{ matrix.looker }}
148+
# set $LOOKER_OPTS to --no-ssl if we want to turn off ssl
149+
docker run --name looker-sdk-codegen-ci -d -p 10000:9999 -p 20000:19999 us-west1-docker.pkg.dev/cloud-looker-sdk-codegen-cicd/looker/${{ matrix.looker }}
150+
docker logs -f looker-sdk-codegen-ci --until=30s &
151+
152+
- name: Install Go ${{ matrix.go-version }}
153+
uses: actions/setup-go@v2
154+
with:
155+
go-version: 1.17.6
156+
check-latest: true
157+
158+
- name: Install dependencies
159+
run: go install github.com/jstemmer/go-junit-report@latest
160+
161+
- name: Determine credentials version
162+
# Prior to 21_18, each version had different credentials and a
163+
# different secret. 21_20 and later all use the same credentials
164+
# as 21_18. The parse_version.sh script parses the version and
165+
# yields 21_12, 21_14, 21_16 etc for those versions but 21_18 for
166+
# anything 21_18, 21_20, 22_0, etc.
167+
#
168+
# This can be factored out entirely once 21_18 is the earliest
169+
# supported looker version.
170+
run: |
171+
echo "CREDENTIALS_VERSION=$(${{ github.workspace }}/.github/scripts/parse_version.sh <<< ${{ matrix.looker }})" >> $GITHUB_ENV
172+
173+
- name: Set up Looker credentials
174+
# Load the correct credentials based on the version from
175+
# the prior step.
176+
run: |
177+
echo "LOOKERSDK_CLIENT_ID=${{ secrets[format('LOOKERSDK_CLIENT_ID__{0}', env.CREDENTIALS_VERSION )] }}" >> $GITHUB_ENV
178+
echo "LOOKERSDK_CLIENT_SECRET=${{ secrets[format('LOOKERSDK_CLIENT_SECRET__{0}', env.CREDENTIALS_VERSION )] }}" >> $GITHUB_ENV
179+
180+
- name: Check that Looker is ready
181+
run: |
182+
${{ github.workspace }}/.github/scripts/wait_for_looker.sh
183+
184+
- name: Run integration tests
185+
run: |
186+
mkdir ${{ env.JUNIT_OUTPUT_DIR }}
187+
cd go/integration
188+
go test -v 2>&1 | go-junit-report > ../../${{ env.JUNIT_OUTPUT_DIR }}/${{ env.GO_JUNIT_OUTPUT_NAME }}
189+
190+
- name: Upload Go unit test results
191+
if: ${{ always() }}
192+
uses: actions/upload-artifact@v2
193+
with:
194+
name: ${{ env.JUNIT_ARTIFACT_DIR }}
195+
path: ${{ env.JUNIT_OUTPUT_DIR }}
196+
197+
publish-test-results:
198+
needs: [unit, integration]
64199
if: success() || failure()
65200
runs-on: ubuntu-latest
66201

go/integration/integration_test.go

+183
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
package integration
2+
3+
import (
4+
"testing"
5+
6+
"github.com/looker-open-source/sdk-codegen/go/rtl"
7+
v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4"
8+
)
9+
10+
func TestIntegrationGoSDK(t *testing.T) {
11+
cfg, err := rtl.NewSettingsFromEnv()
12+
13+
if err != nil {
14+
t.Errorf("TestCRUDuser() error getting settings from env, error = %v", err)
15+
}
16+
17+
sdk := v4.NewLookerSDK(rtl.NewAuthSession(cfg))
18+
19+
t.Run("CRUD User", func(t *testing.T) {
20+
firstName := "John"
21+
lastName := "Doe"
22+
isDisabled := false
23+
locale := "fr"
24+
25+
user, err := sdk.CreateUser(v4.WriteUser{
26+
FirstName: &firstName,
27+
LastName: &lastName,
28+
IsDisabled: &isDisabled,
29+
Locale: &locale,
30+
}, "", nil)
31+
32+
if err != nil {
33+
t.Errorf("CreateUser() failed. error=%v", err)
34+
}
35+
if *user.FirstName != firstName {
36+
t.Errorf("Create user FirstName not the same. got=%v want=%v", *user.FirstName, firstName )
37+
}
38+
if *user.LastName != lastName {
39+
t.Errorf("Create user LastName not the same. got=%v want=%v", *user.LastName, lastName )
40+
}
41+
if *user.IsDisabled != isDisabled {
42+
t.Errorf("Create user IsDisabled not the same. got=%v want=%v", *user.IsDisabled, isDisabled )
43+
}
44+
if *user.Locale != locale {
45+
t.Errorf("Create user Locale not the same. got=%v want=%v", *user.Locale, locale )
46+
}
47+
48+
id := user.Id
49+
50+
user, err = sdk.User(*id, "", nil)
51+
52+
if err != nil {
53+
t.Errorf("User() failed. error=%v", err)
54+
}
55+
if *user.FirstName != firstName {
56+
t.Errorf("Get user FirstName not the same. got=%v want=%v", *user.FirstName, firstName )
57+
}
58+
if *user.LastName != lastName {
59+
t.Errorf("Get user LastName not the same. got=%v want=%v", *user.LastName, lastName )
60+
}
61+
if *user.IsDisabled != isDisabled {
62+
t.Errorf("Get user IsDisabled not the same. got=%v want=%v", *user.IsDisabled, isDisabled )
63+
}
64+
if *user.Locale != locale {
65+
t.Errorf("Get user Locale not the same. got=%v want=%v", *user.Locale, locale )
66+
}
67+
68+
newFirstName := "Jane"
69+
newLocale := "uk"
70+
newIsDisabled := true
71+
72+
user, err = sdk.UpdateUser(*id, v4.WriteUser{
73+
FirstName: &newFirstName,
74+
LastName: &lastName,
75+
IsDisabled: &newIsDisabled,
76+
Locale: &newLocale,
77+
}, "", nil)
78+
79+
if err != nil {
80+
t.Errorf("UpdateUser() failed. error=%v", err)
81+
}
82+
if *user.FirstName != newFirstName {
83+
t.Errorf("Update user FirstName not the same. got=%v want=%v", *user.FirstName, newFirstName )
84+
}
85+
if *user.LastName != lastName {
86+
t.Errorf("Update user LastName not the same. got=%v want=%v", *user.LastName, lastName )
87+
}
88+
if *user.IsDisabled != newIsDisabled {
89+
t.Errorf("Update user IsDisabled not the same. got=%v want=%v", *user.IsDisabled, newIsDisabled )
90+
}
91+
if *user.Locale != newLocale {
92+
t.Errorf("Update user Locale not the same. got=%v want=%v", *user.Locale, newLocale )
93+
}
94+
95+
resp, err := sdk.DeleteUser(*id, nil)
96+
97+
if err != nil {
98+
t.Errorf("DeleteUser() failed. error=%v", err)
99+
}
100+
101+
if resp != "" {
102+
t.Errorf("Delete user returned non empty response. got=%v", resp)
103+
}
104+
})
105+
106+
107+
t.Run("Me()", func(t *testing.T) {
108+
user, err := sdk.Me("", nil)
109+
110+
if err != nil {
111+
t.Errorf("Me() failed. error=%v", err)
112+
}
113+
114+
creds := *user.CredentialsApi3
115+
116+
if len(creds) == 0 {
117+
t.Errorf("Me() returns user with no api credentials")
118+
}
119+
120+
user, err = sdk.Me("id", nil)
121+
122+
if err != nil {
123+
t.Errorf("Me() with filter fields set failed. error=%v", err)
124+
}
125+
126+
if user.CredentialsApi3 != nil {
127+
t.Errorf("Me() returned creds when they should have been filtered")
128+
}
129+
})
130+
131+
t.Run("Get and Update Session", func(t *testing.T) {
132+
session, err := sdk.Session(nil)
133+
134+
if err != nil {
135+
t.Errorf("Session() failed. error=%v", err)
136+
}
137+
138+
if *session.WorkspaceId != "production" {
139+
t.Errorf("Session() does not return 'production' workspace id, got=%v", *session.WorkspaceId)
140+
}
141+
142+
newWorkSpaceId := "dev"
143+
144+
_, err = sdk.UpdateSession(v4.WriteApiSession{
145+
WorkspaceId: &newWorkSpaceId,
146+
}, nil)
147+
148+
if err != nil {
149+
t.Errorf("UpdateSession() failed. error=%v", err)
150+
}
151+
152+
session, err = sdk.Session(nil)
153+
154+
if err != nil {
155+
t.Errorf("Session() failed. error=%v", err)
156+
}
157+
158+
if *session.WorkspaceId != newWorkSpaceId {
159+
t.Errorf("Session() does not return 'dev' workspace id after UpdateSession(), got=%v", *session.WorkspaceId)
160+
}
161+
162+
oldWorkSpaceId := "production"
163+
164+
_, err = sdk.UpdateSession(v4.WriteApiSession{
165+
WorkspaceId: &oldWorkSpaceId,
166+
}, nil)
167+
168+
if err != nil {
169+
t.Errorf("UpdateSession() failed. error=%v", err)
170+
}
171+
172+
session, err = sdk.Session(nil)
173+
174+
if err != nil {
175+
t.Errorf("Session() failed. error=%v", err)
176+
}
177+
178+
if *session.WorkspaceId != oldWorkSpaceId {
179+
t.Errorf("Session() does not return 'production' workspace id after UpdateSession(), got=%v", *session.WorkspaceId)
180+
}
181+
})
182+
}
183+

0 commit comments

Comments
 (0)