test(e2e): migrate e2e setup

This commit is contained in:
Elio Bischof 2022-07-08 10:07:17 +02:00
parent 9fbfe97d2c
commit 2b7600e6e8
No known key found for this signature in database
GPG Key ID: 7B383FDE4DDBF1BD
26 changed files with 668 additions and 65 deletions

118
cmd/e2e-setup/config.go Normal file
View File

@ -0,0 +1,118 @@
package main
import (
"errors"
"fmt"
"regexp"
"github.com/zitadel/zitadel/internal/id"
"github.com/zitadel/zitadel/internal/database"
internal_authz "github.com/zitadel/zitadel/internal/api/authz"
static_config "github.com/zitadel/zitadel/internal/static/config"
"github.com/zitadel/zitadel/internal/config/systemdefaults"
"github.com/mitchellh/mapstructure"
"github.com/spf13/viper"
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/internal/config/hook"
)
type Config struct {
E2E *E2EConfig
Log *logging.Config
ExternalPort uint16
ExternalDomain string
ExternalSecure bool
Database database.Config
AssetStorage static_config.AssetStorageConfig
WebAuthNName string
InternalAuthZ internal_authz.Config
Machine *id.Config
SystemDefaults systemdefaults.SystemDefaults
}
func (c Config) Validate() error {
if c.E2E == nil {
return errors.New("no e2e config found")
}
return c.E2E.Validate()
}
type E2EConfig struct {
Org string
MachineKeyPath string
ZitadelProjectResourceID string
APIURL string
IssuerURL string
Audience string
OrgOwnerPassword string
OrgOwnerViewerPassword string
OrgProjectCreatorPassword string
PasswordComplexityUserPassword string
LoginPolicyUserPassword string
}
func (e E2EConfig) Validate() (err error) {
if e.Org == "" {
return errors.New("field Org is empty")
}
if e.MachineKeyPath == "" {
return errors.New("field MachineKeyPath is empty")
}
if e.ZitadelProjectResourceID == "" {
return errors.New("field ZitadelProjectResourceID is empty")
}
audPattern := "number-[0-9]{17}"
matched, err := regexp.MatchString("number-[0-9]{17}", e.ZitadelProjectResourceID)
if err != nil {
return fmt.Errorf("validating ZitadelProjectResourceID failed: %w", err)
}
if !matched {
return fmt.Errorf("ZitadelProjectResourceID doesn't match regular expression %s", audPattern)
}
if e.APIURL == "" {
return errors.New("field APIURL is empty")
}
if e.IssuerURL == "" {
return errors.New("field IssuerURL is empty")
}
if e.OrgOwnerPassword == "" {
return errors.New("field OrgOwnerPassword is empty")
}
if e.OrgOwnerViewerPassword == "" {
return errors.New("field OrgOwnerViewerPassword is empty")
}
if e.OrgProjectCreatorPassword == "" {
return errors.New("field OrgProjectCreatorPassword is empty")
}
if e.PasswordComplexityUserPassword == "" {
return errors.New("field PasswordComplexityUserPassword is empty")
}
if e.LoginPolicyUserPassword == "" {
return errors.New("field LoginPolicyUserPassword is empty")
}
return nil
}
func MustNewConfig(v *viper.Viper) *Config {
config := new(Config)
err := v.Unmarshal(config,
viper.DecodeHook(mapstructure.ComposeDecodeHookFunc(
hook.Base64ToBytesHookFunc(),
hook.TagToLanguageHookFunc(),
mapstructure.StringToTimeDurationHookFunc(),
mapstructure.StringToSliceHookFunc(","),
)),
)
err = config.Log.SetLogger()
logging.OnError(err).Fatal("unable to set logger")
return config
}

View File

@ -0,0 +1,65 @@
package main
import (
"context"
"fmt"
"time"
"github.com/zitadel/logging"
)
func awaitConsistency(ctx context.Context, cfg E2EConfig, expectUsers []userData) (err error) {
retry := make(chan struct{})
go func() {
// trigger first check
retry <- struct{}{}
}()
for {
select {
case <-retry:
err = checkCondition(ctx, cfg, expectUsers)
if err == nil {
logging.Log("AWAIT-QIOOJ").Info("setup is consistent")
return nil
}
logging.Log("AWAIT-VRk3Y").Info("setup is not consistent yet, retrying in a second: ", err)
time.Sleep(time.Second)
go func() {
retry <- struct{}{}
}()
case <-ctx.Done():
return fmt.Errorf("setup failed to come to a consistent state: %s: %w", ctx.Err(), err)
}
}
}
func checkCondition(ctx context.Context, cfg E2EConfig, expectUsers []userData) error {
token, err := newToken(cfg)
if err != nil {
return err
}
foundUsers, err := listUsers(ctx, cfg.APIURL, token)
if err != nil {
return err
}
var awaitingUsers []string
expectLoop:
for i := range expectUsers {
expectUser := expectUsers[i]
for j := range foundUsers {
foundUser := foundUsers[j]
if expectUser.desc+"_user_name" == foundUser {
continue expectLoop
}
}
awaitingUsers = append(awaitingUsers, expectUser.desc)
}
if len(awaitingUsers) > 0 {
return fmt.Errorf("users %v are not consistent yet", awaitingUsers)
}
return nil
}

110
cmd/e2e-setup/execute.go Normal file
View File

@ -0,0 +1,110 @@
package main
import (
"context"
"io/ioutil"
"os"
"path/filepath"
"time"
"github.com/zitadel/zitadel/internal/command"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
)
func execute(ctx context.Context, cmd *command.Commands, cfg E2EConfig, users []userData) error {
orgOwner := newHuman(users[0])
orgOwnerID, org, err := cmd.SetUpOrg(ctx, &command.OrgSetup{
Name: cfg.Org,
CustomDomain: "localhost",
Human: *orgOwner,
})
if err != nil {
return err
}
// Avoids the MFA nudge
if _, err = cmd.AddLoginPolicy(ctx, org.ResourceOwner, &domain.LoginPolicy{
AllowUsernamePassword: true,
}); err != nil {
return err
}
// Avoids the change password screen
if _, err = cmd.ChangePassword(ctx, org.ResourceOwner, orgOwnerID, cfg.OrgOwnerPassword, cfg.OrgOwnerPassword, ""); err != nil {
return err
}
sa, err := cmd.AddMachine(ctx, org.ResourceOwner, &domain.Machine{
Username: "e2e",
Name: "e2e",
Description: "User who calls the ZITADEL API for preparing end-to-end tests",
})
if err != nil {
return err
}
if _, err = cmd.AddOrgMember(ctx, org.ResourceOwner, sa.AggregateID, domain.RoleOrgOwner); err != nil {
return err
}
key, err := cmd.AddUserMachineKey(ctx, &domain.MachineKey{
ObjectRoot: models.ObjectRoot{
AggregateID: sa.AggregateID,
},
ExpirationDate: time.Now().Add(30 * 24 * time.Hour),
Type: domain.AuthNKeyTypeJSON,
}, org.ResourceOwner)
if err != nil {
return err
}
json, err := key.MarshalJSON()
if err != nil {
return err
}
if err = os.MkdirAll(filepath.Dir(cfg.MachineKeyPath), 0700); err != nil {
return err
}
if err = ioutil.WriteFile(cfg.MachineKeyPath, json, 0600); err != nil {
return err
}
for idx := range users[1:] {
user := users[idx]
createdHuman, err := cmd.AddHuman(ctx, org.ResourceOwner, newHuman(user))
if err != nil {
return err
}
// Avoids the change password screen
if _, err = cmd.ChangePassword(ctx, org.ResourceOwner, createdHuman.ID, user.pw, user.pw, ""); err != nil {
return err
}
if user.role != "" {
if _, err = cmd.AddOrgMember(ctx, org.ResourceOwner, createdHuman.ID, user.role); err != nil {
return err
}
}
}
return nil
}
func newHuman(u userData) *command.AddHuman {
return &command.AddHuman{
Username: u.desc + "_user_name",
FirstName: u.desc + "_first_name",
LastName: u.desc + "_last_name",
Password: u.pw,
Email: command.Email{
Address: u.desc + ".e2e@zitadel.com",
Verified: true,
},
}
}

139
cmd/e2e-setup/main.go Normal file
View File

@ -0,0 +1,139 @@
package main
import (
"context"
_ "embed"
"flag"
"fmt"
"time"
"github.com/zitadel/zitadel/internal/id"
"github.com/spf13/viper"
"github.com/zitadel/zitadel/internal/config/options"
"github.com/zitadel/zitadel/internal/command"
"github.com/zitadel/zitadel/internal/database"
"github.com/zitadel/zitadel/internal/eventstore"
"github.com/zitadel/zitadel/internal/webauthn"
"gopkg.in/yaml.v3"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/logging"
)
type userData struct {
desc, role, pw string
}
func main() {
// masterkey := flag.String("materkey", "MasterkeyNeedsToHave32Characters", "the ZITADEL installations masterkey")
debug := flag.Bool("debug", false, "print information that is helpful for debugging")
err := options.InitViper()
logging.OnError(err).Fatalf("unable to initialize config: %s", err)
flag.Parse()
viper.
fmt.Println(x)
conf := MustNewConfig(viper.GetViper())
if *debug {
printConfig("config", conf)
}
logging.New().OnError(err).Fatal("validating e2e config failed")
startE2ESetup(conf)
}
func startE2ESetup(conf *Config /*, masterkey string*/) {
id.Configure(conf.Machine)
ctx := context.Background()
dbClient, err := database.Connect(conf.Database)
logging.New().OnError(err).Fatalf("cannot start client for projection: %s", err)
/*
keyStorage, err := cryptoDB.NewKeyStorage(dbClient, masterkey)
logging.New().OnError(err).Fatalf("cannot start key storage: %s", err)
keys, err := ensureEncryptionKeys(conf.EncryptionKeys, keyStorage)
logging.New().OnError(err).Fatalf("failed ensuring encryption keys: %s", err)
*/
eventstoreClient, err := eventstore.Start(dbClient)
logging.New().OnError(err).Fatalf("cannot start eventstore for queries: %s", err)
storage, err := conf.AssetStorage.NewStorage(dbClient)
logging.New().OnError(err).Fatalf("cannot start asset storage client: %s", err)
webAuthNConfig := &webauthn.Config{
DisplayName: conf.WebAuthNName,
ExternalSecure: conf.ExternalSecure,
}
commands, err := command.StartCommands(
eventstoreClient,
conf.SystemDefaults,
conf.InternalAuthZ.RolePermissionMappings,
storage,
webAuthNConfig,
conf.ExternalDomain,
conf.ExternalSecure,
conf.ExternalPort,
nil, //keys.IDPConfig,
nil, //keys.OTP,
nil, //keys.SMTP,
nil, //keys.SMS,
nil, //keys.User,
nil, //keys.DomainVerification,
nil, //keys.OIDC,
)
logging.New().OnError(err).Errorf("cannot start commands: %s", err)
users := []userData{{
desc: "org_owner",
pw: conf.E2E.OrgOwnerPassword,
role: domain.RoleOrgOwner,
}, {
desc: "org_owner_viewer",
pw: conf.E2E.OrgOwnerViewerPassword,
role: domain.RoleOrgOwner,
}, {
desc: "org_project_creator",
pw: conf.E2E.OrgProjectCreatorPassword,
role: domain.RoleOrgProjectCreator,
}, {
desc: "login_policy_user",
pw: conf.E2E.LoginPolicyUserPassword,
}, {
desc: "password_complexity_user",
pw: conf.E2E.PasswordComplexityUserPassword,
}}
err = execute(ctx, commands, *conf.E2E, users)
logging.New().OnError(err).Errorf("failed to execute commands steps")
eventualConsistencyCtx, cancel := context.WithTimeout(ctx, 5*time.Minute)
defer cancel()
err = awaitConsistency(
eventualConsistencyCtx,
*conf.E2E,
users,
)
logging.New().OnError(err).Fatal("failed to await consistency")
}
func printConfig(desc string, cfg interface{}) {
bytes, err := yaml.Marshal(cfg)
logging.New().OnError(err).Fatal("cannot marshal config")
logging.New().Info("got the following ", desc, " config")
fmt.Println(string(bytes))
}

85
cmd/e2e-setup/token.go Normal file
View File

@ -0,0 +1,85 @@
package main
import (
"encoding/json"
"fmt"
"github.com/golang-jwt/jwt/v4"
"io/ioutil"
"net/http"
"os"
"strings"
"time"
)
func newToken(cfg E2EConfig) (string, error) {
keyBytes, err := os.ReadFile(cfg.MachineKeyPath)
if err != nil {
return "", err
}
key := struct{ UserId, KeyId, Key string }{}
if err := json.Unmarshal(keyBytes, &key); err != nil {
return "", err
}
if key.KeyId == "" ||
key.UserId == "" ||
key.Key == "" {
return "", fmt.Errorf("key is incomplete: %+v", key)
}
now := time.Now()
iat := now.Unix()
exp := now.Add(55 * time.Minute).Unix()
audience := cfg.Audience
if audience == "" {
audience = cfg.IssuerURL
}
token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims{
"iss": key.UserId,
"sub": key.UserId,
"aud": audience,
"iat": iat,
"exp": exp,
})
token.Header["alg"] = "RS256"
token.Header["kid"] = key.KeyId
rsaKey, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(key.Key))
if err != nil {
return "", err
}
tokenString, err := token.SignedString(rsaKey)
if err != nil {
return "", err
}
resp, err := http.PostForm(fmt.Sprintf("%s/oauth/v2/token", cfg.APIURL), map[string][]string{
"grant_type": {"urn:ietf:params:oauth:grant-type:jwt-bearer"},
"scope": {fmt.Sprintf("openid urn:zitadel:iam:org:project:id:%s:aud", strings.TrimPrefix(cfg.ZitadelProjectResourceID, "bignumber-"))},
"assertion": {tokenString},
})
if err != nil {
return "", err
}
tokenBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
if resp.StatusCode < 200 || resp.StatusCode > 399 {
return "", fmt.Errorf("getting token returned status code %d and body %s", resp.StatusCode, string(tokenBody))
}
tokenResp := struct {
AccessToken string `json:"access_token"`
}{}
return tokenResp.AccessToken, json.Unmarshal(tokenBody, &tokenResp)
}

52
cmd/e2e-setup/users.go Normal file
View File

@ -0,0 +1,52 @@
package main
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func listUsers(ctx context.Context, apiUrl, token string) ([]string, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodPost, apiUrl+"/management/v1/users/_search", nil)
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Bearer "+token)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode < 200 || resp.StatusCode > 399 {
return nil, fmt.Errorf("listing users returned status code %d and body %s", resp.StatusCode, string(bodyBytes))
}
unmarshalledResp := struct {
Result []struct {
UserName string `json:"userName"`
}
}{}
if err = json.Unmarshal(bodyBytes, &unmarshalledResp); err != nil {
return nil, err
}
users := make([]string, len(unmarshalledResp.Result))
for i := range unmarshalledResp.Result {
users[i] = unmarshalledResp.Result[i].UserName
}
return users, nil
}

View File

@ -1,10 +1,11 @@
package start
import (
"time"
"github.com/mitchellh/mapstructure"
"github.com/spf13/viper"
"github.com/zitadel/zitadel/internal/config/hook"
"time"
"github.com/zitadel/logging"
admin_es "github.com/zitadel/zitadel/internal/admin/repository/eventsourcing"
@ -15,7 +16,6 @@ import (
"github.com/zitadel/zitadel/internal/api/ui/login"
auth_es "github.com/zitadel/zitadel/internal/auth/repository/eventsourcing"
"github.com/zitadel/zitadel/internal/command"
"github.com/zitadel/zitadel/internal/config/hook"
"github.com/zitadel/zitadel/internal/config/network"
"github.com/zitadel/zitadel/internal/config/systemdefaults"
"github.com/zitadel/zitadel/internal/crypto"
@ -54,6 +54,18 @@ type Config struct {
CustomerPortal string
}
type encryptionKeyConfig struct {
DomainVerification *crypto.KeyConfig
IDPConfig *crypto.KeyConfig
OIDC *crypto.KeyConfig
OTP *crypto.KeyConfig
SMS *crypto.KeyConfig
SMTP *crypto.KeyConfig
User *crypto.KeyConfig
CSRFCookieKeyID string
UserAgentCookieKeyID string
}
func MustNewConfig(v *viper.Viper) *Config {
config := new(Config)
@ -73,15 +85,3 @@ func MustNewConfig(v *viper.Viper) *Config {
return config
}
type encryptionKeyConfig struct {
DomainVerification *crypto.KeyConfig
IDPConfig *crypto.KeyConfig
OIDC *crypto.KeyConfig
OTP *crypto.KeyConfig
SMS *crypto.KeyConfig
SMTP *crypto.KeyConfig
User *crypto.KeyConfig
CSRFCookieKeyID string
UserAgentCookieKeyID string
}

View File

@ -4,6 +4,7 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/internal/config/options"
"github.com/zitadel/zitadel/cmd/initialise"
"github.com/zitadel/zitadel/cmd/key"
@ -35,7 +36,7 @@ Requirements:
setupSteps := setup.MustNewSteps(viper.New())
setup.Setup(setupConfig, setupSteps, masterKey)
startConfig := MustNewConfig(viper.GetViper())
startConfig := options.MustNewConfig(viper.GetViper())
err = startZitadel(startConfig, masterKey)
logging.OnError(err).Fatal("unable to start zitadel")

View File

@ -1,14 +1,13 @@
package cmd
import (
"bytes"
_ "embed"
"errors"
"io"
"strings"
"github.com/zitadel/zitadel/internal/config/options"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/cmd/admin"
@ -20,9 +19,6 @@ import (
var (
configFiles []string
//go:embed defaults.yaml
defaultConfig []byte
)
func New(out io.Writer, in io.Reader, args []string) *cobra.Command {
@ -35,12 +31,8 @@ func New(out io.Writer, in io.Reader, args []string) *cobra.Command {
},
}
viper.AutomaticEnv()
viper.SetEnvPrefix("ZITADEL")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.SetConfigType("yaml")
err := viper.ReadConfig(bytes.NewBuffer(defaultConfig))
logging.OnError(err).Fatal("unable to read default config")
err := options.InitViper()
logging.OnError(err).Fatalf("unable initialize config: %s", err)
cobra.OnInitialize(initConfig)
cmd.PersistentFlags().StringArrayVar(&configFiles, "config", nil, "path to config file to overwrite system defaults")
@ -58,9 +50,5 @@ func New(out io.Writer, in io.Reader, args []string) *cobra.Command {
}
func initConfig() {
for _, file := range configFiles {
viper.SetConfigFile(file)
err := viper.MergeInConfig()
logging.WithFields("file", file).OnError(err).Warn("unable to read config file")
}
options.MergeToViper(configFiles...)
}

View File

@ -1,14 +0,0 @@
E2E_CYPRESS_PORT=5003
E2E_ORG=e2e-tests
E2E_ORG_OWNER_PW=Password1!
E2E_ORG_OWNER_VIEWER_PW=Password1!
E2E_ORG_PROJECT_CREATOR_PW=Password1!
E2E_PASSWORD_COMPLEXITY_USER_PW=Password1!
E2E_LOGIN_POLICY_USER_PW=Password1!
E2E_SERVICEACCOUNT_KEY_PATH="${projectRoot}/.keys/e2e.json"
E2E_CONSOLE_URL="http://localhost:4200"
E2E_API_URL="http://localhost:50002"
E2E_ACCOUNTS_URL="http://localhost:50003"
E2E_ISSUER_URL="http://localhost:50002/oauth/v2"
E2E_OTHER_ZITADEL_IDP_INSTANCE=false
E2E_ZITADEL_PROJECT_RESOURCE_ID="bignumber-$(echo -n $(docker compose -f ${projectRoot}/build/local/docker-compose-local.yml exec --no-TTY db cockroach sql --insecure --execute "select aggregate_id from eventstore.events where event_type = 'project.added' and event_data = '{\"name\": \"Zitadel\"}';" --format tsv) | cut -d " " -f 2)"

View File

@ -16,7 +16,7 @@ This guide assumes you are already familiar with [running ZITADEL with the most
## Configuration Files
### Runtime Configuration
See a description of all possible _runtime configuration_ options with their defaults [in the source code](https://github.com/zitadel/zitadel/blob/v2-alpha/cmd/defaults.yaml).
See a description of all possible _runtime configuration_ options with their defaults [in the source code](https://github.com/zitadel/zitadel/blob/v2-alpha/internal/config/options/defaults.yaml).
The `zitadel` binary expects the `--config` flag for this configuration.
### Database Initialization
@ -67,7 +67,7 @@ This is the IAM admin users login according to your configuration in the [exampl
- Read more about [the login process](../../manuals/user-login).
- If you want to run ZITADEL in production, you most certainly need to [customize your own domain](./custom-domain).
- Check out all possible [runtime configuration properties and their defaults in the source code](https://github.com/zitadel/zitadel/blob/v2-alpha/cmd/defaults.yaml)
- Check out all possible [runtime configuration properties and their defaults in the source code](https://github.com/zitadel/zitadel/blob/v2-alpha/internal/config/options/defaults.yaml)
- Check out all possible [setup step configuration properties and their defaults in the source code](https://github.com/zitadel/zitadel/blob/v2-alpha/cmd/setup/steps.yaml)
:::caution

View File

@ -1,4 +1,4 @@
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/v2-alpha/cmd/defaults.yaml
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/v2-alpha/internal/config/options/defaults.yaml
Log:
Level: 'info'

View File

@ -1,4 +1,4 @@
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/v2-alpha/cmd/defaults.yaml
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/v2-alpha/internal/config/options/defaults.yaml
# If not using the docker compose example, adjust these values for connecting ZITADEL to your CockroachDB
Database:

View File

@ -1,4 +1,4 @@
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/v2-alpha/cmd/defaults.yaml
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/v2-alpha/internal/config/options/defaults.yaml
zitadel:
masterkey: 'MasterkeyNeedsToHave32Characters'

View File

@ -1,4 +1,4 @@
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/v2-alpha/cmd/defaults.yaml
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/v2-alpha/internal/config/options/defaults.yaml
zitadel:
configmapConfig:
Log:

View File

@ -1,4 +1,4 @@
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/v2-alpha/cmd/defaults.yaml
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/v2-alpha/internal/config/options/defaults.yaml
Log:
Level: 'info'

View File

@ -1,4 +1,4 @@
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/v2-alpha/cmd/defaults.yaml
# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/v2-alpha/internal/config/options/defaults.yaml
# If not using the docker compose example, adjust these values for connecting ZITADEL to your CockroachDB
Database:

View File

@ -1,4 +1,3 @@
services:
zitadel:
image: 'zitadel:${BUILD_DATE}'

3
e2e/docker-compose.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
COMPOSE_DOCKER_CLI_BUILD=1 docker compose --file ./docs/docs/guides/installation/run/docker-compose.yaml --file ./e2e/docker-compose-overwrite.yaml "$@"

11
e2e/e2e-setup-debug.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/bash
set -ex
projectRoot="."
set -a
source ./e2e/local.env
set +a
dlv debug --api-version 2 --headless --listen 127.0.0.1:2345 ./cmd/e2e-setup/*.go "$@"

View File

@ -4,9 +4,8 @@ set -e
DO_BUILD=1
DO_DEPLOY=1
DO_TEST=1
while getopts 'bdt:' OPTION; do
while getopts 'bd:' OPTION; do
case "$OPTION" in
b)
echo "skipping build"
@ -16,15 +15,10 @@ while getopts 'bdt:' OPTION; do
echo "skipping deployment"
DO_DEPLOY=0
;;
s)
echo "skipping tests"
DO_TEST=0
;;
?)
echo "script usage: $(basename \$0) [-b] [-d] [-t]" >&2
echo "-b skip build"
echo "-d skip deployment"
echo "-t skip tests"
exit 1
;;
esac
@ -54,10 +48,10 @@ if [ "$DO_BUILD" -eq "1" ]; then
BUILD_VERSION="$(extract_metadata metadata.json '.version')"
# build the docker image
docker build --file ./build/Dockerfile --tag zitadel:latest --tag zitadel:$BUILD_VERSION --tag zitadel:$BUILD_DATE $BUILD_PATH
DOCKER_BUILDKIT=1 docker build --file ./build/Dockerfile --tag zitadel:latest --tag zitadel:$BUILD_VERSION --tag zitadel:$BUILD_DATE $BUILD_PATH
fi
if [ "$DO_DEPLOY" -eq "1" ]; then
# run cockroach and zitadel
docker compose --file ./docs/docs/guides/installation/run/docker-compose.yaml --file ./e2e/docker-compose-overwrite.yaml up --detach
./e2e/docker-compose.sh up --detach
fi

14
e2e/local.env Normal file
View File

@ -0,0 +1,14 @@
ZITADEL_E2E_CYPRESS_PORT=5000
ZITADEL_E2E_ORG=e2e-tests
ZITADEL_E2E_ORG_OWNER_PW=Password1!
ZITADEL_E2E_ORG_OWNER_VIEWER_PW=Password1!
ZITADEL_E2E_ORG_PROJECT_CREATOR_PW=Password1!
ZITADEL_E2E_PASSWORD_COMPLEXITY_USER_PW=Password1!
ZITADEL_E2E_LOGIN_POLICY_USER_PW=Password1!
ZITADEL_E2E_MACHINE_KEY_PATH="${projectRoot}/.keys/e2e.json"
ZITADEL_E2E_CONSOLE_URL="http://localhost:8080"
ZITADEL_E2E_API_URL="http://localhost:8080"
ZITADEL_E2E_ACCOUNTS_URL="http://localhost:8080"
ZITADEL_E2E_ISSUER_URL="http://localhost:8080/oauth/v2"
ZITADEL_E2E_OTHER_ZITADEL_IDP_INSTANCE=false
ZITADEL_E2E_ZITADEL_PROJECT_RESOURCE_ID="bignumber-$(echo -n $(./e2e/docker-compose.sh exec --no-TTY db cockroach sql --database zitadel --insecure --execute "select aggregate_id from eventstore.events where event_type = 'project.added' and event_data = '{\"name\": \"ZITADEL\"}';" --format tsv) | cut -d " " -f 2)"

View File

@ -0,0 +1,8 @@
package options
import (
_ "embed"
)
//go:embed defaults.yaml
var defaultConfig []byte

View File

@ -0,0 +1,30 @@
package options
import (
"bytes"
"fmt"
"strings"
"github.com/spf13/viper"
"github.com/zitadel/logging"
)
func InitViper() error {
viper.AutomaticEnv()
viper.SetEnvPrefix("ZITADEL")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.SetConfigType("yaml")
err := viper.ReadConfig(bytes.NewBuffer(defaultConfig))
if err != nil {
return fmt.Errorf("unable to read default config: %w", err)
}
return nil
}
func MergeToViper(configFiles ...string) {
for _, file := range configFiles {
viper.SetConfigFile(file)
err := viper.MergeInConfig()
logging.WithFields("file", file).OnError(err).Warn("unable to read config file")
}
}