• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

uber / cadence / 018e86dc-121c-4962-9b30-23df2fb36173

28 Mar 2024 08:59PM UTC coverage: 65.259% (+0.007%) from 65.252%
018e86dc-121c-4962-9b30-23df2fb36173

push

buildkite

web-flow
Do not panic when setting env values (#5811)

89 of 122 new or added lines in 11 files covered. (72.95%)

32 existing lines in 10 files now uncovered.

95429 of 146231 relevant lines covered (65.26%)

2375.25 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

66.04
/common/persistence/sql/sqlplugin/postgres/plugin.go
1
// Copyright (c) 2019 Uber Technologies, Inc.
2
//
3
// Permission is hereby granted, free of charge, to any person obtaining a copy
4
// of this software and associated documentation files (the "Software"), to deal
5
// in the Software without restriction, including without limitation the rights
6
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
// copies of the Software, and to permit persons to whom the Software is
8
// furnished to do so, subject to the following conditions:
9
//
10
// The above copyright notice and this permission notice shall be included in
11
// all copies or substantial portions of the Software.
12
//
13
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
// THE SOFTWARE.
20

21
package postgres
22

23
import (
24
        "fmt"
25
        "net"
26
        "net/url"
27
        "os"
28
        "runtime"
29

30
        "github.com/iancoleman/strcase"
31
        "github.com/jmoiron/sqlx"
32

33
        "github.com/uber/cadence/common/config"
34
        pt "github.com/uber/cadence/common/persistence/persistence-tests"
35
        "github.com/uber/cadence/common/persistence/sql"
36
        "github.com/uber/cadence/common/persistence/sql/sqldriver"
37
        "github.com/uber/cadence/common/persistence/sql/sqlplugin"
38
        "github.com/uber/cadence/environment"
39
)
40

41
const (
42
        // PluginName is the name of the plugin
43
        PluginName = "postgres"
44
        dsnFmt     = "postgres://%s@%s:%s/%s"
45
)
46

47
type plugin struct{}
48

49
var _ sqlplugin.Plugin = (*plugin)(nil)
50

51
func init() {
7✔
52
        sql.RegisterPlugin(PluginName, &plugin{})
7✔
53
}
7✔
54

55
// CreateDB initialize the db object
56
func (d *plugin) CreateDB(cfg *config.SQL) (sqlplugin.DB, error) {
46✔
57
        conns, err := sqldriver.CreateDBConnections(cfg, func(cfg *config.SQL) (*sqlx.DB, error) {
92✔
58
                return d.createSingleDBConn(cfg)
46✔
59
        })
46✔
60
        if err != nil {
46✔
61
                return nil, err
×
62
        }
×
63
        return newDB(conns, nil, sqlplugin.DbShardUndefined, cfg.NumShards)
46✔
64
}
65

66
// CreateAdminDB initialize the adminDB object
67
func (d *plugin) CreateAdminDB(cfg *config.SQL) (sqlplugin.AdminDB, error) {
49✔
68
        conns, err := sqldriver.CreateDBConnections(cfg, func(cfg *config.SQL) (*sqlx.DB, error) {
98✔
69
                return d.createSingleDBConn(cfg)
49✔
70
        })
49✔
71
        if err != nil {
49✔
72
                return nil, err
×
73
        }
×
74
        return newDB(conns, nil, sqlplugin.DbShardUndefined, cfg.NumShards)
49✔
75
}
76

77
// CreateDBConnection creates a returns a reference to a logical connection to the
78
// underlying SQL database. The returned object is to tied to a single
79
// SQL database and the object can be used to perform CRUD operations on
80
// the tables in the database
81
func (d *plugin) createSingleDBConn(cfg *config.SQL) (*sqlx.DB, error) {
94✔
82
        params, err := registerTLSConfig(cfg)
94✔
83
        if err != nil {
94✔
84
                return nil, err
×
85
        }
×
86
        for k, v := range cfg.ConnectAttributes {
94✔
87
                params.Set(k, v)
×
88
        }
×
89
        host, port, err := net.SplitHostPort(cfg.ConnectAddr)
94✔
90
        if err != nil {
94✔
91
                return nil, fmt.Errorf("invalid connect address, it must be in host:port format, %v, err: %v", cfg.ConnectAddr, err)
×
92
        }
×
93

94
        db, err := sqlx.Connect(PluginName, buildDSN(cfg, host, port, params))
94✔
95
        if err != nil {
94✔
96
                return nil, err
×
97
        }
×
98
        if cfg.MaxConns > 0 {
94✔
99
                db.SetMaxOpenConns(cfg.MaxConns)
×
100
        }
×
101
        if cfg.MaxIdleConns > 0 {
94✔
102
                db.SetMaxIdleConns(cfg.MaxIdleConns)
×
103
        }
×
104
        if cfg.MaxConnLifetime > 0 {
94✔
105
                db.SetConnMaxLifetime(cfg.MaxConnLifetime)
×
106
        }
×
107

108
        // Maps struct names in CamelCase to snake without need for db struct tags.
109
        db.MapperFunc(strcase.ToSnake)
94✔
110
        return db, nil
94✔
111
}
112

113
func buildDSN(cfg *config.SQL, host string, port string, params url.Values) string {
94✔
114
        dbName := cfg.DatabaseName
94✔
115
        // NOTE: postgres doesn't allow to connect with empty dbName, the admin dbName is "postgres"
94✔
116
        if dbName == "" {
119✔
117
                dbName = "postgres"
25✔
118
        }
25✔
119

120
        credentialString := generateCredentialString(cfg.User, cfg.Password)
94✔
121
        dsn := fmt.Sprintf(dsnFmt, credentialString, host, port, dbName)
94✔
122
        if attrs := params.Encode(); attrs != "" {
188✔
123
                dsn += "?" + attrs
94✔
124
        }
94✔
125
        return dsn
94✔
126
}
127

128
func generateCredentialString(user string, password string) string {
97✔
129
        userPass := url.PathEscape(user)
97✔
130
        if password != "" {
194✔
131
                userPass += ":" + url.PathEscape(password)
97✔
132
        }
97✔
133
        return userPass
97✔
134
}
135

136
func registerTLSConfig(cfg *config.SQL) (sslParams url.Values, err error) {
94✔
137
        sslParams = url.Values{}
94✔
138
        if cfg.TLS != nil && cfg.TLS.Enabled {
94✔
139
                sslMode := cfg.TLS.SSLMode
×
140
                if sslMode == "" {
×
141
                        // NOTE: Default to require for backward compatibility for Cadence users.
×
142
                        sslMode = "require"
×
143
                }
×
144
                sslParams.Set("sslmode", sslMode)
×
145
                sslParams.Set("sslrootcert", cfg.TLS.CaFile)
×
146
                sslParams.Set("sslkey", cfg.TLS.KeyFile)
×
147
                sslParams.Set("sslcert", cfg.TLS.CertFile)
×
148
        } else {
94✔
149
                sslParams.Set("sslmode", "disable")
94✔
150
        }
94✔
151
        return
94✔
152
}
153

154
const (
155
        testSchemaDir = "schema/postgres"
156
)
157

158
// GetTestClusterOption return test options
159
func GetTestClusterOption() (*pt.TestBaseOptions, error) {
13✔
160
        testUser := "postgres"
13✔
161
        testPassword := "cadence"
13✔
162

13✔
163
        if runtime.GOOS == "darwin" {
13✔
164
                testUser = os.Getenv("USER")
×
165
                testPassword = ""
×
166
        }
×
167

168
        if os.Getenv("POSTGRES_USER") != "" {
13✔
169
                testUser = os.Getenv("POSTGRES_USER")
×
170
        }
×
171

172
        if os.Getenv("POSTGRES_PASSWORD") != "" {
13✔
173
                testPassword = os.Getenv("POSTGRES_PASSWORD")
×
174
        }
×
175
        dbPort, err := environment.GetPostgresPort()
13✔
176
        if err != nil {
13✔
NEW
177
                return nil, err
×
NEW
178
        }
×
179

180
        return &pt.TestBaseOptions{
13✔
181
                DBPluginName: PluginName,
13✔
182
                DBUsername:   testUser,
13✔
183
                DBPassword:   testPassword,
13✔
184
                DBHost:       environment.GetPostgresAddress(),
13✔
185
                DBPort:       dbPort,
13✔
186
                SchemaDir:    testSchemaDir,
13✔
187
        }, nil
13✔
188
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc