Skip to content

Commit

Permalink
feat: Go SDK integration tests and CI (#988)
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremytchang authored Feb 15, 2022
1 parent a4f1dec commit fd7c979
Show file tree
Hide file tree
Showing 2 changed files with 321 additions and 3 deletions.
141 changes: 138 additions & 3 deletions .github/workflows/go-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,20 @@ on:
workflow_dispatch:

env:
LOOKERSDK_BASE_URL: https://localhost:20000
LOOKERSDK_VERIFY_SSL: false
JUNIT_OUTPUT_DIR: results
JUNIT_ARTIFACT_DIR: gosdk-test-results

jobs:
unit:
name: Unit - ${{ matrix.os }} / Go ${{ matrix.go-version }}
env:
GO_JUNIT_OUTPUT_NAME: ${{ matrix.os }}.gosdkunitresult${{ matrix.go-version }}.xml
GO_JUNIT_OUTPUT_NAME: ${{ matrix.os }}.gounit.${{ matrix.go-version }}.xml
runs-on: ${{ matrix.os }}-latest
defaults:
run:
shell: bash

strategy:
matrix:
Expand All @@ -44,7 +49,7 @@ jobs:
go-version: ${{ matrix.go-version }}

- name: Install dependencies
run: go get -u github.com/jstemmer/go-junit-report
run: go install github.com/jstemmer/go-junit-report@latest

- name: Run unit tests
run: |
Expand All @@ -59,8 +64,138 @@ jobs:
name: ${{ env.JUNIT_ARTIFACT_DIR }}
path: ${{ env.JUNIT_OUTPUT_DIR }}

publish-test-results:
integration:
needs: unit
name: Integration - ${{ matrix.os }} / Looker.${{ matrix.looker }}
env:
GO_JUNIT_OUTPUT_NAME: ${{ matrix.os }}.Looker-${{ matrix.looker }}.gointegration.xml
runs-on: ${{ matrix.os }}-latest
defaults:
run:
shell: bash

strategy:
matrix:
os:
- ubuntu
looker:
- '21_18'
- '21_20'
- '22_0'
# TODO uncomment `include:` when either macos or windows works to satisfaction.
#include:
# TODO: macos matrix leg is functional but it takes ~20 minutes (compared
# to ~4 minutes for ubuntu) because docker install takes ~5 minutes
# and docker pull takes ~10 minutes. We can probably figure out how to
# cache the docker install but hopefully github will soon have docker
# available pre-installed on macos so not worth the effort now.
# Regarding docker pull ... it would be nice if there's a way to cache
# only some layers of the image on the runner but we don't want to cache
# the final layer(s) with Looker IP. This would speed up docker pull on
# all OSs.
#- os: macos
# python-version: 3.9
# looker: '7_20'
# TODO: currently can't run linux containers on windows.
# Pending new windows server version
# https://github.com/actions/virtual-environments/issues/1143#issuecomment-698797524
#- os: windows
# python-version: 3.9
# looker: '7_20'
steps:
- name: Repo Checkout
uses: actions/checkout@v2

- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v0.2.0
with:
project_id: ${{ secrets.GCP_PROJECT_ID }}
service_account_key: ${{ secrets.GCP_AR_READER_SA_KEY }}
export_default_credentials: true

- name: Authenticate Artifact Repository
run: gcloud auth configure-docker us-west1-docker.pkg.dev --quiet

- name: Install docker on macos
if: ${{ matrix.os == 'macos' }}
uses: docker-practice/actions-setup-docker@v1
with:
docker_channel: stable
docker_buildx: false
docker_cli_experimental: disabled

- name: Bump docker for mac memory
if: ${{ matrix.os == 'macos' }}
run: |
osascript -e 'quit app "Docker"'
sed -i'.original' -e's/ "memoryMiB" : 2048/ "memoryMiB" : 8192/' ~/Library/Group\ Containers/group.com.docker/settings.json
open -g /Applications/Docker.app
# re-run docker startup logic from docker-practice/actions-setup-docker action
sleep 60
i=0
while ! docker system info &>/dev/null; do
(( i++ == 0 )) && printf %s '-- Waiting for Docker to finish starting up...' || printf '.'
sleep 1
done
(( i )) && printf '\n'
echo "-- Docker is ready."
- name: Pull and run Looker docker image
# TODO: can we cache some layers of the image for faster download?
# we probably don't want to cache the final image for IP security...
run: |
docker pull --quiet us-west1-docker.pkg.dev/cloud-looker-sdk-codegen-cicd/looker/${{ matrix.looker }}
# set $LOOKER_OPTS to --no-ssl if we want to turn off ssl
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 }}
docker logs -f looker-sdk-codegen-ci --until=30s &
- name: Install Go ${{ matrix.go-version }}
uses: actions/setup-go@v2
with:
go-version: 1.17.6
check-latest: true

- name: Install dependencies
run: go install github.com/jstemmer/go-junit-report@latest

- name: Determine credentials version
# Prior to 21_18, each version had different credentials and a
# different secret. 21_20 and later all use the same credentials
# as 21_18. The parse_version.sh script parses the version and
# yields 21_12, 21_14, 21_16 etc for those versions but 21_18 for
# anything 21_18, 21_20, 22_0, etc.
#
# This can be factored out entirely once 21_18 is the earliest
# supported looker version.
run: |
echo "CREDENTIALS_VERSION=$(${{ github.workspace }}/.github/scripts/parse_version.sh <<< ${{ matrix.looker }})" >> $GITHUB_ENV
- name: Set up Looker credentials
# Load the correct credentials based on the version from
# the prior step.
run: |
echo "LOOKERSDK_CLIENT_ID=${{ secrets[format('LOOKERSDK_CLIENT_ID__{0}', env.CREDENTIALS_VERSION )] }}" >> $GITHUB_ENV
echo "LOOKERSDK_CLIENT_SECRET=${{ secrets[format('LOOKERSDK_CLIENT_SECRET__{0}', env.CREDENTIALS_VERSION )] }}" >> $GITHUB_ENV
- name: Check that Looker is ready
run: |
${{ github.workspace }}/.github/scripts/wait_for_looker.sh
- name: Run integration tests
run: |
mkdir ${{ env.JUNIT_OUTPUT_DIR }}
cd go/integration
go test -v 2>&1 | go-junit-report > ../../${{ env.JUNIT_OUTPUT_DIR }}/${{ env.GO_JUNIT_OUTPUT_NAME }}
- name: Upload Go unit test results
if: ${{ always() }}
uses: actions/upload-artifact@v2
with:
name: ${{ env.JUNIT_ARTIFACT_DIR }}
path: ${{ env.JUNIT_OUTPUT_DIR }}

publish-test-results:
needs: [unit, integration]
if: success() || failure()
runs-on: ubuntu-latest

Expand Down
183 changes: 183 additions & 0 deletions go/integration/integration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
package integration

import (
"testing"

"github.com/looker-open-source/sdk-codegen/go/rtl"
v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4"
)

func TestIntegrationGoSDK(t *testing.T) {
cfg, err := rtl.NewSettingsFromEnv()

if err != nil {
t.Errorf("TestCRUDuser() error getting settings from env, error = %v", err)
}

sdk := v4.NewLookerSDK(rtl.NewAuthSession(cfg))

t.Run("CRUD User", func(t *testing.T) {
firstName := "John"
lastName := "Doe"
isDisabled := false
locale := "fr"

user, err := sdk.CreateUser(v4.WriteUser{
FirstName: &firstName,
LastName: &lastName,
IsDisabled: &isDisabled,
Locale: &locale,
}, "", nil)

if err != nil {
t.Errorf("CreateUser() failed. error=%v", err)
}
if *user.FirstName != firstName {
t.Errorf("Create user FirstName not the same. got=%v want=%v", *user.FirstName, firstName )
}
if *user.LastName != lastName {
t.Errorf("Create user LastName not the same. got=%v want=%v", *user.LastName, lastName )
}
if *user.IsDisabled != isDisabled {
t.Errorf("Create user IsDisabled not the same. got=%v want=%v", *user.IsDisabled, isDisabled )
}
if *user.Locale != locale {
t.Errorf("Create user Locale not the same. got=%v want=%v", *user.Locale, locale )
}

id := user.Id

user, err = sdk.User(*id, "", nil)

if err != nil {
t.Errorf("User() failed. error=%v", err)
}
if *user.FirstName != firstName {
t.Errorf("Get user FirstName not the same. got=%v want=%v", *user.FirstName, firstName )
}
if *user.LastName != lastName {
t.Errorf("Get user LastName not the same. got=%v want=%v", *user.LastName, lastName )
}
if *user.IsDisabled != isDisabled {
t.Errorf("Get user IsDisabled not the same. got=%v want=%v", *user.IsDisabled, isDisabled )
}
if *user.Locale != locale {
t.Errorf("Get user Locale not the same. got=%v want=%v", *user.Locale, locale )
}

newFirstName := "Jane"
newLocale := "uk"
newIsDisabled := true

user, err = sdk.UpdateUser(*id, v4.WriteUser{
FirstName: &newFirstName,
LastName: &lastName,
IsDisabled: &newIsDisabled,
Locale: &newLocale,
}, "", nil)

if err != nil {
t.Errorf("UpdateUser() failed. error=%v", err)
}
if *user.FirstName != newFirstName {
t.Errorf("Update user FirstName not the same. got=%v want=%v", *user.FirstName, newFirstName )
}
if *user.LastName != lastName {
t.Errorf("Update user LastName not the same. got=%v want=%v", *user.LastName, lastName )
}
if *user.IsDisabled != newIsDisabled {
t.Errorf("Update user IsDisabled not the same. got=%v want=%v", *user.IsDisabled, newIsDisabled )
}
if *user.Locale != newLocale {
t.Errorf("Update user Locale not the same. got=%v want=%v", *user.Locale, newLocale )
}

resp, err := sdk.DeleteUser(*id, nil)

if err != nil {
t.Errorf("DeleteUser() failed. error=%v", err)
}

if resp != "" {
t.Errorf("Delete user returned non empty response. got=%v", resp)
}
})


t.Run("Me()", func(t *testing.T) {
user, err := sdk.Me("", nil)

if err != nil {
t.Errorf("Me() failed. error=%v", err)
}

creds := *user.CredentialsApi3

if len(creds) == 0 {
t.Errorf("Me() returns user with no api credentials")
}

user, err = sdk.Me("id", nil)

if err != nil {
t.Errorf("Me() with filter fields set failed. error=%v", err)
}

if user.CredentialsApi3 != nil {
t.Errorf("Me() returned creds when they should have been filtered")
}
})

t.Run("Get and Update Session", func(t *testing.T) {
session, err := sdk.Session(nil)

if err != nil {
t.Errorf("Session() failed. error=%v", err)
}

if *session.WorkspaceId != "production" {
t.Errorf("Session() does not return 'production' workspace id, got=%v", *session.WorkspaceId)
}

newWorkSpaceId := "dev"

_, err = sdk.UpdateSession(v4.WriteApiSession{
WorkspaceId: &newWorkSpaceId,
}, nil)

if err != nil {
t.Errorf("UpdateSession() failed. error=%v", err)
}

session, err = sdk.Session(nil)

if err != nil {
t.Errorf("Session() failed. error=%v", err)
}

if *session.WorkspaceId != newWorkSpaceId {
t.Errorf("Session() does not return 'dev' workspace id after UpdateSession(), got=%v", *session.WorkspaceId)
}

oldWorkSpaceId := "production"

_, err = sdk.UpdateSession(v4.WriteApiSession{
WorkspaceId: &oldWorkSpaceId,
}, nil)

if err != nil {
t.Errorf("UpdateSession() failed. error=%v", err)
}

session, err = sdk.Session(nil)

if err != nil {
t.Errorf("Session() failed. error=%v", err)
}

if *session.WorkspaceId != oldWorkSpaceId {
t.Errorf("Session() does not return 'production' workspace id after UpdateSession(), got=%v", *session.WorkspaceId)
}
})
}

0 comments on commit fd7c979

Please sign in to comment.