You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by de...@apache.org on 2017/08/10 16:04:42 UTC
[01/43] incubator-trafficcontrol git commit: Add TO Golang Apache
license headers
Repository: incubator-trafficcontrol
Updated Branches:
refs/heads/master 9c4eccc45 -> 77c0dae32
Add TO Golang Apache license headers
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/5cb00dd9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/5cb00dd9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/5cb00dd9
Branch: refs/heads/master
Commit: 5cb00dd9235335c46328a302624a04aba3285084
Parents: b583346
Author: Robert Butts <ro...@gmail.com>
Authored: Mon Jul 17 22:17:41 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:02 2017 -0600
----------------------------------------------------------------------
traffic_ops/traffic_ops_golang/auth.go | 19 ++++++++++++
traffic_ops/traffic_ops_golang/config.go | 19 ++++++++++++
traffic_ops/traffic_ops_golang/monitoring.go | 19 ++++++++++++
traffic_ops/traffic_ops_golang/routes.go | 19 ++++++++++++
.../traffic_ops_golang/traffic_ops_golang.go | 31 ++++++++++++--------
traffic_ops/traffic_ops_golang/wrappers.go | 19 ++++++++++++
traffic_ops_golang/monitoring_test.go | 19 ++++++++++++
7 files changed, 133 insertions(+), 12 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/5cb00dd9/traffic_ops/traffic_ops_golang/auth.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/auth.go b/traffic_ops/traffic_ops_golang/auth.go
index 75849c1..d7e5efe 100644
--- a/traffic_ops/traffic_ops_golang/auth.go
+++ b/traffic_ops/traffic_ops_golang/auth.go
@@ -1,5 +1,24 @@
package main
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
import (
"database/sql"
"log" // TODO change to traffic_monitor_golang/common/log
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/5cb00dd9/traffic_ops/traffic_ops_golang/config.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/config.go b/traffic_ops/traffic_ops_golang/config.go
index a0f3401..6e4e69c 100644
--- a/traffic_ops/traffic_ops_golang/config.go
+++ b/traffic_ops/traffic_ops_golang/config.go
@@ -1,5 +1,24 @@
package main
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
import (
"encoding/json"
"fmt"
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/5cb00dd9/traffic_ops/traffic_ops_golang/monitoring.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/monitoring.go b/traffic_ops/traffic_ops_golang/monitoring.go
index c669d0b..4c4505f 100644
--- a/traffic_ops/traffic_ops_golang/monitoring.go
+++ b/traffic_ops/traffic_ops_golang/monitoring.go
@@ -1,5 +1,24 @@
package main
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
import (
"database/sql"
"encoding/json"
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/5cb00dd9/traffic_ops/traffic_ops_golang/routes.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index f347eef..5c71dfa 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -1,5 +1,24 @@
package main
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
import (
"crypto/tls"
"database/sql"
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/5cb00dd9/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/traffic_ops_golang.go b/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
index aec0637..173b9b5 100644
--- a/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
+++ b/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
@@ -1,17 +1,24 @@
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
package main
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
import (
"database/sql"
"flag"
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/5cb00dd9/traffic_ops/traffic_ops_golang/wrappers.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/wrappers.go b/traffic_ops/traffic_ops_golang/wrappers.go
index c5fd9c0..f986d2f 100644
--- a/traffic_ops/traffic_ops_golang/wrappers.go
+++ b/traffic_ops/traffic_ops_golang/wrappers.go
@@ -1,5 +1,24 @@
package main
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
import (
"database/sql"
"fmt"
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/5cb00dd9/traffic_ops_golang/monitoring_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/monitoring_test.go b/traffic_ops_golang/monitoring_test.go
index 79b0919..f6958e3 100644
--- a/traffic_ops_golang/monitoring_test.go
+++ b/traffic_ops_golang/monitoring_test.go
@@ -1,5 +1,24 @@
package main
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
import (
"reflect"
"sort"
[36/43] incubator-trafficcontrol git commit: Change TO Golang
'no_auth' cfg key to 'insecure'
Posted by de...@apache.org.
Change TO Golang 'no_auth' cfg key to 'insecure'
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/4ab5a3e2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/4ab5a3e2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/4ab5a3e2
Branch: refs/heads/master
Commit: 4ab5a3e2541abe19a83e32d7a86b11dacff9d996
Parents: 29c1593
Author: Robert Butts <ro...@gmail.com>
Authored: Tue Jul 25 10:44:06 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/traffic_ops_golang/config.go | 2 +-
traffic_ops/traffic_ops_golang/routes.go | 2 +-
traffic_ops/traffic_ops_golang/traffic_ops_golang.config | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4ab5a3e2/traffic_ops/traffic_ops_golang/config.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/config.go b/traffic_ops/traffic_ops_golang/config.go
index 641c9f3..7595181 100644
--- a/traffic_ops/traffic_ops_golang/config.go
+++ b/traffic_ops/traffic_ops_golang/config.go
@@ -38,7 +38,7 @@ type Config struct {
TOSecret string `json:"to_secret"`
TOURLStr string `json:"to_url"`
TOURL *url.URL `json:"-"`
- NoAuth bool `json:"no_auth"`
+ Insecure bool `json:"insecure"`
CertPath string `json:"cert_path"`
KeyPath string `json:"key_path"`
LogLocationError string `json:"log_location_error"`
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4ab5a3e2/traffic_ops/traffic_ops_golang/routes.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index 06f7bae..e744086 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -57,7 +57,7 @@ func GetRoutes(d ServerData) (map[string]RegexHandlerFunc, http.Handler, error)
}
return map[string]RegexHandlerFunc{
- "api/1.2/cdns/{cdn}/configs/monitoring.json": wrapHeaders(wrapAuth(monitoringHandler(d.DB), d.NoAuth, d.TOSecret, privLevelStmt, MonitoringPrivLevel)),
+ "api/1.2/cdns/{cdn}/configs/monitoring.json": wrapHeaders(wrapAuth(monitoringHandler(d.DB), d.Insecure, d.TOSecret, privLevelStmt, MonitoringPrivLevel)),
}, getRootHandler(d), nil
}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4ab5a3e2/traffic_ops/traffic_ops_golang/traffic_ops_golang.config
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/traffic_ops_golang.config b/traffic_ops/traffic_ops_golang/traffic_ops_golang.config
index 6bd9703..570b8b1 100644
--- a/traffic_ops/traffic_ops_golang/traffic_ops_golang.config
+++ b/traffic_ops/traffic_ops_golang/traffic_ops_golang.config
@@ -7,7 +7,7 @@
"db_ssl": true,
"to_secret": "walrus",
"to_url": "https://trafficops.example.net:60443",
- "no_auth": false,
+ "insecure": false,
"cert_path": "/opt/traffic_ops/cert",
"key_path": "/opt/traffic_ops/key"
}
[41/43] incubator-trafficcontrol git commit: Fix TO Golang setting
port in cdn.conf
Posted by de...@apache.org.
Fix TO Golang setting port in cdn.conf
c/o @dangogh @dewrich
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/d45733b2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/d45733b2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/d45733b2
Branch: refs/heads/master
Commit: d45733b25f4c775871e1306c61303786638ac6fd
Parents: f212661
Author: Robert Butts <ro...@gmail.com>
Authored: Tue Aug 1 17:39:14 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/install/bin/_postinstall | 17 +++++++++++------
traffic_ops/install/lib/InstallUtils.pm | 2 +-
2 files changed, 12 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d45733b2/traffic_ops/install/bin/_postinstall
----------------------------------------------------------------------
diff --git a/traffic_ops/install/bin/_postinstall b/traffic_ops/install/bin/_postinstall
old mode 100755
new mode 100644
index b83e65a..4659142
--- a/traffic_ops/install/bin/_postinstall
+++ b/traffic_ops/install/bin/_postinstall
@@ -185,13 +185,17 @@ sub generateDbConf {
sub setCdnConfGoPort {
my $cdnConf = shift;
- if ( exists $cdnConf->{"traffic_ops_golang_port"} ) {
+ if ( exists $cdnConf->{traffic_ops_golang_port} ) {
return $cdnConf;
}
- my ($port) = $cdnConf->{hypnotoad}->{listen}[0] =~ m/\:(\d+)/;
- $cdnConf->{hypnotoad}->{listen}[0] =~ s/\:\d+/\:60443/;
- $cdnConf->{hypnotoad}->{listen}[0] =~ s/https\:\/\/[\:\:]/https\:\/\/127\.0\.0\.1/;
- $cdnConf->{"traffic_ops_golang_port"} = $port;
+
+ my $listen = $cdnConf->{hypnotoad}{listen}[0];
+ my ($port) = $listen =~ /:(\d+)/;
+ $listen =~ s/:$port/:60443/;
+ $listen =~ s{'https://\[::\]}{'https://127.0.0.1};
+
+ $cdnConf->{traffic_ops_golang_port} = $port;
+ $cdnConf->{hypnotoad}{listen} = [ $listen ];
return $cdnConf;
}
@@ -232,6 +236,7 @@ sub generateCdnConf {
}
$cdnConf = setCdnConfGoPort($cdnConf);
$cdnConf->{hypnotoad}{workers} = $cdnConfiguration{workers};
+ #InstallUtils::logger("cdnConf: " . Dumper($cdnConf), "info" );
InstallUtils::writePerl( $fileName, $cdnConf );
InstallUtils::logger( "CDN configuration has been saved", "info" );
}
@@ -868,7 +873,6 @@ sub main {
# The generator functions handle checking input/default/automatic mode
# todbconf will be used later when setting up the database
my $todbconf = generateDbConf( $userInput, $databaseConfFile, $dbConfFile );
- generateCdnConf( $userInput, $cdnConfFile );
generateLdapConf( $userInput, $ldapConfFile );
my $adminconf = generateUsersConf( $userInput, $usersConfFile );
my $custom_profile = generateProfilesDir( $userInput, $profilesConfFile );
@@ -881,6 +885,7 @@ sub main {
setupMaxMind( $todbconf->{"maxmind"} );
setupCertificates( $opensslconf );
+ generateCdnConf( $userInput, $cdnConfFile );
my $dbh = Database::connect($databaseConfFile, $todbconf);
if (!$dbh) {
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d45733b2/traffic_ops/install/lib/InstallUtils.pm
----------------------------------------------------------------------
diff --git a/traffic_ops/install/lib/InstallUtils.pm b/traffic_ops/install/lib/InstallUtils.pm
index 040a8e9..a7df222 100644
--- a/traffic_ops/install/lib/InstallUtils.pm
+++ b/traffic_ops/install/lib/InstallUtils.pm
@@ -225,7 +225,7 @@ sub writePerl {
my $dumper = Data::Dumper->new( [$data] );
# print without var names and with simple indentation
- print $fh $dumper->Terse(1)->Dump();
+ print $fh $dumper->Quotekeys(0)->Terse(1)->Dump();
close $fh;
}
[22/43] incubator-trafficcontrol git commit: Add TO Golang old perl
config reading
Posted by de...@apache.org.
Add TO Golang old perl config reading
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/8b0ac5f9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/8b0ac5f9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/8b0ac5f9
Branch: refs/heads/master
Commit: 8b0ac5f9e00d188e535b6b35a3f6fdb7298c59da
Parents: 70b7e5c
Author: Robert Butts <ro...@gmail.com>
Authored: Sun Jul 23 14:53:08 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/app/lib/TrafficOps.pm | 2 +-
traffic_ops/build/traffic_ops.spec | 13 +-
traffic_ops/traffic_ops_golang/perlconfig.go | 288 +++++++++++++++++++
.../traffic_ops_golang/perlconfig_test.go | 166 +++++++++++
.../traffic_ops_golang/traffic_ops_golang.go | 21 +-
5 files changed, 483 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/8b0ac5f9/traffic_ops/app/lib/TrafficOps.pm
----------------------------------------------------------------------
diff --git a/traffic_ops/app/lib/TrafficOps.pm b/traffic_ops/app/lib/TrafficOps.pm
index 43b5bdf..3695031 100644
--- a/traffic_ops/app/lib/TrafficOps.pm
+++ b/traffic_ops/app/lib/TrafficOps.pm
@@ -349,7 +349,7 @@ sub setup_mojo_plugins {
$self->plugin(
AccessLog => {
- log => "$logging_root_dir/access.log",
+ log => "$logging_root_dir/perl_access.log",
uname_helper => 'set_username',
format => '%h %l %u %t "%r" %>s %b %D "%{User-Agent}i"'
}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/8b0ac5f9/traffic_ops/build/traffic_ops.spec
----------------------------------------------------------------------
diff --git a/traffic_ops/build/traffic_ops.spec b/traffic_ops/build/traffic_ops.spec
index 66d2fd9..8efa676 100644
--- a/traffic_ops/build/traffic_ops.spec
+++ b/traffic_ops/build/traffic_ops.spec
@@ -60,14 +60,23 @@ Built: %(date) by %{getenv: USER}
mkdir -p src pkg bin || { echo "Could not create directories in $(pwd): $!"; exit 1; }
# build tocookie (dependencies within traffic_control will fail to `go get` unless prebuilt)
- godir=src/github.com/apache/incubator-trafficcontrol/traffic_ops/experimental/tocookie
+ godir=src/github.com/apache/incubator-trafficcontrol/traffic_ops/tocookie
( mkdir -p "$godir" && \
cd "$godir" && \
- cp -r "$TC_DIR"/traffic_ops/experimental/tocookie/* . && \
+ cp -r "$TC_DIR"/traffic_ops/tocookie/* . && \
echo "go getting tocookie at $(pwd)" && \
go get -v \
) || { echo "Could not build go tocookie at $(pwd): $!"; exit 1; }
+ # build log (dependencies within traffic_control will fail to `go get` unless prebuilt)
+ godir=src/github.com/apache/incubator-trafficcontrol/traffic_monitor_golang/common/log
+ ( mkdir -p "$godir" && \
+ cd "$godir" && \
+ cp -r "$TC_DIR"/traffic_monitor_golang/common/log/* . && \
+ echo "go getting log at $(pwd)" && \
+ go get -v \
+ ) || { echo "Could not build go log at $(pwd): $!"; exit 1; }
+
# build traffic_ops_golang binary
godir=src/github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang
oldpwd=$(pwd)
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/8b0ac5f9/traffic_ops/traffic_ops_golang/perlconfig.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/perlconfig.go b/traffic_ops/traffic_ops_golang/perlconfig.go
new file mode 100644
index 0000000..c7abf64
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/perlconfig.go
@@ -0,0 +1,288 @@
+package main
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/url"
+ "regexp"
+ "strconv"
+ "strings"
+
+ "github.com/apache/incubator-trafficcontrol/traffic_monitor_golang/common/log"
+)
+
+const OldAccessLogPath = "/var/log/traffic_ops/access.log"
+const NewLogPath = "/var/log/traffic_ops/traffic_ops_golang.log"
+
+func GetPerlConfigs(cdnConfPath string, dbConfPath string) (Config, error) {
+ configBytes, err := ioutil.ReadFile(cdnConfPath)
+ if err != nil {
+ return Config{}, fmt.Errorf("reading CDN conf '%v': %v", cdnConfPath, err)
+ }
+ dbConfBytes, err := ioutil.ReadFile(dbConfPath)
+ if err != nil {
+ return Config{}, fmt.Errorf("reading db conf '%v': %v", dbConfPath, err)
+ }
+ return getPerlConfigsFromStrs(string(configBytes), string(dbConfBytes))
+}
+
+func getPerlConfigsFromStrs(cdnConfBytes string, dbConfBytes string) (Config, error) {
+ cfg, err := getCDNConf(cdnConfBytes)
+ if err != nil {
+ return Config{}, fmt.Errorf("parsing CDN conf '%v': %v", cdnConfBytes, err)
+ }
+
+ dbconf, err := getDbConf(string(dbConfBytes))
+ if err != nil {
+ return Config{}, fmt.Errorf("parsing db conf '%v': %v", dbConfBytes, err)
+ }
+ cfg.DBUser = dbconf.User
+ cfg.DBPass = dbconf.Password
+ cfg.DBServer = dbconf.Hostname
+ cfg.DBDB = dbconf.DBName
+ cfg.DBSSL = false // TODO fix
+ if dbconf.Port != "" {
+ cfg.DBServer += ":" + dbconf.Port
+ }
+
+ cfg.LogLocationInfo = OldAccessLogPath
+ cfg.LogLocationError = NewLogPath
+ cfg.LogLocationWarning = NewLogPath
+ cfg.LogLocationEvent = NewLogPath
+ cfg.LogLocationDebug = log.LogLocationNull
+
+ return cfg, nil
+}
+
+func getCDNConf(s string) (Config, error) {
+ cfg := Config{}
+ obj, err := ParsePerlObj(s)
+ if err != nil {
+ return Config{}, fmt.Errorf("parsing Perl object: %v", err)
+ }
+
+ if cfg.HTTPPort, err = getPort(obj); err != nil {
+ return Config{}, err
+ }
+
+ if cfg.TOSecret, err = getSecret(obj); err != nil {
+ return Config{}, err
+ }
+
+ oldPort, err := getOldPort(obj)
+ if err != nil {
+ return Config{}, err
+ }
+ cfg.TOURLStr = "https://127.0.0.1:" + oldPort
+ if cfg.TOURL, err = url.Parse(cfg.TOURLStr); err != nil {
+ return Config{}, fmt.Errorf("Invalid Traffic Ops URL '%v': err", cfg.TOURL, err)
+ }
+
+ cfg.CertPath, err = getConfigCert(obj)
+ if err != nil {
+ return Config{}, err
+ }
+
+ cfg.KeyPath, err = getConfigKey(obj)
+ if err != nil {
+ return Config{}, err
+ }
+
+ return cfg, nil
+}
+
+func getPort(obj map[string]interface{}) (string, error) {
+ portStrI, ok := obj["traffic_ops_golang_port"]
+ if !ok {
+ return "", fmt.Errorf("missing traffic_ops_golang_port key")
+ }
+ portStr, ok := portStrI.(string)
+ if !ok {
+ return "", fmt.Errorf("traffic_ops_golang_port key '%v' not a string", portStrI)
+ }
+
+ port, err := strconv.Atoi(portStr)
+ if err != nil || port < 0 || port > 65535 {
+ return "", fmt.Errorf("invalid port '%s'", portStr)
+ }
+ return strconv.Itoa(port), nil
+}
+
+func getOldPort(obj map[string]interface{}) (string, error) {
+ hypnotoadI, ok := obj["hypnotoad"]
+ if !ok {
+ return "", fmt.Errorf("missing hypnotoad key")
+ }
+ hypnotoad, ok := hypnotoadI.(map[string]interface{})
+ if !ok {
+ return "", fmt.Errorf("hypnotoad key '%v' not an object", hypnotoadI)
+ }
+
+ listenArrI, ok := hypnotoad["listen"]
+ if !ok {
+ return "", fmt.Errorf("missing hypnotoad.listen key")
+ }
+ listenArr, ok := listenArrI.([]interface{})
+ if !ok {
+ return "", fmt.Errorf("listen key '%v' type %T not an array", listenArrI, listenArrI)
+ }
+ if len(listenArr) < 1 {
+ return "", fmt.Errorf("empty hypnotoad.listen key")
+ }
+ listenI := listenArr[0]
+ listen, ok := listenI.(string)
+ if !ok {
+ return "", fmt.Errorf("listen[0] key '%v' type %T not a string", listenI, listenI)
+ }
+
+ listenRe := regexp.MustCompile(`:(\d+)`)
+ portMatch := listenRe.FindStringSubmatch(listen)
+ if len(portMatch) < 2 {
+ return "", fmt.Errorf("failed to find port in listen '%s'", listen)
+ }
+ portStr := portMatch[1]
+
+ port, err := strconv.Atoi(portStr)
+ if err != nil || port < 0 || port > 65535 {
+ return "", fmt.Errorf("invalid port in listen '%s'", listen)
+ }
+ return strconv.Itoa(port), nil
+}
+
+func getConfigCert(obj map[string]interface{}) (string, error) {
+ hypnotoadI, ok := obj["hypnotoad"]
+ if !ok {
+ return "", fmt.Errorf("missing hypnotoad key")
+ }
+ hypnotoad, ok := hypnotoadI.(map[string]interface{})
+ if !ok {
+ return "", fmt.Errorf("hypnotoad key '%v' not an object", hypnotoadI)
+ }
+
+ listenArrI, ok := hypnotoad["listen"]
+ if !ok {
+ return "", fmt.Errorf("missing hypnotoad.listen key")
+ }
+ listenArr, ok := listenArrI.([]interface{})
+ if !ok {
+ return "", fmt.Errorf("listen key '%v' type %T not an array", listenArrI, listenArrI)
+ }
+ if len(listenArr) < 1 {
+ return "", fmt.Errorf("empty hypnotoad.listen key")
+ }
+ listenI := listenArr[0]
+ listen, ok := listenI.(string)
+ if !ok {
+ return "", fmt.Errorf("listen[0] key '%v' type %T not a string", listenI, listenI)
+ }
+
+ keyStr := "cert="
+ start := strings.Index(listen, keyStr)
+ if start < 0 {
+ return "", fmt.Errorf("failed to find key in listen '%s'", listen)
+ }
+ listen = listen[start+len(keyStr):]
+ end := strings.Index(listen, "&")
+ if end < 0 {
+ return listen[start:], nil
+ }
+ return listen[:end], nil
+}
+
+func getConfigKey(obj map[string]interface{}) (string, error) {
+ hypnotoadI, ok := obj["hypnotoad"]
+ if !ok {
+ return "", fmt.Errorf("missing hypnotoad key")
+ }
+ hypnotoad, ok := hypnotoadI.(map[string]interface{})
+ if !ok {
+ return "", fmt.Errorf("hypnotoad key '%v' not an object", hypnotoadI)
+ }
+
+ listenArrI, ok := hypnotoad["listen"]
+ if !ok {
+ return "", fmt.Errorf("missing hypnotoad.listen key")
+ }
+ listenArr, ok := listenArrI.([]interface{})
+ if !ok {
+ return "", fmt.Errorf("listen key '%v' type %T not an array", listenArrI, listenArrI)
+ }
+ if len(listenArr) < 1 {
+ return "", fmt.Errorf("empty hypnotoad.listen key")
+ }
+ listenI := listenArr[0]
+ listen, ok := listenI.(string)
+ if !ok {
+ return "", fmt.Errorf("listen[0] key '%v' type %T not a string", listenI, listenI)
+ }
+
+ keyStr := "key="
+ start := strings.Index(listen, keyStr)
+ if start < 0 {
+ return "", fmt.Errorf("failed to find key in listen '%s'", listen)
+ }
+ listen = listen[start+len(keyStr):]
+ end := strings.Index(listen, "&")
+ if end < 0 {
+ return listen[start:], nil
+ }
+ return listen[:end], nil
+}
+
+func getSecret(obj map[string]interface{}) (string, error) {
+ secretsI, ok := obj["secrets"]
+ if !ok {
+ return "", fmt.Errorf("missing secrets key")
+ }
+ secrets, ok := secretsI.([]interface{})
+ if !ok {
+ return "", fmt.Errorf("secrets key '%v' not an array", secretsI)
+ }
+
+ if len(secrets) < 1 {
+ return "", fmt.Errorf("empty secrets key")
+ }
+ secretI := secrets[0]
+ secret, ok := secretI.(string)
+ if !ok {
+ return "", fmt.Errorf("secret '%v' not a string", secretI)
+ }
+
+ return secret, nil
+}
+
+type DatabaseConf struct {
+ Description string `json:"description"`
+ DBName string `json:"dbname"`
+ Hostname string `json:"hostname"`
+ User string `json:"user"`
+ Password string `json:"password"`
+ Port string `json:"port"`
+ Type string `json:"type"`
+}
+
+func getDbConf(s string) (DatabaseConf, error) {
+ dbc := DatabaseConf{}
+ err := json.Unmarshal([]byte(s), &dbc)
+ return dbc, err
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/8b0ac5f9/traffic_ops/traffic_ops_golang/perlconfig_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/perlconfig_test.go b/traffic_ops/traffic_ops_golang/perlconfig_test.go
new file mode 100644
index 0000000..8242d5c
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/perlconfig_test.go
@@ -0,0 +1,166 @@
+package main
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import (
+ "net/url"
+ "reflect"
+ "testing"
+
+ "github.com/apache/incubator-trafficcontrol/traffic_monitor_golang/common/log"
+)
+
+func TestGetCDNConf(t *testing.T) {
+ input := `
+{
+ hypnotoad => {
+ listen => [
+ 'https://[::]:60443?cert=/etc/pki/tls/certs/localhost.crt&key=/etc/pki/tls/private/localhost.key&verify=0x00&ciphers=AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL:!EDH:!ED'
+ ],
+ user => 'trafops',
+ group => 'trafops',
+ heartbeat_timeout => 20,
+ pid_file => '/var/run/traffic_ops.pid',
+ workers => 96
+ },
+ cors => {
+ access_control_allow_origin => '*'
+ },
+ to => {
+ base_url => 'http://localhost:3000', # this is where traffic ops app resides
+ email_from => 'no-reply@traffic-ops-domain.com' # traffic ops email address
+ },
+ portal => {
+ base_url => 'http://localhost:8080', # this is where the traffic portal resides (a javascript client that consumes the TO API)
+ email_from => 'no-reply@traffic-portal-domain.com' # traffic portal email address
+ },
+
+ # 1st secret is used to generate new signatures. Older one kept around for existing signed cookies.
+ # Remove old one(s) when ready to invalidate old cookies.
+ secrets => [ 'walrus' ],
+ geniso => {
+ iso_root_path => '/opt/traffic_ops/app/public', # the location where the iso files will be written
+ },
+ inactivity_timeout => 60,
+ traffic_ops_golang_port => '443'
+};
+`
+
+ expected := Config{
+ HTTPPort: "443",
+ TOSecret: "walrus",
+ TOURLStr: "https://127.0.0.1:60443",
+ CertPath: "/etc/pki/tls/certs/localhost.crt",
+ KeyPath: "/etc/pki/tls/private/localhost.key",
+ }
+ err := error(nil)
+ if expected.TOURL, err = url.Parse(expected.TOURLStr); err != nil {
+ t.Errorf("expected URL parse '%+v' err nil actual %+v", expected.TOURLStr, err)
+ }
+
+ cfg, err := getCDNConf(input)
+ if err != nil {
+ t.Errorf("expected nil err actual %v", err)
+ }
+
+ if !reflect.DeepEqual(cfg, expected) {
+ t.Errorf("expected %+v actual %+v", expected, cfg)
+ }
+}
+
+func TestGetPerlConfigsFromStrs(t *testing.T) {
+ cdnConfInput := `
+{
+ hypnotoad => {
+ listen => [
+ 'https://[::]:60443?cert=/etc/pki/tls/certs/localhost.crt&key=/etc/pki/tls/private/localhost.key&verify=0x00&ciphers=AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL:!EDH:!ED'
+ ],
+ user => 'trafops',
+ group => 'trafops',
+ heartbeat_timeout => 20,
+ pid_file => '/var/run/traffic_ops.pid',
+ workers => 96
+ },
+ cors => {
+ access_control_allow_origin => '*'
+ },
+ to => {
+ base_url => 'http://localhost:3000', # this is where traffic ops app resides
+ email_from => 'no-reply@traffic-ops-domain.com' # traffic ops email address
+ },
+ portal => {
+ base_url => 'http://localhost:8080', # this is where the traffic portal resides (a javascript client that consumes the TO API)
+ email_from => 'no-reply@traffic-portal-domain.com' # traffic portal email address
+ },
+
+ # 1st secret is used to generate new signatures. Older one kept around for existing signed cookies.
+ # Remove old one(s) when ready to invalidate old cookies.
+ secrets => [ 'walrus' ],
+ geniso => {
+ iso_root_path => '/opt/traffic_ops/app/public', # the location where the iso files will be written
+ },
+ inactivity_timeout => 60,
+ traffic_ops_golang_port => '443'
+};
+`
+
+ dbConfInput := `
+{
+ "password" : "thelizard",
+ "user" : "bill",
+ "type" : "Pg",
+ "hostname" : "db.to.example.net",
+ "description" : "Postgres database",
+ "port" : "5432",
+ "dbname" : "to"
+}
+`
+
+ expected := Config{
+ HTTPPort: "443",
+ DBUser: "bill",
+ DBPass: "thelizard",
+ DBServer: "db.to.example.net:5432",
+ DBDB: "to",
+ DBSSL: false,
+ TOSecret: "walrus",
+ TOURLStr: "https://127.0.0.1:60443",
+ CertPath: "/etc/pki/tls/certs/localhost.crt",
+ KeyPath: "/etc/pki/tls/private/localhost.key",
+ LogLocationError: NewLogPath,
+ LogLocationWarning: NewLogPath,
+ LogLocationInfo: OldAccessLogPath,
+ LogLocationEvent: NewLogPath,
+ LogLocationDebug: log.LogLocationNull,
+ }
+ err := error(nil)
+ if expected.TOURL, err = url.Parse(expected.TOURLStr); err != nil {
+ t.Errorf("expected URL parse '%+v' err nil actual %+v", expected.TOURLStr, err)
+ }
+
+ cfg, err := getPerlConfigsFromStrs(cdnConfInput, dbConfInput)
+ if err != nil {
+ t.Errorf("expected nil err actual %v", err)
+ }
+
+ if !reflect.DeepEqual(cfg, expected) {
+ t.Errorf("expected %+v actual %+v", expected, cfg)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/8b0ac5f9/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/traffic_ops_golang.go b/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
index 8f70098..6d2c75b 100644
--- a/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
+++ b/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
@@ -34,17 +34,30 @@ const Version = "0.1"
const DefaultConfigPath = "/opt/traffic_ops/traffic_ops_golang.config"
+const OldConfig = true
+const OldConfigCDNConfPath = "/opt/traffic_ops/app/conf/cdn.conf"
+const OldConfigDBConfPath = "/opt/traffic_ops/app/conf/production/database.conf"
+
func main() {
configFileName := flag.String("cfg", "", "The config file path")
+ oldConfig := flag.Bool("oldcfg", true, "Whether to look for old Perl Traffic Ops config files")
flag.Parse()
if *configFileName == "" {
*configFileName = DefaultConfigPath
}
- cfg, err := LoadConfig(*configFileName)
- if err != nil {
- fmt.Println("Error loading config '" + *configFileName + "': " + err.Error())
- return
+ cfg := Config{}
+ err := error(nil)
+ if !*oldConfig {
+ if cfg, err = LoadConfig(*configFileName); err != nil {
+ fmt.Println("Error loading config '" + *configFileName + "': " + err.Error())
+ return
+ }
+ } else {
+ if cfg, err = GetPerlConfigs(OldConfigCDNConfPath, OldConfigDBConfPath); err != nil {
+ fmt.Println("Error loading old configs '" + OldConfigCDNConfPath + "' and '" + OldConfigDBConfPath + "': " + err.Error())
+ return
+ }
}
if err := log.InitCfg(cfg); err != nil {
[11/43] incubator-trafficcontrol git commit: Add TO Golang server
name header
Posted by de...@apache.org.
Add TO Golang server name header
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/46d1f4bf
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/46d1f4bf
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/46d1f4bf
Branch: refs/heads/master
Commit: 46d1f4bfe7c3b752a1d508f3029432139859530d
Parents: 96edf7d
Author: Robert Butts <ro...@gmail.com>
Authored: Fri Jul 21 18:59:16 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/traffic_ops_golang/routes.go | 2 +-
traffic_ops/traffic_ops_golang/traffic_ops_golang.go | 4 +++-
traffic_ops/traffic_ops_golang/wrappers.go | 10 ++++++++++
3 files changed, 14 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/46d1f4bf/traffic_ops/traffic_ops_golang/routes.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index d7061b4..06f7bae 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -57,7 +57,7 @@ func GetRoutes(d ServerData) (map[string]RegexHandlerFunc, http.Handler, error)
}
return map[string]RegexHandlerFunc{
- "api/1.2/cdns/{cdn}/configs/monitoring.json": wrapAuth(monitoringHandler(d.DB), d.NoAuth, d.TOSecret, privLevelStmt, MonitoringPrivLevel),
+ "api/1.2/cdns/{cdn}/configs/monitoring.json": wrapHeaders(wrapAuth(monitoringHandler(d.DB), d.NoAuth, d.TOSecret, privLevelStmt, MonitoringPrivLevel)),
}, getRootHandler(d), nil
}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/46d1f4bf/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/traffic_ops_golang.go b/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
index 2689e7c..8f70098 100644
--- a/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
+++ b/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
@@ -30,7 +30,9 @@ import (
_ "github.com/lib/pq"
)
-const DefaultConfigPath = "/etc/goto/config.json"
+const Version = "0.1"
+
+const DefaultConfigPath = "/opt/traffic_ops/traffic_ops_golang.config"
func main() {
configFileName := flag.String("cfg", "", "The config file path")
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/46d1f4bf/traffic_ops/traffic_ops_golang/wrappers.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/wrappers.go b/traffic_ops/traffic_ops_golang/wrappers.go
index c6eb8cf..64afeff 100644
--- a/traffic_ops/traffic_ops_golang/wrappers.go
+++ b/traffic_ops/traffic_ops_golang/wrappers.go
@@ -28,6 +28,16 @@ import (
"time"
)
+const ServerName = "traffic_ops_golang" + "/" + Version
+
+func wrapHeaders(h RegexHandlerFunc) RegexHandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request, p ParamMap) {
+ w.Header().Set("Access-Control-Allow-Origin", "*")
+ w.Header().Set("X-Server-Name", ServerName)
+ h(w, r, p)
+ }
+}
+
func wrapAuth(h RegexHandlerFunc, noAuth bool, secret string, privLevelStmt *sql.Stmt, privLevelRequired int) RegexHandlerFunc {
if noAuth {
return h
[37/43] incubator-trafficcontrol git commit: Add TO Golang DBMaxConns
config
Posted by de...@apache.org.
Add TO Golang DBMaxConns config
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/10a410a3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/10a410a3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/10a410a3
Branch: refs/heads/master
Commit: 10a410a3467f5e864ff47dd44ec3d7184d34923b
Parents: d45733b
Author: Robert Butts <ro...@gmail.com>
Authored: Tue Aug 1 18:03:43 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/traffic_ops_golang/config.go | 1 +
traffic_ops/traffic_ops_golang/perlconfig.go | 22 +++++++++++++-------
.../traffic_ops_golang/traffic_ops_golang.go | 2 ++
3 files changed, 18 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/10a410a3/traffic_ops/traffic_ops_golang/config.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/config.go b/traffic_ops/traffic_ops_golang/config.go
index 0c87878..3dc06c9 100644
--- a/traffic_ops/traffic_ops_golang/config.go
+++ b/traffic_ops/traffic_ops_golang/config.go
@@ -41,6 +41,7 @@ type Config struct {
Insecure bool `json:"insecure"`
CertPath string `json:"cert_path"`
KeyPath string `json:"key_path"`
+ MaxDBConnections int `json:"max_db_connections"`
LogLocationError string `json:"log_location_error"`
LogLocationWarning string `json:"log_location_warning"`
LogLocationInfo string `json:"log_location_info"`
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/10a410a3/traffic_ops/traffic_ops_golang/perlconfig.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/perlconfig.go b/traffic_ops/traffic_ops_golang/perlconfig.go
index a3013dc..d088fb3 100644
--- a/traffic_ops/traffic_ops_golang/perlconfig.go
+++ b/traffic_ops/traffic_ops_golang/perlconfig.go
@@ -33,6 +33,7 @@ import (
const OldAccessLogPath = "/var/log/traffic_ops/access.log"
const NewLogPath = "/var/log/traffic_ops/traffic_ops_golang.log"
+const DefaultMaxDBConnections = 50
func GetPerlConfigs(cdnConfPath string, dbConfPath string) (Config, error) {
configBytes, err := ioutil.ReadFile(cdnConfPath)
@@ -71,6 +72,12 @@ func getPerlConfigsFromStrs(cdnConfBytes string, dbConfBytes string) (Config, er
cfg.LogLocationEvent = OldAccessLogPath
cfg.LogLocationDebug = log.LogLocationNull
+ if dbconf.MaxConnections != nil {
+ cfg.MaxDBConnections = *dbconf.MaxConnections
+ } else {
+ cfg.MaxDBConnections = DefaultMaxDBConnections
+ }
+
return cfg, nil
}
@@ -272,13 +279,14 @@ func getSecret(obj map[string]interface{}) (string, error) {
}
type DatabaseConf struct {
- Description string `json:"description"`
- DBName string `json:"dbname"`
- Hostname string `json:"hostname"`
- User string `json:"user"`
- Password string `json:"password"`
- Port string `json:"port"`
- Type string `json:"type"`
+ Description string `json:"description"`
+ DBName string `json:"dbname"`
+ Hostname string `json:"hostname"`
+ User string `json:"user"`
+ Password string `json:"password"`
+ Port string `json:"port"`
+ Type string `json:"type"`
+ MaxConnections *int `json:"max_connections"`
}
func getDbConf(s string) (DatabaseConf, error) {
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/10a410a3/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/traffic_ops_golang.go b/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
index 6d2c75b..4a41954 100644
--- a/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
+++ b/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
@@ -77,6 +77,8 @@ func main() {
}
defer db.Close()
+ db.SetMaxOpenConns(cfg.MaxDBConnections)
+
if err := RegisterRoutes(ServerData{DB: db, Config: cfg}); err != nil {
log.Errorf("registering routes: %v\n", err)
return
[31/43] incubator-trafficcontrol git commit: Fix TO Golang
Postinstall to keep existing port
Posted by de...@apache.org.
Fix TO Golang Postinstall to keep existing port
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/84a4b129
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/84a4b129
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/84a4b129
Branch: refs/heads/master
Commit: 84a4b12963d5c6642bc406516d18baf1c09503fa
Parents: 9987fb9
Author: Robert Butts <ro...@gmail.com>
Authored: Sun Aug 6 12:21:24 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/install/bin/generateCert | 12 ++++++++++--
traffic_ops/install/lib/GenerateCert.pm | 12 ++++++++++--
2 files changed, 20 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/84a4b129/traffic_ops/install/bin/generateCert
----------------------------------------------------------------------
diff --git a/traffic_ops/install/bin/generateCert b/traffic_ops/install/bin/generateCert
index faf0b36..713288f 100755
--- a/traffic_ops/install/bin/generateCert
+++ b/traffic_ops/install/bin/generateCert
@@ -46,11 +46,19 @@ EOF
sub writeCdn_conf {
my $cdn_conf = shift;
- # listen param to be inserted
- my $listen_str = "https://[::]:443?cert=${cert}&key=${key}&ca=${ca}&verify=0x00&ciphers=AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL:!EDH:!ED";
# load as perl hash to find string to be replaced
my $cdnh = do $cdn_conf;
+
+ # get existing port, if any
+ my $listen = $cdnh->{hypnotoad}{listen}[0];
+ my ($port) = $listen =~ /:(\d+)/;
+ if (!defined($port)) {
+ $port = 60443;
+ }
+ # listen param to be inserted
+ my $listen_str = "https://[::]:${port}?cert=${cert}&key=${key}&ca=${ca}&verify=0x00&ciphers=AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL:!EDH:!ED";
+
if ( exists $cdnh->{hypnotoad} ) {
$cdnh->{hypnotoad}{listen} = [$listen_str];
}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/84a4b129/traffic_ops/install/lib/GenerateCert.pm
----------------------------------------------------------------------
diff --git a/traffic_ops/install/lib/GenerateCert.pm b/traffic_ops/install/lib/GenerateCert.pm
index 8c2c888..1752aa8 100644
--- a/traffic_ops/install/lib/GenerateCert.pm
+++ b/traffic_ops/install/lib/GenerateCert.pm
@@ -43,11 +43,19 @@ EOF
sub writeCdn_conf {
my $cdn_conf = shift;
- # listen param to be inserted
- my $listen_str = "https://[::]:443?cert=${cert}&key=${key}&ca=${ca}&verify=0x00&ciphers=AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL:!EDH:!ED";
# load as perl hash to find string to be replaced
my $cdnh = do $cdn_conf;
+
+ # get existing port, if any
+ my $listen = $cdnh->{hypnotoad}{listen}[0];
+ my ($port) = $listen =~ /:(\d+)/;
+ if (!defined($port)) {
+ $port = 60443;
+ }
+ # listen param to be inserted
+ my $listen_str = "https://[::]:${port}?cert=${cert}&key=${key}&ca=${ca}&verify=0x00&ciphers=AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL:!EDH:!ED";
+
if ( exists $cdnh->{hypnotoad} ) {
$cdnh->{hypnotoad}{listen} = [$listen_str];
}
[18/43] incubator-trafficcontrol git commit: Move TO tocookie out of
experimental
Posted by de...@apache.org.
Move TO tocookie out of experimental
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/96edf7df
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/96edf7df
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/96edf7df
Branch: refs/heads/master
Commit: 96edf7dfb239479a55b58356a9c497647e4f4bd8
Parents: b5fa231
Author: Robert Butts <ro...@gmail.com>
Authored: Fri Jul 21 18:16:56 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/experimental/tocookie/tocookie.go | 103 ---------------------
traffic_ops/tocookie/tocookie.go | 103 +++++++++++++++++++++
traffic_ops/traffic_ops_golang/wrappers.go | 2 +-
3 files changed, 104 insertions(+), 104 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/96edf7df/traffic_ops/experimental/tocookie/tocookie.go
----------------------------------------------------------------------
diff --git a/traffic_ops/experimental/tocookie/tocookie.go b/traffic_ops/experimental/tocookie/tocookie.go
deleted file mode 100644
index 658224d..0000000
--- a/traffic_ops/experimental/tocookie/tocookie.go
+++ /dev/null
@@ -1,103 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tocookie
-
-import (
- "crypto/hmac"
- "crypto/sha1"
- "encoding/base64"
- "encoding/hex"
- "encoding/json"
- "fmt"
- "strings"
- "time"
-)
-
-const Name = "mojolicious"
-const DefaultDuration = time.Hour
-
-type Cookie struct {
- AuthData string `json:"auth_data"`
- ExpiresUnix int64 `json:"expires"`
-}
-
-func checkHmac(message, messageMAC, key []byte) bool {
- mac := hmac.New(sha1.New, key)
- mac.Write(message)
- expectedMAC := mac.Sum(nil)
- return hmac.Equal(messageMAC, expectedMAC)
-}
-
-func Parse(secret, cookie string) (*Cookie, error) {
- dashPos := strings.Index(cookie, "-")
- if dashPos == -1 {
- return nil, fmt.Errorf("malformed cookie '%s' - no dashes", cookie)
- }
-
- lastDashPos := strings.LastIndex(cookie, "-")
- if lastDashPos == -1 {
- return nil, fmt.Errorf("malformed cookie '%s' - no dashes", cookie)
- }
-
- if len(cookie) < lastDashPos+1 {
- return nil, fmt.Errorf("malformed cookie '%s' -- no signature", cookie)
- }
-
- base64Txt := cookie[:dashPos]
- txtBytes, err := base64.RawURLEncoding.DecodeString(base64Txt)
- if err != nil {
- return nil, fmt.Errorf("error decoding base64 data: %v", err)
- }
- base64TxtSig := cookie[:lastDashPos-1] // the signature signs the base64 including trailing hyphens, but the Go base64 decoder doesn't want the trailing hyphens.
-
- base64Sig := cookie[lastDashPos+1:]
- sigBytes, err := hex.DecodeString(base64Sig)
- if err != nil {
- return nil, fmt.Errorf("error decoding signature: %v", err)
- }
-
- if !checkHmac([]byte(base64TxtSig), sigBytes, []byte(secret)) {
- return nil, fmt.Errorf("bad signature")
- }
-
- cookieData := Cookie{}
- if err := json.Unmarshal(txtBytes, &cookieData); err != nil {
- return nil, fmt.Errorf("error decoding base64 text '%s' to JSON: %v", string(txtBytes), err)
- }
-
- if cookieData.ExpiresUnix-time.Now().Unix() < 0 {
- return nil, fmt.Errorf("signature expired")
- }
-
- return &cookieData, nil
-}
-
-func NewRawMsg(msg, key []byte) string {
- base64Msg := base64.RawURLEncoding.WithPadding('-').EncodeToString(msg)
- mac := hmac.New(sha1.New, []byte(key))
- mac.Write([]byte(base64Msg))
- encMac := mac.Sum(nil)
- base64Sig := hex.EncodeToString(encMac)
- return base64Msg + "--" + base64Sig
-}
-
-func New(user string, expiration time.Time, key string) string {
- cookieMsg := Cookie{AuthData: user, ExpiresUnix: expiration.Unix()}
- msg, _ := json.Marshal(cookieMsg)
- return NewRawMsg(msg, []byte(key))
-}
-
-// Update takes an existing cookie and returns a new serialized cookie with an updated expiration
-func Refresh(c *Cookie, key string) string {
- return New(c.AuthData, time.Now().Add(DefaultDuration), key)
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/96edf7df/traffic_ops/tocookie/tocookie.go
----------------------------------------------------------------------
diff --git a/traffic_ops/tocookie/tocookie.go b/traffic_ops/tocookie/tocookie.go
new file mode 100644
index 0000000..658224d
--- /dev/null
+++ b/traffic_ops/tocookie/tocookie.go
@@ -0,0 +1,103 @@
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package tocookie
+
+import (
+ "crypto/hmac"
+ "crypto/sha1"
+ "encoding/base64"
+ "encoding/hex"
+ "encoding/json"
+ "fmt"
+ "strings"
+ "time"
+)
+
+const Name = "mojolicious"
+const DefaultDuration = time.Hour
+
+type Cookie struct {
+ AuthData string `json:"auth_data"`
+ ExpiresUnix int64 `json:"expires"`
+}
+
+func checkHmac(message, messageMAC, key []byte) bool {
+ mac := hmac.New(sha1.New, key)
+ mac.Write(message)
+ expectedMAC := mac.Sum(nil)
+ return hmac.Equal(messageMAC, expectedMAC)
+}
+
+func Parse(secret, cookie string) (*Cookie, error) {
+ dashPos := strings.Index(cookie, "-")
+ if dashPos == -1 {
+ return nil, fmt.Errorf("malformed cookie '%s' - no dashes", cookie)
+ }
+
+ lastDashPos := strings.LastIndex(cookie, "-")
+ if lastDashPos == -1 {
+ return nil, fmt.Errorf("malformed cookie '%s' - no dashes", cookie)
+ }
+
+ if len(cookie) < lastDashPos+1 {
+ return nil, fmt.Errorf("malformed cookie '%s' -- no signature", cookie)
+ }
+
+ base64Txt := cookie[:dashPos]
+ txtBytes, err := base64.RawURLEncoding.DecodeString(base64Txt)
+ if err != nil {
+ return nil, fmt.Errorf("error decoding base64 data: %v", err)
+ }
+ base64TxtSig := cookie[:lastDashPos-1] // the signature signs the base64 including trailing hyphens, but the Go base64 decoder doesn't want the trailing hyphens.
+
+ base64Sig := cookie[lastDashPos+1:]
+ sigBytes, err := hex.DecodeString(base64Sig)
+ if err != nil {
+ return nil, fmt.Errorf("error decoding signature: %v", err)
+ }
+
+ if !checkHmac([]byte(base64TxtSig), sigBytes, []byte(secret)) {
+ return nil, fmt.Errorf("bad signature")
+ }
+
+ cookieData := Cookie{}
+ if err := json.Unmarshal(txtBytes, &cookieData); err != nil {
+ return nil, fmt.Errorf("error decoding base64 text '%s' to JSON: %v", string(txtBytes), err)
+ }
+
+ if cookieData.ExpiresUnix-time.Now().Unix() < 0 {
+ return nil, fmt.Errorf("signature expired")
+ }
+
+ return &cookieData, nil
+}
+
+func NewRawMsg(msg, key []byte) string {
+ base64Msg := base64.RawURLEncoding.WithPadding('-').EncodeToString(msg)
+ mac := hmac.New(sha1.New, []byte(key))
+ mac.Write([]byte(base64Msg))
+ encMac := mac.Sum(nil)
+ base64Sig := hex.EncodeToString(encMac)
+ return base64Msg + "--" + base64Sig
+}
+
+func New(user string, expiration time.Time, key string) string {
+ cookieMsg := Cookie{AuthData: user, ExpiresUnix: expiration.Unix()}
+ msg, _ := json.Marshal(cookieMsg)
+ return NewRawMsg(msg, []byte(key))
+}
+
+// Update takes an existing cookie and returns a new serialized cookie with an updated expiration
+func Refresh(c *Cookie, key string) string {
+ return New(c.AuthData, time.Now().Add(DefaultDuration), key)
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/96edf7df/traffic_ops/traffic_ops_golang/wrappers.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/wrappers.go b/traffic_ops/traffic_ops_golang/wrappers.go
index 30c36b4..c6eb8cf 100644
--- a/traffic_ops/traffic_ops_golang/wrappers.go
+++ b/traffic_ops/traffic_ops_golang/wrappers.go
@@ -23,7 +23,7 @@ import (
"database/sql"
"fmt"
"github.com/apache/incubator-trafficcontrol/traffic_monitor_golang/common/log"
- "github.com/apache/incubator-trafficcontrol/traffic_ops/experimental/tocookie"
+ "github.com/apache/incubator-trafficcontrol/traffic_ops/tocookie"
"net/http"
"time"
)
[03/43] incubator-trafficcontrol git commit: Vendor TO GOlang
go-sqlmock
Posted by de...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock.go
new file mode 100644
index 0000000..b906a3f
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock.go
@@ -0,0 +1,525 @@
+/*
+Package sqlmock is a mock library implementing sql driver. Which has one and only
+purpose - to simulate any sql driver behavior in tests, without needing a real
+database connection. It helps to maintain correct **TDD** workflow.
+
+It does not require any modifications to your source code in order to test
+and mock database operations. Supports concurrency and multiple database mocking.
+
+The driver allows to mock any sql driver method behavior.
+*/
+package sqlmock
+
+import (
+ "database/sql"
+ "database/sql/driver"
+ "fmt"
+ "regexp"
+ "time"
+)
+
+// Sqlmock interface serves to create expectations
+// for any kind of database action in order to mock
+// and test real database behavior.
+type Sqlmock interface {
+
+ // ExpectClose queues an expectation for this database
+ // action to be triggered. the *ExpectedClose allows
+ // to mock database response
+ ExpectClose() *ExpectedClose
+
+ // ExpectationsWereMet checks whether all queued expectations
+ // were met in order. If any of them was not met - an error is returned.
+ ExpectationsWereMet() error
+
+ // ExpectPrepare expects Prepare() to be called with sql query
+ // which match sqlRegexStr given regexp.
+ // the *ExpectedPrepare allows to mock database response.
+ // Note that you may expect Query() or Exec() on the *ExpectedPrepare
+ // statement to prevent repeating sqlRegexStr
+ ExpectPrepare(sqlRegexStr string) *ExpectedPrepare
+
+ // ExpectQuery expects Query() or QueryRow() to be called with sql query
+ // which match sqlRegexStr given regexp.
+ // the *ExpectedQuery allows to mock database response.
+ ExpectQuery(sqlRegexStr string) *ExpectedQuery
+
+ // ExpectExec expects Exec() to be called with sql query
+ // which match sqlRegexStr given regexp.
+ // the *ExpectedExec allows to mock database response
+ ExpectExec(sqlRegexStr string) *ExpectedExec
+
+ // ExpectBegin expects *sql.DB.Begin to be called.
+ // the *ExpectedBegin allows to mock database response
+ ExpectBegin() *ExpectedBegin
+
+ // ExpectCommit expects *sql.Tx.Commit to be called.
+ // the *ExpectedCommit allows to mock database response
+ ExpectCommit() *ExpectedCommit
+
+ // ExpectRollback expects *sql.Tx.Rollback to be called.
+ // the *ExpectedRollback allows to mock database response
+ ExpectRollback() *ExpectedRollback
+
+ // MatchExpectationsInOrder gives an option whether to match all
+ // expectations in the order they were set or not.
+ //
+ // By default it is set to - true. But if you use goroutines
+ // to parallelize your query executation, that option may
+ // be handy.
+ //
+ // This option may be turned on anytime during tests. As soon
+ // as it is switched to false, expectations will be matched
+ // in any order. Or otherwise if switched to true, any unmatched
+ // expectations will be expected in order
+ MatchExpectationsInOrder(bool)
+}
+
+type sqlmock struct {
+ ordered bool
+ dsn string
+ opened int
+ drv *mockDriver
+
+ expected []expectation
+}
+
+func (c *sqlmock) open() (*sql.DB, Sqlmock, error) {
+ db, err := sql.Open("sqlmock", c.dsn)
+ if err != nil {
+ return db, c, err
+ }
+ return db, c, db.Ping()
+}
+
+func (c *sqlmock) ExpectClose() *ExpectedClose {
+ e := &ExpectedClose{}
+ c.expected = append(c.expected, e)
+ return e
+}
+
+func (c *sqlmock) MatchExpectationsInOrder(b bool) {
+ c.ordered = b
+}
+
+// Close a mock database driver connection. It may or may not
+// be called depending on the sircumstances, but if it is called
+// there must be an *ExpectedClose expectation satisfied.
+// meets http://golang.org/pkg/database/sql/driver/#Conn interface
+func (c *sqlmock) Close() error {
+ c.drv.Lock()
+ defer c.drv.Unlock()
+
+ c.opened--
+ if c.opened == 0 {
+ delete(c.drv.conns, c.dsn)
+ }
+
+ var expected *ExpectedClose
+ var fulfilled int
+ var ok bool
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if expected, ok = next.(*ExpectedClose); ok {
+ break
+ }
+
+ next.Unlock()
+ if c.ordered {
+ return fmt.Errorf("call to database Close, was not expected, next expectation is: %s", next)
+ }
+ }
+
+ if expected == nil {
+ msg := "call to database Close was not expected"
+ if fulfilled == len(c.expected) {
+ msg = "all expectations were already fulfilled, " + msg
+ }
+ return fmt.Errorf(msg)
+ }
+
+ expected.triggered = true
+ expected.Unlock()
+ return expected.err
+}
+
+func (c *sqlmock) ExpectationsWereMet() error {
+ for _, e := range c.expected {
+ if !e.fulfilled() {
+ return fmt.Errorf("there is a remaining expectation which was not matched: %s", e)
+ }
+ }
+ return nil
+}
+
+// Begin meets http://golang.org/pkg/database/sql/driver/#Conn interface
+func (c *sqlmock) Begin() (driver.Tx, error) {
+ ex, err := c.begin()
+ if err != nil {
+ return nil, err
+ }
+
+ time.Sleep(ex.delay)
+ return c, nil
+}
+
+func (c *sqlmock) begin() (*ExpectedBegin, error) {
+ var expected *ExpectedBegin
+ var ok bool
+ var fulfilled int
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if expected, ok = next.(*ExpectedBegin); ok {
+ break
+ }
+
+ next.Unlock()
+ if c.ordered {
+ return nil, fmt.Errorf("call to database transaction Begin, was not expected, next expectation is: %s", next)
+ }
+ }
+ if expected == nil {
+ msg := "call to database transaction Begin was not expected"
+ if fulfilled == len(c.expected) {
+ msg = "all expectations were already fulfilled, " + msg
+ }
+ return nil, fmt.Errorf(msg)
+ }
+
+ expected.triggered = true
+ expected.Unlock()
+
+ return expected, expected.err
+}
+
+func (c *sqlmock) ExpectBegin() *ExpectedBegin {
+ e := &ExpectedBegin{}
+ c.expected = append(c.expected, e)
+ return e
+}
+
+// Exec meets http://golang.org/pkg/database/sql/driver/#Execer
+func (c *sqlmock) Exec(query string, args []driver.Value) (driver.Result, error) {
+ namedArgs := make([]namedValue, len(args))
+ for i, v := range args {
+ namedArgs[i] = namedValue{
+ Ordinal: i + 1,
+ Value: v,
+ }
+ }
+
+ ex, err := c.exec(query, namedArgs)
+ if err != nil {
+ return nil, err
+ }
+
+ time.Sleep(ex.delay)
+ return ex.result, nil
+}
+
+func (c *sqlmock) exec(query string, args []namedValue) (*ExpectedExec, error) {
+ query = stripQuery(query)
+ var expected *ExpectedExec
+ var fulfilled int
+ var ok bool
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if c.ordered {
+ if expected, ok = next.(*ExpectedExec); ok {
+ break
+ }
+ next.Unlock()
+ return nil, fmt.Errorf("call to exec query '%s' with args %+v, was not expected, next expectation is: %s", query, args, next)
+ }
+ if exec, ok := next.(*ExpectedExec); ok {
+ if err := exec.attemptMatch(query, args); err == nil {
+ expected = exec
+ break
+ }
+ }
+ next.Unlock()
+ }
+ if expected == nil {
+ msg := "call to exec '%s' query with args %+v was not expected"
+ if fulfilled == len(c.expected) {
+ msg = "all expectations were already fulfilled, " + msg
+ }
+ return nil, fmt.Errorf(msg, query, args)
+ }
+ defer expected.Unlock()
+
+ if !expected.queryMatches(query) {
+ return nil, fmt.Errorf("exec query '%s', does not match regex '%s'", query, expected.sqlRegex.String())
+ }
+
+ if err := expected.argsMatches(args); err != nil {
+ return nil, fmt.Errorf("exec query '%s', arguments do not match: %s", query, err)
+ }
+
+ expected.triggered = true
+ if expected.err != nil {
+ return nil, expected.err // mocked to return error
+ }
+
+ if expected.result == nil {
+ return nil, fmt.Errorf("exec query '%s' with args %+v, must return a database/sql/driver.result, but it was not set for expectation %T as %+v", query, args, expected, expected)
+ }
+
+ return expected, nil
+}
+
+func (c *sqlmock) ExpectExec(sqlRegexStr string) *ExpectedExec {
+ e := &ExpectedExec{}
+ sqlRegexStr = stripQuery(sqlRegexStr)
+ e.sqlRegex = regexp.MustCompile(sqlRegexStr)
+ c.expected = append(c.expected, e)
+ return e
+}
+
+// Prepare meets http://golang.org/pkg/database/sql/driver/#Conn interface
+func (c *sqlmock) Prepare(query string) (driver.Stmt, error) {
+ ex, err := c.prepare(query)
+ if err != nil {
+ return nil, err
+ }
+
+ time.Sleep(ex.delay)
+ return &statement{c, query, ex.closeErr}, nil
+}
+
+func (c *sqlmock) prepare(query string) (*ExpectedPrepare, error) {
+ var expected *ExpectedPrepare
+ var fulfilled int
+ var ok bool
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if expected, ok = next.(*ExpectedPrepare); ok {
+ break
+ }
+
+ next.Unlock()
+ if c.ordered {
+ return nil, fmt.Errorf("call to Prepare statement with query '%s', was not expected, next expectation is: %s", query, next)
+ }
+ }
+
+ query = stripQuery(query)
+ if expected == nil {
+ msg := "call to Prepare '%s' query was not expected"
+ if fulfilled == len(c.expected) {
+ msg = "all expectations were already fulfilled, " + msg
+ }
+ return nil, fmt.Errorf(msg, query)
+ }
+ defer expected.Unlock()
+ if !expected.sqlRegex.MatchString(query) {
+ return nil, fmt.Errorf("query '%s', does not match regex [%s]", query, expected.sqlRegex.String())
+ }
+
+ expected.triggered = true
+ return expected, expected.err
+}
+
+func (c *sqlmock) ExpectPrepare(sqlRegexStr string) *ExpectedPrepare {
+ sqlRegexStr = stripQuery(sqlRegexStr)
+ e := &ExpectedPrepare{sqlRegex: regexp.MustCompile(sqlRegexStr), mock: c}
+ c.expected = append(c.expected, e)
+ return e
+}
+
+type namedValue struct {
+ Name string
+ Ordinal int
+ Value driver.Value
+}
+
+// Query meets http://golang.org/pkg/database/sql/driver/#Queryer
+func (c *sqlmock) Query(query string, args []driver.Value) (driver.Rows, error) {
+ namedArgs := make([]namedValue, len(args))
+ for i, v := range args {
+ namedArgs[i] = namedValue{
+ Ordinal: i + 1,
+ Value: v,
+ }
+ }
+
+ ex, err := c.query(query, namedArgs)
+ if err != nil {
+ return nil, err
+ }
+
+ time.Sleep(ex.delay)
+ return ex.rows, nil
+}
+
+func (c *sqlmock) query(query string, args []namedValue) (*ExpectedQuery, error) {
+ query = stripQuery(query)
+ var expected *ExpectedQuery
+ var fulfilled int
+ var ok bool
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if c.ordered {
+ if expected, ok = next.(*ExpectedQuery); ok {
+ break
+ }
+ next.Unlock()
+ return nil, fmt.Errorf("call to query '%s' with args %+v, was not expected, next expectation is: %s", query, args, next)
+ }
+ if qr, ok := next.(*ExpectedQuery); ok {
+ if err := qr.attemptMatch(query, args); err == nil {
+ expected = qr
+ break
+ }
+ }
+ next.Unlock()
+ }
+
+ if expected == nil {
+ msg := "call to query '%s' with args %+v was not expected"
+ if fulfilled == len(c.expected) {
+ msg = "all expectations were already fulfilled, " + msg
+ }
+ return nil, fmt.Errorf(msg, query, args)
+ }
+
+ defer expected.Unlock()
+
+ if !expected.queryMatches(query) {
+ return nil, fmt.Errorf("query '%s', does not match regex [%s]", query, expected.sqlRegex.String())
+ }
+
+ if err := expected.argsMatches(args); err != nil {
+ return nil, fmt.Errorf("exec query '%s', arguments do not match: %s", query, err)
+ }
+
+ expected.triggered = true
+ if expected.err != nil {
+ return nil, expected.err // mocked to return error
+ }
+
+ if expected.rows == nil {
+ return nil, fmt.Errorf("query '%s' with args %+v, must return a database/sql/driver.rows, but it was not set for expectation %T as %+v", query, args, expected, expected)
+ }
+ return expected, nil
+}
+
+func (c *sqlmock) ExpectQuery(sqlRegexStr string) *ExpectedQuery {
+ e := &ExpectedQuery{}
+ sqlRegexStr = stripQuery(sqlRegexStr)
+ e.sqlRegex = regexp.MustCompile(sqlRegexStr)
+ c.expected = append(c.expected, e)
+ return e
+}
+
+func (c *sqlmock) ExpectCommit() *ExpectedCommit {
+ e := &ExpectedCommit{}
+ c.expected = append(c.expected, e)
+ return e
+}
+
+func (c *sqlmock) ExpectRollback() *ExpectedRollback {
+ e := &ExpectedRollback{}
+ c.expected = append(c.expected, e)
+ return e
+}
+
+// Commit meets http://golang.org/pkg/database/sql/driver/#Tx
+func (c *sqlmock) Commit() error {
+ var expected *ExpectedCommit
+ var fulfilled int
+ var ok bool
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if expected, ok = next.(*ExpectedCommit); ok {
+ break
+ }
+
+ next.Unlock()
+ if c.ordered {
+ return fmt.Errorf("call to commit transaction, was not expected, next expectation is: %s", next)
+ }
+ }
+ if expected == nil {
+ msg := "call to commit transaction was not expected"
+ if fulfilled == len(c.expected) {
+ msg = "all expectations were already fulfilled, " + msg
+ }
+ return fmt.Errorf(msg)
+ }
+
+ expected.triggered = true
+ expected.Unlock()
+ return expected.err
+}
+
+// Rollback meets http://golang.org/pkg/database/sql/driver/#Tx
+func (c *sqlmock) Rollback() error {
+ var expected *ExpectedRollback
+ var fulfilled int
+ var ok bool
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if expected, ok = next.(*ExpectedRollback); ok {
+ break
+ }
+
+ next.Unlock()
+ if c.ordered {
+ return fmt.Errorf("call to rollback transaction, was not expected, next expectation is: %s", next)
+ }
+ }
+ if expected == nil {
+ msg := "call to rollback transaction was not expected"
+ if fulfilled == len(c.expected) {
+ msg = "all expectations were already fulfilled, " + msg
+ }
+ return fmt.Errorf(msg)
+ }
+
+ expected.triggered = true
+ expected.Unlock()
+ return expected.err
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18.go
new file mode 100644
index 0000000..c49429c
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18.go
@@ -0,0 +1,101 @@
+// +build go1.8
+
+package sqlmock
+
+import (
+ "context"
+ "database/sql/driver"
+ "errors"
+ "time"
+)
+
+var ErrCancelled = errors.New("canceling query due to user request")
+
+// Implement the "QueryerContext" interface
+func (c *sqlmock) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
+ namedArgs := make([]namedValue, len(args))
+ for i, nv := range args {
+ namedArgs[i] = namedValue(nv)
+ }
+
+ ex, err := c.query(query, namedArgs)
+ if err != nil {
+ return nil, err
+ }
+
+ select {
+ case <-time.After(ex.delay):
+ return ex.rows, nil
+ case <-ctx.Done():
+ return nil, ErrCancelled
+ }
+}
+
+// Implement the "ExecerContext" interface
+func (c *sqlmock) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
+ namedArgs := make([]namedValue, len(args))
+ for i, nv := range args {
+ namedArgs[i] = namedValue(nv)
+ }
+
+ ex, err := c.exec(query, namedArgs)
+ if err != nil {
+ return nil, err
+ }
+
+ select {
+ case <-time.After(ex.delay):
+ return ex.result, nil
+ case <-ctx.Done():
+ return nil, ErrCancelled
+ }
+}
+
+// Implement the "ConnBeginTx" interface
+func (c *sqlmock) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
+ ex, err := c.begin()
+ if err != nil {
+ return nil, err
+ }
+
+ select {
+ case <-time.After(ex.delay):
+ return c, nil
+ case <-ctx.Done():
+ return nil, ErrCancelled
+ }
+}
+
+// Implement the "ConnPrepareContext" interface
+func (c *sqlmock) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
+ ex, err := c.prepare(query)
+ if err != nil {
+ return nil, err
+ }
+
+ select {
+ case <-time.After(ex.delay):
+ return &statement{c, query, ex.closeErr}, nil
+ case <-ctx.Done():
+ return nil, ErrCancelled
+ }
+}
+
+// Implement the "Pinger" interface
+// for now we do not have a Ping expectation
+// may be something for the future
+func (c *sqlmock) Ping(ctx context.Context) error {
+ return nil
+}
+
+// Implement the "StmtExecContext" interface
+func (stmt *statement) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
+ return stmt.conn.ExecContext(ctx, stmt.query, args)
+}
+
+// Implement the "StmtQueryContext" interface
+func (stmt *statement) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
+ return stmt.conn.QueryContext(ctx, stmt.query, args)
+}
+
+// @TODO maybe add ExpectedBegin.WithOptions(driver.TxOptions)
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18_test.go
new file mode 100644
index 0000000..9eadcb5
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18_test.go
@@ -0,0 +1,426 @@
+// +build go1.8
+
+package sqlmock
+
+import (
+ "context"
+ "database/sql"
+ "testing"
+ "time"
+)
+
+func TestContextExecCancel(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectExec("DELETE FROM users").
+ WillDelayFor(time.Second).
+ WillReturnResult(NewResult(1, 1))
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ _, err = db.ExecContext(ctx, "DELETE FROM users")
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = db.ExecContext(ctx, "DELETE FROM users")
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestPreparedStatementContextExecCancel(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectPrepare("DELETE FROM users").
+ ExpectExec().
+ WillDelayFor(time.Second).
+ WillReturnResult(NewResult(1, 1))
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ stmt, err := db.Prepare("DELETE FROM users")
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ _, err = stmt.ExecContext(ctx)
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = stmt.ExecContext(ctx)
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextExecWithNamedArg(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectExec("DELETE FROM users").
+ WithArgs(sql.Named("id", 5)).
+ WillDelayFor(time.Second).
+ WillReturnResult(NewResult(1, 1))
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ _, err = db.ExecContext(ctx, "DELETE FROM users WHERE id = :id", sql.Named("id", 5))
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = db.ExecContext(ctx, "DELETE FROM users WHERE id = :id", sql.Named("id", 5))
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextExec(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectExec("DELETE FROM users").
+ WillReturnResult(NewResult(1, 1))
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ res, err := db.ExecContext(ctx, "DELETE FROM users")
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ affected, err := res.RowsAffected()
+ if affected != 1 {
+ t.Errorf("expected affected rows 1, but got %v", affected)
+ }
+
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextQueryCancel(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs := NewRows([]string{"id", "title"}).AddRow(5, "hello world")
+
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+ WithArgs(5).
+ WillDelayFor(time.Second).
+ WillReturnRows(rs)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ _, err = db.QueryContext(ctx, "SELECT id, title FROM articles WHERE id = ?", 5)
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = db.QueryContext(ctx, "SELECT id, title FROM articles WHERE id = ?", 5)
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestPreparedStatementContextQueryCancel(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs := NewRows([]string{"id", "title"}).AddRow(5, "hello world")
+
+ mock.ExpectPrepare("SELECT (.+) FROM articles WHERE id = ?").
+ ExpectQuery().
+ WithArgs(5).
+ WillDelayFor(time.Second).
+ WillReturnRows(rs)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ stmt, err := db.Prepare("SELECT id, title FROM articles WHERE id = ?")
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ _, err = stmt.QueryContext(ctx, 5)
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = stmt.QueryContext(ctx, 5)
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextQuery(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs := NewRows([]string{"id", "title"}).AddRow(5, "hello world")
+
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id =").
+ WithArgs(sql.Named("id", 5)).
+ WillDelayFor(time.Millisecond * 3).
+ WillReturnRows(rs)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ rows, err := db.QueryContext(ctx, "SELECT id, title FROM articles WHERE id = :id", sql.Named("id", 5))
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if !rows.Next() {
+ t.Error("expected one row, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextBeginCancel(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectBegin().WillDelayFor(time.Second)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ _, err = db.BeginTx(ctx, nil)
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = db.BeginTx(ctx, nil)
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextBegin(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectBegin().WillDelayFor(time.Millisecond * 3)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ tx, err := db.BeginTx(ctx, nil)
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if tx == nil {
+ t.Error("expected tx, but there was nil")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextPrepareCancel(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectPrepare("SELECT").WillDelayFor(time.Second)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ _, err = db.PrepareContext(ctx, "SELECT")
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = db.PrepareContext(ctx, "SELECT")
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextPrepare(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectPrepare("SELECT").WillDelayFor(time.Millisecond * 3)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ stmt, err := db.PrepareContext(ctx, "SELECT")
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if stmt == nil {
+ t.Error("expected stmt, but there was nil")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_test.go
new file mode 100644
index 0000000..fe4924b
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_test.go
@@ -0,0 +1,998 @@
+package sqlmock
+
+import (
+ "database/sql"
+ "fmt"
+ "strconv"
+ "sync"
+ "testing"
+ "time"
+)
+
+func cancelOrder(db *sql.DB, orderID int) error {
+ tx, _ := db.Begin()
+ _, _ = tx.Query("SELECT * FROM orders {0} FOR UPDATE", orderID)
+ err := tx.Rollback()
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func Example() {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ // columns to be used for result
+ columns := []string{"id", "status"}
+ // expect transaction begin
+ mock.ExpectBegin()
+ // expect query to fetch order, match it with regexp
+ mock.ExpectQuery("SELECT (.+) FROM orders (.+) FOR UPDATE").
+ WithArgs(1).
+ WillReturnRows(NewRows(columns).AddRow(1, 1))
+ // expect transaction rollback, since order status is "cancelled"
+ mock.ExpectRollback()
+
+ // run the cancel order function
+ someOrderID := 1
+ // call a function which executes expected database operations
+ err = cancelOrder(db, someOrderID)
+ if err != nil {
+ fmt.Printf("unexpected error: %s", err)
+ return
+ }
+
+ // ensure all expectations have been met
+ if err = mock.ExpectationsWereMet(); err != nil {
+ fmt.Printf("unmet expectation error: %s", err)
+ }
+ // Output:
+}
+
+func TestIssue14EscapeSQL(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+ mock.ExpectExec("INSERT INTO mytable\\(a, b\\)").
+ WithArgs("A", "B").
+ WillReturnResult(NewResult(1, 1))
+
+ _, err = db.Exec("INSERT INTO mytable(a, b) VALUES (?, ?)", "A", "B")
+ if err != nil {
+ t.Errorf("error '%s' was not expected, while inserting a row", err)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+// test the case when db is not triggered and expectations
+// are not asserted on close
+func TestIssue4(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectQuery("some sql query which will not be called").
+ WillReturnRows(NewRows([]string{"id"}))
+
+ if err := mock.ExpectationsWereMet(); err == nil {
+ t.Errorf("was expecting an error since query was not triggered")
+ }
+}
+
+func TestMockQuery(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs := NewRows([]string{"id", "title"}).FromCSVString("5,hello world")
+
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+ WithArgs(5).
+ WillReturnRows(rs)
+
+ rows, err := db.Query("SELECT (.+) FROM articles WHERE id = ?", 5)
+ if err != nil {
+ t.Errorf("error '%s' was not expected while retrieving mock rows", err)
+ }
+
+ defer func() {
+ if er := rows.Close(); er != nil {
+ t.Error("Unexpected error while trying to close rows")
+ }
+ }()
+
+ if !rows.Next() {
+ t.Error("it must have had one row as result, but got empty result set instead")
+ }
+
+ var id int
+ var title string
+
+ err = rows.Scan(&id, &title)
+ if err != nil {
+ t.Errorf("error '%s' was not expected while trying to scan row", err)
+ }
+
+ if id != 5 {
+ t.Errorf("expected mocked id to be 5, but got %d instead", id)
+ }
+
+ if title != "hello world" {
+ t.Errorf("expected mocked title to be 'hello world', but got '%s' instead", title)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestMockQueryTypes(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ columns := []string{"id", "timestamp", "sold"}
+
+ timestamp := time.Now()
+ rs := NewRows(columns)
+ rs.AddRow(5, timestamp, true)
+
+ mock.ExpectQuery("SELECT (.+) FROM sales WHERE id = ?").
+ WithArgs(5).
+ WillReturnRows(rs)
+
+ rows, err := db.Query("SELECT (.+) FROM sales WHERE id = ?", 5)
+ if err != nil {
+ t.Errorf("error '%s' was not expected while retrieving mock rows", err)
+ }
+ defer func() {
+ if er := rows.Close(); er != nil {
+ t.Error("Unexpected error while trying to close rows")
+ }
+ }()
+ if !rows.Next() {
+ t.Error("it must have had one row as result, but got empty result set instead")
+ }
+
+ var id int
+ var time time.Time
+ var sold bool
+
+ err = rows.Scan(&id, &time, &sold)
+ if err != nil {
+ t.Errorf("error '%s' was not expected while trying to scan row", err)
+ }
+
+ if id != 5 {
+ t.Errorf("expected mocked id to be 5, but got %d instead", id)
+ }
+
+ if time != timestamp {
+ t.Errorf("expected mocked time to be %s, but got '%s' instead", timestamp, time)
+ }
+
+ if sold != true {
+ t.Errorf("expected mocked boolean to be true, but got %v instead", sold)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestTransactionExpectations(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ // begin and commit
+ mock.ExpectBegin()
+ mock.ExpectCommit()
+
+ tx, err := db.Begin()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when beginning a transaction", err)
+ }
+
+ err = tx.Commit()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when committing a transaction", err)
+ }
+
+ // begin and rollback
+ mock.ExpectBegin()
+ mock.ExpectRollback()
+
+ tx, err = db.Begin()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when beginning a transaction", err)
+ }
+
+ err = tx.Rollback()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when rolling back a transaction", err)
+ }
+
+ // begin with an error
+ mock.ExpectBegin().WillReturnError(fmt.Errorf("some err"))
+
+ tx, err = db.Begin()
+ if err == nil {
+ t.Error("an error was expected when beginning a transaction, but got none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestPrepareExpectations(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectPrepare("SELECT (.+) FROM articles WHERE id = ?")
+
+ stmt, err := db.Prepare("SELECT (.+) FROM articles WHERE id = ?")
+ if err != nil {
+ t.Errorf("error '%s' was not expected while creating a prepared statement", err)
+ }
+ if stmt == nil {
+ t.Errorf("stmt was expected while creating a prepared statement")
+ }
+
+ // expect something else, w/o ExpectPrepare()
+ var id int
+ var title string
+ rs := NewRows([]string{"id", "title"}).FromCSVString("5,hello world")
+
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+ WithArgs(5).
+ WillReturnRows(rs)
+
+ err = stmt.QueryRow(5).Scan(&id, &title)
+ if err != nil {
+ t.Errorf("error '%s' was not expected while retrieving mock rows", err)
+ }
+
+ mock.ExpectPrepare("SELECT (.+) FROM articles WHERE id = ?").
+ WillReturnError(fmt.Errorf("Some DB error occurred"))
+
+ stmt, err = db.Prepare("SELECT id FROM articles WHERE id = ?")
+ if err == nil {
+ t.Error("error was expected while creating a prepared statement")
+ }
+ if stmt != nil {
+ t.Errorf("stmt was not expected while creating a prepared statement returning error")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestPreparedQueryExecutions(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectPrepare("SELECT (.+) FROM articles WHERE id = ?")
+
+ rs1 := NewRows([]string{"id", "title"}).FromCSVString("5,hello world")
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+ WithArgs(5).
+ WillReturnRows(rs1)
+
+ rs2 := NewRows([]string{"id", "title"}).FromCSVString("2,whoop")
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+ WithArgs(2).
+ WillReturnRows(rs2)
+
+ stmt, err := db.Prepare("SELECT id, title FROM articles WHERE id = ?")
+ if err != nil {
+ t.Errorf("error '%s' was not expected while creating a prepared statement", err)
+ }
+
+ var id int
+ var title string
+ err = stmt.QueryRow(5).Scan(&id, &title)
+ if err != nil {
+ t.Errorf("error '%s' was not expected querying row from statement and scanning", err)
+ }
+
+ if id != 5 {
+ t.Errorf("expected mocked id to be 5, but got %d instead", id)
+ }
+
+ if title != "hello world" {
+ t.Errorf("expected mocked title to be 'hello world', but got '%s' instead", title)
+ }
+
+ err = stmt.QueryRow(2).Scan(&id, &title)
+ if err != nil {
+ t.Errorf("error '%s' was not expected querying row from statement and scanning", err)
+ }
+
+ if id != 2 {
+ t.Errorf("expected mocked id to be 2, but got %d instead", id)
+ }
+
+ if title != "whoop" {
+ t.Errorf("expected mocked title to be 'whoop', but got '%s' instead", title)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestUnexpectedOperations(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectPrepare("SELECT (.+) FROM articles WHERE id = ?")
+ stmt, err := db.Prepare("SELECT id, title FROM articles WHERE id = ?")
+ if err != nil {
+ t.Errorf("error '%s' was not expected while creating a prepared statement", err)
+ }
+
+ var id int
+ var title string
+
+ err = stmt.QueryRow(5).Scan(&id, &title)
+ if err == nil {
+ t.Error("error was expected querying row, since there was no such expectation")
+ }
+
+ mock.ExpectRollback()
+
+ if err := mock.ExpectationsWereMet(); err == nil {
+ t.Errorf("was expecting an error since query was not triggered")
+ }
+}
+
+func TestWrongExpectations(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectBegin()
+
+ rs1 := NewRows([]string{"id", "title"}).FromCSVString("5,hello world")
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+ WithArgs(5).
+ WillReturnRows(rs1)
+
+ mock.ExpectCommit().WillReturnError(fmt.Errorf("deadlock occurred"))
+ mock.ExpectRollback() // won't be triggered
+
+ var id int
+ var title string
+
+ err = db.QueryRow("SELECT id, title FROM articles WHERE id = ? FOR UPDATE", 5).Scan(&id, &title)
+ if err == nil {
+ t.Error("error was expected while querying row, since there begin transaction expectation is not fulfilled")
+ }
+
+ // lets go around and start transaction
+ tx, err := db.Begin()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when beginning a transaction", err)
+ }
+
+ err = db.QueryRow("SELECT id, title FROM articles WHERE id = ? FOR UPDATE", 5).Scan(&id, &title)
+ if err != nil {
+ t.Errorf("error '%s' was not expected while querying row, since transaction was started", err)
+ }
+
+ err = tx.Commit()
+ if err == nil {
+ t.Error("a deadlock error was expected when committing a transaction", err)
+ }
+
+ if err := mock.ExpectationsWereMet(); err == nil {
+ t.Errorf("was expecting an error since query was not triggered")
+ }
+}
+
+func TestExecExpectations(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ result := NewResult(1, 1)
+ mock.ExpectExec("^INSERT INTO articles").
+ WithArgs("hello").
+ WillReturnResult(result)
+
+ res, err := db.Exec("INSERT INTO articles (title) VALUES (?)", "hello")
+ if err != nil {
+ t.Errorf("error '%s' was not expected, while inserting a row", err)
+ }
+
+ id, err := res.LastInsertId()
+ if err != nil {
+ t.Errorf("error '%s' was not expected, while getting a last insert id", err)
+ }
+
+ affected, err := res.RowsAffected()
+ if err != nil {
+ t.Errorf("error '%s' was not expected, while getting affected rows", err)
+ }
+
+ if id != 1 {
+ t.Errorf("expected last insert id to be 1, but got %d instead", id)
+ }
+
+ if affected != 1 {
+ t.Errorf("expected affected rows to be 1, but got %d instead", affected)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestRowBuilderAndNilTypes(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs := NewRows([]string{"id", "active", "created", "status"}).
+ AddRow(1, true, time.Now(), 5).
+ AddRow(2, false, nil, nil)
+
+ mock.ExpectQuery("SELECT (.+) FROM sales").WillReturnRows(rs)
+
+ rows, err := db.Query("SELECT * FROM sales")
+ if err != nil {
+ t.Errorf("error '%s' was not expected while retrieving mock rows", err)
+ }
+ defer func() {
+ if er := rows.Close(); er != nil {
+ t.Error("Unexpected error while trying to close rows")
+ }
+ }()
+
+ // NullTime and NullInt are used from stubs_test.go
+ var (
+ id int
+ active bool
+ created NullTime
+ status NullInt
+ )
+
+ if !rows.Next() {
+ t.Error("it must have had row in rows, but got empty result set instead")
+ }
+
+ err = rows.Scan(&id, &active, &created, &status)
+ if err != nil {
+ t.Errorf("error '%s' was not expected while trying to scan row", err)
+ }
+
+ if id != 1 {
+ t.Errorf("expected mocked id to be 1, but got %d instead", id)
+ }
+
+ if !active {
+ t.Errorf("expected 'active' to be 'true', but got '%v' instead", active)
+ }
+
+ if !created.Valid {
+ t.Errorf("expected 'created' to be valid, but it %+v is not", created)
+ }
+
+ if !status.Valid {
+ t.Errorf("expected 'status' to be valid, but it %+v is not", status)
+ }
+
+ if status.Integer != 5 {
+ t.Errorf("expected 'status' to be '5', but got '%d'", status.Integer)
+ }
+
+ // test second row
+ if !rows.Next() {
+ t.Error("it must have had row in rows, but got empty result set instead")
+ }
+
+ err = rows.Scan(&id, &active, &created, &status)
+ if err != nil {
+ t.Errorf("error '%s' was not expected while trying to scan row", err)
+ }
+
+ if id != 2 {
+ t.Errorf("expected mocked id to be 2, but got %d instead", id)
+ }
+
+ if active {
+ t.Errorf("expected 'active' to be 'false', but got '%v' instead", active)
+ }
+
+ if created.Valid {
+ t.Errorf("expected 'created' to be invalid, but it %+v is not", created)
+ }
+
+ if status.Valid {
+ t.Errorf("expected 'status' to be invalid, but it %+v is not", status)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestArgumentReflectValueTypeError(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs := NewRows([]string{"id"}).AddRow(1)
+
+ mock.ExpectQuery("SELECT (.+) FROM sales").WithArgs(5.5).WillReturnRows(rs)
+
+ _, err = db.Query("SELECT * FROM sales WHERE x = ?", 5)
+ if err == nil {
+ t.Error("Expected error, but got none")
+ }
+}
+
+func TestGoroutineExecutionWithUnorderedExpectationMatching(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ // note this line is important for unordered expectation matching
+ mock.MatchExpectationsInOrder(false)
+
+ result := NewResult(1, 1)
+
+ mock.ExpectExec("^UPDATE one").WithArgs("one").WillReturnResult(result)
+ mock.ExpectExec("^UPDATE two").WithArgs("one", "two").WillReturnResult(result)
+ mock.ExpectExec("^UPDATE three").WithArgs("one", "two", "three").WillReturnResult(result)
+
+ var wg sync.WaitGroup
+ queries := map[string][]interface{}{
+ "one": []interface{}{"one"},
+ "two": []interface{}{"one", "two"},
+ "three": []interface{}{"one", "two", "three"},
+ }
+
+ wg.Add(len(queries))
+ for table, args := range queries {
+ go func(tbl string, a []interface{}) {
+ if _, err := db.Exec("UPDATE "+tbl, a...); err != nil {
+ t.Errorf("error was not expected: %s", err)
+ }
+ wg.Done()
+ }(table, args)
+ }
+
+ wg.Wait()
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func ExampleSqlmock_goroutines() {
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("failed to open sqlmock database:", err)
+ }
+ defer db.Close()
+
+ // note this line is important for unordered expectation matching
+ mock.MatchExpectationsInOrder(false)
+
+ result := NewResult(1, 1)
+
+ mock.ExpectExec("^UPDATE one").WithArgs("one").WillReturnResult(result)
+ mock.ExpectExec("^UPDATE two").WithArgs("one", "two").WillReturnResult(result)
+ mock.ExpectExec("^UPDATE three").WithArgs("one", "two", "three").WillReturnResult(result)
+
+ var wg sync.WaitGroup
+ queries := map[string][]interface{}{
+ "one": []interface{}{"one"},
+ "two": []interface{}{"one", "two"},
+ "three": []interface{}{"one", "two", "three"},
+ }
+
+ wg.Add(len(queries))
+ for table, args := range queries {
+ go func(tbl string, a []interface{}) {
+ if _, err := db.Exec("UPDATE "+tbl, a...); err != nil {
+ fmt.Println("error was not expected:", err)
+ }
+ wg.Done()
+ }(table, args)
+ }
+
+ wg.Wait()
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ fmt.Println("there were unfulfilled expections:", err)
+ }
+ // Output:
+}
+
+// False Positive - passes despite mismatched Exec
+// see #37 issue
+func TestRunExecsWithOrderedShouldNotMeetAllExpectations(t *testing.T) {
+ db, dbmock, _ := New()
+ dbmock.ExpectExec("THE FIRST EXEC")
+ dbmock.ExpectExec("THE SECOND EXEC")
+
+ _, _ = db.Exec("THE FIRST EXEC")
+ _, _ = db.Exec("THE WRONG EXEC")
+
+ err := dbmock.ExpectationsWereMet()
+ if err == nil {
+ t.Fatal("was expecting an error, but there wasn't any")
+ }
+}
+
+// False Positive - passes despite mismatched Exec
+// see #37 issue
+func TestRunQueriesWithOrderedShouldNotMeetAllExpectations(t *testing.T) {
+ db, dbmock, _ := New()
+ dbmock.ExpectQuery("THE FIRST QUERY")
+ dbmock.ExpectQuery("THE SECOND QUERY")
+
+ _, _ = db.Query("THE FIRST QUERY")
+ _, _ = db.Query("THE WRONG QUERY")
+
+ err := dbmock.ExpectationsWereMet()
+ if err == nil {
+ t.Fatal("was expecting an error, but there wasn't any")
+ }
+}
+
+func TestRunExecsWithExpectedErrorMeetsExpectations(t *testing.T) {
+ db, dbmock, _ := New()
+ dbmock.ExpectExec("THE FIRST EXEC").WillReturnError(fmt.Errorf("big bad bug"))
+ dbmock.ExpectExec("THE SECOND EXEC").WillReturnResult(NewResult(0, 0))
+
+ _, _ = db.Exec("THE FIRST EXEC")
+ _, _ = db.Exec("THE SECOND EXEC")
+
+ err := dbmock.ExpectationsWereMet()
+ if err != nil {
+ t.Fatalf("all expectations should be met: %s", err)
+ }
+}
+
+func TestRunQueryWithExpectedErrorMeetsExpectations(t *testing.T) {
+ db, dbmock, _ := New()
+ dbmock.ExpectQuery("THE FIRST QUERY").WillReturnError(fmt.Errorf("big bad bug"))
+ dbmock.ExpectQuery("THE SECOND QUERY").WillReturnRows(NewRows([]string{"col"}).AddRow(1))
+
+ _, _ = db.Query("THE FIRST QUERY")
+ _, _ = db.Query("THE SECOND QUERY")
+
+ err := dbmock.ExpectationsWereMet()
+ if err != nil {
+ t.Fatalf("all expectations should be met: %s", err)
+ }
+}
+
+func TestEmptyRowSet(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs := NewRows([]string{"id", "title"})
+
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+ WithArgs(5).
+ WillReturnRows(rs)
+
+ rows, err := db.Query("SELECT (.+) FROM articles WHERE id = ?", 5)
+ if err != nil {
+ t.Errorf("error '%s' was not expected while retrieving mock rows", err)
+ }
+
+ defer func() {
+ if er := rows.Close(); er != nil {
+ t.Error("Unexpected error while trying to close rows")
+ }
+ }()
+
+ if rows.Next() {
+ t.Error("expected no rows but got one")
+ }
+
+ err = mock.ExpectationsWereMet()
+ if err != nil {
+ t.Fatalf("all expectations should be met: %s", err)
+ }
+}
+
+// Based on issue #50
+func TestPrepareExpectationNotFulfilled(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectPrepare("^BADSELECT$")
+
+ if _, err := db.Prepare("SELECT"); err == nil {
+ t.Fatal("prepare should not match expected query string")
+ }
+
+ if err := mock.ExpectationsWereMet(); err == nil {
+ t.Errorf("was expecting an error, since prepared statement query does not match, but there was none")
+ }
+}
+
+func TestRollbackThrow(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ // columns to be used for result
+ columns := []string{"id", "status"}
+ // expect transaction begin
+ mock.ExpectBegin()
+ // expect query to fetch order, match it with regexp
+ mock.ExpectQuery("SELECT (.+) FROM orders (.+) FOR UPDATE").
+ WithArgs(1).
+ WillReturnRows(NewRows(columns).AddRow(1, 1))
+ // expect transaction rollback, since order status is "cancelled"
+ mock.ExpectRollback().WillReturnError(fmt.Errorf("rollback failed"))
+
+ // run the cancel order function
+ someOrderID := 1
+ // call a function which executes expected database operations
+ err = cancelOrder(db, someOrderID)
+ if err == nil {
+ t.Error("an error was expected when rolling back transaction, but got none")
+ }
+
+ // ensure all expectations have been met
+ if err = mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("unmet expectation error: %s", err)
+ }
+ // Output:
+}
+
+func TestUnexpectedCommit(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ mock.ExpectBegin()
+ tx, _ := db.Begin()
+ if err := tx.Commit(); err == nil {
+ t.Error("an error was expected when calling commit, but got none")
+ }
+}
+
+func TestUnexpectedCommitOrder(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ mock.ExpectBegin()
+ mock.ExpectRollback().WillReturnError(fmt.Errorf("Rollback failed"))
+ tx, _ := db.Begin()
+ if err := tx.Commit(); err == nil {
+ t.Error("an error was expected when calling commit, but got none")
+ }
+}
+
+func TestExpectedCommitOrder(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ mock.ExpectCommit().WillReturnError(fmt.Errorf("Commit failed"))
+ if _, err := db.Begin(); err == nil {
+ t.Error("an error was expected when calling begin, but got none")
+ }
+}
+
+func TestUnexpectedRollback(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ mock.ExpectBegin()
+ tx, _ := db.Begin()
+ if err := tx.Rollback(); err == nil {
+ t.Error("an error was expected when calling rollback, but got none")
+ }
+}
+
+func TestUnexpectedRollbackOrder(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ mock.ExpectBegin()
+
+ tx, _ := db.Begin()
+ if err := tx.Rollback(); err == nil {
+ t.Error("an error was expected when calling rollback, but got none")
+ }
+}
+
+func TestPrepareExec(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ defer db.Close()
+ mock.ExpectBegin()
+ ep := mock.ExpectPrepare("INSERT INTO ORDERS\\(ID, STATUS\\) VALUES \\(\\?, \\?\\)")
+ for i := 0; i < 3; i++ {
+ ep.ExpectExec().WillReturnResult(NewResult(1, 1))
+ }
+ mock.ExpectCommit()
+ tx, _ := db.Begin()
+ stmt, err := tx.Prepare("INSERT INTO ORDERS(ID, STATUS) VALUES (?, ?)")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer stmt.Close()
+ for i := 0; i < 3; i++ {
+ _, err := stmt.Exec(i, "Hello"+strconv.Itoa(i))
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ tx.Commit()
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestPrepareQuery(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ defer db.Close()
+ mock.ExpectBegin()
+ ep := mock.ExpectPrepare("SELECT ID, STATUS FROM ORDERS WHERE ID = \\?")
+ ep.ExpectQuery().WithArgs(101).WillReturnRows(NewRows([]string{"ID", "STATUS"}).AddRow(101, "Hello"))
+ mock.ExpectCommit()
+ tx, _ := db.Begin()
+ stmt, err := tx.Prepare("SELECT ID, STATUS FROM ORDERS WHERE ID = ?")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer stmt.Close()
+ rows, err := stmt.Query(101)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer rows.Close()
+ for rows.Next() {
+ var (
+ id int
+ status string
+ )
+ if rows.Scan(&id, &status); id != 101 || status != "Hello" {
+ t.Fatal("wrong query results")
+ }
+
+ }
+ tx.Commit()
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestExpectedCloseError(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ mock.ExpectClose().WillReturnError(fmt.Errorf("Close failed"))
+ if err := db.Close(); err == nil {
+ t.Error("an error was expected when calling close, but got none")
+ }
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestExpectedCloseOrder(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ defer db.Close()
+ mock.ExpectClose().WillReturnError(fmt.Errorf("Close failed"))
+ db.Begin()
+ if err := mock.ExpectationsWereMet(); err == nil {
+ t.Error("expected error on ExpectationsWereMet")
+ }
+}
+
+func TestExpectedBeginOrder(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ mock.ExpectBegin().WillReturnError(fmt.Errorf("Begin failed"))
+ if err := db.Close(); err == nil {
+ t.Error("an error was expected when calling close, but got none")
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement.go
new file mode 100644
index 0000000..df73740
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement.go
@@ -0,0 +1,27 @@
+package sqlmock
+
+import (
+ "database/sql/driver"
+)
+
+type statement struct {
+ conn *sqlmock
+ query string
+ err error
+}
+
+func (stmt *statement) Close() error {
+ return stmt.err
+}
+
+func (stmt *statement) NumInput() int {
+ return -1
+}
+
+func (stmt *statement) Exec(args []driver.Value) (driver.Result, error) {
+ return stmt.conn.Exec(stmt.query, args)
+}
+
+func (stmt *statement) Query(args []driver.Value) (driver.Rows, error) {
+ return stmt.conn.Query(stmt.query, args)
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement_test.go
new file mode 100644
index 0000000..f951f63
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement_test.go
@@ -0,0 +1,33 @@
+// +build go1.6
+
+package sqlmock
+
+import (
+ "errors"
+ "testing"
+)
+
+func TestExpectedPreparedStatemtCloseError(t *testing.T) {
+ conn, mock, err := New()
+ if err != nil {
+ t.Fatal("failed to open sqlmock database:", err)
+ }
+
+ mock.ExpectBegin()
+ want := errors.New("STMT ERROR")
+ mock.ExpectPrepare("SELECT").WillReturnCloseError(want)
+
+ txn, err := conn.Begin()
+ if err != nil {
+ t.Fatal("unexpected error while opening transaction:", err)
+ }
+
+ stmt, err := txn.Prepare("SELECT")
+ if err != nil {
+ t.Fatal("unexpected error while preparing a statement:", err)
+ }
+
+ if err := stmt.Close(); err != want {
+ t.Fatalf("Got = %v, want = %v", err, want)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go
new file mode 100644
index 0000000..d3c6003
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go
@@ -0,0 +1,76 @@
+package sqlmock
+
+import (
+ "database/sql/driver"
+ "fmt"
+ "strconv"
+ "time"
+)
+
+type NullTime struct {
+ Time time.Time
+ Valid bool // Valid is true if Time is not NULL
+}
+
+type NullInt struct {
+ Integer int
+ Valid bool
+}
+
+// Satisfy sql.Scanner interface
+func (ni *NullInt) Scan(value interface{}) (err error) {
+ if value == nil {
+ ni.Integer, ni.Valid = 0, false
+ return
+ }
+
+ switch v := value.(type) {
+ case int, int8, int16, int32, int64:
+ ni.Integer, ni.Valid = v.(int), true
+ return
+ case []byte:
+ ni.Integer, err = strconv.Atoi(string(v))
+ ni.Valid = (err == nil)
+ return
+ case string:
+ ni.Integer, err = strconv.Atoi(v)
+ ni.Valid = (err == nil)
+ return
+ }
+
+ ni.Valid = false
+ return fmt.Errorf("Can't convert %T to integer", value)
+}
+
+// Satisfy sql.Valuer interface.
+func (ni NullInt) Value() (driver.Value, error) {
+ if !ni.Valid {
+ return nil, nil
+ }
+ return ni.Integer, nil
+}
+
+// Satisfy sql.Scanner interface
+func (nt *NullTime) Scan(value interface{}) (err error) {
+ if value == nil {
+ nt.Time, nt.Valid = time.Time{}, false
+ return
+ }
+
+ switch v := value.(type) {
+ case time.Time:
+ nt.Time, nt.Valid = v, true
+ return
+ }
+
+ nt.Valid = false
+ return fmt.Errorf("Can't convert %T to time.Time", value)
+}
+
+// Satisfy sql.Valuer interface.
+func (nt NullTime) Value() (driver.Value, error) {
+ if !nt.Valid {
+ return nil, nil
+ }
+ return nt.Time, nil
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go
new file mode 100644
index 0000000..072e380
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go
@@ -0,0 +1,13 @@
+package sqlmock
+
+import (
+ "regexp"
+ "strings"
+)
+
+var re = regexp.MustCompile("\\s+")
+
+// strip out new lines and trim spaces
+func stripQuery(q string) (s string) {
+ return strings.TrimSpace(re.ReplaceAllString(q, " "))
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util_test.go
new file mode 100644
index 0000000..c4b3974
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util_test.go
@@ -0,0 +1,21 @@
+package sqlmock
+
+import (
+ "testing"
+)
+
+func TestQueryStringStripping(t *testing.T) {
+ assert := func(actual, expected string) {
+ if res := stripQuery(actual); res != expected {
+ t.Errorf("Expected '%s' to be '%s', but got '%s'", actual, expected, res)
+ }
+ }
+
+ assert(" SELECT 1", "SELECT 1")
+ assert("SELECT 1 FROM d", "SELECT 1 FROM d")
+ assert(`
+ SELECT c
+ FROM D
+`, "SELECT c FROM D")
+ assert("UPDATE (.+) SET ", "UPDATE (.+) SET")
+}
[20/43] incubator-trafficcontrol git commit: Add TO Golang setcap to
RPM to allow low port
Posted by de...@apache.org.
Add TO Golang setcap to RPM to allow low port
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/9e67e6ab
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/9e67e6ab
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/9e67e6ab
Branch: refs/heads/master
Commit: 9e67e6aba6de8b7daf2d93ca661d301b31d6ebb4
Parents: 9b9b3fb
Author: Robert Butts <ro...@gmail.com>
Authored: Fri Jul 21 19:46:33 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/build/traffic_ops.spec | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/9e67e6ab/traffic_ops/build/traffic_ops.spec
----------------------------------------------------------------------
diff --git a/traffic_ops/build/traffic_ops.spec b/traffic_ops/build/traffic_ops.spec
index 3c899fe..66d2fd9 100644
--- a/traffic_ops/build/traffic_ops.spec
+++ b/traffic_ops/build/traffic_ops.spec
@@ -34,7 +34,7 @@ Packager: daniel_kirkwood at Cable dot Comcast dot com
AutoReqProv: no
Requires: cpanminus, expat-devel, gcc-c++, libcurl, libpcap-devel, mkisofs, tar
Requires: openssl-devel, perl, perl-core, perl-DBD-Pg, perl-DBI, perl-Digest-SHA1
-Requires: libidn-devel, libcurl-devel
+Requires: libidn-devel, libcurl-devel, libcap
Requires: postgresql96 >= 9.6.2 , postgresql96-devel >= 9.6.2
Requires: perl-JSON, perl-libwww-perl, perl-Test-CPAN-Meta, perl-WWW-Curl, perl-TermReadKey
Requires(pre): /usr/sbin/useradd, /usr/bin/getent
@@ -165,6 +165,7 @@ Built: %(date) by %{getenv: USER}
fi
/bin/chown -R %{TRAFFIC_OPS_USER}:%{TRAFFIC_OPS_GROUP} %{PACKAGEDIR}
/bin/chown -R %{TRAFFIC_OPS_USER}:%{TRAFFIC_OPS_GROUP} %{TRAFFIC_OPS_LOG_DIR}
+ setcap cap_net_bind_service=+ep %{PACKAGEDIR}/app/bin/traffic_ops_golang
%preun
[21/43] incubator-trafficcontrol git commit: Add TO Golang Perl
config parser
Posted by de...@apache.org.
Add TO Golang Perl config parser
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/70b7e5ce
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/70b7e5ce
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/70b7e5ce
Branch: refs/heads/master
Commit: 70b7e5ce10721205d5b0b0db90ee5c906fe787da
Parents: 9e67e6a
Author: Robert Butts <ro...@gmail.com>
Authored: Sun Jul 23 12:12:11 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/traffic_ops_golang/perlhash.go | 249 +++++++++++++++++++
traffic_ops/traffic_ops_golang/perlhash_test.go | 217 ++++++++++++++++
2 files changed, 466 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/70b7e5ce/traffic_ops/traffic_ops_golang/perlhash.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/perlhash.go b/traffic_ops/traffic_ops_golang/perlhash.go
new file mode 100644
index 0000000..f278e42
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/perlhash.go
@@ -0,0 +1,249 @@
+package main
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+*/
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+ "unicode"
+)
+
+func ParsePerlObj(s string) (map[string]interface{}, error) {
+ obj, _, err := getObj(s)
+ return obj, err
+}
+
+func getObj(s string) (map[string]interface{}, string, error) {
+ obj := map[string]interface{}{}
+
+ s = strings.TrimSpace(s)
+ if len(s) < 1 || s[0] != '{' {
+ return obj, "", fmt.Errorf("expected first character '{': %v", s)
+ }
+ s = s[1:] // strip opening {
+ s = strings.TrimSpace(s)
+
+ // read top-level keys
+ for {
+ s = stripComment(s)
+ s = strings.TrimSpace(s)
+ // s = stripComment(s)
+ if len(s) > 0 && s[0] == '}' {
+ return obj, s[1:], nil
+ }
+
+ key := ""
+ key, s = getKey(s)
+
+ s = strings.TrimSpace(s)
+ if len(s) == 0 {
+ return obj, "", fmt.Errorf("malformed string after key '%v'", key)
+ }
+
+ err := error(nil)
+ switch {
+ case s[0] == '{':
+ v := map[string]interface{}{}
+ v, s, err = getObj(s)
+ if err != nil {
+ return obj, "", fmt.Errorf("Error getting object value after key %v: %v", key, err)
+ }
+ obj[key] = v
+ case s[0] == '\'':
+ v := ""
+ v, s, err = getStr(s)
+ if err != nil {
+ return obj, "", fmt.Errorf("Error getting string value after key %v: %v", key, err)
+ }
+ obj[key] = v
+ case unicode.IsDigit(rune(s[0])):
+ v := float64(0.0)
+ v, s, err = getNum(s)
+ if err != nil {
+ return obj, "", fmt.Errorf("Error getting numeric value after key %v: %v", key, err)
+ }
+ obj[key] = v
+ case s[0] == '[':
+ v := []interface{}{}
+ v, s, err = getArr(s)
+ if err != nil {
+ return obj, "", fmt.Errorf("Error getting array value after key %v: %v", key, err)
+ }
+ obj[key] = v
+ default:
+ return obj, "", fmt.Errorf(`malformed string after key "%v"`, key)
+ }
+ s = strings.TrimSpace(s)
+ s = stripComment(s)
+ if len(s) > 0 && s[0] == ',' {
+ s = s[1:]
+ s = strings.TrimSpace(s)
+ s = stripComment(s)
+ s = strings.TrimSpace(s)
+ }
+ }
+}
+
+func getNum(s string) (float64, string, error) {
+ s = strings.TrimSpace(s)
+ i := strings.IndexFunc(s, func(r rune) bool { return !unicode.IsDigit(r) && r != '.' })
+
+ numStr := ""
+ if i < 0 {
+ numStr = s
+ s = ""
+ } else {
+ numStr = s[:i]
+ s = s[i:]
+ }
+ num, err := strconv.ParseFloat(numStr, 64)
+ if err != nil {
+ return 0, "", fmt.Errorf("malformed number: %v", err)
+ }
+
+ return num, s, nil
+}
+
+func getArr(s string) ([]interface{}, string, error) {
+ arr := []interface{}{}
+
+ s = strings.TrimSpace(s)
+ if len(s) == 0 || s[0] != '[' {
+ return nil, "", fmt.Errorf("malformed array, doesn't start with [")
+ }
+ s = s[1:]
+ for {
+ s = strings.TrimSpace(s)
+ if len(s) == 0 {
+ return nil, "", fmt.Errorf("malformed array, doesn't end with ]")
+ }
+ if s[0] == ']' {
+ return arr, s[1:], nil
+ }
+
+ switch {
+ case unicode.IsDigit(rune(s[0])) || s[0] == '-' || s[0] == '+' || s[0] == '.':
+ num := float64(0.0)
+ err := error(nil)
+ num, s, err = getNum(s)
+ if err != nil {
+ return nil, "", fmt.Errorf("malformed number in array: %v", err)
+ }
+ arr = append(arr, num)
+ case s[0] == '\'':
+ str := ""
+ err := error(nil)
+ str, s, err = getStr(s)
+ if err != nil {
+ return nil, "", fmt.Errorf("malformed string in array: %v", err)
+ }
+ arr = append(arr, str)
+ case s[0] == '[':
+ narr := []interface{}{}
+ err := error(nil)
+ narr, s, err = getArr(s)
+ if err != nil {
+ return nil, "", fmt.Errorf("malformed array in array: %v", err)
+ }
+ arr = append(arr, narr)
+ case s[0] == '{':
+ obj := map[string]interface{}{}
+ err := error(nil)
+ obj, s, err = getObj(s)
+ if err != nil {
+ return nil, "", fmt.Errorf("malformed object in array: %v", err)
+ }
+ arr = append(arr, obj)
+ default:
+ return nil, "", fmt.Errorf("malformed element in array, unknown initial character: %v", string(s[0]))
+ }
+ s = strings.TrimSpace(s)
+ s = stripComment(s)
+ if len(s) > 0 && s[0] == ',' {
+ s = s[1:]
+ s = strings.TrimSpace(s)
+ s = stripComment(s)
+ s = strings.TrimSpace(s)
+ }
+ }
+}
+
+func getStr(s string) (string, string, error) {
+ s = strings.TrimSpace(s)
+ if len(s) == 0 || s[0] != '\'' {
+ return "", "", fmt.Errorf("malformed string, doesn't start with '")
+ }
+ s = s[1:]
+
+ str := ""
+
+ escaping := false
+ for {
+ if len(s) == 0 {
+ return "", "", fmt.Errorf("malformed string, doesn't terminate '")
+ }
+
+ if !escaping && s[0] == '\'' {
+ return str, s[1:], nil
+ }
+
+ if escaping {
+ str += s[0:1]
+ s = s[1:]
+ escaping = false
+ continue
+ }
+
+ if s[0] == '\\' {
+ escaping = true
+ s = s[1:]
+ continue
+ }
+
+ str += s[0:1]
+ s = s[1:]
+ continue
+ }
+
+}
+
+func stripComment(s string) string {
+ if len(s) == 0 || s[0] != '#' {
+ return s
+ }
+ i := strings.Index(s, "\n")
+ if i < 0 {
+ return ""
+ }
+ return s[i:]
+}
+
+func getKey(s string) (string, string) {
+ i := strings.Index(s, "=>")
+ if i < 0 {
+ return "", s
+ }
+ key := s[:i]
+ key = strings.TrimSpace(key)
+
+ s = s[i+len("=>"):]
+ return key, s
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/70b7e5ce/traffic_ops/traffic_ops_golang/perlhash_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/perlhash_test.go b/traffic_ops/traffic_ops_golang/perlhash_test.go
new file mode 100644
index 0000000..beb9ac7
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/perlhash_test.go
@@ -0,0 +1,217 @@
+package main
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+*/
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestGetStr(t *testing.T) {
+ type Strtst struct {
+ Input string
+ ExpectedStr string
+ ExpectedS string
+ }
+ strs := []Strtst{
+ Strtst{`'foo'asdf`, `foo`, `asdf`},
+ Strtst{`''asdf`, ``, `asdf`},
+ Strtst{`'1234'asdf`, `1234`, `asdf`},
+ Strtst{`'\\'asdf`, `\`, `asdf`},
+ Strtst{`'\''asdf`, `'`, `asdf`},
+ Strtst{`'\''asdfqhrewoipjasf`, `'`, `asdfqhrewoipjasf`},
+ }
+
+ for _, st := range strs {
+ str, s, err := getStr(st.Input)
+ if err != nil {
+ t.Errorf("expected nil err actual %v", err)
+ }
+ if str != st.ExpectedStr {
+ t.Errorf("expected str '%v' actual '%v'", st.ExpectedStr, str)
+ }
+ if s != st.ExpectedS {
+ t.Errorf("expected s '%v' actual '%v'", st.ExpectedS, s)
+ }
+ }
+}
+
+func TestGetNum(t *testing.T) {
+ type Tst struct {
+ Input string
+ ExpectedNum float64
+ ExpectedS string
+ }
+ strs := []Tst{
+ Tst{`42asdf`, 42, `asdf`},
+ Tst{`42 asdf`, 42, ` asdf`},
+ Tst{`42.1asdf`, 42.1, `asdf`},
+ Tst{`42.1 asdf`, 42.1, ` asdf`},
+ Tst{`42. asdf`, 42, ` asdf`},
+ Tst{`.42 asdf`, 0.42, ` asdf`},
+ Tst{`0.42 asdf`, 0.42, ` asdf`},
+ Tst{`0.42 {asdf`, 0.42, ` {asdf`},
+ Tst{`9{asdf`, 9, `{asdf`},
+ Tst{`42.1`, 42.1, ``},
+ Tst{`9`, 9, ``},
+ }
+
+ for _, st := range strs {
+ num, s, err := getNum(st.Input)
+ if err != nil {
+ t.Errorf("expected nil err actual %v", err)
+ }
+ if num != st.ExpectedNum {
+ t.Errorf("expected num '%v' actual '%v'", st.ExpectedNum, num)
+ }
+ if s != st.ExpectedS {
+ t.Errorf("expected s '%v' actual '%v'", st.ExpectedS, s)
+ }
+ }
+}
+
+func TestGetArr(t *testing.T) {
+ type Tst struct {
+ Input string
+ ExpectedVal []interface{}
+ ExpectedS string
+ }
+ tsts := []Tst{
+ Tst{`[42]asdf`, []interface{}{42.0}, `asdf`},
+ Tst{`[42, 'foo']],1]asdf`, []interface{}{42.0, `foo`}, `],1]asdf`},
+ Tst{`[
+ 'https://[::]:443?cert=/etc/pki/tls/certs/localhost.crt&key=/etc/pki/tls/private/localhost.key&verify=0x00&ciphers=AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL:!EDH:!ED'
+ ],`, []interface{}{`https://[::]:443?cert=/etc/pki/tls/certs/localhost.crt&key=/etc/pki/tls/private/localhost.key&verify=0x00&ciphers=AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL:!EDH:!ED`}, `,`},
+ Tst{`[ 'foobar' ],`, []interface{}{"foobar"}, `,`},
+ Tst{`[ 'foo' , 'bar', 'baz' ],`, []interface{}{`foo`, `bar`, `baz`}, `,`},
+ }
+
+ for _, st := range tsts {
+ val, s, err := getArr(st.Input)
+ if err != nil {
+ t.Errorf("expected nil err actual %v", err)
+ }
+ if !reflect.DeepEqual(val, st.ExpectedVal) {
+ t.Errorf("expected arr '%v' actual '%v'", st.ExpectedVal, val)
+ }
+ if s != st.ExpectedS {
+ t.Errorf("expected s '%v' actual '%v'", st.ExpectedS, s)
+ }
+ }
+}
+
+func TestGetObj(t *testing.T) {
+ type Tst struct {
+ Input string
+ ExpectedVal map[string]interface{}
+ ExpectedS string
+ }
+ tsts := []Tst{
+ Tst{`{ a => 'b', c => [42.0, 'd']},asdf`,
+ map[string]interface{}{
+ `a`: `b`,
+ `c`: []interface{}{42.0, `d`},
+ },
+ `,asdf`},
+ }
+
+ for _, st := range tsts {
+ val, s, err := getObj(st.Input)
+ if err != nil {
+ t.Errorf("expected nil err actual %v", err)
+ }
+ if !reflect.DeepEqual(val, st.ExpectedVal) {
+ t.Errorf("expected obj '%+v' actual '%+v'", st.ExpectedVal, val)
+ }
+ if s != st.ExpectedS {
+ t.Errorf("expected s '%v' actual '%v'", st.ExpectedS, s)
+ }
+ }
+}
+
+func TestParsePerlObj(t *testing.T) {
+ input := `
+{
+ hypnotoad => {
+ listen => [
+ 'https://[::]:443?cert=/etc/pki/tls/certs/localhost.crt&key=/etc/pki/tls/private/localhost.key&verify=0x00&ciphers=AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL:!EDH:!ED'
+ ],
+ user => 'trafops',
+ group => 'trafops',
+ heartbeat_timeout => 20,
+ pid_file => '/var/run/traffic_ops.pid',
+ workers => 96
+ },
+ cors => {
+ access_control_allow_origin => '*'
+ },
+ to => {
+ base_url => 'http://localhost:3000', # this is where traffic ops app resides
+ email_from => 'no-reply@traffic-ops-domain.com' # traffic ops email address
+ },
+ portal => {
+ base_url => 'http://localhost:8080', # this is where the traffic portal resides (a javascript client that consumes the TO API)
+ email_from => 'no-reply@traffic-portal-domain.com' # traffic portal email address
+ },
+
+ # 1st secret is used to generate new signatures. Older one kept around for existing signed cookies.
+ # Remove old one(s) when ready to invalidate old cookies.
+ secrets => [ 'walrus' ],
+ geniso => {
+ iso_root_path => '/opt/traffic_ops/app/public', # the location where the iso files will be written
+ },
+ inactivity_timeout => 60
+};
+`
+ expected := map[string]interface{}{
+ "hypnotoad": map[string]interface{}{
+ "listen": []interface{}{`https://[::]:443?cert=/etc/pki/tls/certs/localhost.crt&key=/etc/pki/tls/private/localhost.key&verify=0x00&ciphers=AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL:!EDH:!ED`},
+ "user": `trafops`,
+ "group": `trafops`,
+ "heartbeat_timeout": 20.0,
+ "pid_file": `/var/run/traffic_ops.pid`,
+ "workers": 96.0,
+ },
+ "cors": map[string]interface{}{
+ "access_control_allow_origin": `*`,
+ },
+ "to": map[string]interface{}{
+ "base_url": `http://localhost:3000`,
+ "email_from": `no-reply@traffic-ops-domain.com`,
+ },
+ "portal": map[string]interface{}{
+ "base_url": `http://localhost:8080`,
+ "email_from": `no-reply@traffic-portal-domain.com`,
+ },
+ "secrets": []interface{}{`walrus`},
+ "geniso": map[string]interface{}{
+ "iso_root_path": `/opt/traffic_ops/app/public`,
+ },
+ "inactivity_timeout": 60.0,
+ }
+
+ val, err := ParsePerlObj(input)
+ if err != nil {
+ t.Errorf("expected nil err actual %v", err)
+ }
+ if !reflect.DeepEqual(val, expected) {
+ t.Errorf("expected '%+v' actual '%+v'", expected, val)
+ }
+}
[34/43] incubator-trafficcontrol git commit: Fix merge conflicts
Posted by de...@apache.org.
Fix merge conflicts
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/b4ccbb1f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/b4ccbb1f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/b4ccbb1f
Branch: refs/heads/master
Commit: b4ccbb1fca54dd2edc7e0b8a4a6eeccc289d8c52
Parents: 67f80fa
Author: Robert Butts <ro...@gmail.com>
Authored: Tue Aug 1 17:26:41 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_monitor_golang/common/log/log.go | 1 -
traffic_monitor_golang/traffic_monitor/config/config.go | 1 -
traffic_ops/traffic_ops_golang/config.go | 10 +++++-----
3 files changed, 5 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b4ccbb1f/traffic_monitor_golang/common/log/log.go
----------------------------------------------------------------------
diff --git a/traffic_monitor_golang/common/log/log.go b/traffic_monitor_golang/common/log/log.go
index a5204b5..e2ff9c8 100644
--- a/traffic_monitor_golang/common/log/log.go
+++ b/traffic_monitor_golang/common/log/log.go
@@ -23,7 +23,6 @@ package log
import (
"fmt"
"io"
- "io/ioutil"
"log"
"os"
"time"
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b4ccbb1f/traffic_monitor_golang/traffic_monitor/config/config.go
----------------------------------------------------------------------
diff --git a/traffic_monitor_golang/traffic_monitor/config/config.go b/traffic_monitor_golang/traffic_monitor/config/config.go
index 358541b..3939587 100644
--- a/traffic_monitor_golang/traffic_monitor/config/config.go
+++ b/traffic_monitor_golang/traffic_monitor/config/config.go
@@ -21,7 +21,6 @@ package config
import (
"encoding/json"
- "io"
"io/ioutil"
"time"
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b4ccbb1f/traffic_ops/traffic_ops_golang/config.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/config.go b/traffic_ops/traffic_ops_golang/config.go
index 5911204..0c87878 100644
--- a/traffic_ops/traffic_ops_golang/config.go
+++ b/traffic_ops/traffic_ops_golang/config.go
@@ -48,11 +48,11 @@ type Config struct {
LogLocationEvent string `json:"log_location_event"`
}
-func (c Config) Error() log.LogLocation { return log.LogLocation(c.LogLocationError) }
-func (c Config) Warning() log.LogLocation { return log.LogLocation(c.LogLocationWarning) }
-func (c Config) Info() log.LogLocation { return log.LogLocation(c.LogLocationInfo) }
-func (c Config) Debug() log.LogLocation { return log.LogLocation(c.LogLocationDebug) }
-func (c Config) Event() log.LogLocation { return log.LogLocation(c.LogLocationEvent) }
+func (c Config) ErrorLog() log.LogLocation { return log.LogLocation(c.LogLocationError) }
+func (c Config) WarningLog() log.LogLocation { return log.LogLocation(c.LogLocationWarning) }
+func (c Config) InfoLog() log.LogLocation { return log.LogLocation(c.LogLocationInfo) }
+func (c Config) DebugLog() log.LogLocation { return log.LogLocation(c.LogLocationDebug) }
+func (c Config) EventLog() log.LogLocation { return log.LogLocation(c.LogLocationEvent) }
func LoadConfig(fileName string) (Config, error) {
if fileName == "" {
[19/43] incubator-trafficcontrol git commit: Add TO Golang
Postinstall setting ports
Posted by de...@apache.org.
Add TO Golang Postinstall setting ports
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/9b9b3fb4
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/9b9b3fb4
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/9b9b3fb4
Branch: refs/heads/master
Commit: 9b9b3fb4107700c2bf90c2ba841e859908073124
Parents: a54b0ef
Author: Robert Butts <ro...@gmail.com>
Authored: Fri Jul 21 19:33:23 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/install/bin/_postinstall | 13 +++++++++++++
1 file changed, 13 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/9b9b3fb4/traffic_ops/install/bin/_postinstall
----------------------------------------------------------------------
diff --git a/traffic_ops/install/bin/_postinstall b/traffic_ops/install/bin/_postinstall
index c595ab4..b83e65a 100755
--- a/traffic_ops/install/bin/_postinstall
+++ b/traffic_ops/install/bin/_postinstall
@@ -183,6 +183,18 @@ sub generateDbConf {
return \%todbconf;
}
+sub setCdnConfGoPort {
+ my $cdnConf = shift;
+ if ( exists $cdnConf->{"traffic_ops_golang_port"} ) {
+ return $cdnConf;
+ }
+ my ($port) = $cdnConf->{hypnotoad}->{listen}[0] =~ m/\:(\d+)/;
+ $cdnConf->{hypnotoad}->{listen}[0] =~ s/\:\d+/\:60443/;
+ $cdnConf->{hypnotoad}->{listen}[0] =~ s/https\:\/\/[\:\:]/https\:\/\/127\.0\.0\.1/;
+ $cdnConf->{"traffic_ops_golang_port"} = $port;
+ return $cdnConf;
+}
+
# userInput: The entire input config file which is either user input or the defaults
# fileName: The filename of the output config file
#
@@ -218,6 +230,7 @@ sub generateCdnConf {
$#secrets = $cdnConfiguration{keepSecrets} - 1;
}
}
+ $cdnConf = setCdnConfGoPort($cdnConf);
$cdnConf->{hypnotoad}{workers} = $cdnConfiguration{workers};
InstallUtils::writePerl( $fileName, $cdnConf );
InstallUtils::logger( "CDN configuration has been saved", "info" );
[02/43] incubator-trafficcontrol git commit: Add TO Golang monitoring
test
Posted by de...@apache.org.
Add TO Golang monitoring test
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/b5833467
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/b5833467
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/b5833467
Branch: refs/heads/master
Commit: b5833467499d6568d5f4f79532786ac45477dfd2
Parents: f9f7cfa
Author: Robert Butts <ro...@gmail.com>
Authored: Mon Jul 17 21:55:35 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:02 2017 -0600
----------------------------------------------------------------------
traffic_ops_golang/monitoring_test.go | 615 +++++++++++++++++++++++++++++
1 file changed, 615 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5833467/traffic_ops_golang/monitoring_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/monitoring_test.go b/traffic_ops_golang/monitoring_test.go
new file mode 100644
index 0000000..79b0919
--- /dev/null
+++ b/traffic_ops_golang/monitoring_test.go
@@ -0,0 +1,615 @@
+package main
+
+import (
+ "reflect"
+ "sort"
+ "testing"
+
+ "github.com/lib/pq"
+ "gopkg.in/DATA-DOG/go-sqlmock.v1"
+)
+
+func TestGetServers(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ cdn := "mycdn"
+
+ monitor := Monitor{
+ BasicServer: BasicServer{Profile: "monitorProfile",
+ Status: "monitorStatus",
+ IP: "1.2.3.4",
+ IP6: "2001::4",
+ Port: 8081,
+ Cachegroup: "monitorCachegroup",
+ HostName: "monitorHost",
+ FQDN: "monitorFqdn.me",
+ },
+ }
+
+ cacheType := "EDGE"
+ cache := Cache{
+ BasicServer: BasicServer{
+ Profile: "cacheProfile",
+ Status: "cacheStatus",
+ IP: "1.2.3.4",
+ IP6: "2001::4",
+ Port: 8081,
+ Cachegroup: "cacheCachegroup",
+ HostName: "cacheHost",
+ FQDN: "cacheFqdn.me",
+ },
+ InterfaceName: "cacheInterface",
+ Type: cacheType,
+ HashID: "cacheHash",
+ }
+
+ router := Router{
+ Type: RouterType,
+ Profile: "routerProfile",
+ }
+
+ rows := sqlmock.NewRows([]string{"hostName", "fqdn", "status", "cachegroup", "port", "ip", "ip6", "profile", "interfaceName", "type", "hashId"})
+ rows = rows.AddRow(monitor.HostName, monitor.FQDN, monitor.Status, monitor.Cachegroup, monitor.Port, monitor.IP, monitor.IP6, monitor.Profile, "noInterface", MonitorType, "noHash")
+ rows = rows.AddRow(cache.HostName, cache.FQDN, cache.Status, cache.Cachegroup, cache.Port, cache.IP, cache.IP6, cache.Profile, cache.InterfaceName, cache.Type, cache.HashID)
+ rows = rows.AddRow("noHostname", "noFqdn", "noStatus", "noGroup", 0, "noIp", "noIp6", router.Profile, "noInterface", RouterType, "noHashid")
+
+ mock.ExpectQuery("SELECT").WithArgs(cdn).WillReturnRows(rows)
+
+ monitors, caches, routers, err := getServers(db, cdn)
+ if err != nil {
+ t.Errorf("getServers expected: nil error, actual: %v", err)
+ }
+
+ if len(monitors) != 1 {
+ t.Errorf("getServers expected: len(monitors) == 1, actual: %v", len(monitors))
+ }
+ sqlMonitor := monitors[0]
+ if sqlMonitor != monitor {
+ t.Errorf("getServers expected: monitor == %+v, actual: %+v", monitor, sqlMonitor)
+ }
+
+ if len(caches) != 1 {
+ t.Errorf("getServers expected: len(caches) == 1, actual: %v", len(caches))
+ }
+ sqlCache := caches[0]
+ if sqlCache != cache {
+ t.Errorf("getServers expected: cache == %+v, actual: %+v", cache, sqlCache)
+ }
+
+ if len(routers) != 1 {
+ t.Errorf("getServers expected: len(routers) == 1, actual: %v", len(routers))
+ }
+ sqlRouter := routers[0]
+ if sqlRouter != router {
+ t.Errorf("getServers expected: router == %+v, actual: %+v", router, sqlRouter)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestGetCachegroups(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ cdn := "mycdn"
+
+ cachegroup := Cachegroup{
+ Name: "myCachegroup",
+ Coordinates: Coordinates{
+ Latitude: 42.42,
+ Longitude: 24.24,
+ },
+ }
+
+ rows := sqlmock.NewRows([]string{"name", "latitude", "longitude"})
+ rows = rows.AddRow(cachegroup.Name, cachegroup.Coordinates.Latitude, cachegroup.Coordinates.Longitude)
+
+ mock.ExpectQuery("SELECT").WithArgs(cdn).WillReturnRows(rows)
+
+ sqlCachegroups, err := getCachegroups(db, cdn)
+ if err != nil {
+ t.Errorf("getCachegroups expected: nil error, actual: %v", err)
+ }
+
+ if len(sqlCachegroups) != 1 {
+ t.Errorf("getCachegroups expected: len(monitors) == 1, actual: %v", len(sqlCachegroups))
+ }
+ sqlCachegroup := sqlCachegroups[0]
+ if sqlCachegroup != cachegroup {
+ t.Errorf("getServers expected: cachegroup == %+v, actual: %+v", cachegroup, sqlCachegroup)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+type SortableProfiles []Profile
+
+func (s SortableProfiles) Len() int {
+ return len(s)
+}
+func (s SortableProfiles) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+func (s SortableProfiles) Less(i, j int) bool {
+ return s[i].Name < s[j].Name
+}
+
+func sortProfiles(p []Profile) []Profile {
+ sort.Sort(SortableProfiles(p))
+ return p
+}
+
+type SortableMonitors []Monitor
+
+func (s SortableMonitors) Len() int {
+ return len(s)
+}
+func (s SortableMonitors) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+func (s SortableMonitors) Less(i, j int) bool {
+ return s[i].HostName < s[j].HostName
+}
+
+func sortMonitors(p []Monitor) []Monitor {
+ sort.Sort(SortableMonitors(p))
+ return p
+}
+
+type SortableCaches []Cache
+
+func (s SortableCaches) Len() int {
+ return len(s)
+}
+func (s SortableCaches) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+func (s SortableCaches) Less(i, j int) bool {
+ return s[i].HostName < s[j].HostName
+}
+
+func sortCaches(p []Cache) []Cache {
+ sort.Sort(SortableCaches(p))
+ return p
+}
+
+type SortableCachegroups []Cachegroup
+
+func (s SortableCachegroups) Len() int {
+ return len(s)
+}
+func (s SortableCachegroups) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+func (s SortableCachegroups) Less(i, j int) bool {
+ return s[i].Name < s[j].Name
+}
+
+func sortCachegroups(p []Cachegroup) []Cachegroup {
+ sort.Sort(SortableCachegroups(p))
+ return p
+}
+
+type SortableDeliveryServices []DeliveryService
+
+func (s SortableDeliveryServices) Len() int {
+ return len(s)
+}
+func (s SortableDeliveryServices) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+func (s SortableDeliveryServices) Less(i, j int) bool {
+ return s[i].XMLID < s[j].XMLID
+}
+
+func sortDeliveryServices(p []DeliveryService) []DeliveryService {
+ sort.Sort(SortableDeliveryServices(p))
+ return p
+}
+
+func TestGetProfiles(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ cache := Cache{
+ BasicServer: BasicServer{
+ Profile: "cacheProfile",
+ Status: "cacheStatus",
+ IP: "1.2.3.4",
+ IP6: "2001::4",
+ Port: 8081,
+ Cachegroup: "cacheCachegroup",
+ HostName: "cacheHost",
+ FQDN: "cacheFqdn.me",
+ },
+ InterfaceName: "cacheInterface",
+ Type: "EDGE",
+ HashID: "cacheHash",
+ }
+
+ router := Router{
+ Type: RouterType,
+ Profile: "routerProfile",
+ }
+
+ profiles := []Profile{
+ Profile{
+ Name: router.Profile,
+ Type: RouterType,
+ Parameters: map[string]string{
+ "param0": "param0Val",
+ "param1": "param1Val",
+ },
+ },
+ Profile{
+ Name: cache.Profile,
+ Type: "myType2",
+ Parameters: map[string]string{
+ "2param0": "2param0Val",
+ "2param1": "2param1Val",
+ },
+ },
+ }
+
+ rows := sqlmock.NewRows([]string{"profile", "name", "value"})
+ for _, profile := range profiles {
+ for paramName, paramVal := range profile.Parameters {
+ rows = rows.AddRow(profile.Name, paramName, paramVal)
+ }
+ }
+
+ caches := []Cache{cache}
+ routers := []Router{router}
+
+ profileNames := []string{"cacheProfile"}
+
+ mock.ExpectQuery("SELECT").WithArgs(pq.Array(profileNames), CacheMonitorConfigFile).WillReturnRows(rows)
+
+ sqlProfiles, err := getProfiles(db, caches, routers)
+ if err != nil {
+ t.Errorf("getProfiles expected: nil error, actual: %v", err)
+ }
+
+ if len(sqlProfiles) != len(profiles) {
+ t.Errorf("getProfiles expected: %+v actual: %+v", profiles, sqlProfiles)
+ }
+
+ profiles = sortProfiles(profiles)
+ sqlProfiles = sortProfiles(sqlProfiles)
+
+ for i, profile := range profiles {
+ if profile.Name != sqlProfiles[i].Name {
+ t.Errorf("getProfiles expected: profiles[%v].Name %v, actual: %v", i, profile.Name, sqlProfiles[i].Name)
+ }
+ for paramName, paramVal := range profile.Parameters {
+ val, ok := sqlProfiles[i].Parameters[paramName]
+ if !ok {
+ t.Errorf("getProfiles expected: profiles[%v].Parameters[%v] = %v, actual: nil", i, paramName, paramVal)
+ }
+ if val != paramVal {
+ t.Errorf("getProfiles expected: profiles[%v].Parameters[%v] = %v, actual: %v", i, paramName, paramVal)
+ }
+ }
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestGetDeliveryServices(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ router := Router{
+ Type: RouterType,
+ Profile: "routerProfile",
+ }
+
+ deliveryservice := DeliveryService{
+ XMLID: "myDsid",
+ TotalTPSThreshold: 42.42,
+ Status: DeliveryServiceStatus,
+ TotalKBPSThreshold: 24.24,
+ }
+
+ deliveryservices := []DeliveryService{deliveryservice}
+ routers := []Router{router}
+
+ rows := sqlmock.NewRows([]string{"xml_id", "global_max_tps", "global_max_mbps"})
+ for _, deliveryservice := range deliveryservices {
+ rows = rows.AddRow(deliveryservice.XMLID, deliveryservice.TotalTPSThreshold, deliveryservice.TotalKBPSThreshold/KilobitsPerMegabit)
+ }
+
+ profileNames := []string{router.Profile}
+
+ mock.ExpectQuery("SELECT").WithArgs(pq.Array(profileNames)).WillReturnRows(rows)
+
+ sqlDeliveryservices, err := getDeliveryServices(db, routers)
+ if err != nil {
+ t.Errorf("getProfiles expected: nil error, actual: %v", err)
+ }
+
+ if len(deliveryservices) != len(sqlDeliveryservices) {
+ t.Errorf("getProfiles expected: %+v actual: %+v", deliveryservices, sqlDeliveryservices)
+ }
+
+ for i, sqlDeliveryservice := range sqlDeliveryservices {
+ deliveryservice := deliveryservices[i]
+ if deliveryservice != sqlDeliveryservice {
+ t.Errorf("getDeliveryServices expected: %v, actual: %v", deliveryservice, sqlDeliveryservice)
+ }
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestGetConfig(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ config := map[string]string{
+ "name0": "val0",
+ "name1": "val1",
+ }
+
+ rows := sqlmock.NewRows([]string{"name", "value"})
+ for name, val := range config {
+ rows = rows.AddRow(name, val)
+ }
+
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ sqlConfig, err := getConfig(db)
+ if err != nil {
+ t.Errorf("getProfiles expected: nil error, actual: %v", err)
+ }
+
+ if !reflect.DeepEqual(config, sqlConfig) {
+ t.Errorf("getConfig expected: %+v actual: %+v", config, sqlConfig)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestGetMonitoringJson(t *testing.T) {
+ resp := MonitoringResponse{}
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ cdn := "mycdn"
+
+ {
+ //
+ // getServers
+ //
+ monitor := Monitor{
+ BasicServer: BasicServer{Profile: "monitorProfile",
+ Status: "monitorStatus",
+ IP: "1.2.3.4",
+ IP6: "2001::4",
+ Port: 8081,
+ Cachegroup: "monitorCachegroup",
+ HostName: "monitorHost",
+ FQDN: "monitorFqdn.me",
+ },
+ }
+
+ cacheType := "EDGE"
+ cache := Cache{
+ BasicServer: BasicServer{
+ Profile: "cacheProfile",
+ Status: "cacheStatus",
+ IP: "1.2.3.4",
+ IP6: "2001::4",
+ Port: 8081,
+ Cachegroup: "cacheCachegroup",
+ HostName: "cacheHost",
+ FQDN: "cacheFqdn.me",
+ },
+ InterfaceName: "cacheInterface",
+ Type: cacheType,
+ HashID: "cacheHash",
+ }
+
+ router := Router{
+ Type: RouterType,
+ Profile: "routerProfile",
+ }
+
+ rows := sqlmock.NewRows([]string{"hostName", "fqdn", "status", "cachegroup", "port", "ip", "ip6", "profile", "interfaceName", "type", "hashId"})
+ rows = rows.AddRow(monitor.HostName, monitor.FQDN, monitor.Status, monitor.Cachegroup, monitor.Port, monitor.IP, monitor.IP6, monitor.Profile, "noInterface", MonitorType, "noHash")
+ rows = rows.AddRow(cache.HostName, cache.FQDN, cache.Status, cache.Cachegroup, cache.Port, cache.IP, cache.IP6, cache.Profile, cache.InterfaceName, cache.Type, cache.HashID)
+ rows = rows.AddRow("noHostname", "noFqdn", "noStatus", "noGroup", 0, "noIp", "noIp6", router.Profile, "noInterface", RouterType, "noHashid")
+
+ mock.ExpectQuery("SELECT").WithArgs(cdn).WillReturnRows(rows)
+ resp.Response.TrafficServers = []Cache{cache}
+ resp.Response.TrafficMonitors = []Monitor{monitor}
+ }
+ {
+ //
+ // getCachegroups
+ //
+ cachegroup := Cachegroup{
+ Name: "myCachegroup",
+ Coordinates: Coordinates{
+ Latitude: 42.42,
+ Longitude: 24.24,
+ },
+ }
+
+ rows := sqlmock.NewRows([]string{"name", "latitude", "longitude"})
+ rows = rows.AddRow(cachegroup.Name, cachegroup.Coordinates.Latitude, cachegroup.Coordinates.Longitude)
+
+ mock.ExpectQuery("SELECT").WithArgs(cdn).WillReturnRows(rows)
+ resp.Response.Cachegroups = []Cachegroup{cachegroup}
+ }
+ {
+ //
+ // getProfiles
+ //
+ cache := Cache{
+ BasicServer: BasicServer{
+ Profile: "cacheProfile",
+ Status: "cacheStatus",
+ IP: "1.2.3.4",
+ IP6: "2001::4",
+ Port: 8081,
+ Cachegroup: "cacheCachegroup",
+ HostName: "cacheHost",
+ FQDN: "cacheFqdn.me",
+ },
+ InterfaceName: "cacheInterface",
+ Type: "EDGE",
+ HashID: "cacheHash",
+ }
+
+ router := Router{
+ Type: RouterType,
+ Profile: "routerProfile",
+ }
+
+ profiles := []Profile{
+ Profile{
+ Name: router.Profile,
+ Type: RouterType,
+ Parameters: map[string]string{
+ "param0": "param0Val",
+ "param1": "param1Val",
+ },
+ },
+ Profile{
+ Name: cache.Profile,
+ Type: "EDGE",
+ Parameters: map[string]string{
+ "2param0": "2param0Val",
+ "2param1": "2param1Val",
+ },
+ },
+ }
+
+ rows := sqlmock.NewRows([]string{"profile", "name", "value"})
+ for _, profile := range profiles {
+ for paramName, paramVal := range profile.Parameters {
+ rows = rows.AddRow(profile.Name, paramName, paramVal)
+ }
+ }
+
+ // caches := []Cache{cache}
+ // routers := []Router{router}
+
+ profileNames := []string{"cacheProfile"}
+
+ mock.ExpectQuery("SELECT").WithArgs(pq.Array(profileNames), CacheMonitorConfigFile).WillReturnRows(rows)
+ resp.Response.Profiles = profiles
+ }
+ {
+ //
+ // getDeliveryServices
+ //
+ router := Router{
+ Type: RouterType,
+ Profile: "routerProfile",
+ }
+
+ deliveryservice := DeliveryService{
+ XMLID: "myDsid",
+ TotalTPSThreshold: 42.42,
+ Status: DeliveryServiceStatus,
+ TotalKBPSThreshold: 24.24,
+ }
+
+ deliveryservices := []DeliveryService{deliveryservice}
+ // routers := []Router{router}
+
+ rows := sqlmock.NewRows([]string{"xml_id", "global_max_tps", "global_max_mbps"})
+ for _, deliveryservice := range deliveryservices {
+ rows = rows.AddRow(deliveryservice.XMLID, deliveryservice.TotalTPSThreshold, deliveryservice.TotalKBPSThreshold/KilobitsPerMegabit)
+ }
+
+ profileNames := []string{router.Profile}
+
+ mock.ExpectQuery("SELECT").WithArgs(pq.Array(profileNames)).WillReturnRows(rows)
+ resp.Response.DeliveryServices = deliveryservices
+ }
+ {
+ //
+ // getConfig
+ //
+ config := map[string]string{
+ "name0": "val0",
+ "name1": "val1",
+ }
+
+ rows := sqlmock.NewRows([]string{"name", "value"})
+ for name, val := range config {
+ rows = rows.AddRow(name, val)
+ }
+
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+ resp.Response.Config = config
+ }
+
+ sqlResp, err := getMonitoringJson(cdn, db)
+ if err != nil {
+ t.Errorf("getMonitoringJson expected: nil error, actual: %v", err)
+ }
+
+ resp.Response.TrafficServers = sortCaches(resp.Response.TrafficServers)
+ sqlResp.Response.TrafficServers = sortCaches(sqlResp.Response.TrafficServers)
+ resp.Response.TrafficMonitors = sortMonitors(resp.Response.TrafficMonitors)
+ sqlResp.Response.TrafficMonitors = sortMonitors(sqlResp.Response.TrafficMonitors)
+ resp.Response.Cachegroups = sortCachegroups(resp.Response.Cachegroups)
+ sqlResp.Response.Cachegroups = sortCachegroups(sqlResp.Response.Cachegroups)
+ resp.Response.Profiles = sortProfiles(resp.Response.Profiles)
+ sqlResp.Response.Profiles = sortProfiles(sqlResp.Response.Profiles)
+ resp.Response.DeliveryServices = sortDeliveryServices(resp.Response.DeliveryServices)
+ sqlResp.Response.DeliveryServices = sortDeliveryServices(sqlResp.Response.DeliveryServices)
+
+ if !reflect.DeepEqual(sqlResp.Response.TrafficServers, resp.Response.TrafficServers) {
+ t.Errorf("getMonitoringJson expected TrafficServers: %+v actual: %+v", resp.Response.TrafficServers, sqlResp.Response.TrafficServers)
+ }
+ if !reflect.DeepEqual(sqlResp.Response.TrafficMonitors, resp.Response.TrafficMonitors) {
+ t.Errorf("getMonitoringJson expected TrafficMonitors: %+v actual: %+v", resp.Response.TrafficMonitors, sqlResp.Response.TrafficMonitors)
+ }
+ if !reflect.DeepEqual(sqlResp.Response.Cachegroups, resp.Response.Cachegroups) {
+ t.Errorf("getMonitoringJson expected Cachegroups: %+v actual: %+v", resp.Response.Cachegroups, sqlResp.Response.Cachegroups)
+ }
+ if !reflect.DeepEqual(sqlResp.Response.Profiles, resp.Response.Profiles) {
+ t.Errorf("getMonitoringJson expected Profiles: %+v actual: %+v", resp.Response.Profiles, sqlResp.Response.Profiles)
+ }
+ if !reflect.DeepEqual(sqlResp.Response.DeliveryServices, resp.Response.DeliveryServices) {
+ t.Errorf("getMonitoringJson expected DeliveryServices: %+v actual: %+v", resp.Response.DeliveryServices, sqlResp.Response.DeliveryServices)
+ }
+ if !reflect.DeepEqual(sqlResp.Response.Config, resp.Response.Config) {
+ t.Errorf("getMonitoringJson expected Config: %+v actual: %+v", resp.Response.Config, sqlResp.Response.Config)
+ }
+
+}
[42/43] incubator-trafficcontrol git commit: Move TO Golang
DBMaxConns from db.conf to cdn.conf
Posted by de...@apache.org.
Move TO Golang DBMaxConns from db.conf to cdn.conf
As requested by @dewrich
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/9987fb9a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/9987fb9a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/9987fb9a
Branch: refs/heads/master
Commit: 9987fb9ae3442048914fead01ed0337227de695d
Parents: 57c1a13
Author: Robert Butts <ro...@gmail.com>
Authored: Sun Aug 6 10:30:17 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/traffic_ops_golang/perlconfig.go | 40 +++++++++++++++--------
1 file changed, 26 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/9987fb9a/traffic_ops/traffic_ops_golang/perlconfig.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/perlconfig.go b/traffic_ops/traffic_ops_golang/perlconfig.go
index d088fb3..ff118b3 100644
--- a/traffic_ops/traffic_ops_golang/perlconfig.go
+++ b/traffic_ops/traffic_ops_golang/perlconfig.go
@@ -72,12 +72,6 @@ func getPerlConfigsFromStrs(cdnConfBytes string, dbConfBytes string) (Config, er
cfg.LogLocationEvent = OldAccessLogPath
cfg.LogLocationDebug = log.LogLocationNull
- if dbconf.MaxConnections != nil {
- cfg.MaxDBConnections = *dbconf.MaxConnections
- } else {
- cfg.MaxDBConnections = DefaultMaxDBConnections
- }
-
return cfg, nil
}
@@ -115,6 +109,13 @@ func getCDNConf(s string) (Config, error) {
return Config{}, err
}
+ if dbMaxConns, err := getDBMaxConns(obj); err != nil {
+ log.Warnf("failed to get Max DB Connections from cdn.conf (%v), using default %v\n", err, DefaultMaxDBConnections)
+ cfg.MaxDBConnections = DefaultMaxDBConnections
+ } else {
+ cfg.MaxDBConnections = dbMaxConns
+ }
+
return cfg, nil
}
@@ -135,6 +136,18 @@ func getPort(obj map[string]interface{}) (string, error) {
return strconv.Itoa(port), nil
}
+func getDBMaxConns(obj map[string]interface{}) (int, error) {
+ inum, ok := obj["traffic_ops_golang_max_db_connections"]
+ if !ok {
+ return 0, fmt.Errorf("missing traffic_ops_golang_max_db_connections key")
+ }
+ num, ok := inum.(float64)
+ if !ok {
+ return 0, fmt.Errorf("traffic_ops_golang_max_db_connections key '%v' type %T not a number", inum, inum)
+ }
+ return int(num), nil
+}
+
func getOldPort(obj map[string]interface{}) (string, error) {
hypnotoadI, ok := obj["hypnotoad"]
if !ok {
@@ -279,14 +292,13 @@ func getSecret(obj map[string]interface{}) (string, error) {
}
type DatabaseConf struct {
- Description string `json:"description"`
- DBName string `json:"dbname"`
- Hostname string `json:"hostname"`
- User string `json:"user"`
- Password string `json:"password"`
- Port string `json:"port"`
- Type string `json:"type"`
- MaxConnections *int `json:"max_connections"`
+ Description string `json:"description"`
+ DBName string `json:"dbname"`
+ Hostname string `json:"hostname"`
+ User string `json:"user"`
+ Password string `json:"password"`
+ Port string `json:"port"`
+ Type string `json:"type"`
}
func getDbConf(s string) (DatabaseConf, error) {
[05/43] incubator-trafficcontrol git commit: Add traffic_ops_golang
to RPM, service
Posted by de...@apache.org.
Add traffic_ops_golang to RPM, service
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/4fd7feb6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/4fd7feb6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/4fd7feb6
Branch: refs/heads/master
Commit: 4fd7feb624a6c888c8fc3b49a1104212b7dc9c2f
Parents: 04ed9f1
Author: Robert Butts <ro...@gmail.com>
Authored: Sun Jul 9 09:23:49 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:02 2017 -0600
----------------------------------------------------------------------
traffic_ops/build/traffic_ops.spec | 36 ++++++++++++++++++++
traffic_ops/etc/init.d/traffic_ops | 2 ++
traffic_ops/traffic_ops_golang/auth.go | 25 ++++++++++++++
traffic_ops/traffic_ops_golang/monitoring.go | 2 ++
traffic_ops/traffic_ops_golang/routes.go | 28 +++++++++------
.../traffic_ops_golang.config | 2 +-
.../traffic_ops_golang/traffic_ops_golang.go | 6 +++-
traffic_ops/traffic_ops_golang/wrappers.go | 9 ++++-
8 files changed, 97 insertions(+), 13 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4fd7feb6/traffic_ops/build/traffic_ops.spec
----------------------------------------------------------------------
diff --git a/traffic_ops/build/traffic_ops.spec b/traffic_ops/build/traffic_ops.spec
index cda9f59..3c899fe 100644
--- a/traffic_ops/build/traffic_ops.spec
+++ b/traffic_ops/build/traffic_ops.spec
@@ -55,6 +55,31 @@ Built: %(date) by %{getenv: USER}
# update version referenced in the source
perl -pi.bak -e 's/__VERSION__/%{version}-%{release}/' app/lib/UI/Utils.pm
+ export GOPATH=$(pwd)
+ # Create build area with proper gopath structure
+ mkdir -p src pkg bin || { echo "Could not create directories in $(pwd): $!"; exit 1; }
+
+ # build tocookie (dependencies within traffic_control will fail to `go get` unless prebuilt)
+ godir=src/github.com/apache/incubator-trafficcontrol/traffic_ops/experimental/tocookie
+ ( mkdir -p "$godir" && \
+ cd "$godir" && \
+ cp -r "$TC_DIR"/traffic_ops/experimental/tocookie/* . && \
+ echo "go getting tocookie at $(pwd)" && \
+ go get -v \
+ ) || { echo "Could not build go tocookie at $(pwd): $!"; exit 1; }
+
+ # build traffic_ops_golang binary
+ godir=src/github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang
+ oldpwd=$(pwd)
+ ( mkdir -p "$godir" && \
+ cd "$godir" && \
+ cp -r "$TC_DIR"/traffic_ops/traffic_ops_golang/* . && \
+ echo "go getting at $(pwd)" && \
+ go get -d -v && \
+ echo "go building at $(pwd)" && \
+ go build -ldflags "-B 0x`git rev-parse HEAD`" \
+ ) || { echo "Could not build go program at $(pwd): $!"; exit 1; }
+
%install
if [ -d $RPM_BUILD_ROOT ]; then
@@ -66,6 +91,9 @@ Built: %(date) by %{getenv: USER}
fi
%__cp -R $RPM_BUILD_DIR/traffic_ops-%{version}/* $RPM_BUILD_ROOT/%{PACKAGEDIR}
+ echo "go rming $RPM_BUILD_ROOT/%{PACKAGEDIR}/{pkg,src,bin}"
+ %__rm -rf $RPM_BUILD_ROOT/%{PACKAGEDIR}/{pkg,src,bin}
+
%__mkdir -p $RPM_BUILD_ROOT/var/www/files
%__cp install/data/perl/osversions.cfg $RPM_BUILD_ROOT/var/www/files/.
@@ -73,6 +101,14 @@ Built: %(date) by %{getenv: USER}
%__mkdir -p $RPM_BUILD_ROOT/%{PACKAGEDIR}/app/public/routing
fi
+ # install traffic_ops_golang binary
+ if [ ! -d $RPM_BUILD_ROOT/%{PACKAGEDIR}/app/bin ]; then
+ %__mkdir -p $RPM_BUILD_ROOT/%{PACKAGEDIR}/app/bin
+ fi
+
+ src=src/github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang
+ %__cp -p "$src"/traffic_ops_golang "${RPM_BUILD_ROOT}"/opt/traffic_ops/app/bin/traffic_ops_golang
+ %__cp -p "$src"/traffic_ops_golang.config "${RPM_BUILD_ROOT}"/opt/traffic_ops/app/conf/traffic_ops_golang.config
%pre
/usr/bin/getent group %{TRAFFIC_OPS_GROUP} || /usr/sbin/groupadd -r %{TRAFFIC_OPS_GROUP}
/usr/bin/getent passwd %{TRAFFIC_OPS_USER} || /usr/sbin/useradd -r -d %{PACKAGEDIR} -s /sbin/nologin %{TRAFFIC_OPS_USER} -g %{TRAFFIC_OPS_GROUP}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4fd7feb6/traffic_ops/etc/init.d/traffic_ops
----------------------------------------------------------------------
diff --git a/traffic_ops/etc/init.d/traffic_ops b/traffic_ops/etc/init.d/traffic_ops
index d3090d5..01eef6f 100755
--- a/traffic_ops/etc/init.d/traffic_ops
+++ b/traffic_ops/etc/init.d/traffic_ops
@@ -59,11 +59,13 @@ stopHypnotoad ()
start ()
{
echo -e "Starting Traffic Ops\n"
+ cd $TO_DIR && $TO_DIR/bin/traffic_ops_golang -cfg $TO_DIR/conf/traffic_ops_golang.config &
cd $TO_DIR && $TO_DIR/local/bin/hypnotoad script/cdn
}
stop ()
{
+ killproc $TO_DIR/bin/traffic_ops_golang
stopHypnotoad
}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4fd7feb6/traffic_ops/traffic_ops_golang/auth.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/auth.go b/traffic_ops/traffic_ops_golang/auth.go
new file mode 100644
index 0000000..75849c1
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/auth.go
@@ -0,0 +1,25 @@
+package main
+
+import (
+ "database/sql"
+ "log" // TODO change to traffic_monitor_golang/common/log
+)
+
+func preparePrivLevelStmt(db *sql.DB) (*sql.Stmt, error) {
+ return db.Prepare("select r.priv_level from tm_user as u join role as r on u.role = r.id where u.username = $1")
+}
+
+func hasPrivLevel(privLevelStmt *sql.Stmt, user string, level int) bool {
+ var privLevel int
+ err := privLevelStmt.QueryRow(user).Scan(&privLevel)
+ switch {
+ case err == sql.ErrNoRows:
+ log.Println("Error checking user " + user + " priv level: user not in database")
+ return false
+ case err != nil:
+ log.Println("Error checking user " + user + " priv level: " + err.Error())
+ return false
+ default:
+ return privLevel >= level
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4fd7feb6/traffic_ops/traffic_ops_golang/monitoring.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/monitoring.go b/traffic_ops/traffic_ops_golang/monitoring.go
index b353fb5..c669d0b 100644
--- a/traffic_ops/traffic_ops_golang/monitoring.go
+++ b/traffic_ops/traffic_ops_golang/monitoring.go
@@ -10,6 +10,8 @@ import (
"time"
)
+const MonitoringPrivLevel = 10
+
const CacheMonitorConfigFile = "rascal.properties"
const MonitorType = "RASCAL"
const RouterType = "CCR"
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4fd7feb6/traffic_ops/traffic_ops_golang/routes.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index cc14450..f347eef 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -3,6 +3,7 @@ package main
import (
"crypto/tls"
"database/sql"
+ "fmt"
"net/http"
"net/http/httputil"
"regexp"
@@ -18,10 +19,6 @@ type ParamMap map[string]string
type RegexHandlerFunc func(w http.ResponseWriter, r *http.Request, params ParamMap)
-func getMonitoringRoute(d ServerData) RegexHandlerFunc {
- return wrapLogTime(wrapAuth(monitoringHandler(d.DB), d.NoAuth, d.TOSecret))
-}
-
// getRootHandler returns the / handler for the service, which reverse-proxies the old Perl Traffic Ops
func getRootHandler(d ServerData) http.Handler {
// debug
@@ -33,11 +30,16 @@ func getRootHandler(d ServerData) http.Handler {
return rp
}
-// GetRoutes returns the map of regex routes, and a catchall route if no regex matches.
-func GetRoutes(d ServerData) (map[string]RegexHandlerFunc, http.Handler) {
+// GetRoutes returns the map of regex routes, and a catchall route for when no regex matches.
+func GetRoutes(d ServerData) (map[string]RegexHandlerFunc, http.Handler, error) {
+ privLevelStmt, err := preparePrivLevelStmt(d.DB)
+ if err != nil {
+ return nil, nil, fmt.Errorf("Error preparing db priv level query: ", err)
+ }
+
return map[string]RegexHandlerFunc{
- "api/1.2/cdns/{cdn}/configs/monitoring.json": getMonitoringRoute(d),
- }, getRootHandler(d)
+ "api/1.2/cdns/{cdn}/configs/monitoring.json": wrapLogTime(wrapAuth(monitoringHandler(d.DB), d.NoAuth, d.TOSecret, privLevelStmt, MonitoringPrivLevel)),
+ }, getRootHandler(d), nil
}
type CompiledRoute struct {
@@ -86,10 +88,16 @@ func Handler(routes map[string]CompiledRoute, catchall http.Handler, w http.Resp
catchall.ServeHTTP(w, r)
}
-func RegisterRoutes(d ServerData) {
- routes, catchall := GetRoutes(d)
+func RegisterRoutes(d ServerData) error {
+ routes, catchall, err := GetRoutes(d)
+ if err != nil {
+ return err
+ }
+
compiledRoutes := CompileRoutes(&routes)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
Handler(compiledRoutes, catchall, w, r)
})
+
+ return nil
}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4fd7feb6/traffic_ops/traffic_ops_golang/traffic_ops_golang.config
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/traffic_ops_golang.config b/traffic_ops/traffic_ops_golang/traffic_ops_golang.config
index 19d2599..6bd9703 100644
--- a/traffic_ops/traffic_ops_golang/traffic_ops_golang.config
+++ b/traffic_ops/traffic_ops_golang/traffic_ops_golang.config
@@ -1,5 +1,5 @@
{
- "port": "443",
+ "port": "",
"db_user": "bill",
"db_pass": "thelizard",
"db_server": "db.trafficops.example.net",
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4fd7feb6/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/traffic_ops_golang.go b/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
index 48d3c4e..aec0637 100644
--- a/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
+++ b/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
@@ -47,7 +47,11 @@ func main() {
}
defer db.Close()
- RegisterRoutes(ServerData{DB: db, Config: cfg})
+ if err := RegisterRoutes(ServerData{DB: db, Config: cfg}); err != nil {
+ fmt.Printf("Error registering routes: %v\n", err)
+ return
+ }
+
fmt.Println("Listening on " + cfg.HTTPPort)
if err := http.ListenAndServeTLS(":"+cfg.HTTPPort, cfg.CertPath, cfg.KeyPath, nil); err != nil {
fmt.Printf("Error stopping server: %v\n", err)
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4fd7feb6/traffic_ops/traffic_ops_golang/wrappers.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/wrappers.go b/traffic_ops/traffic_ops_golang/wrappers.go
index daf5e34..c5fd9c0 100644
--- a/traffic_ops/traffic_ops_golang/wrappers.go
+++ b/traffic_ops/traffic_ops_golang/wrappers.go
@@ -1,6 +1,7 @@
package main
import (
+ "database/sql"
"fmt"
"github.com/apache/incubator-trafficcontrol/traffic_ops/experimental/tocookie"
"log" // TODO change to traffic_monitor_golang/common/log
@@ -8,7 +9,7 @@ import (
"time"
)
-func wrapAuth(h RegexHandlerFunc, noAuth bool, secret string) RegexHandlerFunc {
+func wrapAuth(h RegexHandlerFunc, noAuth bool, secret string, privLevelStmt *sql.Stmt, privLevelRequired int) RegexHandlerFunc {
if noAuth {
return h
}
@@ -37,6 +38,12 @@ func wrapAuth(h RegexHandlerFunc, noAuth bool, secret string) RegexHandlerFunc {
return
}
+ username := oldCookie.AuthData
+ if !hasPrivLevel(privLevelStmt, username, privLevelRequired) {
+ handleUnauthorized("insufficient privileges")
+ return
+ }
+
newCookieVal := tocookie.Refresh(oldCookie, secret)
http.SetCookie(w, &http.Cookie{Name: tocookie.Name, Value: newCookieVal})
h(w, r, p)
[25/43] incubator-trafficcontrol git commit: Fix TO Golang
postinstall to be executable
Posted by de...@apache.org.
Fix TO Golang postinstall to be executable
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/b147f108
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/b147f108
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/b147f108
Branch: refs/heads/master
Commit: b147f108d5821bbdb7c29eabf8e7fc04acbd4bdb
Parents: 8e8383e
Author: Robert Butts <ro...@gmail.com>
Authored: Wed Aug 2 08:23:14 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/install/bin/_postinstall | 0
1 file changed, 0 insertions(+), 0 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b147f108/traffic_ops/install/bin/_postinstall
----------------------------------------------------------------------
diff --git a/traffic_ops/install/bin/_postinstall b/traffic_ops/install/bin/_postinstall
old mode 100644
new mode 100755
[14/43] incubator-trafficcontrol git commit: Add TO Golang
configurable logging
Posted by de...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/monitoring_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/monitoring_test.go b/traffic_ops_golang/monitoring_test.go
deleted file mode 100644
index f6958e3..0000000
--- a/traffic_ops_golang/monitoring_test.go
+++ /dev/null
@@ -1,634 +0,0 @@
-package main
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import (
- "reflect"
- "sort"
- "testing"
-
- "github.com/lib/pq"
- "gopkg.in/DATA-DOG/go-sqlmock.v1"
-)
-
-func TestGetServers(t *testing.T) {
- db, mock, err := sqlmock.New()
- if err != nil {
- t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- cdn := "mycdn"
-
- monitor := Monitor{
- BasicServer: BasicServer{Profile: "monitorProfile",
- Status: "monitorStatus",
- IP: "1.2.3.4",
- IP6: "2001::4",
- Port: 8081,
- Cachegroup: "monitorCachegroup",
- HostName: "monitorHost",
- FQDN: "monitorFqdn.me",
- },
- }
-
- cacheType := "EDGE"
- cache := Cache{
- BasicServer: BasicServer{
- Profile: "cacheProfile",
- Status: "cacheStatus",
- IP: "1.2.3.4",
- IP6: "2001::4",
- Port: 8081,
- Cachegroup: "cacheCachegroup",
- HostName: "cacheHost",
- FQDN: "cacheFqdn.me",
- },
- InterfaceName: "cacheInterface",
- Type: cacheType,
- HashID: "cacheHash",
- }
-
- router := Router{
- Type: RouterType,
- Profile: "routerProfile",
- }
-
- rows := sqlmock.NewRows([]string{"hostName", "fqdn", "status", "cachegroup", "port", "ip", "ip6", "profile", "interfaceName", "type", "hashId"})
- rows = rows.AddRow(monitor.HostName, monitor.FQDN, monitor.Status, monitor.Cachegroup, monitor.Port, monitor.IP, monitor.IP6, monitor.Profile, "noInterface", MonitorType, "noHash")
- rows = rows.AddRow(cache.HostName, cache.FQDN, cache.Status, cache.Cachegroup, cache.Port, cache.IP, cache.IP6, cache.Profile, cache.InterfaceName, cache.Type, cache.HashID)
- rows = rows.AddRow("noHostname", "noFqdn", "noStatus", "noGroup", 0, "noIp", "noIp6", router.Profile, "noInterface", RouterType, "noHashid")
-
- mock.ExpectQuery("SELECT").WithArgs(cdn).WillReturnRows(rows)
-
- monitors, caches, routers, err := getServers(db, cdn)
- if err != nil {
- t.Errorf("getServers expected: nil error, actual: %v", err)
- }
-
- if len(monitors) != 1 {
- t.Errorf("getServers expected: len(monitors) == 1, actual: %v", len(monitors))
- }
- sqlMonitor := monitors[0]
- if sqlMonitor != monitor {
- t.Errorf("getServers expected: monitor == %+v, actual: %+v", monitor, sqlMonitor)
- }
-
- if len(caches) != 1 {
- t.Errorf("getServers expected: len(caches) == 1, actual: %v", len(caches))
- }
- sqlCache := caches[0]
- if sqlCache != cache {
- t.Errorf("getServers expected: cache == %+v, actual: %+v", cache, sqlCache)
- }
-
- if len(routers) != 1 {
- t.Errorf("getServers expected: len(routers) == 1, actual: %v", len(routers))
- }
- sqlRouter := routers[0]
- if sqlRouter != router {
- t.Errorf("getServers expected: router == %+v, actual: %+v", router, sqlRouter)
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestGetCachegroups(t *testing.T) {
- db, mock, err := sqlmock.New()
- if err != nil {
- t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- cdn := "mycdn"
-
- cachegroup := Cachegroup{
- Name: "myCachegroup",
- Coordinates: Coordinates{
- Latitude: 42.42,
- Longitude: 24.24,
- },
- }
-
- rows := sqlmock.NewRows([]string{"name", "latitude", "longitude"})
- rows = rows.AddRow(cachegroup.Name, cachegroup.Coordinates.Latitude, cachegroup.Coordinates.Longitude)
-
- mock.ExpectQuery("SELECT").WithArgs(cdn).WillReturnRows(rows)
-
- sqlCachegroups, err := getCachegroups(db, cdn)
- if err != nil {
- t.Errorf("getCachegroups expected: nil error, actual: %v", err)
- }
-
- if len(sqlCachegroups) != 1 {
- t.Errorf("getCachegroups expected: len(monitors) == 1, actual: %v", len(sqlCachegroups))
- }
- sqlCachegroup := sqlCachegroups[0]
- if sqlCachegroup != cachegroup {
- t.Errorf("getServers expected: cachegroup == %+v, actual: %+v", cachegroup, sqlCachegroup)
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-type SortableProfiles []Profile
-
-func (s SortableProfiles) Len() int {
- return len(s)
-}
-func (s SortableProfiles) Swap(i, j int) {
- s[i], s[j] = s[j], s[i]
-}
-func (s SortableProfiles) Less(i, j int) bool {
- return s[i].Name < s[j].Name
-}
-
-func sortProfiles(p []Profile) []Profile {
- sort.Sort(SortableProfiles(p))
- return p
-}
-
-type SortableMonitors []Monitor
-
-func (s SortableMonitors) Len() int {
- return len(s)
-}
-func (s SortableMonitors) Swap(i, j int) {
- s[i], s[j] = s[j], s[i]
-}
-func (s SortableMonitors) Less(i, j int) bool {
- return s[i].HostName < s[j].HostName
-}
-
-func sortMonitors(p []Monitor) []Monitor {
- sort.Sort(SortableMonitors(p))
- return p
-}
-
-type SortableCaches []Cache
-
-func (s SortableCaches) Len() int {
- return len(s)
-}
-func (s SortableCaches) Swap(i, j int) {
- s[i], s[j] = s[j], s[i]
-}
-func (s SortableCaches) Less(i, j int) bool {
- return s[i].HostName < s[j].HostName
-}
-
-func sortCaches(p []Cache) []Cache {
- sort.Sort(SortableCaches(p))
- return p
-}
-
-type SortableCachegroups []Cachegroup
-
-func (s SortableCachegroups) Len() int {
- return len(s)
-}
-func (s SortableCachegroups) Swap(i, j int) {
- s[i], s[j] = s[j], s[i]
-}
-func (s SortableCachegroups) Less(i, j int) bool {
- return s[i].Name < s[j].Name
-}
-
-func sortCachegroups(p []Cachegroup) []Cachegroup {
- sort.Sort(SortableCachegroups(p))
- return p
-}
-
-type SortableDeliveryServices []DeliveryService
-
-func (s SortableDeliveryServices) Len() int {
- return len(s)
-}
-func (s SortableDeliveryServices) Swap(i, j int) {
- s[i], s[j] = s[j], s[i]
-}
-func (s SortableDeliveryServices) Less(i, j int) bool {
- return s[i].XMLID < s[j].XMLID
-}
-
-func sortDeliveryServices(p []DeliveryService) []DeliveryService {
- sort.Sort(SortableDeliveryServices(p))
- return p
-}
-
-func TestGetProfiles(t *testing.T) {
- db, mock, err := sqlmock.New()
- if err != nil {
- t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- cache := Cache{
- BasicServer: BasicServer{
- Profile: "cacheProfile",
- Status: "cacheStatus",
- IP: "1.2.3.4",
- IP6: "2001::4",
- Port: 8081,
- Cachegroup: "cacheCachegroup",
- HostName: "cacheHost",
- FQDN: "cacheFqdn.me",
- },
- InterfaceName: "cacheInterface",
- Type: "EDGE",
- HashID: "cacheHash",
- }
-
- router := Router{
- Type: RouterType,
- Profile: "routerProfile",
- }
-
- profiles := []Profile{
- Profile{
- Name: router.Profile,
- Type: RouterType,
- Parameters: map[string]string{
- "param0": "param0Val",
- "param1": "param1Val",
- },
- },
- Profile{
- Name: cache.Profile,
- Type: "myType2",
- Parameters: map[string]string{
- "2param0": "2param0Val",
- "2param1": "2param1Val",
- },
- },
- }
-
- rows := sqlmock.NewRows([]string{"profile", "name", "value"})
- for _, profile := range profiles {
- for paramName, paramVal := range profile.Parameters {
- rows = rows.AddRow(profile.Name, paramName, paramVal)
- }
- }
-
- caches := []Cache{cache}
- routers := []Router{router}
-
- profileNames := []string{"cacheProfile"}
-
- mock.ExpectQuery("SELECT").WithArgs(pq.Array(profileNames), CacheMonitorConfigFile).WillReturnRows(rows)
-
- sqlProfiles, err := getProfiles(db, caches, routers)
- if err != nil {
- t.Errorf("getProfiles expected: nil error, actual: %v", err)
- }
-
- if len(sqlProfiles) != len(profiles) {
- t.Errorf("getProfiles expected: %+v actual: %+v", profiles, sqlProfiles)
- }
-
- profiles = sortProfiles(profiles)
- sqlProfiles = sortProfiles(sqlProfiles)
-
- for i, profile := range profiles {
- if profile.Name != sqlProfiles[i].Name {
- t.Errorf("getProfiles expected: profiles[%v].Name %v, actual: %v", i, profile.Name, sqlProfiles[i].Name)
- }
- for paramName, paramVal := range profile.Parameters {
- val, ok := sqlProfiles[i].Parameters[paramName]
- if !ok {
- t.Errorf("getProfiles expected: profiles[%v].Parameters[%v] = %v, actual: nil", i, paramName, paramVal)
- }
- if val != paramVal {
- t.Errorf("getProfiles expected: profiles[%v].Parameters[%v] = %v, actual: %v", i, paramName, paramVal)
- }
- }
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestGetDeliveryServices(t *testing.T) {
- db, mock, err := sqlmock.New()
- if err != nil {
- t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- router := Router{
- Type: RouterType,
- Profile: "routerProfile",
- }
-
- deliveryservice := DeliveryService{
- XMLID: "myDsid",
- TotalTPSThreshold: 42.42,
- Status: DeliveryServiceStatus,
- TotalKBPSThreshold: 24.24,
- }
-
- deliveryservices := []DeliveryService{deliveryservice}
- routers := []Router{router}
-
- rows := sqlmock.NewRows([]string{"xml_id", "global_max_tps", "global_max_mbps"})
- for _, deliveryservice := range deliveryservices {
- rows = rows.AddRow(deliveryservice.XMLID, deliveryservice.TotalTPSThreshold, deliveryservice.TotalKBPSThreshold/KilobitsPerMegabit)
- }
-
- profileNames := []string{router.Profile}
-
- mock.ExpectQuery("SELECT").WithArgs(pq.Array(profileNames)).WillReturnRows(rows)
-
- sqlDeliveryservices, err := getDeliveryServices(db, routers)
- if err != nil {
- t.Errorf("getProfiles expected: nil error, actual: %v", err)
- }
-
- if len(deliveryservices) != len(sqlDeliveryservices) {
- t.Errorf("getProfiles expected: %+v actual: %+v", deliveryservices, sqlDeliveryservices)
- }
-
- for i, sqlDeliveryservice := range sqlDeliveryservices {
- deliveryservice := deliveryservices[i]
- if deliveryservice != sqlDeliveryservice {
- t.Errorf("getDeliveryServices expected: %v, actual: %v", deliveryservice, sqlDeliveryservice)
- }
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestGetConfig(t *testing.T) {
- db, mock, err := sqlmock.New()
- if err != nil {
- t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- config := map[string]string{
- "name0": "val0",
- "name1": "val1",
- }
-
- rows := sqlmock.NewRows([]string{"name", "value"})
- for name, val := range config {
- rows = rows.AddRow(name, val)
- }
-
- mock.ExpectQuery("SELECT").WillReturnRows(rows)
-
- sqlConfig, err := getConfig(db)
- if err != nil {
- t.Errorf("getProfiles expected: nil error, actual: %v", err)
- }
-
- if !reflect.DeepEqual(config, sqlConfig) {
- t.Errorf("getConfig expected: %+v actual: %+v", config, sqlConfig)
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestGetMonitoringJson(t *testing.T) {
- resp := MonitoringResponse{}
- db, mock, err := sqlmock.New()
- if err != nil {
- t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- cdn := "mycdn"
-
- {
- //
- // getServers
- //
- monitor := Monitor{
- BasicServer: BasicServer{Profile: "monitorProfile",
- Status: "monitorStatus",
- IP: "1.2.3.4",
- IP6: "2001::4",
- Port: 8081,
- Cachegroup: "monitorCachegroup",
- HostName: "monitorHost",
- FQDN: "monitorFqdn.me",
- },
- }
-
- cacheType := "EDGE"
- cache := Cache{
- BasicServer: BasicServer{
- Profile: "cacheProfile",
- Status: "cacheStatus",
- IP: "1.2.3.4",
- IP6: "2001::4",
- Port: 8081,
- Cachegroup: "cacheCachegroup",
- HostName: "cacheHost",
- FQDN: "cacheFqdn.me",
- },
- InterfaceName: "cacheInterface",
- Type: cacheType,
- HashID: "cacheHash",
- }
-
- router := Router{
- Type: RouterType,
- Profile: "routerProfile",
- }
-
- rows := sqlmock.NewRows([]string{"hostName", "fqdn", "status", "cachegroup", "port", "ip", "ip6", "profile", "interfaceName", "type", "hashId"})
- rows = rows.AddRow(monitor.HostName, monitor.FQDN, monitor.Status, monitor.Cachegroup, monitor.Port, monitor.IP, monitor.IP6, monitor.Profile, "noInterface", MonitorType, "noHash")
- rows = rows.AddRow(cache.HostName, cache.FQDN, cache.Status, cache.Cachegroup, cache.Port, cache.IP, cache.IP6, cache.Profile, cache.InterfaceName, cache.Type, cache.HashID)
- rows = rows.AddRow("noHostname", "noFqdn", "noStatus", "noGroup", 0, "noIp", "noIp6", router.Profile, "noInterface", RouterType, "noHashid")
-
- mock.ExpectQuery("SELECT").WithArgs(cdn).WillReturnRows(rows)
- resp.Response.TrafficServers = []Cache{cache}
- resp.Response.TrafficMonitors = []Monitor{monitor}
- }
- {
- //
- // getCachegroups
- //
- cachegroup := Cachegroup{
- Name: "myCachegroup",
- Coordinates: Coordinates{
- Latitude: 42.42,
- Longitude: 24.24,
- },
- }
-
- rows := sqlmock.NewRows([]string{"name", "latitude", "longitude"})
- rows = rows.AddRow(cachegroup.Name, cachegroup.Coordinates.Latitude, cachegroup.Coordinates.Longitude)
-
- mock.ExpectQuery("SELECT").WithArgs(cdn).WillReturnRows(rows)
- resp.Response.Cachegroups = []Cachegroup{cachegroup}
- }
- {
- //
- // getProfiles
- //
- cache := Cache{
- BasicServer: BasicServer{
- Profile: "cacheProfile",
- Status: "cacheStatus",
- IP: "1.2.3.4",
- IP6: "2001::4",
- Port: 8081,
- Cachegroup: "cacheCachegroup",
- HostName: "cacheHost",
- FQDN: "cacheFqdn.me",
- },
- InterfaceName: "cacheInterface",
- Type: "EDGE",
- HashID: "cacheHash",
- }
-
- router := Router{
- Type: RouterType,
- Profile: "routerProfile",
- }
-
- profiles := []Profile{
- Profile{
- Name: router.Profile,
- Type: RouterType,
- Parameters: map[string]string{
- "param0": "param0Val",
- "param1": "param1Val",
- },
- },
- Profile{
- Name: cache.Profile,
- Type: "EDGE",
- Parameters: map[string]string{
- "2param0": "2param0Val",
- "2param1": "2param1Val",
- },
- },
- }
-
- rows := sqlmock.NewRows([]string{"profile", "name", "value"})
- for _, profile := range profiles {
- for paramName, paramVal := range profile.Parameters {
- rows = rows.AddRow(profile.Name, paramName, paramVal)
- }
- }
-
- // caches := []Cache{cache}
- // routers := []Router{router}
-
- profileNames := []string{"cacheProfile"}
-
- mock.ExpectQuery("SELECT").WithArgs(pq.Array(profileNames), CacheMonitorConfigFile).WillReturnRows(rows)
- resp.Response.Profiles = profiles
- }
- {
- //
- // getDeliveryServices
- //
- router := Router{
- Type: RouterType,
- Profile: "routerProfile",
- }
-
- deliveryservice := DeliveryService{
- XMLID: "myDsid",
- TotalTPSThreshold: 42.42,
- Status: DeliveryServiceStatus,
- TotalKBPSThreshold: 24.24,
- }
-
- deliveryservices := []DeliveryService{deliveryservice}
- // routers := []Router{router}
-
- rows := sqlmock.NewRows([]string{"xml_id", "global_max_tps", "global_max_mbps"})
- for _, deliveryservice := range deliveryservices {
- rows = rows.AddRow(deliveryservice.XMLID, deliveryservice.TotalTPSThreshold, deliveryservice.TotalKBPSThreshold/KilobitsPerMegabit)
- }
-
- profileNames := []string{router.Profile}
-
- mock.ExpectQuery("SELECT").WithArgs(pq.Array(profileNames)).WillReturnRows(rows)
- resp.Response.DeliveryServices = deliveryservices
- }
- {
- //
- // getConfig
- //
- config := map[string]string{
- "name0": "val0",
- "name1": "val1",
- }
-
- rows := sqlmock.NewRows([]string{"name", "value"})
- for name, val := range config {
- rows = rows.AddRow(name, val)
- }
-
- mock.ExpectQuery("SELECT").WillReturnRows(rows)
- resp.Response.Config = config
- }
-
- sqlResp, err := getMonitoringJson(cdn, db)
- if err != nil {
- t.Errorf("getMonitoringJson expected: nil error, actual: %v", err)
- }
-
- resp.Response.TrafficServers = sortCaches(resp.Response.TrafficServers)
- sqlResp.Response.TrafficServers = sortCaches(sqlResp.Response.TrafficServers)
- resp.Response.TrafficMonitors = sortMonitors(resp.Response.TrafficMonitors)
- sqlResp.Response.TrafficMonitors = sortMonitors(sqlResp.Response.TrafficMonitors)
- resp.Response.Cachegroups = sortCachegroups(resp.Response.Cachegroups)
- sqlResp.Response.Cachegroups = sortCachegroups(sqlResp.Response.Cachegroups)
- resp.Response.Profiles = sortProfiles(resp.Response.Profiles)
- sqlResp.Response.Profiles = sortProfiles(sqlResp.Response.Profiles)
- resp.Response.DeliveryServices = sortDeliveryServices(resp.Response.DeliveryServices)
- sqlResp.Response.DeliveryServices = sortDeliveryServices(sqlResp.Response.DeliveryServices)
-
- if !reflect.DeepEqual(sqlResp.Response.TrafficServers, resp.Response.TrafficServers) {
- t.Errorf("getMonitoringJson expected TrafficServers: %+v actual: %+v", resp.Response.TrafficServers, sqlResp.Response.TrafficServers)
- }
- if !reflect.DeepEqual(sqlResp.Response.TrafficMonitors, resp.Response.TrafficMonitors) {
- t.Errorf("getMonitoringJson expected TrafficMonitors: %+v actual: %+v", resp.Response.TrafficMonitors, sqlResp.Response.TrafficMonitors)
- }
- if !reflect.DeepEqual(sqlResp.Response.Cachegroups, resp.Response.Cachegroups) {
- t.Errorf("getMonitoringJson expected Cachegroups: %+v actual: %+v", resp.Response.Cachegroups, sqlResp.Response.Cachegroups)
- }
- if !reflect.DeepEqual(sqlResp.Response.Profiles, resp.Response.Profiles) {
- t.Errorf("getMonitoringJson expected Profiles: %+v actual: %+v", resp.Response.Profiles, sqlResp.Response.Profiles)
- }
- if !reflect.DeepEqual(sqlResp.Response.DeliveryServices, resp.Response.DeliveryServices) {
- t.Errorf("getMonitoringJson expected DeliveryServices: %+v actual: %+v", resp.Response.DeliveryServices, sqlResp.Response.DeliveryServices)
- }
- if !reflect.DeepEqual(sqlResp.Response.Config, resp.Response.Config) {
- t.Errorf("getMonitoringJson expected Config: %+v actual: %+v", resp.Response.Config, sqlResp.Response.Config)
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/LICENSE
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/LICENSE b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/LICENSE
deleted file mode 100644
index 7f8bedf..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/LICENSE
+++ /dev/null
@@ -1,28 +0,0 @@
-The three clause BSD license (http://en.wikipedia.org/wiki/BSD_licenses)
-
-Copyright (c) 2013-2017, DATA-DOG team
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* The name DataDog.lt may not be used to endorse or promote products
- derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
-OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
-EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/README.md
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/README.md b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/README.md
deleted file mode 100644
index f3d5487..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/README.md
+++ /dev/null
@@ -1,223 +0,0 @@
-[](https://travis-ci.org/DATA-DOG/go-sqlmock)
-[](https://godoc.org/github.com/DATA-DOG/go-sqlmock)
-[](https://codecov.io/github/DATA-DOG/go-sqlmock)
-
-# Sql driver mock for Golang
-
-**sqlmock** is a mock library implementing [sql/driver](https://godoc.org/database/sql/driver). Which has one and only
-purpose - to simulate any **sql** driver behavior in tests, without needing a real database connection. It helps to
-maintain correct **TDD** workflow.
-
-- this library is now complete and stable. (you may not find new changes for this reason)
-- supports concurrency and multiple connections.
-- supports **go1.8** Context related feature mocking and Named sql parameters.
-- does not require any modifications to your source code.
-- the driver allows to mock any sql driver method behavior.
-- has strict by default expectation order matching.
-- has no third party dependencies.
-
-## Install
-
- go get gopkg.in/DATA-DOG/go-sqlmock.v1
-
-## Documentation and Examples
-
-Visit [godoc](http://godoc.org/github.com/DATA-DOG/go-sqlmock) for general examples and public api reference.
-See **.travis.yml** for supported **go** versions.
-Different use case, is to functionally test with a real database - [go-txdb](https://github.com/DATA-DOG/go-txdb)
-all database related actions are isolated within a single transaction so the database can remain in the same state.
-
-See implementation examples:
-
-- [blog API server](https://github.com/DATA-DOG/go-sqlmock/tree/master/examples/blog)
-- [the same orders example](https://github.com/DATA-DOG/go-sqlmock/tree/master/examples/orders)
-
-### Something you may want to test
-
-``` go
-package main
-
-import "database/sql"
-
-func recordStats(db *sql.DB, userID, productID int64) (err error) {
- tx, err := db.Begin()
- if err != nil {
- return
- }
-
- defer func() {
- switch err {
- case nil:
- err = tx.Commit()
- default:
- tx.Rollback()
- }
- }()
-
- if _, err = tx.Exec("UPDATE products SET views = views + 1"); err != nil {
- return
- }
- if _, err = tx.Exec("INSERT INTO product_viewers (user_id, product_id) VALUES (?, ?)", userID, productID); err != nil {
- return
- }
- return
-}
-
-func main() {
- // @NOTE: the real connection is not required for tests
- db, err := sql.Open("mysql", "root@/blog")
- if err != nil {
- panic(err)
- }
- defer db.Close()
-
- if err = recordStats(db, 1 /*some user id*/, 5 /*some product id*/); err != nil {
- panic(err)
- }
-}
-```
-
-### Tests with sqlmock
-
-``` go
-package main
-
-import (
- "fmt"
- "testing"
-
- "gopkg.in/DATA-DOG/go-sqlmock.v1"
-)
-
-// a successful case
-func TestShouldUpdateStats(t *testing.T) {
- db, mock, err := sqlmock.New()
- if err != nil {
- t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectBegin()
- mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))
- mock.ExpectExec("INSERT INTO product_viewers").WithArgs(2, 3).WillReturnResult(sqlmock.NewResult(1, 1))
- mock.ExpectCommit()
-
- // now we execute our method
- if err = recordStats(db, 2, 3); err != nil {
- t.Errorf("error was not expected while updating stats: %s", err)
- }
-
- // we make sure that all expectations were met
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-// a failing test case
-func TestShouldRollbackStatUpdatesOnFailure(t *testing.T) {
- db, mock, err := sqlmock.New()
- if err != nil {
- t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectBegin()
- mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))
- mock.ExpectExec("INSERT INTO product_viewers").
- WithArgs(2, 3).
- WillReturnError(fmt.Errorf("some error"))
- mock.ExpectRollback()
-
- // now we execute our method
- if err = recordStats(db, 2, 3); err == nil {
- t.Errorf("was expecting an error, but there was none")
- }
-
- // we make sure that all expectations were met
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-```
-
-## Matching arguments like time.Time
-
-There may be arguments which are of `struct` type and cannot be compared easily by value like `time.Time`. In this case
-**sqlmock** provides an [Argument](https://godoc.org/github.com/DATA-DOG/go-sqlmock#Argument) interface which
-can be used in more sophisticated matching. Here is a simple example of time argument matching:
-
-``` go
-type AnyTime struct{}
-
-// Match satisfies sqlmock.Argument interface
-func (a AnyTime) Match(v driver.Value) bool {
- _, ok := v.(time.Time)
- return ok
-}
-
-func TestAnyTimeArgument(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectExec("INSERT INTO users").
- WithArgs("john", AnyTime{}).
- WillReturnResult(NewResult(1, 1))
-
- _, err = db.Exec("INSERT INTO users(name, created_at) VALUES (?, ?)", "john", time.Now())
- if err != nil {
- t.Errorf("error '%s' was not expected, while inserting a row", err)
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-```
-
-It only asserts that argument is of `time.Time` type.
-
-## Run tests
-
- go test -race
-
-## Change Log
-
-- **2017-02-09** - implemented support for **go1.8** features. **Rows** interface was changed to struct
- but contains all methods as before and should maintain backwards compatibility. **ExpectedQuery.WillReturnRows** may now
- accept multiple row sets.
-- **2016-11-02** - `db.Prepare()` was not validating expected prepare SQL
- query. It should still be validated even if Exec or Query is not
- executed on that prepared statement.
-- **2016-02-23** - added **sqlmock.AnyArg()** function to provide any kind
- of argument matcher.
-- **2016-02-23** - convert expected arguments to driver.Value as natural
- driver does, the change may affect time.Time comparison and will be
- stricter. See [issue](https://github.com/DATA-DOG/go-sqlmock/issues/31).
-- **2015-08-27** - **v1** api change, concurrency support, all known issues fixed.
-- **2014-08-16** instead of **panic** during reflect type mismatch when comparing query arguments - now return error
-- **2014-08-14** added **sqlmock.NewErrorResult** which gives an option to return driver.Result with errors for
-interface methods, see [issue](https://github.com/DATA-DOG/go-sqlmock/issues/5)
-- **2014-05-29** allow to match arguments in more sophisticated ways, by providing an **sqlmock.Argument** interface
-- **2014-04-21** introduce **sqlmock.New()** to open a mock database connection for tests. This method
-calls sql.DB.Ping to ensure that connection is open, see [issue](https://github.com/DATA-DOG/go-sqlmock/issues/4).
-This way on Close it will surely assert if all expectations are met, even if database was not triggered at all.
-The old way is still available, but it is advisable to call db.Ping manually before asserting with db.Close.
-- **2014-02-14** RowsFromCSVString is now a part of Rows interface named as FromCSVString.
-It has changed to allow more ways to construct rows and to easily extend this API in future.
-See [issue 1](https://github.com/DATA-DOG/go-sqlmock/issues/1)
-**RowsFromCSVString** is deprecated and will be removed in future
-
-## Contributions
-
-Feel free to open a pull request. Note, if you wish to contribute an extension to public (exported methods or types) -
-please open an issue before, to discuss whether these changes can be accepted. All backward incompatible changes are
-and will be treated cautiously
-
-## License
-
-The [three clause BSD license](http://en.wikipedia.org/wiki/BSD_licenses)
-
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument.go
deleted file mode 100644
index 7727481..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package sqlmock
-
-import "database/sql/driver"
-
-// Argument interface allows to match
-// any argument in specific way when used with
-// ExpectedQuery and ExpectedExec expectations.
-type Argument interface {
- Match(driver.Value) bool
-}
-
-// AnyArg will return an Argument which can
-// match any kind of arguments.
-//
-// Useful for time.Time or similar kinds of arguments.
-func AnyArg() Argument {
- return anyArgument{}
-}
-
-type anyArgument struct{}
-
-func (a anyArgument) Match(_ driver.Value) bool {
- return true
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument_test.go
deleted file mode 100644
index 3088ed4..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument_test.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package sqlmock
-
-import (
- "database/sql/driver"
- "testing"
- "time"
-)
-
-type AnyTime struct{}
-
-// Match satisfies sqlmock.Argument interface
-func (a AnyTime) Match(v driver.Value) bool {
- _, ok := v.(time.Time)
- return ok
-}
-
-func TestAnyTimeArgument(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectExec("INSERT INTO users").
- WithArgs("john", AnyTime{}).
- WillReturnResult(NewResult(1, 1))
-
- _, err = db.Exec("INSERT INTO users(name, created_at) VALUES (?, ?)", "john", time.Now())
- if err != nil {
- t.Errorf("error '%s' was not expected, while inserting a row", err)
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestByteSliceArgument(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- username := []byte("user")
- mock.ExpectExec("INSERT INTO users").WithArgs(username).WillReturnResult(NewResult(1, 1))
-
- _, err = db.Exec("INSERT INTO users(username) VALUES (?)", username)
- if err != nil {
- t.Errorf("error '%s' was not expected, while inserting a row", err)
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver.go
deleted file mode 100644
index 2a480fe..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver.go
+++ /dev/null
@@ -1,78 +0,0 @@
-package sqlmock
-
-import (
- "database/sql"
- "database/sql/driver"
- "fmt"
- "sync"
-)
-
-var pool *mockDriver
-
-func init() {
- pool = &mockDriver{
- conns: make(map[string]*sqlmock),
- }
- sql.Register("sqlmock", pool)
-}
-
-type mockDriver struct {
- sync.Mutex
- counter int
- conns map[string]*sqlmock
-}
-
-func (d *mockDriver) Open(dsn string) (driver.Conn, error) {
- d.Lock()
- defer d.Unlock()
-
- c, ok := d.conns[dsn]
- if !ok {
- return c, fmt.Errorf("expected a connection to be available, but it is not")
- }
-
- c.opened++
- return c, nil
-}
-
-// New creates sqlmock database connection
-// and a mock to manage expectations.
-// Pings db so that all expectations could be
-// asserted.
-func New() (*sql.DB, Sqlmock, error) {
- pool.Lock()
- dsn := fmt.Sprintf("sqlmock_db_%d", pool.counter)
- pool.counter++
-
- smock := &sqlmock{dsn: dsn, drv: pool, ordered: true}
- pool.conns[dsn] = smock
- pool.Unlock()
-
- return smock.open()
-}
-
-// NewWithDSN creates sqlmock database connection
-// with a specific DSN and a mock to manage expectations.
-// Pings db so that all expectations could be asserted.
-//
-// This method is introduced because of sql abstraction
-// libraries, which do not provide a way to initialize
-// with sql.DB instance. For example GORM library.
-//
-// Note, it will error if attempted to create with an
-// already used dsn
-//
-// It is not recommended to use this method, unless you
-// really need it and there is no other way around.
-func NewWithDSN(dsn string) (*sql.DB, Sqlmock, error) {
- pool.Lock()
- if _, ok := pool.conns[dsn]; ok {
- pool.Unlock()
- return nil, nil, fmt.Errorf("cannot create a new mock database with the same dsn: %s", dsn)
- }
- smock := &sqlmock{dsn: dsn, drv: pool, ordered: true}
- pool.conns[dsn] = smock
- pool.Unlock()
-
- return smock.open()
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver_test.go
deleted file mode 100644
index 1a65c1c..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver_test.go
+++ /dev/null
@@ -1,112 +0,0 @@
-package sqlmock
-
-import (
- "fmt"
- "testing"
-)
-
-type void struct{}
-
-func (void) Print(...interface{}) {}
-
-func ExampleNew() {
- db, mock, err := New()
- if err != nil {
- fmt.Println("expected no error, but got:", err)
- return
- }
- defer db.Close()
- // now we can expect operations performed on db
- mock.ExpectBegin().WillReturnError(fmt.Errorf("an error will occur on db.Begin() call"))
-}
-
-func TestShouldOpenConnectionIssue15(t *testing.T) {
- db, mock, err := New()
- if err != nil {
- t.Errorf("expected no error, but got: %s", err)
- }
- if len(pool.conns) != 1 {
- t.Errorf("expected 1 connection in pool, but there is: %d", len(pool.conns))
- }
-
- smock, _ := mock.(*sqlmock)
- if smock.opened != 1 {
- t.Errorf("expected 1 connection on mock to be opened, but there is: %d", smock.opened)
- }
-
- // defer so the rows gets closed first
- defer func() {
- if smock.opened != 0 {
- t.Errorf("expected no connections on mock to be opened, but there is: %d", smock.opened)
- }
- }()
-
- mock.ExpectQuery("SELECT").WillReturnRows(NewRows([]string{"one", "two"}).AddRow("val1", "val2"))
- rows, err := db.Query("SELECT")
- if err != nil {
- t.Errorf("unexpected error: %s", err)
- }
- defer rows.Close()
-
- mock.ExpectExec("UPDATE").WillReturnResult(NewResult(1, 1))
- if _, err = db.Exec("UPDATE"); err != nil {
- t.Errorf("unexpected error: %s", err)
- }
-
- // now there should be two connections open
- if smock.opened != 2 {
- t.Errorf("expected 2 connection on mock to be opened, but there is: %d", smock.opened)
- }
-
- mock.ExpectClose()
- if err = db.Close(); err != nil {
- t.Errorf("expected no error on close, but got: %s", err)
- }
-
- // one is still reserved for rows
- if smock.opened != 1 {
- t.Errorf("expected 1 connection on mock to be still reserved for rows, but there is: %d", smock.opened)
- }
-}
-
-func TestTwoOpenConnectionsOnTheSameDSN(t *testing.T) {
- db, mock, err := New()
- if err != nil {
- t.Errorf("expected no error, but got: %s", err)
- }
- db2, mock2, err := New()
- if err != nil {
- t.Errorf("expected no error, but got: %s", err)
- }
- if len(pool.conns) != 2 {
- t.Errorf("expected 2 connection in pool, but there is: %d", len(pool.conns))
- }
-
- if db == db2 {
- t.Errorf("expected not the same database instance, but it is the same")
- }
- if mock == mock2 {
- t.Errorf("expected not the same mock instance, but it is the same")
- }
-}
-
-func TestWrongDSN(t *testing.T) {
- t.Parallel()
- db, _, _ := New()
- defer db.Close()
- if _, err := db.Driver().Open("wrong_dsn"); err == nil {
- t.Error("expected error on Open")
- }
-}
-
-func TestNewDSN(t *testing.T) {
- if _, _, err := NewWithDSN("sqlmock_db_99"); err != nil {
- t.Errorf("expected no error on NewWithDSN, but got: %s", err)
- }
-}
-
-func TestDuplicateNewDSN(t *testing.T) {
- if _, _, err := NewWithDSN("sqlmock_db_1"); err == nil {
- t.Error("expected error on NewWithDSN")
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic.go
deleted file mode 100644
index 0fbf98d..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package main
-
-import "database/sql"
-
-func recordStats(db *sql.DB, userID, productID int64) (err error) {
- tx, err := db.Begin()
- if err != nil {
- return
- }
-
- defer func() {
- switch err {
- case nil:
- err = tx.Commit()
- default:
- tx.Rollback()
- }
- }()
-
- if _, err = tx.Exec("UPDATE products SET views = views + 1"); err != nil {
- return
- }
- if _, err = tx.Exec("INSERT INTO product_viewers (user_id, product_id) VALUES (?, ?)", userID, productID); err != nil {
- return
- }
- return
-}
-
-func main() {
- // @NOTE: the real connection is not required for tests
- db, err := sql.Open("mysql", "root@/blog")
- if err != nil {
- panic(err)
- }
- defer db.Close()
-
- if err = recordStats(db, 1 /*some user id*/, 5 /*some product id*/); err != nil {
- panic(err)
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic_test.go
deleted file mode 100644
index 0825f90..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic_test.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package main
-
-import (
- "fmt"
- "testing"
-
- "github.com/DATA-DOG/go-sqlmock"
-)
-
-// a successful case
-func TestShouldUpdateStats(t *testing.T) {
- db, mock, err := sqlmock.New()
- if err != nil {
- t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectBegin()
- mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))
- mock.ExpectExec("INSERT INTO product_viewers").WithArgs(2, 3).WillReturnResult(sqlmock.NewResult(1, 1))
- mock.ExpectCommit()
-
- // now we execute our method
- if err = recordStats(db, 2, 3); err != nil {
- t.Errorf("error was not expected while updating stats: %s", err)
- }
-
- // we make sure that all expectations were met
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-// a failing test case
-func TestShouldRollbackStatUpdatesOnFailure(t *testing.T) {
- db, mock, err := sqlmock.New()
- if err != nil {
- t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectBegin()
- mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))
- mock.ExpectExec("INSERT INTO product_viewers").
- WithArgs(2, 3).
- WillReturnError(fmt.Errorf("some error"))
- mock.ExpectRollback()
-
- // now we execute our method
- if err = recordStats(db, 2, 3); err == nil {
- t.Errorf("was expecting an error, but there was none")
- }
-
- // we make sure that all expectations were met
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog.go
deleted file mode 100644
index c4aec06..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog.go
+++ /dev/null
@@ -1,81 +0,0 @@
-package main
-
-import (
- "database/sql"
- "encoding/json"
- "net/http"
-)
-
-type api struct {
- db *sql.DB
-}
-
-type post struct {
- ID int
- Title string
- Body string
-}
-
-func (a *api) posts(w http.ResponseWriter, r *http.Request) {
- rows, err := a.db.Query("SELECT id, title, body FROM posts")
- if err != nil {
- a.fail(w, "failed to fetch posts: "+err.Error(), 500)
- return
- }
- defer rows.Close()
-
- var posts []*post
- for rows.Next() {
- p := &post{}
- if err := rows.Scan(&p.ID, &p.Title, &p.Body); err != nil {
- a.fail(w, "failed to scan post: "+err.Error(), 500)
- return
- }
- posts = append(posts, p)
- }
- if rows.Err() != nil {
- a.fail(w, "failed to read all posts: "+rows.Err().Error(), 500)
- return
- }
-
- data := struct {
- Posts []*post
- }{posts}
-
- a.ok(w, data)
-}
-
-func main() {
- // @NOTE: the real connection is not required for tests
- db, err := sql.Open("mysql", "root@/blog")
- if err != nil {
- panic(err)
- }
- app := &api{db: db}
- http.HandleFunc("/posts", app.posts)
- http.ListenAndServe(":8080", nil)
-}
-
-func (a *api) fail(w http.ResponseWriter, msg string, status int) {
- w.Header().Set("Content-Type", "application/json")
-
- data := struct {
- Error string
- }{Error: msg}
-
- resp, _ := json.Marshal(data)
- w.WriteHeader(status)
- w.Write(resp)
-}
-
-func (a *api) ok(w http.ResponseWriter, data interface{}) {
- w.Header().Set("Content-Type", "application/json")
-
- resp, err := json.Marshal(data)
- if err != nil {
- w.WriteHeader(http.StatusInternalServerError)
- a.fail(w, "oops something evil has happened", 500)
- return
- }
- w.Write(resp)
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog_test.go
deleted file mode 100644
index aa1881a..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog_test.go
+++ /dev/null
@@ -1,102 +0,0 @@
-package main
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "net/http"
- "net/http/httptest"
- "testing"
-
- "github.com/DATA-DOG/go-sqlmock"
-)
-
-func (a *api) assertJSON(actual []byte, data interface{}, t *testing.T) {
- expected, err := json.Marshal(data)
- if err != nil {
- t.Fatalf("an error '%s' was not expected when marshaling expected json data", err)
- }
-
- if bytes.Compare(expected, actual) != 0 {
- t.Errorf("the expected json: %s is different from actual %s", expected, actual)
- }
-}
-
-func TestShouldGetPosts(t *testing.T) {
- db, mock, err := sqlmock.New()
- if err != nil {
- t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- // create app with mocked db, request and response to test
- app := &api{db}
- req, err := http.NewRequest("GET", "http://localhost/posts", nil)
- if err != nil {
- t.Fatalf("an error '%s' was not expected while creating request", err)
- }
- w := httptest.NewRecorder()
-
- // before we actually execute our api function, we need to expect required DB actions
- rows := sqlmock.NewRows([]string{"id", "title", "body"}).
- AddRow(1, "post 1", "hello").
- AddRow(2, "post 2", "world")
-
- mock.ExpectQuery("^SELECT (.+) FROM posts$").WillReturnRows(rows)
-
- // now we execute our request
- app.posts(w, req)
-
- if w.Code != 200 {
- t.Fatalf("expected status code to be 200, but got: %d", w.Code)
- }
-
- data := struct {
- Posts []*post
- }{Posts: []*post{
- {ID: 1, Title: "post 1", Body: "hello"},
- {ID: 2, Title: "post 2", Body: "world"},
- }}
- app.assertJSON(w.Body.Bytes(), data, t)
-
- // we make sure that all expectations were met
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestShouldRespondWithErrorOnFailure(t *testing.T) {
- db, mock, err := sqlmock.New()
- if err != nil {
- t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- // create app with mocked db, request and response to test
- app := &api{db}
- req, err := http.NewRequest("GET", "http://localhost/posts", nil)
- if err != nil {
- t.Fatalf("an error '%s' was not expected while creating request", err)
- }
- w := httptest.NewRecorder()
-
- // before we actually execute our api function, we need to expect required DB actions
- mock.ExpectQuery("^SELECT (.+) FROM posts$").WillReturnError(fmt.Errorf("some error"))
-
- // now we execute our request
- app.posts(w, req)
-
- if w.Code != 500 {
- t.Fatalf("expected status code to be 500, but got: %d", w.Code)
- }
-
- data := struct {
- Error string
- }{"failed to fetch posts: some error"}
- app.assertJSON(w.Body.Bytes(), data, t)
-
- // we make sure that all expectations were met
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/doc.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/doc.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/doc.go
deleted file mode 100644
index c7842af..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/doc.go
+++ /dev/null
@@ -1 +0,0 @@
-package examples
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders.go
deleted file mode 100644
index fb7e47e..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders.go
+++ /dev/null
@@ -1,121 +0,0 @@
-package main
-
-import (
- "database/sql"
- "fmt"
- "log"
-
- "github.com/kisielk/sqlstruct"
-)
-
-const ORDER_PENDING = 0
-const ORDER_CANCELLED = 1
-
-type User struct {
- Id int `sql:"id"`
- Username string `sql:"username"`
- Balance float64 `sql:"balance"`
-}
-
-type Order struct {
- Id int `sql:"id"`
- Value float64 `sql:"value"`
- ReservedFee float64 `sql:"reserved_fee"`
- Status int `sql:"status"`
-}
-
-func cancelOrder(id int, db *sql.DB) (err error) {
- tx, err := db.Begin()
- if err != nil {
- return
- }
-
- var order Order
- var user User
- sql := fmt.Sprintf(`
-SELECT %s, %s
-FROM orders AS o
-INNER JOIN users AS u ON o.buyer_id = u.id
-WHERE o.id = ?
-FOR UPDATE`,
- sqlstruct.ColumnsAliased(order, "o"),
- sqlstruct.ColumnsAliased(user, "u"))
-
- // fetch order to cancel
- rows, err := tx.Query(sql, id)
- if err != nil {
- tx.Rollback()
- return
- }
-
- defer rows.Close()
- // no rows, nothing to do
- if !rows.Next() {
- tx.Rollback()
- return
- }
-
- // read order
- err = sqlstruct.ScanAliased(&order, rows, "o")
- if err != nil {
- tx.Rollback()
- return
- }
-
- // ensure order status
- if order.Status != ORDER_PENDING {
- tx.Rollback()
- return
- }
-
- // read user
- err = sqlstruct.ScanAliased(&user, rows, "u")
- if err != nil {
- tx.Rollback()
- return
- }
- rows.Close() // manually close before other prepared statements
-
- // refund order value
- sql = "UPDATE users SET balance = balance + ? WHERE id = ?"
- refundStmt, err := tx.Prepare(sql)
- if err != nil {
- tx.Rollback()
- return
- }
- defer refundStmt.Close()
- _, err = refundStmt.Exec(order.Value+order.ReservedFee, user.Id)
- if err != nil {
- tx.Rollback()
- return
- }
-
- // update order status
- order.Status = ORDER_CANCELLED
- sql = "UPDATE orders SET status = ?, updated = NOW() WHERE id = ?"
- orderUpdStmt, err := tx.Prepare(sql)
- if err != nil {
- tx.Rollback()
- return
- }
- defer orderUpdStmt.Close()
- _, err = orderUpdStmt.Exec(order.Status, order.Id)
- if err != nil {
- tx.Rollback()
- return
- }
- return tx.Commit()
-}
-
-func main() {
- // @NOTE: the real connection is not required for tests
- db, err := sql.Open("mysql", "root:@/orders")
- if err != nil {
- log.Fatal(err)
- }
- defer db.Close()
- err = cancelOrder(1, db)
- if err != nil {
- log.Fatal(err)
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders_test.go
deleted file mode 100644
index 7562b8f..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders_test.go
+++ /dev/null
@@ -1,108 +0,0 @@
-package main
-
-import (
- "fmt"
- "testing"
-
- "github.com/DATA-DOG/go-sqlmock"
-)
-
-// will test that order with a different status, cannot be cancelled
-func TestShouldNotCancelOrderWithNonPendingStatus(t *testing.T) {
- // open database stub
- db, mock, err := sqlmock.New()
- if err != nil {
- t.Errorf("An error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- // columns are prefixed with "o" since we used sqlstruct to generate them
- columns := []string{"o_id", "o_status"}
- // expect transaction begin
- mock.ExpectBegin()
- // expect query to fetch order and user, match it with regexp
- mock.ExpectQuery("SELECT (.+) FROM orders AS o INNER JOIN users AS u (.+) FOR UPDATE").
- WithArgs(1).
- WillReturnRows(sqlmock.NewRows(columns).FromCSVString("1,1"))
- // expect transaction rollback, since order status is "cancelled"
- mock.ExpectRollback()
-
- // run the cancel order function
- err = cancelOrder(1, db)
- if err != nil {
- t.Errorf("Expected no error, but got %s instead", err)
- }
- // we make sure that all expectations were met
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-// will test order cancellation
-func TestShouldRefundUserWhenOrderIsCancelled(t *testing.T) {
- // open database stub
- db, mock, err := sqlmock.New()
- if err != nil {
- t.Errorf("An error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- // columns are prefixed with "o" since we used sqlstruct to generate them
- columns := []string{"o_id", "o_status", "o_value", "o_reserved_fee", "u_id", "u_balance"}
- // expect transaction begin
- mock.ExpectBegin()
- // expect query to fetch order and user, match it with regexp
- mock.ExpectQuery("SELECT (.+) FROM orders AS o INNER JOIN users AS u (.+) FOR UPDATE").
- WithArgs(1).
- WillReturnRows(sqlmock.NewRows(columns).AddRow(1, 0, 25.75, 3.25, 2, 10.00))
- // expect user balance update
- mock.ExpectPrepare("UPDATE users SET balance").ExpectExec().
- WithArgs(25.75+3.25, 2). // refund amount, user id
- WillReturnResult(sqlmock.NewResult(0, 1)) // no insert id, 1 affected row
- // expect order status update
- mock.ExpectPrepare("UPDATE orders SET status").ExpectExec().
- WithArgs(ORDER_CANCELLED, 1). // status, id
- WillReturnResult(sqlmock.NewResult(0, 1)) // no insert id, 1 affected row
- // expect a transaction commit
- mock.ExpectCommit()
-
- // run the cancel order function
- err = cancelOrder(1, db)
- if err != nil {
- t.Errorf("Expected no error, but got %s instead", err)
- }
- // we make sure that all expectations were met
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-// will test order cancellation
-func TestShouldRollbackOnError(t *testing.T) {
- // open database stub
- db, mock, err := sqlmock.New()
- if err != nil {
- t.Errorf("An error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- // expect transaction begin
- mock.ExpectBegin()
- // expect query to fetch order and user, match it with regexp
- mock.ExpectQuery("SELECT (.+) FROM orders AS o INNER JOIN users AS u (.+) FOR UPDATE").
- WithArgs(1).
- WillReturnError(fmt.Errorf("Some error"))
- // should rollback since error was returned from query execution
- mock.ExpectRollback()
-
- // run the cancel order function
- err = cancelOrder(1, db)
- // error should return back
- if err == nil {
- t.Error("Expected error, but got none")
- }
- // we make sure that all expectations were met
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations.go
deleted file mode 100644
index 415759e..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations.go
+++ /dev/null
@@ -1,344 +0,0 @@
-package sqlmock
-
-import (
- "database/sql/driver"
- "fmt"
- "regexp"
- "strings"
- "sync"
- "time"
-)
-
-// an expectation interface
-type expectation interface {
- fulfilled() bool
- Lock()
- Unlock()
- String() string
-}
-
-// common expectation struct
-// satisfies the expectation interface
-type commonExpectation struct {
- sync.Mutex
- triggered bool
- err error
-}
-
-func (e *commonExpectation) fulfilled() bool {
- return e.triggered
-}
-
-// ExpectedClose is used to manage *sql.DB.Close expectation
-// returned by *Sqlmock.ExpectClose.
-type ExpectedClose struct {
- commonExpectation
-}
-
-// WillReturnError allows to set an error for *sql.DB.Close action
-func (e *ExpectedClose) WillReturnError(err error) *ExpectedClose {
- e.err = err
- return e
-}
-
-// String returns string representation
-func (e *ExpectedClose) String() string {
- msg := "ExpectedClose => expecting database Close"
- if e.err != nil {
- msg += fmt.Sprintf(", which should return error: %s", e.err)
- }
- return msg
-}
-
-// ExpectedBegin is used to manage *sql.DB.Begin expectation
-// returned by *Sqlmock.ExpectBegin.
-type ExpectedBegin struct {
- commonExpectation
- delay time.Duration
-}
-
-// WillReturnError allows to set an error for *sql.DB.Begin action
-func (e *ExpectedBegin) WillReturnError(err error) *ExpectedBegin {
- e.err = err
- return e
-}
-
-// String returns string representation
-func (e *ExpectedBegin) String() string {
- msg := "ExpectedBegin => expecting database transaction Begin"
- if e.err != nil {
- msg += fmt.Sprintf(", which should return error: %s", e.err)
- }
- return msg
-}
-
-// WillDelayFor allows to specify duration for which it will delay
-// result. May be used together with Context
-func (e *ExpectedBegin) WillDelayFor(duration time.Duration) *ExpectedBegin {
- e.delay = duration
- return e
-}
-
-// ExpectedCommit is used to manage *sql.Tx.Commit expectation
-// returned by *Sqlmock.ExpectCommit.
-type ExpectedCommit struct {
- commonExpectation
-}
-
-// WillReturnError allows to set an error for *sql.Tx.Close action
-func (e *ExpectedCommit) WillReturnError(err error) *ExpectedCommit {
- e.err = err
- return e
-}
-
-// String returns string representation
-func (e *ExpectedCommit) String() string {
- msg := "ExpectedCommit => expecting transaction Commit"
- if e.err != nil {
- msg += fmt.Sprintf(", which should return error: %s", e.err)
- }
- return msg
-}
-
-// ExpectedRollback is used to manage *sql.Tx.Rollback expectation
-// returned by *Sqlmock.ExpectRollback.
-type ExpectedRollback struct {
- commonExpectation
-}
-
-// WillReturnError allows to set an error for *sql.Tx.Rollback action
-func (e *ExpectedRollback) WillReturnError(err error) *ExpectedRollback {
- e.err = err
- return e
-}
-
-// String returns string representation
-func (e *ExpectedRollback) String() string {
- msg := "ExpectedRollback => expecting transaction Rollback"
- if e.err != nil {
- msg += fmt.Sprintf(", which should return error: %s", e.err)
- }
- return msg
-}
-
-// ExpectedQuery is used to manage *sql.DB.Query, *dql.DB.QueryRow, *sql.Tx.Query,
-// *sql.Tx.QueryRow, *sql.Stmt.Query or *sql.Stmt.QueryRow expectations.
-// Returned by *Sqlmock.ExpectQuery.
-type ExpectedQuery struct {
- queryBasedExpectation
- rows driver.Rows
- delay time.Duration
-}
-
-// WithArgs will match given expected args to actual database query arguments.
-// if at least one argument does not match, it will return an error. For specific
-// arguments an sqlmock.Argument interface can be used to match an argument.
-func (e *ExpectedQuery) WithArgs(args ...driver.Value) *ExpectedQuery {
- e.args = args
- return e
-}
-
-// WillReturnError allows to set an error for expected database query
-func (e *ExpectedQuery) WillReturnError(err error) *ExpectedQuery {
- e.err = err
- return e
-}
-
-// WillDelayFor allows to specify duration for which it will delay
-// result. May be used together with Context
-func (e *ExpectedQuery) WillDelayFor(duration time.Duration) *ExpectedQuery {
- e.delay = duration
- return e
-}
-
-// String returns string representation
-func (e *ExpectedQuery) String() string {
- msg := "ExpectedQuery => expecting Query or QueryRow which:"
- msg += "\n - matches sql: '" + e.sqlRegex.String() + "'"
-
- if len(e.args) == 0 {
- msg += "\n - is without arguments"
- } else {
- msg += "\n - is with arguments:\n"
- for i, arg := range e.args {
- msg += fmt.Sprintf(" %d - %+v\n", i, arg)
- }
- msg = strings.TrimSpace(msg)
- }
-
- if e.rows != nil {
- msg += fmt.Sprintf("\n - %s", e.rows)
- }
-
- if e.err != nil {
- msg += fmt.Sprintf("\n - should return error: %s", e.err)
- }
-
- return msg
-}
-
-// ExpectedExec is used to manage *sql.DB.Exec, *sql.Tx.Exec or *sql.Stmt.Exec expectations.
-// Returned by *Sqlmock.ExpectExec.
-type ExpectedExec struct {
- queryBasedExpectation
- result driver.Result
- delay time.Duration
-}
-
-// WithArgs will match given expected args to actual database exec operation arguments.
-// if at least one argument does not match, it will return an error. For specific
-// arguments an sqlmock.Argument interface can be used to match an argument.
-func (e *ExpectedExec) WithArgs(args ...driver.Value) *ExpectedExec {
- e.args = args
- return e
-}
-
-// WillReturnError allows to set an error for expected database exec action
-func (e *ExpectedExec) WillReturnError(err error) *ExpectedExec {
- e.err = err
- return e
-}
-
-// WillDelayFor allows to specify duration for which it will delay
-// result. May be used together with Context
-func (e *ExpectedExec) WillDelayFor(duration time.Duration) *ExpectedExec {
- e.delay = duration
- return e
-}
-
-// String returns string representation
-func (e *ExpectedExec) String() string {
- msg := "ExpectedExec => expecting Exec which:"
- msg += "\n - matches sql: '" + e.sqlRegex.String() + "'"
-
- if len(e.args) == 0 {
- msg += "\n - is without arguments"
- } else {
- msg += "\n - is with arguments:\n"
- var margs []string
- for i, arg := range e.args {
- margs = append(margs, fmt.Sprintf(" %d - %+v", i, arg))
- }
- msg += strings.Join(margs, "\n")
- }
-
- if e.result != nil {
- res, _ := e.result.(*result)
- msg += "\n - should return Result having:"
- msg += fmt.Sprintf("\n LastInsertId: %d", res.insertID)
- msg += fmt.Sprintf("\n RowsAffected: %d", res.rowsAffected)
- if res.err != nil {
- msg += fmt.Sprintf("\n Error: %s", res.err)
- }
- }
-
- if e.err != nil {
- msg += fmt.Sprintf("\n - should return error: %s", e.err)
- }
-
- return msg
-}
-
-// WillReturnResult arranges for an expected Exec() to return a particular
-// result, there is sqlmock.NewResult(lastInsertID int64, affectedRows int64) method
-// to build a corresponding result. Or if actions needs to be tested against errors
-// sqlmock.NewErrorResult(err error) to return a given error.
-func (e *ExpectedExec) WillReturnResult(result driver.Result) *ExpectedExec {
- e.result = result
- return e
-}
-
-// ExpectedPrepare is used to manage *sql.DB.Prepare or *sql.Tx.Prepare expectations.
-// Returned by *Sqlmock.ExpectPrepare.
-type ExpectedPrepare struct {
- commonExpectation
- mock *sqlmock
- sqlRegex *regexp.Regexp
- statement driver.Stmt
- closeErr error
- delay time.Duration
-}
-
-// WillReturnError allows to set an error for the expected *sql.DB.Prepare or *sql.Tx.Prepare action.
-func (e *ExpectedPrepare) WillReturnError(err error) *ExpectedPrepare {
- e.err = err
- return e
-}
-
-// WillReturnCloseError allows to set an error for this prapared statement Close action
-func (e *ExpectedPrepare) WillReturnCloseError(err error) *ExpectedPrepare {
- e.closeErr = err
- return e
-}
-
-// WillDelayFor allows to specify duration for which it will delay
-// result. May be used together with Context
-func (e *ExpectedPrepare) WillDelayFor(duration time.Duration) *ExpectedPrepare {
- e.delay = duration
- return e
-}
-
-// ExpectQuery allows to expect Query() or QueryRow() on this prepared statement.
-// this method is convenient in order to prevent duplicating sql query string matching.
-func (e *ExpectedPrepare) ExpectQuery() *ExpectedQuery {
- eq := &ExpectedQuery{}
- eq.sqlRegex = e.sqlRegex
- e.mock.expected = append(e.mock.expected, eq)
- return eq
-}
-
-// ExpectExec allows to expect Exec() on this prepared statement.
-// this method is convenient in order to prevent duplicating sql query string matching.
-func (e *ExpectedPrepare) ExpectExec() *ExpectedExec {
- eq := &ExpectedExec{}
- eq.sqlRegex = e.sqlRegex
- e.mock.expected = append(e.mock.expected, eq)
- return eq
-}
-
-// String returns string representation
-func (e *ExpectedPrepare) String() string {
- msg := "ExpectedPrepare => expecting Prepare statement which:"
- msg += "\n - matches sql: '" + e.sqlRegex.String() + "'"
-
- if e.err != nil {
- msg += fmt.Sprintf("\n - should return error: %s", e.err)
- }
-
- if e.closeErr != nil {
- msg += fmt.Sprintf("\n - should return error on Close: %s", e.closeErr)
- }
-
- return msg
-}
-
-// query based expectation
-// adds a query matching logic
-type queryBasedExpectation struct {
- commonExpectation
- sqlRegex *regexp.Regexp
- args []driver.Value
-}
-
-func (e *queryBasedExpectation) attemptMatch(sql string, args []namedValue) (err error) {
- if !e.queryMatches(sql) {
- return fmt.Errorf(`could not match sql: "%s" with expected regexp "%s"`, sql, e.sqlRegex.String())
- }
-
- // catch panic
- defer func() {
- if e := recover(); e != nil {
- _, ok := e.(error)
- if !ok {
- err = fmt.Errorf(e.(string))
- }
- }
- }()
-
- err = e.argsMatches(args)
- return
-}
-
-func (e *queryBasedExpectation) queryMatches(sql string) bool {
- return e.sqlRegex.MatchString(sql)
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_before_go18.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_before_go18.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_before_go18.go
deleted file mode 100644
index 146f240..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_before_go18.go
+++ /dev/null
@@ -1,52 +0,0 @@
-// +build !go1.8
-
-package sqlmock
-
-import (
- "database/sql/driver"
- "fmt"
- "reflect"
-)
-
-// WillReturnRows specifies the set of resulting rows that will be returned
-// by the triggered query
-func (e *ExpectedQuery) WillReturnRows(rows *Rows) *ExpectedQuery {
- e.rows = &rowSets{sets: []*Rows{rows}}
- return e
-}
-
-func (e *queryBasedExpectation) argsMatches(args []namedValue) error {
- if nil == e.args {
- return nil
- }
- if len(args) != len(e.args) {
- return fmt.Errorf("expected %d, but got %d arguments", len(e.args), len(args))
- }
- for k, v := range args {
- // custom argument matcher
- matcher, ok := e.args[k].(Argument)
- if ok {
- // @TODO: does it make sense to pass value instead of named value?
- if !matcher.Match(v.Value) {
- return fmt.Errorf("matcher %T could not match %d argument %T - %+v", matcher, k, args[k], args[k])
- }
- continue
- }
-
- dval := e.args[k]
- // convert to driver converter
- darg, err := driver.DefaultParameterConverter.ConvertValue(dval)
- if err != nil {
- return fmt.Errorf("could not convert %d argument %T - %+v to driver value: %s", k, e.args[k], e.args[k], err)
- }
-
- if !driver.IsValue(darg) {
- return fmt.Errorf("argument %d: non-subset type %T returned from Value", k, darg)
- }
-
- if !reflect.DeepEqual(darg, v.Value) {
- return fmt.Errorf("argument %d expected [%T - %+v] does not match actual [%T - %+v]", k, darg, darg, v.Value, v.Value)
- }
- }
- return nil
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18.go
deleted file mode 100644
index 2b4b44e..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18.go
+++ /dev/null
@@ -1,66 +0,0 @@
-// +build go1.8
-
-package sqlmock
-
-import (
- "database/sql"
- "database/sql/driver"
- "fmt"
- "reflect"
-)
-
-// WillReturnRows specifies the set of resulting rows that will be returned
-// by the triggered query
-func (e *ExpectedQuery) WillReturnRows(rows ...*Rows) *ExpectedQuery {
- sets := make([]*Rows, len(rows))
- for i, r := range rows {
- sets[i] = r
- }
- e.rows = &rowSets{sets: sets}
- return e
-}
-
-func (e *queryBasedExpectation) argsMatches(args []namedValue) error {
- if nil == e.args {
- return nil
- }
- if len(args) != len(e.args) {
- return fmt.Errorf("expected %d, but got %d arguments", len(e.args), len(args))
- }
- // @TODO should we assert either all args are named or ordinal?
- for k, v := range args {
- // custom argument matcher
- matcher, ok := e.args[k].(Argument)
- if ok {
- if !matcher.Match(v.Value) {
- return fmt.Errorf("matcher %T could not match %d argument %T - %+v", matcher, k, args[k], args[k])
- }
- continue
- }
-
- dval := e.args[k]
- if named, isNamed := dval.(sql.NamedArg); isNamed {
- dval = named.Value
- if v.Name != named.Name {
- return fmt.Errorf("named argument %d: name: \"%s\" does not match expected: \"%s\"", k, v.Name, named.Name)
- }
- } else if k+1 != v.Ordinal {
- return fmt.Errorf("argument %d: ordinal position: %d does not match expected: %d", k, k+1, v.Ordinal)
- }
-
- // convert to driver converter
- darg, err := driver.DefaultParameterConverter.ConvertValue(dval)
- if err != nil {
- return fmt.Errorf("could not convert %d argument %T - %+v to driver value: %s", k, e.args[k], e.args[k], err)
- }
-
- if !driver.IsValue(darg) {
- return fmt.Errorf("argument %d: non-subset type %T returned from Value", k, darg)
- }
-
- if !reflect.DeepEqual(darg, v.Value) {
- return fmt.Errorf("argument %d expected [%T - %+v] does not match actual [%T - %+v]", k, darg, darg, v.Value, v.Value)
- }
- }
- return nil
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18_test.go
deleted file mode 100644
index 5f30d2f..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18_test.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// +build go1.8
-
-package sqlmock
-
-import (
- "database/sql"
- "database/sql/driver"
- "testing"
-)
-
-func TestQueryExpectationNamedArgComparison(t *testing.T) {
- e := &queryBasedExpectation{}
- against := []namedValue{{Value: int64(5), Name: "id"}}
- if err := e.argsMatches(against); err != nil {
- t.Errorf("arguments should match, since the no expectation was set, but got err: %s", err)
- }
-
- e.args = []driver.Value{
- sql.Named("id", 5),
- sql.Named("s", "str"),
- }
-
- if err := e.argsMatches(against); err == nil {
- t.Error("arguments should not match, since the size is not the same")
- }
-
- against = []namedValue{
- {Value: int64(5), Name: "id"},
- {Value: "str", Name: "s"},
- }
-
- if err := e.argsMatches(against); err != nil {
- t.Errorf("arguments should have matched, but it did not: %v", err)
- }
-
- against = []namedValue{
- {Value: int64(5), Name: "id"},
- {Value: "str", Name: "username"},
- }
-
- if err := e.argsMatches(against); err == nil {
- t.Error("arguments matched, but it should have not due to Name")
- }
-
- e.args = []driver.Value{int64(5), "str"}
-
- against = []namedValue{
- {Value: int64(5), Ordinal: 0},
- {Value: "str", Ordinal: 1},
- }
-
- if err := e.argsMatches(against); err == nil {
- t.Error("arguments matched, but it should have not due to wrong Ordinal position")
- }
-
- against = []namedValue{
- {Value: int64(5), Ordinal: 1},
- {Value: "str", Ordinal: 2},
- }
-
- if err := e.argsMatches(against); err != nil {
- t.Errorf("arguments should have matched, but it did not: %v", err)
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_test.go
deleted file mode 100644
index 2e3c097..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_test.go
+++ /dev/null
@@ -1,154 +0,0 @@
-package sqlmock
-
-import (
- "database/sql/driver"
- "fmt"
- "regexp"
- "testing"
- "time"
-)
-
-func TestQueryExpectationArgComparison(t *testing.T) {
- e := &queryBasedExpectation{}
- against := []namedValue{{Value: int64(5), Ordinal: 1}}
- if err := e.argsMatches(against); err != nil {
- t.Errorf("arguments should match, since the no expectation was set, but got err: %s", err)
- }
-
- e.args = []driver.Value{5, "str"}
-
- against = []namedValue{{Value: int64(5), Ordinal: 1}}
- if err := e.argsMatches(against); err == nil {
- t.Error("arguments should not match, since the size is not the same")
- }
-
- against = []namedValue{
- {Value: int64(3), Ordinal: 1},
- {Value: "str", Ordinal: 2},
- }
- if err := e.argsMatches(against); err == nil {
- t.Error("arguments should not match, since the first argument (int value) is different")
- }
-
- against = []namedValue{
- {Value: int64(5), Ordinal: 1},
- {Value: "st", Ordinal: 2},
- }
- if err := e.argsMatches(against); err == nil {
- t.Error("arguments should not match, since the second argument (string value) is different")
- }
-
- against = []namedValue{
- {Value: int64(5), Ordinal: 1},
- {Value: "str", Ordinal: 2},
- }
- if err := e.argsMatches(against); err != nil {
- t.Errorf("arguments should match, but it did not: %s", err)
- }
-
- const longForm = "Jan 2, 2006 at 3:04pm (MST)"
- tm, _ := time.Parse(longForm, "Feb 3, 2013 at 7:54pm (PST)")
- e.args = []driver.Value{5, tm}
-
- against = []namedValue{
- {Value: int64(5), Ordinal: 1},
- {Value: tm, Ordinal: 2},
- }
- if err := e.argsMatches(against); err != nil {
- t.Error("arguments should match, but it did not")
- }
-
- e.args = []driver.Value{5, AnyArg()}
- if err := e.argsMatches(against); err != nil {
- t.Errorf("arguments should match, but it did not: %s", err)
- }
-}
-
-func TestQueryExpectationArgComparisonBool(t *testing.T) {
- var e *queryBasedExpectation
-
- e = &queryBasedExpectation{args: []driver.Value{true}}
- against := []namedValue{
- {Value: true, Ordinal: 1},
- }
- if err := e.argsMatches(against); err != nil {
- t.Error("arguments should match, since arguments are the same")
- }
-
- e = &queryBasedExpectation{args: []driver.Value{false}}
- against = []namedValue{
- {Value: false, Ordinal: 1},
- }
- if err := e.argsMatches(against); err != nil {
- t.Error("arguments should match, since argument are the same")
- }
-
- e = &queryBasedExpectation{args: []driver.Value{true}}
- against = []namedValue{
- {Value: false, Ordinal: 1},
- }
- if err := e.argsMatches(against); err == nil {
- t.Error("arguments should not match, since argument is different")
- }
-
- e = &queryBasedExpectation{args: []driver.Value{false}}
- against = []namedValue{
- {Value: true, Ordinal: 1},
- }
- if err := e.argsMatches(against); err == nil {
- t.Error("arguments should not match, since argument is different")
- }
-}
-
-func TestQueryExpectationSqlMatch(t *testing.T) {
- e := &ExpectedExec{}
-
- e.sqlRegex = regexp.MustCompile("SELECT x FROM")
- if !e.queryMatches("SELECT x FROM someting") {
- t.Errorf("Sql must have matched the query")
- }
-
- e.sqlRegex = regexp.MustCompile("SELECT COUNT\\(x\\) FROM")
- if !e.queryMatches("SELECT COUNT(x) FROM someting") {
- t.Errorf("Sql must have matched the query")
- }
-}
-
-func ExampleExpectedExec() {
- db, mock, _ := New()
- result := NewErrorResult(fmt.Errorf("some error"))
- mock.ExpectExec("^INSERT (.+)").WillReturnResult(result)
- res, _ := db.Exec("INSERT something")
- _, err := res.LastInsertId()
- fmt.Println(err)
- // Output: some error
-}
-
-func TestBuildQuery(t *testing.T) {
- db, mock, _ := New()
- query := `
- SELECT
- name,
- email,
- address,
- anotherfield
- FROM user
- where
- name = 'John'
- and
- address = 'Jakarta'
-
- `
-
- mock.ExpectQuery(query)
- mock.ExpectExec(query)
- mock.ExpectPrepare(query)
-
- db.QueryRow(query)
- db.Exec(query)
- db.Prepare(query)
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Error(err)
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result.go
deleted file mode 100644
index a63e72b..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result.go
+++ /dev/null
@@ -1,39 +0,0 @@
-package sqlmock
-
-import (
- "database/sql/driver"
-)
-
-// Result satisfies sql driver Result, which
-// holds last insert id and rows affected
-// by Exec queries
-type result struct {
- insertID int64
- rowsAffected int64
- err error
-}
-
-// NewResult creates a new sql driver Result
-// for Exec based query mocks.
-func NewResult(lastInsertID int64, rowsAffected int64) driver.Result {
- return &result{
- insertID: lastInsertID,
- rowsAffected: rowsAffected,
- }
-}
-
-// NewErrorResult creates a new sql driver Result
-// which returns an error given for both interface methods
-func NewErrorResult(err error) driver.Result {
- return &result{
- err: err,
- }
-}
-
-func (r *result) LastInsertId() (int64, error) {
- return r.insertID, r.err
-}
-
-func (r *result) RowsAffected() (int64, error) {
- return r.rowsAffected, r.err
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result_test.go
deleted file mode 100644
index 08d47c9..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result_test.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package sqlmock
-
-import (
- "fmt"
- "testing"
-)
-
-// used for examples
-var mock = &sqlmock{}
-
-func ExampleNewErrorResult() {
- db, mock, _ := New()
- result := NewErrorResult(fmt.Errorf("some error"))
- mock.ExpectExec("^INSERT (.+)").WillReturnResult(result)
- res, _ := db.Exec("INSERT something")
- _, err := res.LastInsertId()
- fmt.Println(err)
- // Output: some error
-}
-
-func ExampleNewResult() {
- var lastInsertID, affected int64
- result := NewResult(lastInsertID, affected)
- mock.ExpectExec("^INSERT (.+)").WillReturnResult(result)
- fmt.Println(mock.ExpectationsWereMet())
- // Output: there is a remaining expectation which was not matched: ExpectedExec => expecting Exec which:
- // - matches sql: '^INSERT (.+)'
- // - is without arguments
- // - should return Result having:
- // LastInsertId: 0
- // RowsAffected: 0
-}
-
-func TestShouldReturnValidSqlDriverResult(t *testing.T) {
- result := NewResult(1, 2)
- id, err := result.LastInsertId()
- if 1 != id {
- t.Errorf("Expected last insert id to be 1, but got: %d", id)
- }
- if err != nil {
- t.Errorf("expected no error, but got: %s", err)
- }
- affected, err := result.RowsAffected()
- if 2 != affected {
- t.Errorf("Expected affected rows to be 2, but got: %d", affected)
- }
- if err != nil {
- t.Errorf("expected no error, but got: %s", err)
- }
-}
-
-func TestShouldReturnErroeSqlDriverResult(t *testing.T) {
- result := NewErrorResult(fmt.Errorf("some error"))
- _, err := result.LastInsertId()
- if err == nil {
- t.Error("expected error, but got none")
- }
- _, err = result.RowsAffected()
- if err == nil {
- t.Error("expected error, but got none")
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows.go
deleted file mode 100644
index 39f9f83..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows.go
+++ /dev/null
@@ -1,144 +0,0 @@
-package sqlmock
-
-import (
- "database/sql/driver"
- "encoding/csv"
- "fmt"
- "io"
- "strings"
-)
-
-// CSVColumnParser is a function which converts trimmed csv
-// column string to a []byte representation. currently
-// transforms NULL to nil
-var CSVColumnParser = func(s string) []byte {
- switch {
- case strings.ToLower(s) == "null":
- return nil
- }
- return []byte(s)
-}
-
-type rowSets struct {
- sets []*Rows
- pos int
-}
-
-func (rs *rowSets) Columns() []string {
- return rs.sets[rs.pos].cols
-}
-
-func (rs *rowSets) Close() error {
- return rs.sets[rs.pos].closeErr
-}
-
-// advances to next row
-func (rs *rowSets) Next(dest []driver.Value) error {
- r := rs.sets[rs.pos]
- r.pos++
- if r.pos > len(r.rows) {
- return io.EOF // per interface spec
- }
-
- for i, col := range r.rows[r.pos-1] {
- dest[i] = col
- }
-
- return r.nextErr[r.pos-1]
-}
-
-// transforms to debuggable printable string
-func (rs *rowSets) String() string {
- msg := "should return rows:\n"
- if len(rs.sets) == 1 {
- for n, row := range rs.sets[0].rows {
- msg += fmt.Sprintf(" row %d - %+v\n", n, row)
- }
- return strings.TrimSpace(msg)
- }
- for i, set := range rs.sets {
- msg += fmt.Sprintf(" result set: %d\n", i)
- for n, row := range set.rows {
- msg += fmt.Sprintf(" row %d - %+v\n", n, row)
- }
- }
- return strings.TrimSpace(msg)
-}
-
-// Rows is a mocked collection of rows to
-// return for Query result
-type Rows struct {
- cols []string
- rows [][]driver.Value
- pos int
- nextErr map[int]error
- closeErr error
-}
-
-// NewRows allows Rows to be created from a
-// sql driver.Value slice or from the CSV string and
-// to be used as sql driver.Rows
-func NewRows(columns []string) *Rows {
- return &Rows{cols: columns, nextErr: make(map[int]error)}
-}
-
-// CloseError allows to set an error
-// which will be returned by rows.Close
-// function.
-//
-// The close error will be triggered only in cases
-// when rows.Next() EOF was not yet reached, that is
-// a default sql library behavior
-func (r *Rows) CloseError(err error) *Rows {
- r.closeErr = err
- return r
-}
-
-// RowError allows to set an error
-// which will be returned when a given
-// row number is read
-func (r *Rows) RowError(row int, err error) *Rows {
- r.nextErr[row] = err
- return r
-}
-
-// AddRow composed from database driver.Value slice
-// return the same instance to perform subsequent actions.
-// Note that the number of values must match the number
-// of columns
-func (r *Rows) AddRow(values ...driver.Value) *Rows {
- if len(values) != len(r.cols) {
- panic("Expected number of values to match number of columns")
- }
-
- row := make([]driver.Value, len(r.cols))
- for i, v := range values {
- row[i] = v
- }
-
- r.rows = append(r.rows, row)
- return r
-}
-
-// FromCSVString build rows from csv string.
-// return the same instance to perform subsequent actions.
-// Note that the number of values must match the number
-// of columns
-func (r *Rows) FromCSVString(s string) *Rows {
- res := strings.NewReader(strings.TrimSpace(s))
- csvReader := csv.NewReader(res)
-
- for {
- res, err := csvReader.Read()
- if err != nil || res == nil {
- break
- }
-
- row := make([]driver.Value, len(r.cols))
- for i, v := range res {
- row[i] = CSVColumnParser(strings.TrimSpace(v))
- }
- r.rows = append(r.rows, row)
- }
- return r
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18.go
deleted file mode 100644
index 4ecf84e..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// +build go1.8
-
-package sqlmock
-
-import "io"
-
-// Implement the "RowsNextResultSet" interface
-func (rs *rowSets) HasNextResultSet() bool {
- return rs.pos+1 < len(rs.sets)
-}
-
-// Implement the "RowsNextResultSet" interface
-func (rs *rowSets) NextResultSet() error {
- if !rs.HasNextResultSet() {
- return io.EOF
- }
-
- rs.pos++
- return nil
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18_test.go
deleted file mode 100644
index 297e7c0..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18_test.go
+++ /dev/null
@@ -1,92 +0,0 @@
-// +build go1.8
-
-package sqlmock
-
-import (
- "fmt"
- "testing"
-)
-
-func TestQueryMultiRows(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- rs1 := NewRows([]string{"id", "title"}).AddRow(5, "hello world")
- rs2 := NewRows([]string{"name"}).AddRow("gopher").AddRow("john").AddRow("jane").RowError(2, fmt.Errorf("error"))
-
- mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = \\?;SELECT name FROM users").
- WithArgs(5).
- WillReturnRows(rs1, rs2)
-
- rows, err := db.Query("SELECT id, title FROM articles WHERE id = ?;SELECT name FROM users", 5)
- if err != nil {
- t.Errorf("error was not expected, but got: %v", err)
- }
- defer rows.Close()
-
- if !rows.Next() {
- t.Error("expected a row to be available in first result set")
- }
-
- var id int
- var name string
-
- err = rows.Scan(&id, &name)
- if err != nil {
- t.Errorf("error was not expected, but got: %v", err)
- }
-
- if id != 5 || name != "hello world" {
- t.Errorf("unexpected row values id: %v name: %v", id, name)
- }
-
- if rows.Next() {
- t.Error("was not expecting next row in first result set")
- }
-
- if !rows.NextResultSet() {
- t.Error("had to have next result set")
- }
-
- if !rows.Next() {
- t.Error("expected a row to be available in second result set")
- }
-
- err = rows.Scan(&name)
- if err != nil {
- t.Errorf("error was not expected, but got: %v", err)
- }
-
- if name != "gopher" {
- t.Errorf("unexpected row name: %v", name)
- }
-
- if !rows.Next() {
- t.Error("expected a row to be available in second result set")
- }
-
- err = rows.Scan(&name)
- if err != nil {
- t.Errorf("error was not expected, but got: %v", err)
- }
-
- if name != "john" {
- t.Errorf("unexpected row name: %v", name)
- }
-
- if rows.Next() {
- t.Error("expected next row to produce error")
- }
-
- if rows.Err() == nil {
- t.Error("expected an error, but there was none")
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
[43/43] incubator-trafficcontrol git commit: Add TO Golang route for
path without .json
Posted by de...@apache.org.
Add TO Golang route for path without .json
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/e23a6171
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/e23a6171
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/e23a6171
Branch: refs/heads/master
Commit: e23a6171f661e586569affd009a418dadd01e8f7
Parents: 9d24e39
Author: Robert Butts <ro...@gmail.com>
Authored: Wed Jul 26 17:51:16 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/traffic_ops_golang/routes.go | 1 +
1 file changed, 1 insertion(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/e23a6171/traffic_ops/traffic_ops_golang/routes.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index 8ad994e..a9eaf08 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -59,6 +59,7 @@ func GetRoutes(d ServerData) (map[string]RegexHandlerFunc, http.Handler, error)
}
return map[string]RegexHandlerFunc{
+ "api/1.2/cdns/{cdn}/configs/monitoring": wrapHeaders(wrapAuth(monitoringHandler(d.DB), d.Insecure, d.TOSecret, privLevelStmt, MonitoringPrivLevel)),
"api/1.2/cdns/{cdn}/configs/monitoring.json": wrapHeaders(wrapAuth(monitoringHandler(d.DB), d.Insecure, d.TOSecret, privLevelStmt, MonitoringPrivLevel)),
}, getRootHandler(d), nil
}
[27/43] incubator-trafficcontrol git commit: Fix TO GOlang swapped
log bytes and time
Posted by de...@apache.org.
Fix TO GOlang swapped log bytes and time
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/d50d93ed
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/d50d93ed
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/d50d93ed
Branch: refs/heads/master
Commit: d50d93ed1b62d576e8aa9d80a147943a9293465b
Parents: fcc34ac
Author: Robert Butts <ro...@gmail.com>
Authored: Wed Jul 26 17:27:31 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/traffic_ops_golang/wrappers.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d50d93ed/traffic_ops/traffic_ops_golang/wrappers.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/wrappers.go b/traffic_ops/traffic_ops_golang/wrappers.go
index b20cd53..17f3e1c 100644
--- a/traffic_ops/traffic_ops_golang/wrappers.go
+++ b/traffic_ops/traffic_ops_golang/wrappers.go
@@ -49,7 +49,7 @@ func wrapAuth(h RegexHandlerFunc, noAuth bool, secret string, privLevelStmt *sql
w = iw
username := "-"
defer func() {
- log.EventfRaw(`%s - %s [%s] "%v %v HTTP/1.1" %v %v %v "%v"`, r.RemoteAddr, username, time.Now().Format(AccessLogTimeFormat), r.Method, r.URL.Path, iw.code, int(time.Now().Sub(start)/time.Millisecond), iw.byteCount, r.UserAgent())
+ log.EventfRaw(`%s - %s [%s] "%v %v HTTP/1.1" %v %v %v "%v"`, r.RemoteAddr, username, time.Now().Format(AccessLogTimeFormat), r.Method, r.URL.Path, iw.code, iw.byteCount, int(time.Now().Sub(start)/time.Millisecond), r.UserAgent())
}()
handleUnauthorized := func(reason string) {
[33/43] incubator-trafficcontrol git commit: Add TO Golang logrotate
Posted by de...@apache.org.
Add TO Golang logrotate
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/89491c1c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/89491c1c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/89491c1c
Branch: refs/heads/master
Commit: 89491c1c033ac54810216e72c746b36ee97e0413
Parents: e1dab67
Author: Robert Butts <ro...@gmail.com>
Authored: Wed Jul 26 18:28:25 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/build/traffic_ops.spec | 4 ++++
traffic_ops/etc/logrotate.d/traffic_ops_golang | 22 ++++++++++++++++++++
.../etc/logrotate.d/traffic_ops_perl_access | 22 ++++++++++++++++++++
3 files changed, 48 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/89491c1c/traffic_ops/build/traffic_ops.spec
----------------------------------------------------------------------
diff --git a/traffic_ops/build/traffic_ops.spec b/traffic_ops/build/traffic_ops.spec
index 8efa676..26d19e8 100644
--- a/traffic_ops/build/traffic_ops.spec
+++ b/traffic_ops/build/traffic_ops.spec
@@ -140,13 +140,17 @@ Built: %(date) by %{getenv: USER}
%__cp %{PACKAGEDIR}/etc/cron.d/trafops_dnssec_refresh /etc/cron.d/trafops_dnssec_refresh
%__cp %{PACKAGEDIR}/etc/cron.d/trafops_clean_isos /etc/cron.d/trafops_clean_isos
%__cp %{PACKAGEDIR}/etc/logrotate.d/traffic_ops /etc/logrotate.d/traffic_ops
+ %__cp %{PACKAGEDIR}/etc/logrotate.d/traffic_ops_golang /etc/logrotate.d/traffic_ops_golang
%__cp %{PACKAGEDIR}/etc/logrotate.d/traffic_ops_access /etc/logrotate.d/traffic_ops_access
+ %__cp %{PACKAGEDIR}/etc/logrotate.d/traffic_ops_perl_access /etc/logrotate.d/traffic_ops_perl_access
%__cp %{PACKAGEDIR}/etc/profile.d/traffic_ops.sh /etc/profile.d/traffic_ops.sh
%__chown root:root /etc/init.d/traffic_ops
%__chown root:root /etc/cron.d/trafops_dnssec_refresh
%__chown root:root /etc/cron.d/trafops_clean_isos
%__chown root:root /etc/logrotate.d/traffic_ops
+ %__chown root:root /etc/logrotate.d/traffic_ops_golang
%__chown root:root /etc/logrotate.d/traffic_ops_access
+ %__chown root:root /etc/logrotate.d/traffic_ops_perl_access
%__chmod +x /etc/init.d/traffic_ops
%__chmod +x %{PACKAGEDIR}/install/bin/*
/sbin/chkconfig --add traffic_ops
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/89491c1c/traffic_ops/etc/logrotate.d/traffic_ops_golang
----------------------------------------------------------------------
diff --git a/traffic_ops/etc/logrotate.d/traffic_ops_golang b/traffic_ops/etc/logrotate.d/traffic_ops_golang
new file mode 100644
index 0000000..088aa34
--- /dev/null
+++ b/traffic_ops/etc/logrotate.d/traffic_ops_golang
@@ -0,0 +1,22 @@
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+/var/log/traffic_ops/traffic_ops_golang.log {
+ missingok
+ notifempty
+ size 200M
+ rotate 7
+ copytruncate
+ compress
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/89491c1c/traffic_ops/etc/logrotate.d/traffic_ops_perl_access
----------------------------------------------------------------------
diff --git a/traffic_ops/etc/logrotate.d/traffic_ops_perl_access b/traffic_ops/etc/logrotate.d/traffic_ops_perl_access
new file mode 100644
index 0000000..8014de9
--- /dev/null
+++ b/traffic_ops/etc/logrotate.d/traffic_ops_perl_access
@@ -0,0 +1,22 @@
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+/var/log/traffic_ops/perl_access.log {
+ missingok
+ notifempty
+ size 200M
+ rotate 7
+ copytruncate
+ compress
+}
[26/43] incubator-trafficcontrol git commit: Change TO Golang config
parse to return all errs
Posted by de...@apache.org.
Change TO Golang config parse to return all errs
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/fcc34ac9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/fcc34ac9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/fcc34ac9
Branch: refs/heads/master
Commit: fcc34ac9cf77490f100cb89731591567953ee82f
Parents: 4ab5a3e
Author: Robert Butts <ro...@gmail.com>
Authored: Tue Jul 25 22:50:43 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/traffic_ops_golang/config.go | 34 ++++++++++++++++++++-------
1 file changed, 25 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/fcc34ac9/traffic_ops/traffic_ops_golang/config.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/config.go b/traffic_ops/traffic_ops_golang/config.go
index 7595181..5911204 100644
--- a/traffic_ops/traffic_ops_golang/config.go
+++ b/traffic_ops/traffic_ops_golang/config.go
@@ -78,30 +78,32 @@ func LoadConfig(fileName string) (Config, error) {
// ParseConfig validates required fields, and parses non-JSON types
func ParseConfig(cfg Config) (Config, error) {
+ missings := ""
if cfg.HTTPPort == "" {
- return Config{}, fmt.Errorf("missing port")
+ missings += "port, "
}
if cfg.DBUser == "" {
- return Config{}, fmt.Errorf("missing database user")
+ missings += "db_user, "
}
if cfg.DBPass == "" {
- return Config{}, fmt.Errorf("missing database password")
+ missings += "db_pass, "
}
if cfg.DBServer == "" {
- return Config{}, fmt.Errorf("missing database server")
+ missings += "db_server, "
}
if cfg.DBDB == "" {
- return Config{}, fmt.Errorf("missing database name")
+ missings += "db_name, "
}
if cfg.TOSecret == "" {
- return Config{}, fmt.Errorf("missing secret")
+ missings += "to_secret, "
}
if cfg.CertPath == "" {
- return Config{}, fmt.Errorf("missing certificate path")
+ missings += "cert_path, "
}
if cfg.KeyPath == "" {
- return Config{}, fmt.Errorf("missing certificate key path")
+ missings += "key_path, "
}
+
if cfg.LogLocationError == "" {
cfg.LogLocationError = log.LogLocationNull
}
@@ -118,9 +120,23 @@ func ParseConfig(cfg Config) (Config, error) {
cfg.LogLocationEvent = log.LogLocationNull
}
+ invalidTOURLStr := ""
var err error
if cfg.TOURL, err = url.Parse(cfg.TOURLStr); err != nil {
- return Config{}, fmt.Errorf("Invalid Traffic Ops URL '%v': err", cfg.TOURL, err)
+ invalidTOURLStr = fmt.Sprintf("invalid Traffic Ops URL '%v': %v", cfg.TOURLStr, err)
+ }
+
+ if len(missings) > 0 {
+ missings = "missing fields: " + missings[:len(missings)-2] // strip final `, `
+ }
+
+ errStr := missings
+ if errStr != "" && invalidTOURLStr != "" {
+ errStr += "; "
+ }
+ errStr += invalidTOURLStr
+ if errStr != "" {
+ return Config{}, fmt.Errorf(errStr)
}
return cfg, nil
[32/43] incubator-trafficcontrol git commit: Add TO Golang log
unauthorized request reason
Posted by de...@apache.org.
Add TO Golang log unauthorized request reason
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/67f80faf
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/67f80faf
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/67f80faf
Branch: refs/heads/master
Commit: 67f80fafe05d645d2b30ce32737a57aafe983044
Parents: 128c6a2
Author: Robert Butts <ro...@gmail.com>
Authored: Thu Jul 27 11:30:03 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/traffic_ops_golang/wrappers.go | 1 +
1 file changed, 1 insertion(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/67f80faf/traffic_ops/traffic_ops_golang/wrappers.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/wrappers.go b/traffic_ops/traffic_ops_golang/wrappers.go
index 39137ac..66af5d9 100644
--- a/traffic_ops/traffic_ops_golang/wrappers.go
+++ b/traffic_ops/traffic_ops_golang/wrappers.go
@@ -59,6 +59,7 @@ func wrapAuth(h RegexHandlerFunc, noAuth bool, secret string, privLevelStmt *sql
status := http.StatusUnauthorized
w.WriteHeader(status)
fmt.Fprintf(w, http.StatusText(status))
+ log.Infof("%v %v %v %v returned unauthorized: %v\n", r.RemoteAddr, r.Method, r.URL.Path, username, reason)
}
cookie, err := r.Cookie(tocookie.Name)
[29/43] incubator-trafficcontrol git commit: Add TO Golang CORS
headers
Posted by de...@apache.org.
Add TO Golang CORS headers
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/b9780d89
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/b9780d89
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/b9780d89
Branch: refs/heads/master
Commit: b9780d89e8476064afd3b98a2dd189e23e193a27
Parents: e23a617
Author: Robert Butts <ro...@gmail.com>
Authored: Wed Jul 26 17:57:40 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/traffic_ops_golang/wrappers.go | 3 +++
1 file changed, 3 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b9780d89/traffic_ops/traffic_ops_golang/wrappers.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/wrappers.go b/traffic_ops/traffic_ops_golang/wrappers.go
index 5a5cfce..386e278 100644
--- a/traffic_ops/traffic_ops_golang/wrappers.go
+++ b/traffic_ops/traffic_ops_golang/wrappers.go
@@ -32,6 +32,9 @@ const ServerName = "traffic_ops_golang" + "/" + Version
func wrapHeaders(h RegexHandlerFunc) RegexHandlerFunc {
return func(w http.ResponseWriter, r *http.Request, p ParamMap) {
+ w.Header().Set("Access-Control-Allow-Credentials", "true")
+ w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
+ w.Header().Set("Access-Control-Allow-Methods", "POST,GET,OPTIONS,PUT,DELETE")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("X-Server-Name", ServerName)
h(w, r, p)
[09/43] incubator-trafficcontrol git commit: Fix TO Golang test for
MaxDBConnections default
Posted by de...@apache.org.
Fix TO Golang test for MaxDBConnections default
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/722915a7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/722915a7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/722915a7
Branch: refs/heads/master
Commit: 722915a77b233333a309fe10d7566d59872059b7
Parents: b147f10
Author: Robert Butts <ro...@gmail.com>
Authored: Wed Aug 2 08:54:38 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/traffic_ops_golang/perlconfig_test.go | 1 +
1 file changed, 1 insertion(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/722915a7/traffic_ops/traffic_ops_golang/perlconfig_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/perlconfig_test.go b/traffic_ops/traffic_ops_golang/perlconfig_test.go
index d3cffe4..8c3f2c2 100644
--- a/traffic_ops/traffic_ops_golang/perlconfig_test.go
+++ b/traffic_ops/traffic_ops_golang/perlconfig_test.go
@@ -144,6 +144,7 @@ func TestGetPerlConfigsFromStrs(t *testing.T) {
TOURLStr: "https://127.0.0.1:60443",
CertPath: "/etc/pki/tls/certs/localhost.crt",
KeyPath: "/etc/pki/tls/private/localhost.key",
+ MaxDBConnections: DefaultMaxDBConnections,
LogLocationError: NewLogPath,
LogLocationWarning: NewLogPath,
LogLocationInfo: NewLogPath,
[17/43] incubator-trafficcontrol git commit: Add TO tocookie
generated-by data
Posted by de...@apache.org.
Add TO tocookie generated-by data
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/a54b0eff
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/a54b0eff
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/a54b0eff
Branch: refs/heads/master
Commit: a54b0eff53891d9dcc4f9912a4d3bf8e18cee844
Parents: 46d1f4b
Author: Robert Butts <ro...@gmail.com>
Authored: Fri Jul 21 19:03:14 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/tocookie/tocookie.go | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/a54b0eff/traffic_ops/tocookie/tocookie.go
----------------------------------------------------------------------
diff --git a/traffic_ops/tocookie/tocookie.go b/traffic_ops/tocookie/tocookie.go
index 658224d..a8a3f53 100644
--- a/traffic_ops/tocookie/tocookie.go
+++ b/traffic_ops/tocookie/tocookie.go
@@ -23,12 +23,14 @@ import (
"time"
)
+const GeneratedByStr = "trafficcontrol-go-tocookie"
const Name = "mojolicious"
const DefaultDuration = time.Hour
type Cookie struct {
AuthData string `json:"auth_data"`
ExpiresUnix int64 `json:"expires"`
+ By string `json:"by"`
}
func checkHmac(message, messageMAC, key []byte) bool {
@@ -92,7 +94,7 @@ func NewRawMsg(msg, key []byte) string {
}
func New(user string, expiration time.Time, key string) string {
- cookieMsg := Cookie{AuthData: user, ExpiresUnix: expiration.Unix()}
+ cookieMsg := Cookie{By: GeneratedByStr, AuthData: user, ExpiresUnix: expiration.Unix()}
msg, _ := json.Marshal(cookieMsg)
return NewRawMsg(msg, []byte(key))
}
[12/43] incubator-trafficcontrol git commit: Add TO Golang
documentation
Posted by de...@apache.org.
Add TO Golang documentation
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/e1dab673
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/e1dab673
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/e1dab673
Branch: refs/heads/master
Commit: e1dab673e47974d049540fe871c4a6b6b16ee277
Parents: b9780d8
Author: Robert Butts <ro...@gmail.com>
Authored: Wed Jul 26 18:20:07 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
docs/source/admin/traffic_ops/configuration.rst | 5 ++++-
docs/source/overview/traffic_ops.rst | 4 +++-
2 files changed, 7 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/e1dab673/docs/source/admin/traffic_ops/configuration.rst
----------------------------------------------------------------------
diff --git a/docs/source/admin/traffic_ops/configuration.rst b/docs/source/admin/traffic_ops/configuration.rst
index d293b89..66158d9 100644
--- a/docs/source/admin/traffic_ops/configuration.rst
+++ b/docs/source/admin/traffic_ops/configuration.rst
@@ -296,5 +296,8 @@ This is a standard kickstart formatted file that the generate ISO process uses t
.. seealso:: For in-depth instructions, please see `Kickstart Installation <https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Installation_Guide/s1-kickstart2-howuse.html>`_
+Configuring the Go Application
+=======================
+Traffic Ops is in the process of migrating from Perl to Go, and currently runs as two applications. The Go application serves all endpoints which have been rewritten in the Go language, and transparently proxies all other requests to the old Perl application. Both applications are installed by the RPM, and both run as a single service. When the project has fully migrated to Go, the Perl application will be removed, and the RPM and service will consist solely of the Go application.
-
+By default, the postinstall script configures the Go application to behave and transparently serve as the old Perl Traffic Ops did in previous versions. This includes reading the old ``cdn.conf`` and ``database.conf`` config files, and logging to the old ``access.log`` location. However, if you wish to customize the Go Traffic Ops application, you can do so by running it with the ``-oldcfg=false`` argument. By default, it will then look for a config file in ``/opt/traffic_ops/conf/traffic_ops_golang.json``. The new config file location may also be customized via the ``-cfg`` flag. A sample config file is installed by the RPM at ``/opt/traffic_ops/conf/traffic_ops_golang.json``. If you wish to run the new Go Traffic Ops application as a service with a new config file, the ``-oldcfg=false`` and ``-cfg`` flags may be added to the ``start`` function in the service file, located by default at ``etc/init.d/traffic_ops``.
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/e1dab673/docs/source/overview/traffic_ops.rst
----------------------------------------------------------------------
diff --git a/docs/source/overview/traffic_ops.rst b/docs/source/overview/traffic_ops.rst
index 9cc72ee..7053c7b 100644
--- a/docs/source/overview/traffic_ops.rst
+++ b/docs/source/overview/traffic_ops.rst
@@ -21,10 +21,12 @@ Traffic Ops is the tool for administration (configuration and monitoring) of all
Traffic Ops uses a MySQL or PostgreSQL database to store the configuration information, and the `Mojolicious framework <http://mojolicio.us/>`_ to generate the user interface and APIs. Not all configuration data is in this database however; for sensitive data, like SSL private keys or token based authentication shared secrets, a separate key-value store is used, allowing the operator to harden the server that runs this key-value store better from a security perspective (i.e only allow Traffic Ops access it with a cert). The Traffic Ops server, by design, needs to be accessible from all the other servers in the Traffic Control CDN.
-Traffic Ops generates all the application specific configuration files for the caches and other servers. The caches and other servers check in with Traffic Ops at a regular interval (default 15 minutes) to see if updated configuration files require application.
+Traffic Ops generates all the application specific configuration files for the caches and other servers. The caches and other servers check in with Traffic Ops at a regular interval (default 15 minutes) to see if updated configuration files require application.
Traffic Ops also runs a collection of periodic checks to determine the operational readiness of the caches. These periodic checks are customizable by the Traffic Ops admin using extensions.
+Traffic Ops is in the process of migrating from Perl to Go, and currently runs as two applications. The Go application serves all endpoints which have been rewritten in the Go language, and transparently proxies all other requests to the old Perl application. Both applications are installed by the RPM, and both run as a single service. When the project has fully migrated to Go, the Perl application will be removed, and the RPM and service will consist solely of the Go application.
+
|
.. _rl-trops-ext:
[08/43] incubator-trafficcontrol git commit: Fix TO Golang test for
default MaxDBConns
Posted by de...@apache.org.
Fix TO Golang test for default MaxDBConns
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/d728b597
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/d728b597
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/d728b597
Branch: refs/heads/master
Commit: d728b597622e1ffaae2fa59948758c47f069dbe1
Parents: 84a4b12
Author: Robert Butts <ro...@gmail.com>
Authored: Tue Aug 8 16:38:55 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/traffic_ops_golang/perlconfig_test.go | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d728b597/traffic_ops/traffic_ops_golang/perlconfig_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/perlconfig_test.go b/traffic_ops/traffic_ops_golang/perlconfig_test.go
index 8c3f2c2..a942f86 100644
--- a/traffic_ops/traffic_ops_golang/perlconfig_test.go
+++ b/traffic_ops/traffic_ops_golang/perlconfig_test.go
@@ -64,11 +64,12 @@ func TestGetCDNConf(t *testing.T) {
`
expected := Config{
- HTTPPort: "443",
- TOSecret: "walrus",
- TOURLStr: "https://127.0.0.1:60443",
- CertPath: "/etc/pki/tls/certs/localhost.crt",
- KeyPath: "/etc/pki/tls/private/localhost.key",
+ HTTPPort: "443",
+ TOSecret: "walrus",
+ TOURLStr: "https://127.0.0.1:60443",
+ CertPath: "/etc/pki/tls/certs/localhost.crt",
+ KeyPath: "/etc/pki/tls/private/localhost.key",
+ MaxDBConnections: 50,
}
err := error(nil)
if expected.TOURL, err = url.Parse(expected.TOURLStr); err != nil {
[06/43] incubator-trafficcontrol git commit: Move TO Golang
microservice out of experimental
Posted by de...@apache.org.
Move TO Golang microservice out of experimental
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/04ed9f14
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/04ed9f14
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/04ed9f14
Branch: refs/heads/master
Commit: 04ed9f141da0022678571f343752124e46a18969
Parents: aa90195
Author: Robert Butts <ro...@gmail.com>
Authored: Sun Jul 9 09:22:28 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:02 2017 -0600
----------------------------------------------------------------------
traffic_ops/experimental/goto/config.go | 80 ----
traffic_ops/experimental/goto/config.json | 13 -
traffic_ops/experimental/goto/goto.go | 56 ---
traffic_ops/experimental/goto/monitoring.go | 398 -------------------
traffic_ops/experimental/goto/routes.go | 95 -----
traffic_ops/experimental/goto/wrappers.go | 55 ---
traffic_ops/traffic_ops_golang/config.go | 80 ++++
traffic_ops/traffic_ops_golang/monitoring.go | 398 +++++++++++++++++++
traffic_ops/traffic_ops_golang/routes.go | 95 +++++
.../traffic_ops_golang.config | 13 +
.../traffic_ops_golang/traffic_ops_golang.go | 56 +++
traffic_ops/traffic_ops_golang/wrappers.go | 55 +++
12 files changed, 697 insertions(+), 697 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/04ed9f14/traffic_ops/experimental/goto/config.go
----------------------------------------------------------------------
diff --git a/traffic_ops/experimental/goto/config.go b/traffic_ops/experimental/goto/config.go
deleted file mode 100644
index a0f3401..0000000
--- a/traffic_ops/experimental/goto/config.go
+++ /dev/null
@@ -1,80 +0,0 @@
-package main
-
-import (
- "encoding/json"
- "fmt"
- "io/ioutil"
- "net/url"
-)
-
-type Config struct {
- HTTPPort string `json:"port"`
- DBUser string `json:"db_user"`
- DBPass string `json:"db_pass"`
- DBServer string `json:"db_server"`
- DBDB string `json:"db_name"`
- DBSSL bool `json:"db_ssl"`
- TOSecret string `json:"to_secret"`
- TOURLStr string `json:"to_url"`
- TOURL *url.URL `json:"-"`
- NoAuth bool `json:"no_auth"`
- CertPath string `json:"cert_path"`
- KeyPath string `json:"key_path"`
-}
-
-func LoadConfig(fileName string) (Config, error) {
- if fileName == "" {
- return Config{}, fmt.Errorf("no filename")
- }
-
- configBytes, err := ioutil.ReadFile(fileName)
- if err != nil {
- return Config{}, err
- }
-
- cfg := Config{}
- if err := json.Unmarshal(configBytes, &cfg); err != nil {
- return Config{}, err
- }
-
- if cfg, err = ParseConfig(cfg); err != nil {
- return Config{}, err
- }
-
- return cfg, nil
-}
-
-// ParseConfig validates required fields, and parses non-JSON types
-func ParseConfig(cfg Config) (Config, error) {
- if cfg.HTTPPort == "" {
- return Config{}, fmt.Errorf("missing port")
- }
- if cfg.DBUser == "" {
- return Config{}, fmt.Errorf("missing database user")
- }
- if cfg.DBPass == "" {
- return Config{}, fmt.Errorf("missing database password")
- }
- if cfg.DBServer == "" {
- return Config{}, fmt.Errorf("missing database server")
- }
- if cfg.DBDB == "" {
- return Config{}, fmt.Errorf("missing database name")
- }
- if cfg.TOSecret == "" {
- return Config{}, fmt.Errorf("missing secret")
- }
- if cfg.CertPath == "" {
- return Config{}, fmt.Errorf("missing certificate path")
- }
- if cfg.KeyPath == "" {
- return Config{}, fmt.Errorf("missing certificate key path")
- }
-
- var err error
- if cfg.TOURL, err = url.Parse(cfg.TOURLStr); err != nil {
- return Config{}, fmt.Errorf("Invalid Traffic Ops URL '%v': err", cfg.TOURL, err)
- }
-
- return cfg, nil
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/04ed9f14/traffic_ops/experimental/goto/config.json
----------------------------------------------------------------------
diff --git a/traffic_ops/experimental/goto/config.json b/traffic_ops/experimental/goto/config.json
deleted file mode 100644
index 19d2599..0000000
--- a/traffic_ops/experimental/goto/config.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "port": "443",
- "db_user": "bill",
- "db_pass": "thelizard",
- "db_server": "db.trafficops.example.net",
- "db_name": "trafficops",
- "db_ssl": true,
- "to_secret": "walrus",
- "to_url": "https://trafficops.example.net:60443",
- "no_auth": false,
- "cert_path": "/opt/traffic_ops/cert",
- "key_path": "/opt/traffic_ops/key"
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/04ed9f14/traffic_ops/experimental/goto/goto.go
----------------------------------------------------------------------
diff --git a/traffic_ops/experimental/goto/goto.go b/traffic_ops/experimental/goto/goto.go
deleted file mode 100644
index 48d3c4e..0000000
--- a/traffic_ops/experimental/goto/goto.go
+++ /dev/null
@@ -1,56 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
- "database/sql"
- "flag"
- "fmt"
- _ "github.com/lib/pq"
- "net/http"
-)
-
-const DefaultConfigPath = "/etc/goto/config.json"
-
-func main() {
- configFileName := flag.String("cfg", "", "The config file path")
- flag.Parse()
- if *configFileName == "" {
- *configFileName = DefaultConfigPath
- }
-
- cfg, err := LoadConfig(*configFileName)
- if err != nil {
- fmt.Println("Error loading config '" + *configFileName + "': " + err.Error())
- return
- }
-
- sslStr := "require"
- if !cfg.DBSSL {
- sslStr = "disable"
- }
-
- db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s", cfg.DBUser, cfg.DBPass, cfg.DBServer, cfg.DBDB, sslStr))
- if err != nil {
- fmt.Printf("Error opening database: %v\n", err)
- return
- }
- defer db.Close()
-
- RegisterRoutes(ServerData{DB: db, Config: cfg})
- fmt.Println("Listening on " + cfg.HTTPPort)
- if err := http.ListenAndServeTLS(":"+cfg.HTTPPort, cfg.CertPath, cfg.KeyPath, nil); err != nil {
- fmt.Printf("Error stopping server: %v\n", err)
- return
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/04ed9f14/traffic_ops/experimental/goto/monitoring.go
----------------------------------------------------------------------
diff --git a/traffic_ops/experimental/goto/monitoring.go b/traffic_ops/experimental/goto/monitoring.go
deleted file mode 100644
index b353fb5..0000000
--- a/traffic_ops/experimental/goto/monitoring.go
+++ /dev/null
@@ -1,398 +0,0 @@
-package main
-
-import (
- "database/sql"
- "encoding/json"
- "fmt"
- "github.com/lib/pq"
- "net/http"
- "strings"
- "time"
-)
-
-const CacheMonitorConfigFile = "rascal.properties"
-const MonitorType = "RASCAL"
-const RouterType = "CCR"
-const MonitorProfilePrefix = "RASCAL"
-const MonitorConfigFile = "rascal-config.txt"
-const KilobitsPerMegabit = 1000
-const DeliveryServiceStatus = "REPORTED"
-
-type BasicServer struct {
- Profile string `json:"profile"`
- Status string `json:"status"`
- IP string `json:"ip"`
- IP6 string `json:"ip6"`
- Port int `json:"port"`
- Cachegroup string `json:"cachegroup"`
- HostName string `json:"hostName"`
- FQDN string `json:"fqdn"`
-}
-
-type Monitor struct {
- BasicServer
-}
-
-type Cache struct {
- BasicServer
- InterfaceName string `json:"interfaceName"`
- Type string `json:"type"`
- HashID string `json:"hashId"`
-}
-
-type Cachegroup struct {
- Name string `json:"name"`
- Coordinates Coordinates `json:"coordinates"`
-}
-
-type Coordinates struct {
- Latitude float64 `json:"latitude"`
- Longitude float64 `json:"longitude"`
-}
-
-type Profile struct {
- Name string `json:"name"`
- Type string `json:"type"`
- Parameters map[string]string `json:"parameters"`
-}
-
-type Monitoring struct {
- TrafficServers []Cache `json:"trafficServers"`
- TrafficMonitors []Monitor `json:"trafficMonitors"`
- Cachegroups []Cachegroup `json:"cacheGroups"`
- Profiles []Profile `json:"profiles"`
- DeliveryServices []DeliveryService `json:"deliveryServices"`
- Config map[string]string `json:"config"`
-}
-
-type MonitoringResponse struct {
- Response Monitoring `json:"response"`
-}
-
-type Router struct {
- Type string
- Profile string
-}
-
-type DeliveryService struct {
- XMLID string `json:"xmlId"`
- TotalTPSThreshold float64 `json:"totalTpsThreshold"`
- Status string `json:"status"`
- TotalKBPSThreshold float64 `json:"totalKbpsThreshold"`
-}
-
-// TODO change to use the ParamMap, instead of parsing the URL
-func monitoringHandler(db *sql.DB) RegexHandlerFunc {
- return func(w http.ResponseWriter, r *http.Request, p ParamMap) {
- handleErr := func(err error, status int) {
- fmt.Printf("%v %v error %v\n", time.Now(), r.RemoteAddr, err)
- w.WriteHeader(status)
- fmt.Fprintf(w, http.StatusText(status))
- }
-
- cdnName := p["cdn"]
-
- resp, err := getMonitoringJson(cdnName, db)
- if err != nil {
- handleErr(err, http.StatusInternalServerError)
- return
- }
-
- respBts, err := json.Marshal(resp)
- if err != nil {
- handleErr(err, http.StatusInternalServerError)
- return
- }
-
- w.Header().Set("Content-Type", "application/json")
- fmt.Fprintf(w, "%s", respBts)
- }
-}
-
-func getServers(db *sql.DB, cdn string) ([]Monitor, []Cache, []Router, error) {
- query := `SELECT
-me.host_name as hostName,
-CONCAT(me.host_name, '.', me.domain_name) as fqdn,
-status.name as status,
-cachegroup.name as cachegroup,
-me.tcp_port as port,
-me.ip_address as ip,
-me.ip6_address as ip6,
-profile.name as profile,
-me.interface_name as interfaceName,
-type.name as type,
-me.xmpp_id as hashId
-FROM server me
-JOIN type type ON type.id = me.type
-JOIN status status ON status.id = me.status
-JOIN cachegroup cachegroup ON cachegroup.id = me.cachegroup
-JOIN profile profile ON profile.id = me.profile
-JOIN cdn cdn ON cdn.id = me.cdn_id
-WHERE cdn.name = $1`
-
- rows, err := db.Query(query, cdn)
- if err != nil {
- return nil, nil, nil, err
- }
- defer rows.Close()
-
- monitors := []Monitor{}
- caches := []Cache{}
- routers := []Router{}
-
- for rows.Next() {
- var hostName sql.NullString
- var fqdn sql.NullString
- var status sql.NullString
- var cachegroup sql.NullString
- var port sql.NullInt64
- var ip sql.NullString
- var ip6 sql.NullString
- var profile sql.NullString
- var interfaceName sql.NullString
- var ttype sql.NullString
- var hashId sql.NullString
-
- if err := rows.Scan(&hostName, &fqdn, &status, &cachegroup, &port, &ip, &ip6, &profile, &interfaceName, &ttype, &hashId); err != nil {
- return nil, nil, nil, err
- }
-
- if ttype.String == MonitorType {
- monitors = append(monitors, Monitor{
- BasicServer: BasicServer{
- Profile: profile.String,
- Status: status.String,
- IP: ip.String,
- IP6: ip6.String,
- Port: int(port.Int64),
- Cachegroup: cachegroup.String,
- HostName: hostName.String,
- FQDN: fqdn.String,
- },
- })
- } else if strings.HasPrefix(ttype.String, "EDGE") || strings.HasPrefix(ttype.String, "MID") {
- caches = append(caches, Cache{
- BasicServer: BasicServer{
- Profile: profile.String,
- Status: status.String,
- IP: ip.String,
- IP6: ip6.String,
- Port: int(port.Int64),
- Cachegroup: cachegroup.String,
- HostName: hostName.String,
- FQDN: fqdn.String,
- },
- InterfaceName: interfaceName.String,
- Type: ttype.String,
- HashID: hashId.String,
- })
- } else if ttype.String == RouterType {
- routers = append(routers, Router{
- Type: ttype.String,
- Profile: profile.String,
- })
- }
- }
- return monitors, caches, routers, nil
-}
-
-func getCachegroups(db *sql.DB, cdn string) ([]Cachegroup, error) {
- query := `
-SELECT name, latitude, longitude
-FROM cachegroup
-WHERE id IN
- (SELECT cachegroup FROM server WHERE server.cdn_id =
- (SELECT id FROM cdn WHERE name = $1));`
-
- rows, err := db.Query(query, cdn)
- if err != nil {
- return nil, err
- }
- defer rows.Close()
-
- cachegroups := []Cachegroup{}
-
- for rows.Next() {
- var name sql.NullString
- var lat sql.NullFloat64
- var lon sql.NullFloat64
- if err := rows.Scan(&name, &lat, &lon); err != nil {
- return nil, err
- }
- cachegroups = append(cachegroups, Cachegroup{
- Name: name.String,
- Coordinates: Coordinates{
- Latitude: lat.Float64,
- Longitude: lon.Float64,
- },
- })
- }
- return cachegroups, nil
-}
-
-func getProfiles(db *sql.DB, caches []Cache, routers []Router) ([]Profile, error) {
- cacheProfileTypes := map[string]string{}
- profiles := map[string]Profile{}
- profileNames := []string{}
- for _, router := range routers {
- profiles[router.Profile] = Profile{
- Name: router.Profile,
- Type: router.Type,
- }
- }
-
- for _, cache := range caches {
- if _, ok := cacheProfileTypes[cache.Profile]; !ok {
- cacheProfileTypes[cache.Profile] = cache.Type
- profiles[cache.Profile] = Profile{
- Name: cache.Profile,
- Type: cache.Type,
- }
- profileNames = append(profileNames, cache.Profile)
- }
- }
-
- query := `
-SELECT p.name as profile, pr.name, pr.value
-FROM parameter pr
-JOIN profile p ON p.name = ANY($1)
-JOIN profile_parameter pp ON pp.profile = p.id and pp.parameter = pr.id
-WHERE pr.config_file = $2;
-`
- rows, err := db.Query(query, pq.Array(profileNames), CacheMonitorConfigFile)
- if err != nil {
- return nil, err
- }
- defer rows.Close()
-
- for rows.Next() {
- var profileName sql.NullString
- var name sql.NullString
- var value sql.NullString
- if err := rows.Scan(&profileName, &name, &value); err != nil {
- return nil, err
- }
- if name.String == "" {
- return nil, fmt.Errorf("null name") // TODO continue and warn?
- }
- profile := profiles[profileName.String]
- if profile.Parameters == nil {
- profile.Parameters = map[string]string{}
- }
- profile.Parameters[name.String] = value.String
- profiles[profileName.String] = profile
-
- }
-
- profilesArr := []Profile{} // TODO make for efficiency?
- for _, profile := range profiles {
- profilesArr = append(profilesArr, profile)
- }
- return profilesArr, nil
-}
-
-func getDeliveryServices(db *sql.DB, routers []Router) ([]DeliveryService, error) {
- profileNames := []string{}
- for _, router := range routers {
- profileNames = append(profileNames, router.Profile)
- }
-
- query := `
-SELECT ds.xml_id, ds.global_max_tps, ds.global_max_mbps
-FROM deliveryservice ds
-JOIN profile profile ON profile.id = ds.profile
-WHERE profile.name = ANY($1)
-AND ds.active = true
-`
- rows, err := db.Query(query, pq.Array(profileNames))
- if err != nil {
- return nil, err
- }
- defer rows.Close()
-
- dses := []DeliveryService{}
-
- for rows.Next() {
- var xmlid sql.NullString
- var tps sql.NullFloat64
- var mbps sql.NullFloat64
- if err := rows.Scan(&xmlid, &tps, &mbps); err != nil {
- return nil, err
- }
- dses = append(dses, DeliveryService{
- XMLID: xmlid.String,
- TotalTPSThreshold: tps.Float64,
- Status: DeliveryServiceStatus,
- TotalKBPSThreshold: mbps.Float64 * KilobitsPerMegabit,
- })
- }
- return dses, nil
-}
-
-func getConfig(db *sql.DB) (map[string]string, error) {
- // TODO remove 'like' in query? Slow?
- query := fmt.Sprintf(`
-SELECT pr.name, pr.value
-FROM parameter pr
-JOIN profile p ON p.name LIKE '%s%%'
-JOIN profile_parameter pp ON pp.profile = p.id and pp.parameter = pr.id
-WHERE pr.config_file = '%s'
-`, MonitorProfilePrefix, MonitorConfigFile)
-
- rows, err := db.Query(query)
- if err != nil {
- return nil, err
- }
- defer rows.Close()
-
- cfg := map[string]string{}
-
- for rows.Next() {
- var name sql.NullString
- var val sql.NullString
- if err := rows.Scan(&name, &val); err != nil {
- return nil, err
- }
- cfg[name.String] = val.String
- }
- return cfg, nil
-}
-
-func getMonitoringJson(cdnName string, db *sql.DB) (*MonitoringResponse, error) {
- monitors, caches, routers, err := getServers(db, cdnName)
- if err != nil {
- return nil, fmt.Errorf("error getting servers: %v", err)
- }
-
- cachegroups, err := getCachegroups(db, cdnName)
- if err != nil {
- return nil, fmt.Errorf("error getting cachegroups: %v", err)
- }
-
- profiles, err := getProfiles(db, caches, routers)
- if err != nil {
- return nil, fmt.Errorf("error getting profiles: %v", err)
- }
-
- deliveryServices, err := getDeliveryServices(db, routers)
- if err != nil {
- return nil, fmt.Errorf("error getting deliveryservices: %v", err)
- }
-
- config, err := getConfig(db)
- if err != nil {
- return nil, fmt.Errorf("error getting config: %v", err)
- }
-
- resp := MonitoringResponse{
- Response: Monitoring{
- TrafficServers: caches,
- TrafficMonitors: monitors,
- Cachegroups: cachegroups,
- Profiles: profiles,
- DeliveryServices: deliveryServices,
- Config: config,
- },
- }
- return &resp, nil
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/04ed9f14/traffic_ops/experimental/goto/routes.go
----------------------------------------------------------------------
diff --git a/traffic_ops/experimental/goto/routes.go b/traffic_ops/experimental/goto/routes.go
deleted file mode 100644
index cc14450..0000000
--- a/traffic_ops/experimental/goto/routes.go
+++ /dev/null
@@ -1,95 +0,0 @@
-package main
-
-import (
- "crypto/tls"
- "database/sql"
- "net/http"
- "net/http/httputil"
- "regexp"
- "strings"
-)
-
-type ServerData struct {
- Config
- DB *sql.DB
-}
-
-type ParamMap map[string]string
-
-type RegexHandlerFunc func(w http.ResponseWriter, r *http.Request, params ParamMap)
-
-func getMonitoringRoute(d ServerData) RegexHandlerFunc {
- return wrapLogTime(wrapAuth(monitoringHandler(d.DB), d.NoAuth, d.TOSecret))
-}
-
-// getRootHandler returns the / handler for the service, which reverse-proxies the old Perl Traffic Ops
-func getRootHandler(d ServerData) http.Handler {
- // debug
- tr := &http.Transport{
- TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
- }
- rp := httputil.NewSingleHostReverseProxy(d.TOURL)
- rp.Transport = tr
- return rp
-}
-
-// GetRoutes returns the map of regex routes, and a catchall route if no regex matches.
-func GetRoutes(d ServerData) (map[string]RegexHandlerFunc, http.Handler) {
- return map[string]RegexHandlerFunc{
- "api/1.2/cdns/{cdn}/configs/monitoring.json": getMonitoringRoute(d),
- }, getRootHandler(d)
-}
-
-type CompiledRoute struct {
- Handler RegexHandlerFunc
- Regex *regexp.Regexp
- Params []string
-}
-
-func CompileRoutes(routes *map[string]RegexHandlerFunc) map[string]CompiledRoute {
- compiledRoutes := map[string]CompiledRoute{}
- for route, handler := range *routes {
- originalRoute := route
- var params []string
- for open := strings.Index(route, "{"); open > 0; open = strings.Index(route, "{") {
- close := strings.Index(route, "}")
- if close < 0 {
- panic("malformed route")
- }
- param := route[open+1 : close]
-
- params = append(params, param)
- route = route[:open] + `(.+)` + route[close+1:]
- }
- regex := regexp.MustCompile(route)
- compiledRoutes[originalRoute] = CompiledRoute{Handler: handler, Regex: regex, Params: params}
- }
- return compiledRoutes
-}
-
-func Handler(routes map[string]CompiledRoute, catchall http.Handler, w http.ResponseWriter, r *http.Request) {
- requested := r.URL.Path[1:]
-
- for _, compiledRoute := range routes {
- match := compiledRoute.Regex.FindStringSubmatch(requested)
- if len(match) == 0 {
- continue
- }
-
- params := map[string]string{}
- for i, v := range compiledRoute.Params {
- params[v] = match[i+1]
- }
- compiledRoute.Handler(w, r, params)
- return
- }
- catchall.ServeHTTP(w, r)
-}
-
-func RegisterRoutes(d ServerData) {
- routes, catchall := GetRoutes(d)
- compiledRoutes := CompileRoutes(&routes)
- http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- Handler(compiledRoutes, catchall, w, r)
- })
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/04ed9f14/traffic_ops/experimental/goto/wrappers.go
----------------------------------------------------------------------
diff --git a/traffic_ops/experimental/goto/wrappers.go b/traffic_ops/experimental/goto/wrappers.go
deleted file mode 100644
index daf5e34..0000000
--- a/traffic_ops/experimental/goto/wrappers.go
+++ /dev/null
@@ -1,55 +0,0 @@
-package main
-
-import (
- "fmt"
- "github.com/apache/incubator-trafficcontrol/traffic_ops/experimental/tocookie"
- "log" // TODO change to traffic_monitor_golang/common/log
- "net/http"
- "time"
-)
-
-func wrapAuth(h RegexHandlerFunc, noAuth bool, secret string) RegexHandlerFunc {
- if noAuth {
- return h
- }
- return func(w http.ResponseWriter, r *http.Request, p ParamMap) {
- handleUnauthorized := func(reason string) {
- log.Printf("%v %v %v sent 401 - %v\n", time.Now(), r.RemoteAddr, r.URL.Path, reason)
- status := http.StatusUnauthorized
- w.WriteHeader(status)
- fmt.Fprintf(w, http.StatusText(status))
- }
-
- cookie, err := r.Cookie(tocookie.Name)
- if err != nil {
- handleUnauthorized("error getting cookie: " + err.Error())
- return
- }
-
- if cookie == nil {
- handleUnauthorized("no auth cookie")
- return
- }
-
- oldCookie, err := tocookie.Parse(secret, cookie.Value)
- if err != nil {
- handleUnauthorized("cookie error: " + err.Error())
- return
- }
-
- newCookieVal := tocookie.Refresh(oldCookie, secret)
- http.SetCookie(w, &http.Cookie{Name: tocookie.Name, Value: newCookieVal})
- h(w, r, p)
- }
-}
-
-func wrapLogTime(h RegexHandlerFunc) RegexHandlerFunc {
- return func(w http.ResponseWriter, r *http.Request, p ParamMap) {
- start := time.Now()
- defer func() {
- now := time.Now()
- log.Printf("%v %v served %v in %v\n", now, r.RemoteAddr, r.URL.Path, now.Sub(start))
- }()
- h(w, r, p)
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/04ed9f14/traffic_ops/traffic_ops_golang/config.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/config.go b/traffic_ops/traffic_ops_golang/config.go
new file mode 100644
index 0000000..a0f3401
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/config.go
@@ -0,0 +1,80 @@
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/url"
+)
+
+type Config struct {
+ HTTPPort string `json:"port"`
+ DBUser string `json:"db_user"`
+ DBPass string `json:"db_pass"`
+ DBServer string `json:"db_server"`
+ DBDB string `json:"db_name"`
+ DBSSL bool `json:"db_ssl"`
+ TOSecret string `json:"to_secret"`
+ TOURLStr string `json:"to_url"`
+ TOURL *url.URL `json:"-"`
+ NoAuth bool `json:"no_auth"`
+ CertPath string `json:"cert_path"`
+ KeyPath string `json:"key_path"`
+}
+
+func LoadConfig(fileName string) (Config, error) {
+ if fileName == "" {
+ return Config{}, fmt.Errorf("no filename")
+ }
+
+ configBytes, err := ioutil.ReadFile(fileName)
+ if err != nil {
+ return Config{}, err
+ }
+
+ cfg := Config{}
+ if err := json.Unmarshal(configBytes, &cfg); err != nil {
+ return Config{}, err
+ }
+
+ if cfg, err = ParseConfig(cfg); err != nil {
+ return Config{}, err
+ }
+
+ return cfg, nil
+}
+
+// ParseConfig validates required fields, and parses non-JSON types
+func ParseConfig(cfg Config) (Config, error) {
+ if cfg.HTTPPort == "" {
+ return Config{}, fmt.Errorf("missing port")
+ }
+ if cfg.DBUser == "" {
+ return Config{}, fmt.Errorf("missing database user")
+ }
+ if cfg.DBPass == "" {
+ return Config{}, fmt.Errorf("missing database password")
+ }
+ if cfg.DBServer == "" {
+ return Config{}, fmt.Errorf("missing database server")
+ }
+ if cfg.DBDB == "" {
+ return Config{}, fmt.Errorf("missing database name")
+ }
+ if cfg.TOSecret == "" {
+ return Config{}, fmt.Errorf("missing secret")
+ }
+ if cfg.CertPath == "" {
+ return Config{}, fmt.Errorf("missing certificate path")
+ }
+ if cfg.KeyPath == "" {
+ return Config{}, fmt.Errorf("missing certificate key path")
+ }
+
+ var err error
+ if cfg.TOURL, err = url.Parse(cfg.TOURLStr); err != nil {
+ return Config{}, fmt.Errorf("Invalid Traffic Ops URL '%v': err", cfg.TOURL, err)
+ }
+
+ return cfg, nil
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/04ed9f14/traffic_ops/traffic_ops_golang/monitoring.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/monitoring.go b/traffic_ops/traffic_ops_golang/monitoring.go
new file mode 100644
index 0000000..b353fb5
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/monitoring.go
@@ -0,0 +1,398 @@
+package main
+
+import (
+ "database/sql"
+ "encoding/json"
+ "fmt"
+ "github.com/lib/pq"
+ "net/http"
+ "strings"
+ "time"
+)
+
+const CacheMonitorConfigFile = "rascal.properties"
+const MonitorType = "RASCAL"
+const RouterType = "CCR"
+const MonitorProfilePrefix = "RASCAL"
+const MonitorConfigFile = "rascal-config.txt"
+const KilobitsPerMegabit = 1000
+const DeliveryServiceStatus = "REPORTED"
+
+type BasicServer struct {
+ Profile string `json:"profile"`
+ Status string `json:"status"`
+ IP string `json:"ip"`
+ IP6 string `json:"ip6"`
+ Port int `json:"port"`
+ Cachegroup string `json:"cachegroup"`
+ HostName string `json:"hostName"`
+ FQDN string `json:"fqdn"`
+}
+
+type Monitor struct {
+ BasicServer
+}
+
+type Cache struct {
+ BasicServer
+ InterfaceName string `json:"interfaceName"`
+ Type string `json:"type"`
+ HashID string `json:"hashId"`
+}
+
+type Cachegroup struct {
+ Name string `json:"name"`
+ Coordinates Coordinates `json:"coordinates"`
+}
+
+type Coordinates struct {
+ Latitude float64 `json:"latitude"`
+ Longitude float64 `json:"longitude"`
+}
+
+type Profile struct {
+ Name string `json:"name"`
+ Type string `json:"type"`
+ Parameters map[string]string `json:"parameters"`
+}
+
+type Monitoring struct {
+ TrafficServers []Cache `json:"trafficServers"`
+ TrafficMonitors []Monitor `json:"trafficMonitors"`
+ Cachegroups []Cachegroup `json:"cacheGroups"`
+ Profiles []Profile `json:"profiles"`
+ DeliveryServices []DeliveryService `json:"deliveryServices"`
+ Config map[string]string `json:"config"`
+}
+
+type MonitoringResponse struct {
+ Response Monitoring `json:"response"`
+}
+
+type Router struct {
+ Type string
+ Profile string
+}
+
+type DeliveryService struct {
+ XMLID string `json:"xmlId"`
+ TotalTPSThreshold float64 `json:"totalTpsThreshold"`
+ Status string `json:"status"`
+ TotalKBPSThreshold float64 `json:"totalKbpsThreshold"`
+}
+
+// TODO change to use the ParamMap, instead of parsing the URL
+func monitoringHandler(db *sql.DB) RegexHandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request, p ParamMap) {
+ handleErr := func(err error, status int) {
+ fmt.Printf("%v %v error %v\n", time.Now(), r.RemoteAddr, err)
+ w.WriteHeader(status)
+ fmt.Fprintf(w, http.StatusText(status))
+ }
+
+ cdnName := p["cdn"]
+
+ resp, err := getMonitoringJson(cdnName, db)
+ if err != nil {
+ handleErr(err, http.StatusInternalServerError)
+ return
+ }
+
+ respBts, err := json.Marshal(resp)
+ if err != nil {
+ handleErr(err, http.StatusInternalServerError)
+ return
+ }
+
+ w.Header().Set("Content-Type", "application/json")
+ fmt.Fprintf(w, "%s", respBts)
+ }
+}
+
+func getServers(db *sql.DB, cdn string) ([]Monitor, []Cache, []Router, error) {
+ query := `SELECT
+me.host_name as hostName,
+CONCAT(me.host_name, '.', me.domain_name) as fqdn,
+status.name as status,
+cachegroup.name as cachegroup,
+me.tcp_port as port,
+me.ip_address as ip,
+me.ip6_address as ip6,
+profile.name as profile,
+me.interface_name as interfaceName,
+type.name as type,
+me.xmpp_id as hashId
+FROM server me
+JOIN type type ON type.id = me.type
+JOIN status status ON status.id = me.status
+JOIN cachegroup cachegroup ON cachegroup.id = me.cachegroup
+JOIN profile profile ON profile.id = me.profile
+JOIN cdn cdn ON cdn.id = me.cdn_id
+WHERE cdn.name = $1`
+
+ rows, err := db.Query(query, cdn)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ defer rows.Close()
+
+ monitors := []Monitor{}
+ caches := []Cache{}
+ routers := []Router{}
+
+ for rows.Next() {
+ var hostName sql.NullString
+ var fqdn sql.NullString
+ var status sql.NullString
+ var cachegroup sql.NullString
+ var port sql.NullInt64
+ var ip sql.NullString
+ var ip6 sql.NullString
+ var profile sql.NullString
+ var interfaceName sql.NullString
+ var ttype sql.NullString
+ var hashId sql.NullString
+
+ if err := rows.Scan(&hostName, &fqdn, &status, &cachegroup, &port, &ip, &ip6, &profile, &interfaceName, &ttype, &hashId); err != nil {
+ return nil, nil, nil, err
+ }
+
+ if ttype.String == MonitorType {
+ monitors = append(monitors, Monitor{
+ BasicServer: BasicServer{
+ Profile: profile.String,
+ Status: status.String,
+ IP: ip.String,
+ IP6: ip6.String,
+ Port: int(port.Int64),
+ Cachegroup: cachegroup.String,
+ HostName: hostName.String,
+ FQDN: fqdn.String,
+ },
+ })
+ } else if strings.HasPrefix(ttype.String, "EDGE") || strings.HasPrefix(ttype.String, "MID") {
+ caches = append(caches, Cache{
+ BasicServer: BasicServer{
+ Profile: profile.String,
+ Status: status.String,
+ IP: ip.String,
+ IP6: ip6.String,
+ Port: int(port.Int64),
+ Cachegroup: cachegroup.String,
+ HostName: hostName.String,
+ FQDN: fqdn.String,
+ },
+ InterfaceName: interfaceName.String,
+ Type: ttype.String,
+ HashID: hashId.String,
+ })
+ } else if ttype.String == RouterType {
+ routers = append(routers, Router{
+ Type: ttype.String,
+ Profile: profile.String,
+ })
+ }
+ }
+ return monitors, caches, routers, nil
+}
+
+func getCachegroups(db *sql.DB, cdn string) ([]Cachegroup, error) {
+ query := `
+SELECT name, latitude, longitude
+FROM cachegroup
+WHERE id IN
+ (SELECT cachegroup FROM server WHERE server.cdn_id =
+ (SELECT id FROM cdn WHERE name = $1));`
+
+ rows, err := db.Query(query, cdn)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ cachegroups := []Cachegroup{}
+
+ for rows.Next() {
+ var name sql.NullString
+ var lat sql.NullFloat64
+ var lon sql.NullFloat64
+ if err := rows.Scan(&name, &lat, &lon); err != nil {
+ return nil, err
+ }
+ cachegroups = append(cachegroups, Cachegroup{
+ Name: name.String,
+ Coordinates: Coordinates{
+ Latitude: lat.Float64,
+ Longitude: lon.Float64,
+ },
+ })
+ }
+ return cachegroups, nil
+}
+
+func getProfiles(db *sql.DB, caches []Cache, routers []Router) ([]Profile, error) {
+ cacheProfileTypes := map[string]string{}
+ profiles := map[string]Profile{}
+ profileNames := []string{}
+ for _, router := range routers {
+ profiles[router.Profile] = Profile{
+ Name: router.Profile,
+ Type: router.Type,
+ }
+ }
+
+ for _, cache := range caches {
+ if _, ok := cacheProfileTypes[cache.Profile]; !ok {
+ cacheProfileTypes[cache.Profile] = cache.Type
+ profiles[cache.Profile] = Profile{
+ Name: cache.Profile,
+ Type: cache.Type,
+ }
+ profileNames = append(profileNames, cache.Profile)
+ }
+ }
+
+ query := `
+SELECT p.name as profile, pr.name, pr.value
+FROM parameter pr
+JOIN profile p ON p.name = ANY($1)
+JOIN profile_parameter pp ON pp.profile = p.id and pp.parameter = pr.id
+WHERE pr.config_file = $2;
+`
+ rows, err := db.Query(query, pq.Array(profileNames), CacheMonitorConfigFile)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ for rows.Next() {
+ var profileName sql.NullString
+ var name sql.NullString
+ var value sql.NullString
+ if err := rows.Scan(&profileName, &name, &value); err != nil {
+ return nil, err
+ }
+ if name.String == "" {
+ return nil, fmt.Errorf("null name") // TODO continue and warn?
+ }
+ profile := profiles[profileName.String]
+ if profile.Parameters == nil {
+ profile.Parameters = map[string]string{}
+ }
+ profile.Parameters[name.String] = value.String
+ profiles[profileName.String] = profile
+
+ }
+
+ profilesArr := []Profile{} // TODO make for efficiency?
+ for _, profile := range profiles {
+ profilesArr = append(profilesArr, profile)
+ }
+ return profilesArr, nil
+}
+
+func getDeliveryServices(db *sql.DB, routers []Router) ([]DeliveryService, error) {
+ profileNames := []string{}
+ for _, router := range routers {
+ profileNames = append(profileNames, router.Profile)
+ }
+
+ query := `
+SELECT ds.xml_id, ds.global_max_tps, ds.global_max_mbps
+FROM deliveryservice ds
+JOIN profile profile ON profile.id = ds.profile
+WHERE profile.name = ANY($1)
+AND ds.active = true
+`
+ rows, err := db.Query(query, pq.Array(profileNames))
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ dses := []DeliveryService{}
+
+ for rows.Next() {
+ var xmlid sql.NullString
+ var tps sql.NullFloat64
+ var mbps sql.NullFloat64
+ if err := rows.Scan(&xmlid, &tps, &mbps); err != nil {
+ return nil, err
+ }
+ dses = append(dses, DeliveryService{
+ XMLID: xmlid.String,
+ TotalTPSThreshold: tps.Float64,
+ Status: DeliveryServiceStatus,
+ TotalKBPSThreshold: mbps.Float64 * KilobitsPerMegabit,
+ })
+ }
+ return dses, nil
+}
+
+func getConfig(db *sql.DB) (map[string]string, error) {
+ // TODO remove 'like' in query? Slow?
+ query := fmt.Sprintf(`
+SELECT pr.name, pr.value
+FROM parameter pr
+JOIN profile p ON p.name LIKE '%s%%'
+JOIN profile_parameter pp ON pp.profile = p.id and pp.parameter = pr.id
+WHERE pr.config_file = '%s'
+`, MonitorProfilePrefix, MonitorConfigFile)
+
+ rows, err := db.Query(query)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ cfg := map[string]string{}
+
+ for rows.Next() {
+ var name sql.NullString
+ var val sql.NullString
+ if err := rows.Scan(&name, &val); err != nil {
+ return nil, err
+ }
+ cfg[name.String] = val.String
+ }
+ return cfg, nil
+}
+
+func getMonitoringJson(cdnName string, db *sql.DB) (*MonitoringResponse, error) {
+ monitors, caches, routers, err := getServers(db, cdnName)
+ if err != nil {
+ return nil, fmt.Errorf("error getting servers: %v", err)
+ }
+
+ cachegroups, err := getCachegroups(db, cdnName)
+ if err != nil {
+ return nil, fmt.Errorf("error getting cachegroups: %v", err)
+ }
+
+ profiles, err := getProfiles(db, caches, routers)
+ if err != nil {
+ return nil, fmt.Errorf("error getting profiles: %v", err)
+ }
+
+ deliveryServices, err := getDeliveryServices(db, routers)
+ if err != nil {
+ return nil, fmt.Errorf("error getting deliveryservices: %v", err)
+ }
+
+ config, err := getConfig(db)
+ if err != nil {
+ return nil, fmt.Errorf("error getting config: %v", err)
+ }
+
+ resp := MonitoringResponse{
+ Response: Monitoring{
+ TrafficServers: caches,
+ TrafficMonitors: monitors,
+ Cachegroups: cachegroups,
+ Profiles: profiles,
+ DeliveryServices: deliveryServices,
+ Config: config,
+ },
+ }
+ return &resp, nil
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/04ed9f14/traffic_ops/traffic_ops_golang/routes.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
new file mode 100644
index 0000000..cc14450
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -0,0 +1,95 @@
+package main
+
+import (
+ "crypto/tls"
+ "database/sql"
+ "net/http"
+ "net/http/httputil"
+ "regexp"
+ "strings"
+)
+
+type ServerData struct {
+ Config
+ DB *sql.DB
+}
+
+type ParamMap map[string]string
+
+type RegexHandlerFunc func(w http.ResponseWriter, r *http.Request, params ParamMap)
+
+func getMonitoringRoute(d ServerData) RegexHandlerFunc {
+ return wrapLogTime(wrapAuth(monitoringHandler(d.DB), d.NoAuth, d.TOSecret))
+}
+
+// getRootHandler returns the / handler for the service, which reverse-proxies the old Perl Traffic Ops
+func getRootHandler(d ServerData) http.Handler {
+ // debug
+ tr := &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+ }
+ rp := httputil.NewSingleHostReverseProxy(d.TOURL)
+ rp.Transport = tr
+ return rp
+}
+
+// GetRoutes returns the map of regex routes, and a catchall route if no regex matches.
+func GetRoutes(d ServerData) (map[string]RegexHandlerFunc, http.Handler) {
+ return map[string]RegexHandlerFunc{
+ "api/1.2/cdns/{cdn}/configs/monitoring.json": getMonitoringRoute(d),
+ }, getRootHandler(d)
+}
+
+type CompiledRoute struct {
+ Handler RegexHandlerFunc
+ Regex *regexp.Regexp
+ Params []string
+}
+
+func CompileRoutes(routes *map[string]RegexHandlerFunc) map[string]CompiledRoute {
+ compiledRoutes := map[string]CompiledRoute{}
+ for route, handler := range *routes {
+ originalRoute := route
+ var params []string
+ for open := strings.Index(route, "{"); open > 0; open = strings.Index(route, "{") {
+ close := strings.Index(route, "}")
+ if close < 0 {
+ panic("malformed route")
+ }
+ param := route[open+1 : close]
+
+ params = append(params, param)
+ route = route[:open] + `(.+)` + route[close+1:]
+ }
+ regex := regexp.MustCompile(route)
+ compiledRoutes[originalRoute] = CompiledRoute{Handler: handler, Regex: regex, Params: params}
+ }
+ return compiledRoutes
+}
+
+func Handler(routes map[string]CompiledRoute, catchall http.Handler, w http.ResponseWriter, r *http.Request) {
+ requested := r.URL.Path[1:]
+
+ for _, compiledRoute := range routes {
+ match := compiledRoute.Regex.FindStringSubmatch(requested)
+ if len(match) == 0 {
+ continue
+ }
+
+ params := map[string]string{}
+ for i, v := range compiledRoute.Params {
+ params[v] = match[i+1]
+ }
+ compiledRoute.Handler(w, r, params)
+ return
+ }
+ catchall.ServeHTTP(w, r)
+}
+
+func RegisterRoutes(d ServerData) {
+ routes, catchall := GetRoutes(d)
+ compiledRoutes := CompileRoutes(&routes)
+ http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ Handler(compiledRoutes, catchall, w, r)
+ })
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/04ed9f14/traffic_ops/traffic_ops_golang/traffic_ops_golang.config
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/traffic_ops_golang.config b/traffic_ops/traffic_ops_golang/traffic_ops_golang.config
new file mode 100644
index 0000000..19d2599
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/traffic_ops_golang.config
@@ -0,0 +1,13 @@
+{
+ "port": "443",
+ "db_user": "bill",
+ "db_pass": "thelizard",
+ "db_server": "db.trafficops.example.net",
+ "db_name": "trafficops",
+ "db_ssl": true,
+ "to_secret": "walrus",
+ "to_url": "https://trafficops.example.net:60443",
+ "no_auth": false,
+ "cert_path": "/opt/traffic_ops/cert",
+ "key_path": "/opt/traffic_ops/key"
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/04ed9f14/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/traffic_ops_golang.go b/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
new file mode 100644
index 0000000..48d3c4e
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
@@ -0,0 +1,56 @@
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "database/sql"
+ "flag"
+ "fmt"
+ _ "github.com/lib/pq"
+ "net/http"
+)
+
+const DefaultConfigPath = "/etc/goto/config.json"
+
+func main() {
+ configFileName := flag.String("cfg", "", "The config file path")
+ flag.Parse()
+ if *configFileName == "" {
+ *configFileName = DefaultConfigPath
+ }
+
+ cfg, err := LoadConfig(*configFileName)
+ if err != nil {
+ fmt.Println("Error loading config '" + *configFileName + "': " + err.Error())
+ return
+ }
+
+ sslStr := "require"
+ if !cfg.DBSSL {
+ sslStr = "disable"
+ }
+
+ db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s", cfg.DBUser, cfg.DBPass, cfg.DBServer, cfg.DBDB, sslStr))
+ if err != nil {
+ fmt.Printf("Error opening database: %v\n", err)
+ return
+ }
+ defer db.Close()
+
+ RegisterRoutes(ServerData{DB: db, Config: cfg})
+ fmt.Println("Listening on " + cfg.HTTPPort)
+ if err := http.ListenAndServeTLS(":"+cfg.HTTPPort, cfg.CertPath, cfg.KeyPath, nil); err != nil {
+ fmt.Printf("Error stopping server: %v\n", err)
+ return
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/04ed9f14/traffic_ops/traffic_ops_golang/wrappers.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/wrappers.go b/traffic_ops/traffic_ops_golang/wrappers.go
new file mode 100644
index 0000000..daf5e34
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/wrappers.go
@@ -0,0 +1,55 @@
+package main
+
+import (
+ "fmt"
+ "github.com/apache/incubator-trafficcontrol/traffic_ops/experimental/tocookie"
+ "log" // TODO change to traffic_monitor_golang/common/log
+ "net/http"
+ "time"
+)
+
+func wrapAuth(h RegexHandlerFunc, noAuth bool, secret string) RegexHandlerFunc {
+ if noAuth {
+ return h
+ }
+ return func(w http.ResponseWriter, r *http.Request, p ParamMap) {
+ handleUnauthorized := func(reason string) {
+ log.Printf("%v %v %v sent 401 - %v\n", time.Now(), r.RemoteAddr, r.URL.Path, reason)
+ status := http.StatusUnauthorized
+ w.WriteHeader(status)
+ fmt.Fprintf(w, http.StatusText(status))
+ }
+
+ cookie, err := r.Cookie(tocookie.Name)
+ if err != nil {
+ handleUnauthorized("error getting cookie: " + err.Error())
+ return
+ }
+
+ if cookie == nil {
+ handleUnauthorized("no auth cookie")
+ return
+ }
+
+ oldCookie, err := tocookie.Parse(secret, cookie.Value)
+ if err != nil {
+ handleUnauthorized("cookie error: " + err.Error())
+ return
+ }
+
+ newCookieVal := tocookie.Refresh(oldCookie, secret)
+ http.SetCookie(w, &http.Cookie{Name: tocookie.Name, Value: newCookieVal})
+ h(w, r, p)
+ }
+}
+
+func wrapLogTime(h RegexHandlerFunc) RegexHandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request, p ParamMap) {
+ start := time.Now()
+ defer func() {
+ now := time.Now()
+ log.Printf("%v %v served %v in %v\n", now, r.RemoteAddr, r.URL.Path, now.Sub(start))
+ }()
+ h(w, r, p)
+ }
+}
[07/43] incubator-trafficcontrol git commit: Add experimental Go TO
proxying old Perl app
Posted by de...@apache.org.
Add experimental Go TO proxying old Perl app
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/aa901953
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/aa901953
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/aa901953
Branch: refs/heads/master
Commit: aa901953ae5ba309ae97a793cf90818b0096ea08
Parents: 9c4eccc
Author: Robert Butts <ro...@gmail.com>
Authored: Sat Jul 8 21:02:56 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:02 2017 -0600
----------------------------------------------------------------------
.../go-monitoring/to-go-monitoring.go | 528 -------------------
traffic_ops/experimental/goto/config.go | 80 +++
traffic_ops/experimental/goto/config.json | 13 +
traffic_ops/experimental/goto/goto.go | 56 ++
traffic_ops/experimental/goto/monitoring.go | 398 ++++++++++++++
traffic_ops/experimental/goto/routes.go | 95 ++++
traffic_ops/experimental/goto/wrappers.go | 55 ++
traffic_ops/experimental/tocookie/tocookie.go | 6 +
8 files changed, 703 insertions(+), 528 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/aa901953/traffic_ops/experimental/go-monitoring/to-go-monitoring.go
----------------------------------------------------------------------
diff --git a/traffic_ops/experimental/go-monitoring/to-go-monitoring.go b/traffic_ops/experimental/go-monitoring/to-go-monitoring.go
deleted file mode 100644
index a508212..0000000
--- a/traffic_ops/experimental/go-monitoring/to-go-monitoring.go
+++ /dev/null
@@ -1,528 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
- "database/sql"
- "encoding/json"
- "flag"
- "fmt"
- "github.com/apache/incubator-trafficcontrol/traffic_ops/experimental/tocookie"
- "github.com/lib/pq"
- "net/http"
- "strings"
- "time"
-)
-
-const CacheMonitorConfigFile = "rascal.properties"
-const MonitorType = "RASCAL"
-const RouterType = "CCR"
-const MonitorProfilePrefix = "RASCAL"
-const MonitorConfigFile = "rascal-config.txt"
-
-const KilobitsPerMegabit = 1000
-const DeliveryServiceStatus = "REPORTED"
-
-// Args encapsulates the command line arguments
-type Args struct {
- HTTPPort string
- DBUser string
- DBPass string
- DBServer string
- DBDB string
- DBSSL bool
- Auth bool
- TOSecret string
-}
-
-// getFlags parses and returns the command line arguments. The returned error
-// will be non-nil if any expected arg is missing.
-func getFlags() (Args, error) {
- var args Args
- flag.StringVar(&args.HTTPPort, "port", "", "the port to serve on")
- flag.StringVar(&args.DBUser, "user", "", "the database user")
- flag.StringVar(&args.DBPass, "pass", "", "the database password")
- flag.StringVar(&args.DBServer, "server", "", "the database server IP or FQDN, without scheme")
- flag.StringVar(&args.DBDB, "db", "", "the database name")
- flag.BoolVar(&args.DBSSL, "ssl", true, "whether to require or disable SSL connecting to the database")
- flag.StringVar(&args.TOSecret, "secret", "", "the Traffic Ops secret, used to authenticate mojolicious cookies")
- flag.BoolVar(&args.Auth, "authenticate", true, "whether to authenticate requests, requiring valid Traffic Ops cookies")
- flag.Parse()
- if args.HTTPPort == "" {
- return args, fmt.Errorf("missing port")
- }
- if args.DBUser == "" {
- return args, fmt.Errorf("missing user")
- }
- if args.DBPass == "" {
- return args, fmt.Errorf("missing password")
- }
- if args.DBServer == "" {
- return args, fmt.Errorf("missing server")
- }
- if args.DBDB == "" {
- return args, fmt.Errorf("missing database")
- }
- if args.Auth && args.TOSecret == "" {
- return args, fmt.Errorf("missing secret")
- }
- return args, nil
-}
-
-func printUsage() {
- fmt.Println("Usage:")
- flag.PrintDefaults()
- fmt.Println("Example: to-go-monitoring -port 80 -user bill -pass thelizard -server db.to.example.net -db to")
-}
-
-type BasicServer struct {
- Profile string `json:"profile"`
- Status string `json:"status"`
- IP string `json:"ip"`
- IP6 string `json:"ip6"`
- Port int `json:"port"`
- Cachegroup string `json:"cachegroup"`
- HostName string `json:"hostName"`
- FQDN string `json:"fqdn"`
-}
-
-type Monitor struct {
- BasicServer
-}
-
-type Cache struct {
- BasicServer
- InterfaceName string `json:"interfaceName"`
- Type string `json:"type"`
- HashID string `json:"hashId"`
-}
-
-type Cachegroup struct {
- Name string `json:"name"`
- Coordinates Coordinates `json:"coordinates"`
-}
-
-type Coordinates struct {
- Latitude float64 `json:"latitude"`
- Longitude float64 `json:"longitude"`
-}
-
-type Profile struct {
- Name string `json:"name"`
- Type string `json:"type"`
- Parameters map[string]string `json:"parameters"`
-}
-
-type Monitoring struct {
- TrafficServers []Cache `json:"trafficServers"`
- TrafficMonitors []Monitor `json:"trafficMonitors"`
- Cachegroups []Cachegroup `json:"cacheGroups"`
- Profiles []Profile `json:"profiles"`
- DeliveryServices []DeliveryService `json:"deliveryServices"`
- Config map[string]string `json:"config"`
-}
-
-type MonitoringResponse struct {
- Response Monitoring `json:"response"`
-}
-
-type Router struct {
- Type string
- Profile string
-}
-
-type DeliveryService struct {
- XMLID string `json:"xmlId"`
- TotalTPSThreshold float64 `json:"totalTpsThreshold"`
- Status string `json:"status"`
- TotalKBPSThreshold float64 `json:"totalKbpsThreshold"`
-}
-
-func getServers(db *sql.DB, cdn string) ([]Monitor, []Cache, []Router, error) {
- query := `SELECT
-me.host_name as hostName,
-CONCAT(me.host_name, '.', me.domain_name) as fqdn,
-status.name as status,
-cachegroup.name as cachegroup,
-me.tcp_port as port,
-me.ip_address as ip,
-me.ip6_address as ip6,
-profile.name as profile,
-me.interface_name as interfaceName,
-type.name as type,
-me.xmpp_id as hashId
-FROM server me
-JOIN type type ON type.id = me.type
-JOIN status status ON status.id = me.status
-JOIN cachegroup cachegroup ON cachegroup.id = me.cachegroup
-JOIN profile profile ON profile.id = me.profile
-JOIN cdn cdn ON cdn.id = me.cdn_id
-WHERE cdn.name = $1`
-
- rows, err := db.Query(query, cdn)
- if err != nil {
- return nil, nil, nil, err
- }
- defer rows.Close()
-
- monitors := []Monitor{}
- caches := []Cache{}
- routers := []Router{}
-
- for rows.Next() {
- var hostName sql.NullString
- var fqdn sql.NullString
- var status sql.NullString
- var cachegroup sql.NullString
- var port sql.NullInt64
- var ip sql.NullString
- var ip6 sql.NullString
- var profile sql.NullString
- var interfaceName sql.NullString
- var ttype sql.NullString
- var hashId sql.NullString
-
- if err := rows.Scan(&hostName, &fqdn, &status, &cachegroup, &port, &ip, &ip6, &profile, &interfaceName, &ttype, &hashId); err != nil {
- return nil, nil, nil, err
- }
-
- if ttype.String == MonitorType {
- monitors = append(monitors, Monitor{
- BasicServer: BasicServer{
- Profile: profile.String,
- Status: status.String,
- IP: ip.String,
- IP6: ip6.String,
- Port: int(port.Int64),
- Cachegroup: cachegroup.String,
- HostName: hostName.String,
- FQDN: fqdn.String,
- },
- })
- } else if strings.HasPrefix(ttype.String, "EDGE") || strings.HasPrefix(ttype.String, "MID") {
- caches = append(caches, Cache{
- BasicServer: BasicServer{
- Profile: profile.String,
- Status: status.String,
- IP: ip.String,
- IP6: ip6.String,
- Port: int(port.Int64),
- Cachegroup: cachegroup.String,
- HostName: hostName.String,
- FQDN: fqdn.String,
- },
- InterfaceName: interfaceName.String,
- Type: ttype.String,
- HashID: hashId.String,
- })
- } else if ttype.String == RouterType {
- routers = append(routers, Router{
- Type: ttype.String,
- Profile: profile.String,
- })
- }
- }
- return monitors, caches, routers, nil
-}
-
-func getCachegroups(db *sql.DB, cdn string) ([]Cachegroup, error) {
- query := `
-SELECT name, latitude, longitude
-FROM cachegroup
-WHERE id IN
- (SELECT cachegroup FROM server WHERE server.cdn_id =
- (SELECT id FROM cdn WHERE name = $1));`
-
- rows, err := db.Query(query, cdn)
- if err != nil {
- return nil, err
- }
- defer rows.Close()
-
- cachegroups := []Cachegroup{}
-
- for rows.Next() {
- var name sql.NullString
- var lat sql.NullFloat64
- var lon sql.NullFloat64
- if err := rows.Scan(&name, &lat, &lon); err != nil {
- return nil, err
- }
- cachegroups = append(cachegroups, Cachegroup{
- Name: name.String,
- Coordinates: Coordinates{
- Latitude: lat.Float64,
- Longitude: lon.Float64,
- },
- })
- }
- return cachegroups, nil
-}
-
-func getProfiles(db *sql.DB, caches []Cache, routers []Router) ([]Profile, error) {
- cacheProfileTypes := map[string]string{}
- profiles := map[string]Profile{}
- profileNames := []string{}
- for _, router := range routers {
- profiles[router.Profile] = Profile{
- Name: router.Profile,
- Type: router.Type,
- }
- }
-
- for _, cache := range caches {
- if _, ok := cacheProfileTypes[cache.Profile]; !ok {
- cacheProfileTypes[cache.Profile] = cache.Type
- profiles[cache.Profile] = Profile{
- Name: cache.Profile,
- Type: cache.Type,
- }
- profileNames = append(profileNames, cache.Profile)
- }
- }
-
- query := `
-SELECT p.name as profile, pr.name, pr.value
-FROM parameter pr
-JOIN profile p ON p.name = ANY($1)
-JOIN profile_parameter pp ON pp.profile = p.id and pp.parameter = pr.id
-WHERE pr.config_file = $2;
-`
- rows, err := db.Query(query, pq.Array(profileNames), CacheMonitorConfigFile)
- if err != nil {
- return nil, err
- }
- defer rows.Close()
-
- for rows.Next() {
- var profileName sql.NullString
- var name sql.NullString
- var value sql.NullString
- if err := rows.Scan(&profileName, &name, &value); err != nil {
- return nil, err
- }
- if name.String == "" {
- return nil, fmt.Errorf("null name") // TODO continue and warn?
- }
- profile := profiles[profileName.String]
- if profile.Parameters == nil {
- profile.Parameters = map[string]string{}
- }
- profile.Parameters[name.String] = value.String
- profiles[profileName.String] = profile
-
- }
-
- profilesArr := []Profile{} // TODO make for efficiency?
- for _, profile := range profiles {
- profilesArr = append(profilesArr, profile)
- }
- return profilesArr, nil
-}
-
-func getDeliveryServices(db *sql.DB, routers []Router) ([]DeliveryService, error) {
- profileNames := []string{}
- for _, router := range routers {
- profileNames = append(profileNames, router.Profile)
- }
-
- query := `
-SELECT ds.xml_id, ds.global_max_tps, ds.global_max_mbps
-FROM deliveryservice ds
-JOIN profile profile ON profile.id = ds.profile
-WHERE profile.name = ANY($1)
-AND ds.active = true
-`
- rows, err := db.Query(query, pq.Array(profileNames))
- if err != nil {
- return nil, err
- }
- defer rows.Close()
-
- dses := []DeliveryService{}
-
- for rows.Next() {
- var xmlid sql.NullString
- var tps sql.NullFloat64
- var mbps sql.NullFloat64
- if err := rows.Scan(&xmlid, &tps, &mbps); err != nil {
- return nil, err
- }
- dses = append(dses, DeliveryService{
- XMLID: xmlid.String,
- TotalTPSThreshold: tps.Float64,
- Status: DeliveryServiceStatus,
- TotalKBPSThreshold: mbps.Float64 * KilobitsPerMegabit,
- })
- }
- return dses, nil
-}
-
-func getConfig(db *sql.DB) (map[string]string, error) {
- // TODO remove 'like' in query? Slow?
- query := fmt.Sprintf(`
-SELECT pr.name, pr.value
-FROM parameter pr
-JOIN profile p ON p.name LIKE '%s%%'
-JOIN profile_parameter pp ON pp.profile = p.id and pp.parameter = pr.id
-WHERE pr.config_file = '%s'
-`, MonitorProfilePrefix, MonitorConfigFile)
-
- rows, err := db.Query(query)
- if err != nil {
- return nil, err
- }
- defer rows.Close()
-
- cfg := map[string]string{}
-
- for rows.Next() {
- var name sql.NullString
- var val sql.NullString
- if err := rows.Scan(&name, &val); err != nil {
- return nil, err
- }
- cfg[name.String] = val.String
- }
- return cfg, nil
-}
-
-func getMonitoringJson(cdnName string, db *sql.DB) (*MonitoringResponse, error) {
- monitors, caches, routers, err := getServers(db, cdnName)
- if err != nil {
- return nil, fmt.Errorf("error getting servers: %v", err)
- }
-
- cachegroups, err := getCachegroups(db, cdnName)
- if err != nil {
- return nil, fmt.Errorf("error getting cachegroups: %v", err)
- }
-
- profiles, err := getProfiles(db, caches, routers)
- if err != nil {
- return nil, fmt.Errorf("error getting profiles: %v", err)
- }
-
- deliveryServices, err := getDeliveryServices(db, routers)
- if err != nil {
- return nil, fmt.Errorf("error getting deliveryservices: %v", err)
- }
-
- config, err := getConfig(db)
- if err != nil {
- return nil, fmt.Errorf("error getting config: %v", err)
- }
-
- resp := MonitoringResponse{
- Response: Monitoring{
- TrafficServers: caches,
- TrafficMonitors: monitors,
- Cachegroups: cachegroups,
- Profiles: profiles,
- DeliveryServices: deliveryServices,
- Config: config,
- },
- }
- return &resp, nil
-}
-
-// authenticate attempts to authenticate the given request, looking for an auth cookie, using the auth settings in args. Returns nil if authentication succeeds, or a descriptive error if authentication fails (which should NOT be returned to clients, for security reasons).
-func authenticate(r *http.Request, args Args) error {
- if !args.Auth {
- return nil
- }
-
- cookie, err := r.Cookie(tocookie.Name)
- if err != nil {
- return fmt.Errorf("getting cookie: %v", err)
- }
- if cookie == nil {
- return fmt.Errorf("no auth cookie")
- }
-
- if _, err := tocookie.Parse(args.TOSecret, cookie.Value); err != nil {
- return fmt.Errorf("parsing cookie: %v", err)
- }
- return nil
-}
-
-func rootHandler(w http.ResponseWriter, r *http.Request, db *sql.DB, args Args) {
- start := time.Now()
- defer func() {
- now := time.Now()
- fmt.Printf("%v %v served %v in %v\n", now, r.RemoteAddr, r.URL.Path, now.Sub(start))
- }()
-
- handleErr := func(err error, status int) {
- fmt.Printf("%v %v error %v\n", time.Now(), r.RemoteAddr, err)
- w.WriteHeader(status)
- fmt.Fprintf(w, http.StatusText(status))
- }
-
- if err := authenticate(r, args); err != nil {
- handleErr(err, http.StatusUnauthorized)
- return
- }
-
- pathParts := strings.Split(r.URL.Path, "/")
- if len(pathParts) < 5 {
- handleErr(fmt.Errorf("nonexistent path requested: '%v'", r.URL.Path), http.StatusNotFound)
- return
- }
- cdnName := pathParts[4]
-
- resp, err := getMonitoringJson(cdnName, db)
- if err != nil {
- handleErr(err, http.StatusInternalServerError)
- return
- }
-
- respBts, err := json.Marshal(resp)
- if err != nil {
- handleErr(err, http.StatusInternalServerError)
- return
- }
-
- w.Header().Set("Content-Type", "application/json")
- fmt.Fprintf(w, "%s", respBts)
-}
-
-func main() {
- args, err := getFlags()
- if err != nil {
- fmt.Println(err)
- printUsage()
- return
- }
-
- sslStr := "require"
- if !args.DBSSL {
- sslStr = "disable"
- }
-
- db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s", args.DBUser, args.DBPass, args.DBServer, args.DBDB, sslStr))
- if err != nil {
- fmt.Printf("Error opening database: %v\n", err)
- return
- }
- defer db.Close()
-
- http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- rootHandler(w, r, db, args)
- })
-
- if err := http.ListenAndServe(":"+args.HTTPPort, nil); err != nil {
- fmt.Printf("Error stopping server: %v\n", err)
- return
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/aa901953/traffic_ops/experimental/goto/config.go
----------------------------------------------------------------------
diff --git a/traffic_ops/experimental/goto/config.go b/traffic_ops/experimental/goto/config.go
new file mode 100644
index 0000000..a0f3401
--- /dev/null
+++ b/traffic_ops/experimental/goto/config.go
@@ -0,0 +1,80 @@
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/url"
+)
+
+type Config struct {
+ HTTPPort string `json:"port"`
+ DBUser string `json:"db_user"`
+ DBPass string `json:"db_pass"`
+ DBServer string `json:"db_server"`
+ DBDB string `json:"db_name"`
+ DBSSL bool `json:"db_ssl"`
+ TOSecret string `json:"to_secret"`
+ TOURLStr string `json:"to_url"`
+ TOURL *url.URL `json:"-"`
+ NoAuth bool `json:"no_auth"`
+ CertPath string `json:"cert_path"`
+ KeyPath string `json:"key_path"`
+}
+
+func LoadConfig(fileName string) (Config, error) {
+ if fileName == "" {
+ return Config{}, fmt.Errorf("no filename")
+ }
+
+ configBytes, err := ioutil.ReadFile(fileName)
+ if err != nil {
+ return Config{}, err
+ }
+
+ cfg := Config{}
+ if err := json.Unmarshal(configBytes, &cfg); err != nil {
+ return Config{}, err
+ }
+
+ if cfg, err = ParseConfig(cfg); err != nil {
+ return Config{}, err
+ }
+
+ return cfg, nil
+}
+
+// ParseConfig validates required fields, and parses non-JSON types
+func ParseConfig(cfg Config) (Config, error) {
+ if cfg.HTTPPort == "" {
+ return Config{}, fmt.Errorf("missing port")
+ }
+ if cfg.DBUser == "" {
+ return Config{}, fmt.Errorf("missing database user")
+ }
+ if cfg.DBPass == "" {
+ return Config{}, fmt.Errorf("missing database password")
+ }
+ if cfg.DBServer == "" {
+ return Config{}, fmt.Errorf("missing database server")
+ }
+ if cfg.DBDB == "" {
+ return Config{}, fmt.Errorf("missing database name")
+ }
+ if cfg.TOSecret == "" {
+ return Config{}, fmt.Errorf("missing secret")
+ }
+ if cfg.CertPath == "" {
+ return Config{}, fmt.Errorf("missing certificate path")
+ }
+ if cfg.KeyPath == "" {
+ return Config{}, fmt.Errorf("missing certificate key path")
+ }
+
+ var err error
+ if cfg.TOURL, err = url.Parse(cfg.TOURLStr); err != nil {
+ return Config{}, fmt.Errorf("Invalid Traffic Ops URL '%v': err", cfg.TOURL, err)
+ }
+
+ return cfg, nil
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/aa901953/traffic_ops/experimental/goto/config.json
----------------------------------------------------------------------
diff --git a/traffic_ops/experimental/goto/config.json b/traffic_ops/experimental/goto/config.json
new file mode 100644
index 0000000..19d2599
--- /dev/null
+++ b/traffic_ops/experimental/goto/config.json
@@ -0,0 +1,13 @@
+{
+ "port": "443",
+ "db_user": "bill",
+ "db_pass": "thelizard",
+ "db_server": "db.trafficops.example.net",
+ "db_name": "trafficops",
+ "db_ssl": true,
+ "to_secret": "walrus",
+ "to_url": "https://trafficops.example.net:60443",
+ "no_auth": false,
+ "cert_path": "/opt/traffic_ops/cert",
+ "key_path": "/opt/traffic_ops/key"
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/aa901953/traffic_ops/experimental/goto/goto.go
----------------------------------------------------------------------
diff --git a/traffic_ops/experimental/goto/goto.go b/traffic_ops/experimental/goto/goto.go
new file mode 100644
index 0000000..48d3c4e
--- /dev/null
+++ b/traffic_ops/experimental/goto/goto.go
@@ -0,0 +1,56 @@
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+// http://www.apache.org/licenses/LICENSE-2.0
+
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "database/sql"
+ "flag"
+ "fmt"
+ _ "github.com/lib/pq"
+ "net/http"
+)
+
+const DefaultConfigPath = "/etc/goto/config.json"
+
+func main() {
+ configFileName := flag.String("cfg", "", "The config file path")
+ flag.Parse()
+ if *configFileName == "" {
+ *configFileName = DefaultConfigPath
+ }
+
+ cfg, err := LoadConfig(*configFileName)
+ if err != nil {
+ fmt.Println("Error loading config '" + *configFileName + "': " + err.Error())
+ return
+ }
+
+ sslStr := "require"
+ if !cfg.DBSSL {
+ sslStr = "disable"
+ }
+
+ db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s", cfg.DBUser, cfg.DBPass, cfg.DBServer, cfg.DBDB, sslStr))
+ if err != nil {
+ fmt.Printf("Error opening database: %v\n", err)
+ return
+ }
+ defer db.Close()
+
+ RegisterRoutes(ServerData{DB: db, Config: cfg})
+ fmt.Println("Listening on " + cfg.HTTPPort)
+ if err := http.ListenAndServeTLS(":"+cfg.HTTPPort, cfg.CertPath, cfg.KeyPath, nil); err != nil {
+ fmt.Printf("Error stopping server: %v\n", err)
+ return
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/aa901953/traffic_ops/experimental/goto/monitoring.go
----------------------------------------------------------------------
diff --git a/traffic_ops/experimental/goto/monitoring.go b/traffic_ops/experimental/goto/monitoring.go
new file mode 100644
index 0000000..b353fb5
--- /dev/null
+++ b/traffic_ops/experimental/goto/monitoring.go
@@ -0,0 +1,398 @@
+package main
+
+import (
+ "database/sql"
+ "encoding/json"
+ "fmt"
+ "github.com/lib/pq"
+ "net/http"
+ "strings"
+ "time"
+)
+
+const CacheMonitorConfigFile = "rascal.properties"
+const MonitorType = "RASCAL"
+const RouterType = "CCR"
+const MonitorProfilePrefix = "RASCAL"
+const MonitorConfigFile = "rascal-config.txt"
+const KilobitsPerMegabit = 1000
+const DeliveryServiceStatus = "REPORTED"
+
+type BasicServer struct {
+ Profile string `json:"profile"`
+ Status string `json:"status"`
+ IP string `json:"ip"`
+ IP6 string `json:"ip6"`
+ Port int `json:"port"`
+ Cachegroup string `json:"cachegroup"`
+ HostName string `json:"hostName"`
+ FQDN string `json:"fqdn"`
+}
+
+type Monitor struct {
+ BasicServer
+}
+
+type Cache struct {
+ BasicServer
+ InterfaceName string `json:"interfaceName"`
+ Type string `json:"type"`
+ HashID string `json:"hashId"`
+}
+
+type Cachegroup struct {
+ Name string `json:"name"`
+ Coordinates Coordinates `json:"coordinates"`
+}
+
+type Coordinates struct {
+ Latitude float64 `json:"latitude"`
+ Longitude float64 `json:"longitude"`
+}
+
+type Profile struct {
+ Name string `json:"name"`
+ Type string `json:"type"`
+ Parameters map[string]string `json:"parameters"`
+}
+
+type Monitoring struct {
+ TrafficServers []Cache `json:"trafficServers"`
+ TrafficMonitors []Monitor `json:"trafficMonitors"`
+ Cachegroups []Cachegroup `json:"cacheGroups"`
+ Profiles []Profile `json:"profiles"`
+ DeliveryServices []DeliveryService `json:"deliveryServices"`
+ Config map[string]string `json:"config"`
+}
+
+type MonitoringResponse struct {
+ Response Monitoring `json:"response"`
+}
+
+type Router struct {
+ Type string
+ Profile string
+}
+
+type DeliveryService struct {
+ XMLID string `json:"xmlId"`
+ TotalTPSThreshold float64 `json:"totalTpsThreshold"`
+ Status string `json:"status"`
+ TotalKBPSThreshold float64 `json:"totalKbpsThreshold"`
+}
+
+// TODO change to use the ParamMap, instead of parsing the URL
+func monitoringHandler(db *sql.DB) RegexHandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request, p ParamMap) {
+ handleErr := func(err error, status int) {
+ fmt.Printf("%v %v error %v\n", time.Now(), r.RemoteAddr, err)
+ w.WriteHeader(status)
+ fmt.Fprintf(w, http.StatusText(status))
+ }
+
+ cdnName := p["cdn"]
+
+ resp, err := getMonitoringJson(cdnName, db)
+ if err != nil {
+ handleErr(err, http.StatusInternalServerError)
+ return
+ }
+
+ respBts, err := json.Marshal(resp)
+ if err != nil {
+ handleErr(err, http.StatusInternalServerError)
+ return
+ }
+
+ w.Header().Set("Content-Type", "application/json")
+ fmt.Fprintf(w, "%s", respBts)
+ }
+}
+
+func getServers(db *sql.DB, cdn string) ([]Monitor, []Cache, []Router, error) {
+ query := `SELECT
+me.host_name as hostName,
+CONCAT(me.host_name, '.', me.domain_name) as fqdn,
+status.name as status,
+cachegroup.name as cachegroup,
+me.tcp_port as port,
+me.ip_address as ip,
+me.ip6_address as ip6,
+profile.name as profile,
+me.interface_name as interfaceName,
+type.name as type,
+me.xmpp_id as hashId
+FROM server me
+JOIN type type ON type.id = me.type
+JOIN status status ON status.id = me.status
+JOIN cachegroup cachegroup ON cachegroup.id = me.cachegroup
+JOIN profile profile ON profile.id = me.profile
+JOIN cdn cdn ON cdn.id = me.cdn_id
+WHERE cdn.name = $1`
+
+ rows, err := db.Query(query, cdn)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ defer rows.Close()
+
+ monitors := []Monitor{}
+ caches := []Cache{}
+ routers := []Router{}
+
+ for rows.Next() {
+ var hostName sql.NullString
+ var fqdn sql.NullString
+ var status sql.NullString
+ var cachegroup sql.NullString
+ var port sql.NullInt64
+ var ip sql.NullString
+ var ip6 sql.NullString
+ var profile sql.NullString
+ var interfaceName sql.NullString
+ var ttype sql.NullString
+ var hashId sql.NullString
+
+ if err := rows.Scan(&hostName, &fqdn, &status, &cachegroup, &port, &ip, &ip6, &profile, &interfaceName, &ttype, &hashId); err != nil {
+ return nil, nil, nil, err
+ }
+
+ if ttype.String == MonitorType {
+ monitors = append(monitors, Monitor{
+ BasicServer: BasicServer{
+ Profile: profile.String,
+ Status: status.String,
+ IP: ip.String,
+ IP6: ip6.String,
+ Port: int(port.Int64),
+ Cachegroup: cachegroup.String,
+ HostName: hostName.String,
+ FQDN: fqdn.String,
+ },
+ })
+ } else if strings.HasPrefix(ttype.String, "EDGE") || strings.HasPrefix(ttype.String, "MID") {
+ caches = append(caches, Cache{
+ BasicServer: BasicServer{
+ Profile: profile.String,
+ Status: status.String,
+ IP: ip.String,
+ IP6: ip6.String,
+ Port: int(port.Int64),
+ Cachegroup: cachegroup.String,
+ HostName: hostName.String,
+ FQDN: fqdn.String,
+ },
+ InterfaceName: interfaceName.String,
+ Type: ttype.String,
+ HashID: hashId.String,
+ })
+ } else if ttype.String == RouterType {
+ routers = append(routers, Router{
+ Type: ttype.String,
+ Profile: profile.String,
+ })
+ }
+ }
+ return monitors, caches, routers, nil
+}
+
+func getCachegroups(db *sql.DB, cdn string) ([]Cachegroup, error) {
+ query := `
+SELECT name, latitude, longitude
+FROM cachegroup
+WHERE id IN
+ (SELECT cachegroup FROM server WHERE server.cdn_id =
+ (SELECT id FROM cdn WHERE name = $1));`
+
+ rows, err := db.Query(query, cdn)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ cachegroups := []Cachegroup{}
+
+ for rows.Next() {
+ var name sql.NullString
+ var lat sql.NullFloat64
+ var lon sql.NullFloat64
+ if err := rows.Scan(&name, &lat, &lon); err != nil {
+ return nil, err
+ }
+ cachegroups = append(cachegroups, Cachegroup{
+ Name: name.String,
+ Coordinates: Coordinates{
+ Latitude: lat.Float64,
+ Longitude: lon.Float64,
+ },
+ })
+ }
+ return cachegroups, nil
+}
+
+func getProfiles(db *sql.DB, caches []Cache, routers []Router) ([]Profile, error) {
+ cacheProfileTypes := map[string]string{}
+ profiles := map[string]Profile{}
+ profileNames := []string{}
+ for _, router := range routers {
+ profiles[router.Profile] = Profile{
+ Name: router.Profile,
+ Type: router.Type,
+ }
+ }
+
+ for _, cache := range caches {
+ if _, ok := cacheProfileTypes[cache.Profile]; !ok {
+ cacheProfileTypes[cache.Profile] = cache.Type
+ profiles[cache.Profile] = Profile{
+ Name: cache.Profile,
+ Type: cache.Type,
+ }
+ profileNames = append(profileNames, cache.Profile)
+ }
+ }
+
+ query := `
+SELECT p.name as profile, pr.name, pr.value
+FROM parameter pr
+JOIN profile p ON p.name = ANY($1)
+JOIN profile_parameter pp ON pp.profile = p.id and pp.parameter = pr.id
+WHERE pr.config_file = $2;
+`
+ rows, err := db.Query(query, pq.Array(profileNames), CacheMonitorConfigFile)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ for rows.Next() {
+ var profileName sql.NullString
+ var name sql.NullString
+ var value sql.NullString
+ if err := rows.Scan(&profileName, &name, &value); err != nil {
+ return nil, err
+ }
+ if name.String == "" {
+ return nil, fmt.Errorf("null name") // TODO continue and warn?
+ }
+ profile := profiles[profileName.String]
+ if profile.Parameters == nil {
+ profile.Parameters = map[string]string{}
+ }
+ profile.Parameters[name.String] = value.String
+ profiles[profileName.String] = profile
+
+ }
+
+ profilesArr := []Profile{} // TODO make for efficiency?
+ for _, profile := range profiles {
+ profilesArr = append(profilesArr, profile)
+ }
+ return profilesArr, nil
+}
+
+func getDeliveryServices(db *sql.DB, routers []Router) ([]DeliveryService, error) {
+ profileNames := []string{}
+ for _, router := range routers {
+ profileNames = append(profileNames, router.Profile)
+ }
+
+ query := `
+SELECT ds.xml_id, ds.global_max_tps, ds.global_max_mbps
+FROM deliveryservice ds
+JOIN profile profile ON profile.id = ds.profile
+WHERE profile.name = ANY($1)
+AND ds.active = true
+`
+ rows, err := db.Query(query, pq.Array(profileNames))
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ dses := []DeliveryService{}
+
+ for rows.Next() {
+ var xmlid sql.NullString
+ var tps sql.NullFloat64
+ var mbps sql.NullFloat64
+ if err := rows.Scan(&xmlid, &tps, &mbps); err != nil {
+ return nil, err
+ }
+ dses = append(dses, DeliveryService{
+ XMLID: xmlid.String,
+ TotalTPSThreshold: tps.Float64,
+ Status: DeliveryServiceStatus,
+ TotalKBPSThreshold: mbps.Float64 * KilobitsPerMegabit,
+ })
+ }
+ return dses, nil
+}
+
+func getConfig(db *sql.DB) (map[string]string, error) {
+ // TODO remove 'like' in query? Slow?
+ query := fmt.Sprintf(`
+SELECT pr.name, pr.value
+FROM parameter pr
+JOIN profile p ON p.name LIKE '%s%%'
+JOIN profile_parameter pp ON pp.profile = p.id and pp.parameter = pr.id
+WHERE pr.config_file = '%s'
+`, MonitorProfilePrefix, MonitorConfigFile)
+
+ rows, err := db.Query(query)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ cfg := map[string]string{}
+
+ for rows.Next() {
+ var name sql.NullString
+ var val sql.NullString
+ if err := rows.Scan(&name, &val); err != nil {
+ return nil, err
+ }
+ cfg[name.String] = val.String
+ }
+ return cfg, nil
+}
+
+func getMonitoringJson(cdnName string, db *sql.DB) (*MonitoringResponse, error) {
+ monitors, caches, routers, err := getServers(db, cdnName)
+ if err != nil {
+ return nil, fmt.Errorf("error getting servers: %v", err)
+ }
+
+ cachegroups, err := getCachegroups(db, cdnName)
+ if err != nil {
+ return nil, fmt.Errorf("error getting cachegroups: %v", err)
+ }
+
+ profiles, err := getProfiles(db, caches, routers)
+ if err != nil {
+ return nil, fmt.Errorf("error getting profiles: %v", err)
+ }
+
+ deliveryServices, err := getDeliveryServices(db, routers)
+ if err != nil {
+ return nil, fmt.Errorf("error getting deliveryservices: %v", err)
+ }
+
+ config, err := getConfig(db)
+ if err != nil {
+ return nil, fmt.Errorf("error getting config: %v", err)
+ }
+
+ resp := MonitoringResponse{
+ Response: Monitoring{
+ TrafficServers: caches,
+ TrafficMonitors: monitors,
+ Cachegroups: cachegroups,
+ Profiles: profiles,
+ DeliveryServices: deliveryServices,
+ Config: config,
+ },
+ }
+ return &resp, nil
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/aa901953/traffic_ops/experimental/goto/routes.go
----------------------------------------------------------------------
diff --git a/traffic_ops/experimental/goto/routes.go b/traffic_ops/experimental/goto/routes.go
new file mode 100644
index 0000000..cc14450
--- /dev/null
+++ b/traffic_ops/experimental/goto/routes.go
@@ -0,0 +1,95 @@
+package main
+
+import (
+ "crypto/tls"
+ "database/sql"
+ "net/http"
+ "net/http/httputil"
+ "regexp"
+ "strings"
+)
+
+type ServerData struct {
+ Config
+ DB *sql.DB
+}
+
+type ParamMap map[string]string
+
+type RegexHandlerFunc func(w http.ResponseWriter, r *http.Request, params ParamMap)
+
+func getMonitoringRoute(d ServerData) RegexHandlerFunc {
+ return wrapLogTime(wrapAuth(monitoringHandler(d.DB), d.NoAuth, d.TOSecret))
+}
+
+// getRootHandler returns the / handler for the service, which reverse-proxies the old Perl Traffic Ops
+func getRootHandler(d ServerData) http.Handler {
+ // debug
+ tr := &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+ }
+ rp := httputil.NewSingleHostReverseProxy(d.TOURL)
+ rp.Transport = tr
+ return rp
+}
+
+// GetRoutes returns the map of regex routes, and a catchall route if no regex matches.
+func GetRoutes(d ServerData) (map[string]RegexHandlerFunc, http.Handler) {
+ return map[string]RegexHandlerFunc{
+ "api/1.2/cdns/{cdn}/configs/monitoring.json": getMonitoringRoute(d),
+ }, getRootHandler(d)
+}
+
+type CompiledRoute struct {
+ Handler RegexHandlerFunc
+ Regex *regexp.Regexp
+ Params []string
+}
+
+func CompileRoutes(routes *map[string]RegexHandlerFunc) map[string]CompiledRoute {
+ compiledRoutes := map[string]CompiledRoute{}
+ for route, handler := range *routes {
+ originalRoute := route
+ var params []string
+ for open := strings.Index(route, "{"); open > 0; open = strings.Index(route, "{") {
+ close := strings.Index(route, "}")
+ if close < 0 {
+ panic("malformed route")
+ }
+ param := route[open+1 : close]
+
+ params = append(params, param)
+ route = route[:open] + `(.+)` + route[close+1:]
+ }
+ regex := regexp.MustCompile(route)
+ compiledRoutes[originalRoute] = CompiledRoute{Handler: handler, Regex: regex, Params: params}
+ }
+ return compiledRoutes
+}
+
+func Handler(routes map[string]CompiledRoute, catchall http.Handler, w http.ResponseWriter, r *http.Request) {
+ requested := r.URL.Path[1:]
+
+ for _, compiledRoute := range routes {
+ match := compiledRoute.Regex.FindStringSubmatch(requested)
+ if len(match) == 0 {
+ continue
+ }
+
+ params := map[string]string{}
+ for i, v := range compiledRoute.Params {
+ params[v] = match[i+1]
+ }
+ compiledRoute.Handler(w, r, params)
+ return
+ }
+ catchall.ServeHTTP(w, r)
+}
+
+func RegisterRoutes(d ServerData) {
+ routes, catchall := GetRoutes(d)
+ compiledRoutes := CompileRoutes(&routes)
+ http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ Handler(compiledRoutes, catchall, w, r)
+ })
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/aa901953/traffic_ops/experimental/goto/wrappers.go
----------------------------------------------------------------------
diff --git a/traffic_ops/experimental/goto/wrappers.go b/traffic_ops/experimental/goto/wrappers.go
new file mode 100644
index 0000000..daf5e34
--- /dev/null
+++ b/traffic_ops/experimental/goto/wrappers.go
@@ -0,0 +1,55 @@
+package main
+
+import (
+ "fmt"
+ "github.com/apache/incubator-trafficcontrol/traffic_ops/experimental/tocookie"
+ "log" // TODO change to traffic_monitor_golang/common/log
+ "net/http"
+ "time"
+)
+
+func wrapAuth(h RegexHandlerFunc, noAuth bool, secret string) RegexHandlerFunc {
+ if noAuth {
+ return h
+ }
+ return func(w http.ResponseWriter, r *http.Request, p ParamMap) {
+ handleUnauthorized := func(reason string) {
+ log.Printf("%v %v %v sent 401 - %v\n", time.Now(), r.RemoteAddr, r.URL.Path, reason)
+ status := http.StatusUnauthorized
+ w.WriteHeader(status)
+ fmt.Fprintf(w, http.StatusText(status))
+ }
+
+ cookie, err := r.Cookie(tocookie.Name)
+ if err != nil {
+ handleUnauthorized("error getting cookie: " + err.Error())
+ return
+ }
+
+ if cookie == nil {
+ handleUnauthorized("no auth cookie")
+ return
+ }
+
+ oldCookie, err := tocookie.Parse(secret, cookie.Value)
+ if err != nil {
+ handleUnauthorized("cookie error: " + err.Error())
+ return
+ }
+
+ newCookieVal := tocookie.Refresh(oldCookie, secret)
+ http.SetCookie(w, &http.Cookie{Name: tocookie.Name, Value: newCookieVal})
+ h(w, r, p)
+ }
+}
+
+func wrapLogTime(h RegexHandlerFunc) RegexHandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request, p ParamMap) {
+ start := time.Now()
+ defer func() {
+ now := time.Now()
+ log.Printf("%v %v served %v in %v\n", now, r.RemoteAddr, r.URL.Path, now.Sub(start))
+ }()
+ h(w, r, p)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/aa901953/traffic_ops/experimental/tocookie/tocookie.go
----------------------------------------------------------------------
diff --git a/traffic_ops/experimental/tocookie/tocookie.go b/traffic_ops/experimental/tocookie/tocookie.go
index 4dd319b..658224d 100644
--- a/traffic_ops/experimental/tocookie/tocookie.go
+++ b/traffic_ops/experimental/tocookie/tocookie.go
@@ -24,6 +24,7 @@ import (
)
const Name = "mojolicious"
+const DefaultDuration = time.Hour
type Cookie struct {
AuthData string `json:"auth_data"`
@@ -95,3 +96,8 @@ func New(user string, expiration time.Time, key string) string {
msg, _ := json.Marshal(cookieMsg)
return NewRawMsg(msg, []byte(key))
}
+
+// Update takes an existing cookie and returns a new serialized cookie with an updated expiration
+func Refresh(c *Cookie, key string) string {
+ return New(c.AuthData, time.Now().Add(DefaultDuration), key)
+}
[16/43] incubator-trafficcontrol git commit: Add TO Golang
configurable logging
Posted by de...@apache.org.
Add TO Golang configurable logging
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/b5fa231b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/b5fa231b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/b5fa231b
Branch: refs/heads/master
Commit: b5fa231b1d258c257984c3a24226901092a81b9f
Parents: 5cb00dd
Author: Robert Butts <ro...@gmail.com>
Authored: Fri Jul 21 18:14:38 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_monitor_golang/common/log/log.go | 1 +
.../traffic_monitor/config/config.go | 1 +
traffic_ops/traffic_ops_golang/auth.go | 7 +-
traffic_ops/traffic_ops_golang/config.go | 52 +-
traffic_ops/traffic_ops_golang/monitoring.go | 5 +-
.../traffic_ops_golang/monitoring_test.go | 634 ++++++++++++
traffic_ops/traffic_ops_golang/routes.go | 2 +-
.../traffic_ops_golang/traffic_ops_golang.go | 18 +-
.../vendor/gopkg.in/DATA-DOG/go-sqlmock/LICENSE | 28 +
.../gopkg.in/DATA-DOG/go-sqlmock/README.md | 223 +++++
.../gopkg.in/DATA-DOG/go-sqlmock/argument.go | 24 +
.../DATA-DOG/go-sqlmock/argument_test.go | 58 ++
.../gopkg.in/DATA-DOG/go-sqlmock/driver.go | 78 ++
.../gopkg.in/DATA-DOG/go-sqlmock/driver_test.go | 112 +++
.../DATA-DOG/go-sqlmock/examples/basic/basic.go | 40 +
.../go-sqlmock/examples/basic/basic_test.go | 58 ++
.../DATA-DOG/go-sqlmock/examples/blog/blog.go | 81 ++
.../go-sqlmock/examples/blog/blog_test.go | 102 ++
.../DATA-DOG/go-sqlmock/examples/doc.go | 1 +
.../go-sqlmock/examples/orders/orders.go | 121 +++
.../go-sqlmock/examples/orders/orders_test.go | 108 ++
.../DATA-DOG/go-sqlmock/expectations.go | 344 +++++++
.../go-sqlmock/expectations_before_go18.go | 52 +
.../DATA-DOG/go-sqlmock/expectations_go18.go | 66 ++
.../go-sqlmock/expectations_go18_test.go | 64 ++
.../DATA-DOG/go-sqlmock/expectations_test.go | 154 +++
.../gopkg.in/DATA-DOG/go-sqlmock/result.go | 39 +
.../gopkg.in/DATA-DOG/go-sqlmock/result_test.go | 62 ++
.../vendor/gopkg.in/DATA-DOG/go-sqlmock/rows.go | 144 +++
.../gopkg.in/DATA-DOG/go-sqlmock/rows_go18.go | 20 +
.../DATA-DOG/go-sqlmock/rows_go18_test.go | 92 ++
.../gopkg.in/DATA-DOG/go-sqlmock/rows_test.go | 265 +++++
.../gopkg.in/DATA-DOG/go-sqlmock/sqlmock.go | 525 ++++++++++
.../DATA-DOG/go-sqlmock/sqlmock_go18.go | 101 ++
.../DATA-DOG/go-sqlmock/sqlmock_go18_test.go | 426 ++++++++
.../DATA-DOG/go-sqlmock/sqlmock_test.go | 998 +++++++++++++++++++
.../gopkg.in/DATA-DOG/go-sqlmock/statement.go | 27 +
.../DATA-DOG/go-sqlmock/statement_test.go | 33 +
.../gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go | 76 ++
.../vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go | 13 +
.../gopkg.in/DATA-DOG/go-sqlmock/util_test.go | 21 +
traffic_ops/traffic_ops_golang/wrappers.go | 45 +-
traffic_ops_golang/monitoring_test.go | 634 ------------
.../vendor/gopkg.in/DATA-DOG/go-sqlmock/LICENSE | 28 -
.../gopkg.in/DATA-DOG/go-sqlmock/README.md | 223 -----
.../gopkg.in/DATA-DOG/go-sqlmock/argument.go | 24 -
.../DATA-DOG/go-sqlmock/argument_test.go | 58 --
.../gopkg.in/DATA-DOG/go-sqlmock/driver.go | 78 --
.../gopkg.in/DATA-DOG/go-sqlmock/driver_test.go | 112 ---
.../DATA-DOG/go-sqlmock/examples/basic/basic.go | 40 -
.../go-sqlmock/examples/basic/basic_test.go | 58 --
.../DATA-DOG/go-sqlmock/examples/blog/blog.go | 81 --
.../go-sqlmock/examples/blog/blog_test.go | 102 --
.../DATA-DOG/go-sqlmock/examples/doc.go | 1 -
.../go-sqlmock/examples/orders/orders.go | 121 ---
.../go-sqlmock/examples/orders/orders_test.go | 108 --
.../DATA-DOG/go-sqlmock/expectations.go | 344 -------
.../go-sqlmock/expectations_before_go18.go | 52 -
.../DATA-DOG/go-sqlmock/expectations_go18.go | 66 --
.../go-sqlmock/expectations_go18_test.go | 64 --
.../DATA-DOG/go-sqlmock/expectations_test.go | 154 ---
.../gopkg.in/DATA-DOG/go-sqlmock/result.go | 39 -
.../gopkg.in/DATA-DOG/go-sqlmock/result_test.go | 62 --
.../vendor/gopkg.in/DATA-DOG/go-sqlmock/rows.go | 144 ---
.../gopkg.in/DATA-DOG/go-sqlmock/rows_go18.go | 20 -
.../DATA-DOG/go-sqlmock/rows_go18_test.go | 92 --
.../gopkg.in/DATA-DOG/go-sqlmock/rows_test.go | 265 -----
.../gopkg.in/DATA-DOG/go-sqlmock/sqlmock.go | 525 ----------
.../DATA-DOG/go-sqlmock/sqlmock_go18.go | 101 --
.../DATA-DOG/go-sqlmock/sqlmock_go18_test.go | 426 --------
.../DATA-DOG/go-sqlmock/sqlmock_test.go | 998 -------------------
.../gopkg.in/DATA-DOG/go-sqlmock/statement.go | 27 -
.../DATA-DOG/go-sqlmock/statement_test.go | 33 -
.../gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go | 76 --
.../vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go | 13 -
.../gopkg.in/DATA-DOG/go-sqlmock/util_test.go | 21 -
76 files changed, 5292 insertions(+), 5219 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_monitor_golang/common/log/log.go
----------------------------------------------------------------------
diff --git a/traffic_monitor_golang/common/log/log.go b/traffic_monitor_golang/common/log/log.go
index bfa4a6e..dd63892 100644
--- a/traffic_monitor_golang/common/log/log.go
+++ b/traffic_monitor_golang/common/log/log.go
@@ -23,6 +23,7 @@ package log
import (
"fmt"
"io"
+ "io/ioutil"
"log"
"os"
"time"
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_monitor_golang/traffic_monitor/config/config.go
----------------------------------------------------------------------
diff --git a/traffic_monitor_golang/traffic_monitor/config/config.go b/traffic_monitor_golang/traffic_monitor/config/config.go
index 3939587..358541b 100644
--- a/traffic_monitor_golang/traffic_monitor/config/config.go
+++ b/traffic_monitor_golang/traffic_monitor/config/config.go
@@ -21,6 +21,7 @@ package config
import (
"encoding/json"
+ "io"
"io/ioutil"
"time"
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/auth.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/auth.go b/traffic_ops/traffic_ops_golang/auth.go
index d7e5efe..8ad646a 100644
--- a/traffic_ops/traffic_ops_golang/auth.go
+++ b/traffic_ops/traffic_ops_golang/auth.go
@@ -21,7 +21,8 @@ package main
import (
"database/sql"
- "log" // TODO change to traffic_monitor_golang/common/log
+
+ "github.com/apache/incubator-trafficcontrol/traffic_monitor_golang/common/log"
)
func preparePrivLevelStmt(db *sql.DB) (*sql.Stmt, error) {
@@ -33,10 +34,10 @@ func hasPrivLevel(privLevelStmt *sql.Stmt, user string, level int) bool {
err := privLevelStmt.QueryRow(user).Scan(&privLevel)
switch {
case err == sql.ErrNoRows:
- log.Println("Error checking user " + user + " priv level: user not in database")
+ log.Errorf("checking user %v priv level: user not in database", user)
return false
case err != nil:
- log.Println("Error checking user " + user + " priv level: " + err.Error())
+ log.Errorf("Error checking user %v priv level: %v", user, err.Error())
return false
default:
return privLevel >= level
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/config.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/config.go b/traffic_ops/traffic_ops_golang/config.go
index 6e4e69c..641c9f3 100644
--- a/traffic_ops/traffic_ops_golang/config.go
+++ b/traffic_ops/traffic_ops_golang/config.go
@@ -24,23 +24,36 @@ import (
"fmt"
"io/ioutil"
"net/url"
+
+ "github.com/apache/incubator-trafficcontrol/traffic_monitor_golang/common/log"
)
type Config struct {
- HTTPPort string `json:"port"`
- DBUser string `json:"db_user"`
- DBPass string `json:"db_pass"`
- DBServer string `json:"db_server"`
- DBDB string `json:"db_name"`
- DBSSL bool `json:"db_ssl"`
- TOSecret string `json:"to_secret"`
- TOURLStr string `json:"to_url"`
- TOURL *url.URL `json:"-"`
- NoAuth bool `json:"no_auth"`
- CertPath string `json:"cert_path"`
- KeyPath string `json:"key_path"`
+ HTTPPort string `json:"port"`
+ DBUser string `json:"db_user"`
+ DBPass string `json:"db_pass"`
+ DBServer string `json:"db_server"`
+ DBDB string `json:"db_name"`
+ DBSSL bool `json:"db_ssl"`
+ TOSecret string `json:"to_secret"`
+ TOURLStr string `json:"to_url"`
+ TOURL *url.URL `json:"-"`
+ NoAuth bool `json:"no_auth"`
+ CertPath string `json:"cert_path"`
+ KeyPath string `json:"key_path"`
+ LogLocationError string `json:"log_location_error"`
+ LogLocationWarning string `json:"log_location_warning"`
+ LogLocationInfo string `json:"log_location_info"`
+ LogLocationDebug string `json:"log_location_debug"`
+ LogLocationEvent string `json:"log_location_event"`
}
+func (c Config) Error() log.LogLocation { return log.LogLocation(c.LogLocationError) }
+func (c Config) Warning() log.LogLocation { return log.LogLocation(c.LogLocationWarning) }
+func (c Config) Info() log.LogLocation { return log.LogLocation(c.LogLocationInfo) }
+func (c Config) Debug() log.LogLocation { return log.LogLocation(c.LogLocationDebug) }
+func (c Config) Event() log.LogLocation { return log.LogLocation(c.LogLocationEvent) }
+
func LoadConfig(fileName string) (Config, error) {
if fileName == "" {
return Config{}, fmt.Errorf("no filename")
@@ -89,6 +102,21 @@ func ParseConfig(cfg Config) (Config, error) {
if cfg.KeyPath == "" {
return Config{}, fmt.Errorf("missing certificate key path")
}
+ if cfg.LogLocationError == "" {
+ cfg.LogLocationError = log.LogLocationNull
+ }
+ if cfg.LogLocationWarning == "" {
+ cfg.LogLocationWarning = log.LogLocationNull
+ }
+ if cfg.LogLocationInfo == "" {
+ cfg.LogLocationInfo = log.LogLocationNull
+ }
+ if cfg.LogLocationDebug == "" {
+ cfg.LogLocationDebug = log.LogLocationNull
+ }
+ if cfg.LogLocationEvent == "" {
+ cfg.LogLocationEvent = log.LogLocationNull
+ }
var err error
if cfg.TOURL, err = url.Parse(cfg.TOURLStr); err != nil {
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/monitoring.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/monitoring.go b/traffic_ops/traffic_ops_golang/monitoring.go
index 4c4505f..62d356c 100644
--- a/traffic_ops/traffic_ops_golang/monitoring.go
+++ b/traffic_ops/traffic_ops_golang/monitoring.go
@@ -26,7 +26,8 @@ import (
"github.com/lib/pq"
"net/http"
"strings"
- "time"
+
+ "github.com/apache/incubator-trafficcontrol/traffic_monitor_golang/common/log"
)
const MonitoringPrivLevel = 10
@@ -106,7 +107,7 @@ type DeliveryService struct {
func monitoringHandler(db *sql.DB) RegexHandlerFunc {
return func(w http.ResponseWriter, r *http.Request, p ParamMap) {
handleErr := func(err error, status int) {
- fmt.Printf("%v %v error %v\n", time.Now(), r.RemoteAddr, err)
+ log.Errorf("%v %v\n", r.RemoteAddr, err)
w.WriteHeader(status)
fmt.Fprintf(w, http.StatusText(status))
}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/monitoring_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/monitoring_test.go b/traffic_ops/traffic_ops_golang/monitoring_test.go
new file mode 100644
index 0000000..f6958e3
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/monitoring_test.go
@@ -0,0 +1,634 @@
+package main
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import (
+ "reflect"
+ "sort"
+ "testing"
+
+ "github.com/lib/pq"
+ "gopkg.in/DATA-DOG/go-sqlmock.v1"
+)
+
+func TestGetServers(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ cdn := "mycdn"
+
+ monitor := Monitor{
+ BasicServer: BasicServer{Profile: "monitorProfile",
+ Status: "monitorStatus",
+ IP: "1.2.3.4",
+ IP6: "2001::4",
+ Port: 8081,
+ Cachegroup: "monitorCachegroup",
+ HostName: "monitorHost",
+ FQDN: "monitorFqdn.me",
+ },
+ }
+
+ cacheType := "EDGE"
+ cache := Cache{
+ BasicServer: BasicServer{
+ Profile: "cacheProfile",
+ Status: "cacheStatus",
+ IP: "1.2.3.4",
+ IP6: "2001::4",
+ Port: 8081,
+ Cachegroup: "cacheCachegroup",
+ HostName: "cacheHost",
+ FQDN: "cacheFqdn.me",
+ },
+ InterfaceName: "cacheInterface",
+ Type: cacheType,
+ HashID: "cacheHash",
+ }
+
+ router := Router{
+ Type: RouterType,
+ Profile: "routerProfile",
+ }
+
+ rows := sqlmock.NewRows([]string{"hostName", "fqdn", "status", "cachegroup", "port", "ip", "ip6", "profile", "interfaceName", "type", "hashId"})
+ rows = rows.AddRow(monitor.HostName, monitor.FQDN, monitor.Status, monitor.Cachegroup, monitor.Port, monitor.IP, monitor.IP6, monitor.Profile, "noInterface", MonitorType, "noHash")
+ rows = rows.AddRow(cache.HostName, cache.FQDN, cache.Status, cache.Cachegroup, cache.Port, cache.IP, cache.IP6, cache.Profile, cache.InterfaceName, cache.Type, cache.HashID)
+ rows = rows.AddRow("noHostname", "noFqdn", "noStatus", "noGroup", 0, "noIp", "noIp6", router.Profile, "noInterface", RouterType, "noHashid")
+
+ mock.ExpectQuery("SELECT").WithArgs(cdn).WillReturnRows(rows)
+
+ monitors, caches, routers, err := getServers(db, cdn)
+ if err != nil {
+ t.Errorf("getServers expected: nil error, actual: %v", err)
+ }
+
+ if len(monitors) != 1 {
+ t.Errorf("getServers expected: len(monitors) == 1, actual: %v", len(monitors))
+ }
+ sqlMonitor := monitors[0]
+ if sqlMonitor != monitor {
+ t.Errorf("getServers expected: monitor == %+v, actual: %+v", monitor, sqlMonitor)
+ }
+
+ if len(caches) != 1 {
+ t.Errorf("getServers expected: len(caches) == 1, actual: %v", len(caches))
+ }
+ sqlCache := caches[0]
+ if sqlCache != cache {
+ t.Errorf("getServers expected: cache == %+v, actual: %+v", cache, sqlCache)
+ }
+
+ if len(routers) != 1 {
+ t.Errorf("getServers expected: len(routers) == 1, actual: %v", len(routers))
+ }
+ sqlRouter := routers[0]
+ if sqlRouter != router {
+ t.Errorf("getServers expected: router == %+v, actual: %+v", router, sqlRouter)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestGetCachegroups(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ cdn := "mycdn"
+
+ cachegroup := Cachegroup{
+ Name: "myCachegroup",
+ Coordinates: Coordinates{
+ Latitude: 42.42,
+ Longitude: 24.24,
+ },
+ }
+
+ rows := sqlmock.NewRows([]string{"name", "latitude", "longitude"})
+ rows = rows.AddRow(cachegroup.Name, cachegroup.Coordinates.Latitude, cachegroup.Coordinates.Longitude)
+
+ mock.ExpectQuery("SELECT").WithArgs(cdn).WillReturnRows(rows)
+
+ sqlCachegroups, err := getCachegroups(db, cdn)
+ if err != nil {
+ t.Errorf("getCachegroups expected: nil error, actual: %v", err)
+ }
+
+ if len(sqlCachegroups) != 1 {
+ t.Errorf("getCachegroups expected: len(monitors) == 1, actual: %v", len(sqlCachegroups))
+ }
+ sqlCachegroup := sqlCachegroups[0]
+ if sqlCachegroup != cachegroup {
+ t.Errorf("getServers expected: cachegroup == %+v, actual: %+v", cachegroup, sqlCachegroup)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+type SortableProfiles []Profile
+
+func (s SortableProfiles) Len() int {
+ return len(s)
+}
+func (s SortableProfiles) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+func (s SortableProfiles) Less(i, j int) bool {
+ return s[i].Name < s[j].Name
+}
+
+func sortProfiles(p []Profile) []Profile {
+ sort.Sort(SortableProfiles(p))
+ return p
+}
+
+type SortableMonitors []Monitor
+
+func (s SortableMonitors) Len() int {
+ return len(s)
+}
+func (s SortableMonitors) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+func (s SortableMonitors) Less(i, j int) bool {
+ return s[i].HostName < s[j].HostName
+}
+
+func sortMonitors(p []Monitor) []Monitor {
+ sort.Sort(SortableMonitors(p))
+ return p
+}
+
+type SortableCaches []Cache
+
+func (s SortableCaches) Len() int {
+ return len(s)
+}
+func (s SortableCaches) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+func (s SortableCaches) Less(i, j int) bool {
+ return s[i].HostName < s[j].HostName
+}
+
+func sortCaches(p []Cache) []Cache {
+ sort.Sort(SortableCaches(p))
+ return p
+}
+
+type SortableCachegroups []Cachegroup
+
+func (s SortableCachegroups) Len() int {
+ return len(s)
+}
+func (s SortableCachegroups) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+func (s SortableCachegroups) Less(i, j int) bool {
+ return s[i].Name < s[j].Name
+}
+
+func sortCachegroups(p []Cachegroup) []Cachegroup {
+ sort.Sort(SortableCachegroups(p))
+ return p
+}
+
+type SortableDeliveryServices []DeliveryService
+
+func (s SortableDeliveryServices) Len() int {
+ return len(s)
+}
+func (s SortableDeliveryServices) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+func (s SortableDeliveryServices) Less(i, j int) bool {
+ return s[i].XMLID < s[j].XMLID
+}
+
+func sortDeliveryServices(p []DeliveryService) []DeliveryService {
+ sort.Sort(SortableDeliveryServices(p))
+ return p
+}
+
+func TestGetProfiles(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ cache := Cache{
+ BasicServer: BasicServer{
+ Profile: "cacheProfile",
+ Status: "cacheStatus",
+ IP: "1.2.3.4",
+ IP6: "2001::4",
+ Port: 8081,
+ Cachegroup: "cacheCachegroup",
+ HostName: "cacheHost",
+ FQDN: "cacheFqdn.me",
+ },
+ InterfaceName: "cacheInterface",
+ Type: "EDGE",
+ HashID: "cacheHash",
+ }
+
+ router := Router{
+ Type: RouterType,
+ Profile: "routerProfile",
+ }
+
+ profiles := []Profile{
+ Profile{
+ Name: router.Profile,
+ Type: RouterType,
+ Parameters: map[string]string{
+ "param0": "param0Val",
+ "param1": "param1Val",
+ },
+ },
+ Profile{
+ Name: cache.Profile,
+ Type: "myType2",
+ Parameters: map[string]string{
+ "2param0": "2param0Val",
+ "2param1": "2param1Val",
+ },
+ },
+ }
+
+ rows := sqlmock.NewRows([]string{"profile", "name", "value"})
+ for _, profile := range profiles {
+ for paramName, paramVal := range profile.Parameters {
+ rows = rows.AddRow(profile.Name, paramName, paramVal)
+ }
+ }
+
+ caches := []Cache{cache}
+ routers := []Router{router}
+
+ profileNames := []string{"cacheProfile"}
+
+ mock.ExpectQuery("SELECT").WithArgs(pq.Array(profileNames), CacheMonitorConfigFile).WillReturnRows(rows)
+
+ sqlProfiles, err := getProfiles(db, caches, routers)
+ if err != nil {
+ t.Errorf("getProfiles expected: nil error, actual: %v", err)
+ }
+
+ if len(sqlProfiles) != len(profiles) {
+ t.Errorf("getProfiles expected: %+v actual: %+v", profiles, sqlProfiles)
+ }
+
+ profiles = sortProfiles(profiles)
+ sqlProfiles = sortProfiles(sqlProfiles)
+
+ for i, profile := range profiles {
+ if profile.Name != sqlProfiles[i].Name {
+ t.Errorf("getProfiles expected: profiles[%v].Name %v, actual: %v", i, profile.Name, sqlProfiles[i].Name)
+ }
+ for paramName, paramVal := range profile.Parameters {
+ val, ok := sqlProfiles[i].Parameters[paramName]
+ if !ok {
+ t.Errorf("getProfiles expected: profiles[%v].Parameters[%v] = %v, actual: nil", i, paramName, paramVal)
+ }
+ if val != paramVal {
+ t.Errorf("getProfiles expected: profiles[%v].Parameters[%v] = %v, actual: %v", i, paramName, paramVal)
+ }
+ }
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestGetDeliveryServices(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ router := Router{
+ Type: RouterType,
+ Profile: "routerProfile",
+ }
+
+ deliveryservice := DeliveryService{
+ XMLID: "myDsid",
+ TotalTPSThreshold: 42.42,
+ Status: DeliveryServiceStatus,
+ TotalKBPSThreshold: 24.24,
+ }
+
+ deliveryservices := []DeliveryService{deliveryservice}
+ routers := []Router{router}
+
+ rows := sqlmock.NewRows([]string{"xml_id", "global_max_tps", "global_max_mbps"})
+ for _, deliveryservice := range deliveryservices {
+ rows = rows.AddRow(deliveryservice.XMLID, deliveryservice.TotalTPSThreshold, deliveryservice.TotalKBPSThreshold/KilobitsPerMegabit)
+ }
+
+ profileNames := []string{router.Profile}
+
+ mock.ExpectQuery("SELECT").WithArgs(pq.Array(profileNames)).WillReturnRows(rows)
+
+ sqlDeliveryservices, err := getDeliveryServices(db, routers)
+ if err != nil {
+ t.Errorf("getProfiles expected: nil error, actual: %v", err)
+ }
+
+ if len(deliveryservices) != len(sqlDeliveryservices) {
+ t.Errorf("getProfiles expected: %+v actual: %+v", deliveryservices, sqlDeliveryservices)
+ }
+
+ for i, sqlDeliveryservice := range sqlDeliveryservices {
+ deliveryservice := deliveryservices[i]
+ if deliveryservice != sqlDeliveryservice {
+ t.Errorf("getDeliveryServices expected: %v, actual: %v", deliveryservice, sqlDeliveryservice)
+ }
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestGetConfig(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ config := map[string]string{
+ "name0": "val0",
+ "name1": "val1",
+ }
+
+ rows := sqlmock.NewRows([]string{"name", "value"})
+ for name, val := range config {
+ rows = rows.AddRow(name, val)
+ }
+
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ sqlConfig, err := getConfig(db)
+ if err != nil {
+ t.Errorf("getProfiles expected: nil error, actual: %v", err)
+ }
+
+ if !reflect.DeepEqual(config, sqlConfig) {
+ t.Errorf("getConfig expected: %+v actual: %+v", config, sqlConfig)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestGetMonitoringJson(t *testing.T) {
+ resp := MonitoringResponse{}
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ cdn := "mycdn"
+
+ {
+ //
+ // getServers
+ //
+ monitor := Monitor{
+ BasicServer: BasicServer{Profile: "monitorProfile",
+ Status: "monitorStatus",
+ IP: "1.2.3.4",
+ IP6: "2001::4",
+ Port: 8081,
+ Cachegroup: "monitorCachegroup",
+ HostName: "monitorHost",
+ FQDN: "monitorFqdn.me",
+ },
+ }
+
+ cacheType := "EDGE"
+ cache := Cache{
+ BasicServer: BasicServer{
+ Profile: "cacheProfile",
+ Status: "cacheStatus",
+ IP: "1.2.3.4",
+ IP6: "2001::4",
+ Port: 8081,
+ Cachegroup: "cacheCachegroup",
+ HostName: "cacheHost",
+ FQDN: "cacheFqdn.me",
+ },
+ InterfaceName: "cacheInterface",
+ Type: cacheType,
+ HashID: "cacheHash",
+ }
+
+ router := Router{
+ Type: RouterType,
+ Profile: "routerProfile",
+ }
+
+ rows := sqlmock.NewRows([]string{"hostName", "fqdn", "status", "cachegroup", "port", "ip", "ip6", "profile", "interfaceName", "type", "hashId"})
+ rows = rows.AddRow(monitor.HostName, monitor.FQDN, monitor.Status, monitor.Cachegroup, monitor.Port, monitor.IP, monitor.IP6, monitor.Profile, "noInterface", MonitorType, "noHash")
+ rows = rows.AddRow(cache.HostName, cache.FQDN, cache.Status, cache.Cachegroup, cache.Port, cache.IP, cache.IP6, cache.Profile, cache.InterfaceName, cache.Type, cache.HashID)
+ rows = rows.AddRow("noHostname", "noFqdn", "noStatus", "noGroup", 0, "noIp", "noIp6", router.Profile, "noInterface", RouterType, "noHashid")
+
+ mock.ExpectQuery("SELECT").WithArgs(cdn).WillReturnRows(rows)
+ resp.Response.TrafficServers = []Cache{cache}
+ resp.Response.TrafficMonitors = []Monitor{monitor}
+ }
+ {
+ //
+ // getCachegroups
+ //
+ cachegroup := Cachegroup{
+ Name: "myCachegroup",
+ Coordinates: Coordinates{
+ Latitude: 42.42,
+ Longitude: 24.24,
+ },
+ }
+
+ rows := sqlmock.NewRows([]string{"name", "latitude", "longitude"})
+ rows = rows.AddRow(cachegroup.Name, cachegroup.Coordinates.Latitude, cachegroup.Coordinates.Longitude)
+
+ mock.ExpectQuery("SELECT").WithArgs(cdn).WillReturnRows(rows)
+ resp.Response.Cachegroups = []Cachegroup{cachegroup}
+ }
+ {
+ //
+ // getProfiles
+ //
+ cache := Cache{
+ BasicServer: BasicServer{
+ Profile: "cacheProfile",
+ Status: "cacheStatus",
+ IP: "1.2.3.4",
+ IP6: "2001::4",
+ Port: 8081,
+ Cachegroup: "cacheCachegroup",
+ HostName: "cacheHost",
+ FQDN: "cacheFqdn.me",
+ },
+ InterfaceName: "cacheInterface",
+ Type: "EDGE",
+ HashID: "cacheHash",
+ }
+
+ router := Router{
+ Type: RouterType,
+ Profile: "routerProfile",
+ }
+
+ profiles := []Profile{
+ Profile{
+ Name: router.Profile,
+ Type: RouterType,
+ Parameters: map[string]string{
+ "param0": "param0Val",
+ "param1": "param1Val",
+ },
+ },
+ Profile{
+ Name: cache.Profile,
+ Type: "EDGE",
+ Parameters: map[string]string{
+ "2param0": "2param0Val",
+ "2param1": "2param1Val",
+ },
+ },
+ }
+
+ rows := sqlmock.NewRows([]string{"profile", "name", "value"})
+ for _, profile := range profiles {
+ for paramName, paramVal := range profile.Parameters {
+ rows = rows.AddRow(profile.Name, paramName, paramVal)
+ }
+ }
+
+ // caches := []Cache{cache}
+ // routers := []Router{router}
+
+ profileNames := []string{"cacheProfile"}
+
+ mock.ExpectQuery("SELECT").WithArgs(pq.Array(profileNames), CacheMonitorConfigFile).WillReturnRows(rows)
+ resp.Response.Profiles = profiles
+ }
+ {
+ //
+ // getDeliveryServices
+ //
+ router := Router{
+ Type: RouterType,
+ Profile: "routerProfile",
+ }
+
+ deliveryservice := DeliveryService{
+ XMLID: "myDsid",
+ TotalTPSThreshold: 42.42,
+ Status: DeliveryServiceStatus,
+ TotalKBPSThreshold: 24.24,
+ }
+
+ deliveryservices := []DeliveryService{deliveryservice}
+ // routers := []Router{router}
+
+ rows := sqlmock.NewRows([]string{"xml_id", "global_max_tps", "global_max_mbps"})
+ for _, deliveryservice := range deliveryservices {
+ rows = rows.AddRow(deliveryservice.XMLID, deliveryservice.TotalTPSThreshold, deliveryservice.TotalKBPSThreshold/KilobitsPerMegabit)
+ }
+
+ profileNames := []string{router.Profile}
+
+ mock.ExpectQuery("SELECT").WithArgs(pq.Array(profileNames)).WillReturnRows(rows)
+ resp.Response.DeliveryServices = deliveryservices
+ }
+ {
+ //
+ // getConfig
+ //
+ config := map[string]string{
+ "name0": "val0",
+ "name1": "val1",
+ }
+
+ rows := sqlmock.NewRows([]string{"name", "value"})
+ for name, val := range config {
+ rows = rows.AddRow(name, val)
+ }
+
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+ resp.Response.Config = config
+ }
+
+ sqlResp, err := getMonitoringJson(cdn, db)
+ if err != nil {
+ t.Errorf("getMonitoringJson expected: nil error, actual: %v", err)
+ }
+
+ resp.Response.TrafficServers = sortCaches(resp.Response.TrafficServers)
+ sqlResp.Response.TrafficServers = sortCaches(sqlResp.Response.TrafficServers)
+ resp.Response.TrafficMonitors = sortMonitors(resp.Response.TrafficMonitors)
+ sqlResp.Response.TrafficMonitors = sortMonitors(sqlResp.Response.TrafficMonitors)
+ resp.Response.Cachegroups = sortCachegroups(resp.Response.Cachegroups)
+ sqlResp.Response.Cachegroups = sortCachegroups(sqlResp.Response.Cachegroups)
+ resp.Response.Profiles = sortProfiles(resp.Response.Profiles)
+ sqlResp.Response.Profiles = sortProfiles(sqlResp.Response.Profiles)
+ resp.Response.DeliveryServices = sortDeliveryServices(resp.Response.DeliveryServices)
+ sqlResp.Response.DeliveryServices = sortDeliveryServices(sqlResp.Response.DeliveryServices)
+
+ if !reflect.DeepEqual(sqlResp.Response.TrafficServers, resp.Response.TrafficServers) {
+ t.Errorf("getMonitoringJson expected TrafficServers: %+v actual: %+v", resp.Response.TrafficServers, sqlResp.Response.TrafficServers)
+ }
+ if !reflect.DeepEqual(sqlResp.Response.TrafficMonitors, resp.Response.TrafficMonitors) {
+ t.Errorf("getMonitoringJson expected TrafficMonitors: %+v actual: %+v", resp.Response.TrafficMonitors, sqlResp.Response.TrafficMonitors)
+ }
+ if !reflect.DeepEqual(sqlResp.Response.Cachegroups, resp.Response.Cachegroups) {
+ t.Errorf("getMonitoringJson expected Cachegroups: %+v actual: %+v", resp.Response.Cachegroups, sqlResp.Response.Cachegroups)
+ }
+ if !reflect.DeepEqual(sqlResp.Response.Profiles, resp.Response.Profiles) {
+ t.Errorf("getMonitoringJson expected Profiles: %+v actual: %+v", resp.Response.Profiles, sqlResp.Response.Profiles)
+ }
+ if !reflect.DeepEqual(sqlResp.Response.DeliveryServices, resp.Response.DeliveryServices) {
+ t.Errorf("getMonitoringJson expected DeliveryServices: %+v actual: %+v", resp.Response.DeliveryServices, sqlResp.Response.DeliveryServices)
+ }
+ if !reflect.DeepEqual(sqlResp.Response.Config, resp.Response.Config) {
+ t.Errorf("getMonitoringJson expected Config: %+v actual: %+v", resp.Response.Config, sqlResp.Response.Config)
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/routes.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index 5c71dfa..d7061b4 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -57,7 +57,7 @@ func GetRoutes(d ServerData) (map[string]RegexHandlerFunc, http.Handler, error)
}
return map[string]RegexHandlerFunc{
- "api/1.2/cdns/{cdn}/configs/monitoring.json": wrapLogTime(wrapAuth(monitoringHandler(d.DB), d.NoAuth, d.TOSecret, privLevelStmt, MonitoringPrivLevel)),
+ "api/1.2/cdns/{cdn}/configs/monitoring.json": wrapAuth(monitoringHandler(d.DB), d.NoAuth, d.TOSecret, privLevelStmt, MonitoringPrivLevel),
}, getRootHandler(d), nil
}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/traffic_ops_golang.go b/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
index 173b9b5..2689e7c 100644
--- a/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
+++ b/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
@@ -23,8 +23,11 @@ import (
"database/sql"
"flag"
"fmt"
- _ "github.com/lib/pq"
"net/http"
+
+ "github.com/apache/incubator-trafficcontrol/traffic_monitor_golang/common/log"
+
+ _ "github.com/lib/pq"
)
const DefaultConfigPath = "/etc/goto/config.json"
@@ -42,6 +45,11 @@ func main() {
return
}
+ if err := log.InitCfg(cfg); err != nil {
+ fmt.Println("Error initializing loggers: %v", err)
+ return
+ }
+
sslStr := "require"
if !cfg.DBSSL {
sslStr = "disable"
@@ -49,19 +57,19 @@ func main() {
db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s", cfg.DBUser, cfg.DBPass, cfg.DBServer, cfg.DBDB, sslStr))
if err != nil {
- fmt.Printf("Error opening database: %v\n", err)
+ log.Errorf("opening database: %v\n", err)
return
}
defer db.Close()
if err := RegisterRoutes(ServerData{DB: db, Config: cfg}); err != nil {
- fmt.Printf("Error registering routes: %v\n", err)
+ log.Errorf("registering routes: %v\n", err)
return
}
- fmt.Println("Listening on " + cfg.HTTPPort)
+ log.Infof("Listening on " + cfg.HTTPPort)
if err := http.ListenAndServeTLS(":"+cfg.HTTPPort, cfg.CertPath, cfg.KeyPath, nil); err != nil {
- fmt.Printf("Error stopping server: %v\n", err)
+ log.Errorf("stopping server: %v\n", err)
return
}
}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/LICENSE
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/LICENSE b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/LICENSE
new file mode 100644
index 0000000..7f8bedf
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/LICENSE
@@ -0,0 +1,28 @@
+The three clause BSD license (http://en.wikipedia.org/wiki/BSD_licenses)
+
+Copyright (c) 2013-2017, DATA-DOG team
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* The name DataDog.lt may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/README.md
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/README.md b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/README.md
new file mode 100644
index 0000000..f3d5487
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/README.md
@@ -0,0 +1,223 @@
+[](https://travis-ci.org/DATA-DOG/go-sqlmock)
+[](https://godoc.org/github.com/DATA-DOG/go-sqlmock)
+[](https://codecov.io/github/DATA-DOG/go-sqlmock)
+
+# Sql driver mock for Golang
+
+**sqlmock** is a mock library implementing [sql/driver](https://godoc.org/database/sql/driver). Which has one and only
+purpose - to simulate any **sql** driver behavior in tests, without needing a real database connection. It helps to
+maintain correct **TDD** workflow.
+
+- this library is now complete and stable. (you may not find new changes for this reason)
+- supports concurrency and multiple connections.
+- supports **go1.8** Context related feature mocking and Named sql parameters.
+- does not require any modifications to your source code.
+- the driver allows to mock any sql driver method behavior.
+- has strict by default expectation order matching.
+- has no third party dependencies.
+
+## Install
+
+ go get gopkg.in/DATA-DOG/go-sqlmock.v1
+
+## Documentation and Examples
+
+Visit [godoc](http://godoc.org/github.com/DATA-DOG/go-sqlmock) for general examples and public api reference.
+See **.travis.yml** for supported **go** versions.
+Different use case, is to functionally test with a real database - [go-txdb](https://github.com/DATA-DOG/go-txdb)
+all database related actions are isolated within a single transaction so the database can remain in the same state.
+
+See implementation examples:
+
+- [blog API server](https://github.com/DATA-DOG/go-sqlmock/tree/master/examples/blog)
+- [the same orders example](https://github.com/DATA-DOG/go-sqlmock/tree/master/examples/orders)
+
+### Something you may want to test
+
+``` go
+package main
+
+import "database/sql"
+
+func recordStats(db *sql.DB, userID, productID int64) (err error) {
+ tx, err := db.Begin()
+ if err != nil {
+ return
+ }
+
+ defer func() {
+ switch err {
+ case nil:
+ err = tx.Commit()
+ default:
+ tx.Rollback()
+ }
+ }()
+
+ if _, err = tx.Exec("UPDATE products SET views = views + 1"); err != nil {
+ return
+ }
+ if _, err = tx.Exec("INSERT INTO product_viewers (user_id, product_id) VALUES (?, ?)", userID, productID); err != nil {
+ return
+ }
+ return
+}
+
+func main() {
+ // @NOTE: the real connection is not required for tests
+ db, err := sql.Open("mysql", "root@/blog")
+ if err != nil {
+ panic(err)
+ }
+ defer db.Close()
+
+ if err = recordStats(db, 1 /*some user id*/, 5 /*some product id*/); err != nil {
+ panic(err)
+ }
+}
+```
+
+### Tests with sqlmock
+
+``` go
+package main
+
+import (
+ "fmt"
+ "testing"
+
+ "gopkg.in/DATA-DOG/go-sqlmock.v1"
+)
+
+// a successful case
+func TestShouldUpdateStats(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectBegin()
+ mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))
+ mock.ExpectExec("INSERT INTO product_viewers").WithArgs(2, 3).WillReturnResult(sqlmock.NewResult(1, 1))
+ mock.ExpectCommit()
+
+ // now we execute our method
+ if err = recordStats(db, 2, 3); err != nil {
+ t.Errorf("error was not expected while updating stats: %s", err)
+ }
+
+ // we make sure that all expectations were met
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+// a failing test case
+func TestShouldRollbackStatUpdatesOnFailure(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectBegin()
+ mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))
+ mock.ExpectExec("INSERT INTO product_viewers").
+ WithArgs(2, 3).
+ WillReturnError(fmt.Errorf("some error"))
+ mock.ExpectRollback()
+
+ // now we execute our method
+ if err = recordStats(db, 2, 3); err == nil {
+ t.Errorf("was expecting an error, but there was none")
+ }
+
+ // we make sure that all expectations were met
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+```
+
+## Matching arguments like time.Time
+
+There may be arguments which are of `struct` type and cannot be compared easily by value like `time.Time`. In this case
+**sqlmock** provides an [Argument](https://godoc.org/github.com/DATA-DOG/go-sqlmock#Argument) interface which
+can be used in more sophisticated matching. Here is a simple example of time argument matching:
+
+``` go
+type AnyTime struct{}
+
+// Match satisfies sqlmock.Argument interface
+func (a AnyTime) Match(v driver.Value) bool {
+ _, ok := v.(time.Time)
+ return ok
+}
+
+func TestAnyTimeArgument(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectExec("INSERT INTO users").
+ WithArgs("john", AnyTime{}).
+ WillReturnResult(NewResult(1, 1))
+
+ _, err = db.Exec("INSERT INTO users(name, created_at) VALUES (?, ?)", "john", time.Now())
+ if err != nil {
+ t.Errorf("error '%s' was not expected, while inserting a row", err)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+```
+
+It only asserts that argument is of `time.Time` type.
+
+## Run tests
+
+ go test -race
+
+## Change Log
+
+- **2017-02-09** - implemented support for **go1.8** features. **Rows** interface was changed to struct
+ but contains all methods as before and should maintain backwards compatibility. **ExpectedQuery.WillReturnRows** may now
+ accept multiple row sets.
+- **2016-11-02** - `db.Prepare()` was not validating expected prepare SQL
+ query. It should still be validated even if Exec or Query is not
+ executed on that prepared statement.
+- **2016-02-23** - added **sqlmock.AnyArg()** function to provide any kind
+ of argument matcher.
+- **2016-02-23** - convert expected arguments to driver.Value as natural
+ driver does, the change may affect time.Time comparison and will be
+ stricter. See [issue](https://github.com/DATA-DOG/go-sqlmock/issues/31).
+- **2015-08-27** - **v1** api change, concurrency support, all known issues fixed.
+- **2014-08-16** instead of **panic** during reflect type mismatch when comparing query arguments - now return error
+- **2014-08-14** added **sqlmock.NewErrorResult** which gives an option to return driver.Result with errors for
+interface methods, see [issue](https://github.com/DATA-DOG/go-sqlmock/issues/5)
+- **2014-05-29** allow to match arguments in more sophisticated ways, by providing an **sqlmock.Argument** interface
+- **2014-04-21** introduce **sqlmock.New()** to open a mock database connection for tests. This method
+calls sql.DB.Ping to ensure that connection is open, see [issue](https://github.com/DATA-DOG/go-sqlmock/issues/4).
+This way on Close it will surely assert if all expectations are met, even if database was not triggered at all.
+The old way is still available, but it is advisable to call db.Ping manually before asserting with db.Close.
+- **2014-02-14** RowsFromCSVString is now a part of Rows interface named as FromCSVString.
+It has changed to allow more ways to construct rows and to easily extend this API in future.
+See [issue 1](https://github.com/DATA-DOG/go-sqlmock/issues/1)
+**RowsFromCSVString** is deprecated and will be removed in future
+
+## Contributions
+
+Feel free to open a pull request. Note, if you wish to contribute an extension to public (exported methods or types) -
+please open an issue before, to discuss whether these changes can be accepted. All backward incompatible changes are
+and will be treated cautiously
+
+## License
+
+The [three clause BSD license](http://en.wikipedia.org/wiki/BSD_licenses)
+
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument.go
new file mode 100644
index 0000000..7727481
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument.go
@@ -0,0 +1,24 @@
+package sqlmock
+
+import "database/sql/driver"
+
+// Argument interface allows to match
+// any argument in specific way when used with
+// ExpectedQuery and ExpectedExec expectations.
+type Argument interface {
+ Match(driver.Value) bool
+}
+
+// AnyArg will return an Argument which can
+// match any kind of arguments.
+//
+// Useful for time.Time or similar kinds of arguments.
+func AnyArg() Argument {
+ return anyArgument{}
+}
+
+type anyArgument struct{}
+
+func (a anyArgument) Match(_ driver.Value) bool {
+ return true
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument_test.go
new file mode 100644
index 0000000..3088ed4
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument_test.go
@@ -0,0 +1,58 @@
+package sqlmock
+
+import (
+ "database/sql/driver"
+ "testing"
+ "time"
+)
+
+type AnyTime struct{}
+
+// Match satisfies sqlmock.Argument interface
+func (a AnyTime) Match(v driver.Value) bool {
+ _, ok := v.(time.Time)
+ return ok
+}
+
+func TestAnyTimeArgument(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectExec("INSERT INTO users").
+ WithArgs("john", AnyTime{}).
+ WillReturnResult(NewResult(1, 1))
+
+ _, err = db.Exec("INSERT INTO users(name, created_at) VALUES (?, ?)", "john", time.Now())
+ if err != nil {
+ t.Errorf("error '%s' was not expected, while inserting a row", err)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestByteSliceArgument(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ username := []byte("user")
+ mock.ExpectExec("INSERT INTO users").WithArgs(username).WillReturnResult(NewResult(1, 1))
+
+ _, err = db.Exec("INSERT INTO users(username) VALUES (?)", username)
+ if err != nil {
+ t.Errorf("error '%s' was not expected, while inserting a row", err)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver.go
new file mode 100644
index 0000000..2a480fe
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver.go
@@ -0,0 +1,78 @@
+package sqlmock
+
+import (
+ "database/sql"
+ "database/sql/driver"
+ "fmt"
+ "sync"
+)
+
+var pool *mockDriver
+
+func init() {
+ pool = &mockDriver{
+ conns: make(map[string]*sqlmock),
+ }
+ sql.Register("sqlmock", pool)
+}
+
+type mockDriver struct {
+ sync.Mutex
+ counter int
+ conns map[string]*sqlmock
+}
+
+func (d *mockDriver) Open(dsn string) (driver.Conn, error) {
+ d.Lock()
+ defer d.Unlock()
+
+ c, ok := d.conns[dsn]
+ if !ok {
+ return c, fmt.Errorf("expected a connection to be available, but it is not")
+ }
+
+ c.opened++
+ return c, nil
+}
+
+// New creates sqlmock database connection
+// and a mock to manage expectations.
+// Pings db so that all expectations could be
+// asserted.
+func New() (*sql.DB, Sqlmock, error) {
+ pool.Lock()
+ dsn := fmt.Sprintf("sqlmock_db_%d", pool.counter)
+ pool.counter++
+
+ smock := &sqlmock{dsn: dsn, drv: pool, ordered: true}
+ pool.conns[dsn] = smock
+ pool.Unlock()
+
+ return smock.open()
+}
+
+// NewWithDSN creates sqlmock database connection
+// with a specific DSN and a mock to manage expectations.
+// Pings db so that all expectations could be asserted.
+//
+// This method is introduced because of sql abstraction
+// libraries, which do not provide a way to initialize
+// with sql.DB instance. For example GORM library.
+//
+// Note, it will error if attempted to create with an
+// already used dsn
+//
+// It is not recommended to use this method, unless you
+// really need it and there is no other way around.
+func NewWithDSN(dsn string) (*sql.DB, Sqlmock, error) {
+ pool.Lock()
+ if _, ok := pool.conns[dsn]; ok {
+ pool.Unlock()
+ return nil, nil, fmt.Errorf("cannot create a new mock database with the same dsn: %s", dsn)
+ }
+ smock := &sqlmock{dsn: dsn, drv: pool, ordered: true}
+ pool.conns[dsn] = smock
+ pool.Unlock()
+
+ return smock.open()
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver_test.go
new file mode 100644
index 0000000..1a65c1c
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver_test.go
@@ -0,0 +1,112 @@
+package sqlmock
+
+import (
+ "fmt"
+ "testing"
+)
+
+type void struct{}
+
+func (void) Print(...interface{}) {}
+
+func ExampleNew() {
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("expected no error, but got:", err)
+ return
+ }
+ defer db.Close()
+ // now we can expect operations performed on db
+ mock.ExpectBegin().WillReturnError(fmt.Errorf("an error will occur on db.Begin() call"))
+}
+
+func TestShouldOpenConnectionIssue15(t *testing.T) {
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("expected no error, but got: %s", err)
+ }
+ if len(pool.conns) != 1 {
+ t.Errorf("expected 1 connection in pool, but there is: %d", len(pool.conns))
+ }
+
+ smock, _ := mock.(*sqlmock)
+ if smock.opened != 1 {
+ t.Errorf("expected 1 connection on mock to be opened, but there is: %d", smock.opened)
+ }
+
+ // defer so the rows gets closed first
+ defer func() {
+ if smock.opened != 0 {
+ t.Errorf("expected no connections on mock to be opened, but there is: %d", smock.opened)
+ }
+ }()
+
+ mock.ExpectQuery("SELECT").WillReturnRows(NewRows([]string{"one", "two"}).AddRow("val1", "val2"))
+ rows, err := db.Query("SELECT")
+ if err != nil {
+ t.Errorf("unexpected error: %s", err)
+ }
+ defer rows.Close()
+
+ mock.ExpectExec("UPDATE").WillReturnResult(NewResult(1, 1))
+ if _, err = db.Exec("UPDATE"); err != nil {
+ t.Errorf("unexpected error: %s", err)
+ }
+
+ // now there should be two connections open
+ if smock.opened != 2 {
+ t.Errorf("expected 2 connection on mock to be opened, but there is: %d", smock.opened)
+ }
+
+ mock.ExpectClose()
+ if err = db.Close(); err != nil {
+ t.Errorf("expected no error on close, but got: %s", err)
+ }
+
+ // one is still reserved for rows
+ if smock.opened != 1 {
+ t.Errorf("expected 1 connection on mock to be still reserved for rows, but there is: %d", smock.opened)
+ }
+}
+
+func TestTwoOpenConnectionsOnTheSameDSN(t *testing.T) {
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("expected no error, but got: %s", err)
+ }
+ db2, mock2, err := New()
+ if err != nil {
+ t.Errorf("expected no error, but got: %s", err)
+ }
+ if len(pool.conns) != 2 {
+ t.Errorf("expected 2 connection in pool, but there is: %d", len(pool.conns))
+ }
+
+ if db == db2 {
+ t.Errorf("expected not the same database instance, but it is the same")
+ }
+ if mock == mock2 {
+ t.Errorf("expected not the same mock instance, but it is the same")
+ }
+}
+
+func TestWrongDSN(t *testing.T) {
+ t.Parallel()
+ db, _, _ := New()
+ defer db.Close()
+ if _, err := db.Driver().Open("wrong_dsn"); err == nil {
+ t.Error("expected error on Open")
+ }
+}
+
+func TestNewDSN(t *testing.T) {
+ if _, _, err := NewWithDSN("sqlmock_db_99"); err != nil {
+ t.Errorf("expected no error on NewWithDSN, but got: %s", err)
+ }
+}
+
+func TestDuplicateNewDSN(t *testing.T) {
+ if _, _, err := NewWithDSN("sqlmock_db_1"); err == nil {
+ t.Error("expected error on NewWithDSN")
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic.go
new file mode 100644
index 0000000..0fbf98d
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic.go
@@ -0,0 +1,40 @@
+package main
+
+import "database/sql"
+
+func recordStats(db *sql.DB, userID, productID int64) (err error) {
+ tx, err := db.Begin()
+ if err != nil {
+ return
+ }
+
+ defer func() {
+ switch err {
+ case nil:
+ err = tx.Commit()
+ default:
+ tx.Rollback()
+ }
+ }()
+
+ if _, err = tx.Exec("UPDATE products SET views = views + 1"); err != nil {
+ return
+ }
+ if _, err = tx.Exec("INSERT INTO product_viewers (user_id, product_id) VALUES (?, ?)", userID, productID); err != nil {
+ return
+ }
+ return
+}
+
+func main() {
+ // @NOTE: the real connection is not required for tests
+ db, err := sql.Open("mysql", "root@/blog")
+ if err != nil {
+ panic(err)
+ }
+ defer db.Close()
+
+ if err = recordStats(db, 1 /*some user id*/, 5 /*some product id*/); err != nil {
+ panic(err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic_test.go
new file mode 100644
index 0000000..0825f90
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic_test.go
@@ -0,0 +1,58 @@
+package main
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/DATA-DOG/go-sqlmock"
+)
+
+// a successful case
+func TestShouldUpdateStats(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectBegin()
+ mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))
+ mock.ExpectExec("INSERT INTO product_viewers").WithArgs(2, 3).WillReturnResult(sqlmock.NewResult(1, 1))
+ mock.ExpectCommit()
+
+ // now we execute our method
+ if err = recordStats(db, 2, 3); err != nil {
+ t.Errorf("error was not expected while updating stats: %s", err)
+ }
+
+ // we make sure that all expectations were met
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+// a failing test case
+func TestShouldRollbackStatUpdatesOnFailure(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectBegin()
+ mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))
+ mock.ExpectExec("INSERT INTO product_viewers").
+ WithArgs(2, 3).
+ WillReturnError(fmt.Errorf("some error"))
+ mock.ExpectRollback()
+
+ // now we execute our method
+ if err = recordStats(db, 2, 3); err == nil {
+ t.Errorf("was expecting an error, but there was none")
+ }
+
+ // we make sure that all expectations were met
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog.go
new file mode 100644
index 0000000..c4aec06
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog.go
@@ -0,0 +1,81 @@
+package main
+
+import (
+ "database/sql"
+ "encoding/json"
+ "net/http"
+)
+
+type api struct {
+ db *sql.DB
+}
+
+type post struct {
+ ID int
+ Title string
+ Body string
+}
+
+func (a *api) posts(w http.ResponseWriter, r *http.Request) {
+ rows, err := a.db.Query("SELECT id, title, body FROM posts")
+ if err != nil {
+ a.fail(w, "failed to fetch posts: "+err.Error(), 500)
+ return
+ }
+ defer rows.Close()
+
+ var posts []*post
+ for rows.Next() {
+ p := &post{}
+ if err := rows.Scan(&p.ID, &p.Title, &p.Body); err != nil {
+ a.fail(w, "failed to scan post: "+err.Error(), 500)
+ return
+ }
+ posts = append(posts, p)
+ }
+ if rows.Err() != nil {
+ a.fail(w, "failed to read all posts: "+rows.Err().Error(), 500)
+ return
+ }
+
+ data := struct {
+ Posts []*post
+ }{posts}
+
+ a.ok(w, data)
+}
+
+func main() {
+ // @NOTE: the real connection is not required for tests
+ db, err := sql.Open("mysql", "root@/blog")
+ if err != nil {
+ panic(err)
+ }
+ app := &api{db: db}
+ http.HandleFunc("/posts", app.posts)
+ http.ListenAndServe(":8080", nil)
+}
+
+func (a *api) fail(w http.ResponseWriter, msg string, status int) {
+ w.Header().Set("Content-Type", "application/json")
+
+ data := struct {
+ Error string
+ }{Error: msg}
+
+ resp, _ := json.Marshal(data)
+ w.WriteHeader(status)
+ w.Write(resp)
+}
+
+func (a *api) ok(w http.ResponseWriter, data interface{}) {
+ w.Header().Set("Content-Type", "application/json")
+
+ resp, err := json.Marshal(data)
+ if err != nil {
+ w.WriteHeader(http.StatusInternalServerError)
+ a.fail(w, "oops something evil has happened", 500)
+ return
+ }
+ w.Write(resp)
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog_test.go
new file mode 100644
index 0000000..aa1881a
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog_test.go
@@ -0,0 +1,102 @@
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/DATA-DOG/go-sqlmock"
+)
+
+func (a *api) assertJSON(actual []byte, data interface{}, t *testing.T) {
+ expected, err := json.Marshal(data)
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when marshaling expected json data", err)
+ }
+
+ if bytes.Compare(expected, actual) != 0 {
+ t.Errorf("the expected json: %s is different from actual %s", expected, actual)
+ }
+}
+
+func TestShouldGetPosts(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ // create app with mocked db, request and response to test
+ app := &api{db}
+ req, err := http.NewRequest("GET", "http://localhost/posts", nil)
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected while creating request", err)
+ }
+ w := httptest.NewRecorder()
+
+ // before we actually execute our api function, we need to expect required DB actions
+ rows := sqlmock.NewRows([]string{"id", "title", "body"}).
+ AddRow(1, "post 1", "hello").
+ AddRow(2, "post 2", "world")
+
+ mock.ExpectQuery("^SELECT (.+) FROM posts$").WillReturnRows(rows)
+
+ // now we execute our request
+ app.posts(w, req)
+
+ if w.Code != 200 {
+ t.Fatalf("expected status code to be 200, but got: %d", w.Code)
+ }
+
+ data := struct {
+ Posts []*post
+ }{Posts: []*post{
+ {ID: 1, Title: "post 1", Body: "hello"},
+ {ID: 2, Title: "post 2", Body: "world"},
+ }}
+ app.assertJSON(w.Body.Bytes(), data, t)
+
+ // we make sure that all expectations were met
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestShouldRespondWithErrorOnFailure(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ // create app with mocked db, request and response to test
+ app := &api{db}
+ req, err := http.NewRequest("GET", "http://localhost/posts", nil)
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected while creating request", err)
+ }
+ w := httptest.NewRecorder()
+
+ // before we actually execute our api function, we need to expect required DB actions
+ mock.ExpectQuery("^SELECT (.+) FROM posts$").WillReturnError(fmt.Errorf("some error"))
+
+ // now we execute our request
+ app.posts(w, req)
+
+ if w.Code != 500 {
+ t.Fatalf("expected status code to be 500, but got: %d", w.Code)
+ }
+
+ data := struct {
+ Error string
+ }{"failed to fetch posts: some error"}
+ app.assertJSON(w.Body.Bytes(), data, t)
+
+ // we make sure that all expectations were met
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/doc.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/doc.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/doc.go
new file mode 100644
index 0000000..c7842af
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/doc.go
@@ -0,0 +1 @@
+package examples
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders.go
new file mode 100644
index 0000000..fb7e47e
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders.go
@@ -0,0 +1,121 @@
+package main
+
+import (
+ "database/sql"
+ "fmt"
+ "log"
+
+ "github.com/kisielk/sqlstruct"
+)
+
+const ORDER_PENDING = 0
+const ORDER_CANCELLED = 1
+
+type User struct {
+ Id int `sql:"id"`
+ Username string `sql:"username"`
+ Balance float64 `sql:"balance"`
+}
+
+type Order struct {
+ Id int `sql:"id"`
+ Value float64 `sql:"value"`
+ ReservedFee float64 `sql:"reserved_fee"`
+ Status int `sql:"status"`
+}
+
+func cancelOrder(id int, db *sql.DB) (err error) {
+ tx, err := db.Begin()
+ if err != nil {
+ return
+ }
+
+ var order Order
+ var user User
+ sql := fmt.Sprintf(`
+SELECT %s, %s
+FROM orders AS o
+INNER JOIN users AS u ON o.buyer_id = u.id
+WHERE o.id = ?
+FOR UPDATE`,
+ sqlstruct.ColumnsAliased(order, "o"),
+ sqlstruct.ColumnsAliased(user, "u"))
+
+ // fetch order to cancel
+ rows, err := tx.Query(sql, id)
+ if err != nil {
+ tx.Rollback()
+ return
+ }
+
+ defer rows.Close()
+ // no rows, nothing to do
+ if !rows.Next() {
+ tx.Rollback()
+ return
+ }
+
+ // read order
+ err = sqlstruct.ScanAliased(&order, rows, "o")
+ if err != nil {
+ tx.Rollback()
+ return
+ }
+
+ // ensure order status
+ if order.Status != ORDER_PENDING {
+ tx.Rollback()
+ return
+ }
+
+ // read user
+ err = sqlstruct.ScanAliased(&user, rows, "u")
+ if err != nil {
+ tx.Rollback()
+ return
+ }
+ rows.Close() // manually close before other prepared statements
+
+ // refund order value
+ sql = "UPDATE users SET balance = balance + ? WHERE id = ?"
+ refundStmt, err := tx.Prepare(sql)
+ if err != nil {
+ tx.Rollback()
+ return
+ }
+ defer refundStmt.Close()
+ _, err = refundStmt.Exec(order.Value+order.ReservedFee, user.Id)
+ if err != nil {
+ tx.Rollback()
+ return
+ }
+
+ // update order status
+ order.Status = ORDER_CANCELLED
+ sql = "UPDATE orders SET status = ?, updated = NOW() WHERE id = ?"
+ orderUpdStmt, err := tx.Prepare(sql)
+ if err != nil {
+ tx.Rollback()
+ return
+ }
+ defer orderUpdStmt.Close()
+ _, err = orderUpdStmt.Exec(order.Status, order.Id)
+ if err != nil {
+ tx.Rollback()
+ return
+ }
+ return tx.Commit()
+}
+
+func main() {
+ // @NOTE: the real connection is not required for tests
+ db, err := sql.Open("mysql", "root:@/orders")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer db.Close()
+ err = cancelOrder(1, db)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders_test.go
new file mode 100644
index 0000000..7562b8f
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders_test.go
@@ -0,0 +1,108 @@
+package main
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/DATA-DOG/go-sqlmock"
+)
+
+// will test that order with a different status, cannot be cancelled
+func TestShouldNotCancelOrderWithNonPendingStatus(t *testing.T) {
+ // open database stub
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Errorf("An error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ // columns are prefixed with "o" since we used sqlstruct to generate them
+ columns := []string{"o_id", "o_status"}
+ // expect transaction begin
+ mock.ExpectBegin()
+ // expect query to fetch order and user, match it with regexp
+ mock.ExpectQuery("SELECT (.+) FROM orders AS o INNER JOIN users AS u (.+) FOR UPDATE").
+ WithArgs(1).
+ WillReturnRows(sqlmock.NewRows(columns).FromCSVString("1,1"))
+ // expect transaction rollback, since order status is "cancelled"
+ mock.ExpectRollback()
+
+ // run the cancel order function
+ err = cancelOrder(1, db)
+ if err != nil {
+ t.Errorf("Expected no error, but got %s instead", err)
+ }
+ // we make sure that all expectations were met
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+// will test order cancellation
+func TestShouldRefundUserWhenOrderIsCancelled(t *testing.T) {
+ // open database stub
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Errorf("An error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ // columns are prefixed with "o" since we used sqlstruct to generate them
+ columns := []string{"o_id", "o_status", "o_value", "o_reserved_fee", "u_id", "u_balance"}
+ // expect transaction begin
+ mock.ExpectBegin()
+ // expect query to fetch order and user, match it with regexp
+ mock.ExpectQuery("SELECT (.+) FROM orders AS o INNER JOIN users AS u (.+) FOR UPDATE").
+ WithArgs(1).
+ WillReturnRows(sqlmock.NewRows(columns).AddRow(1, 0, 25.75, 3.25, 2, 10.00))
+ // expect user balance update
+ mock.ExpectPrepare("UPDATE users SET balance").ExpectExec().
+ WithArgs(25.75+3.25, 2). // refund amount, user id
+ WillReturnResult(sqlmock.NewResult(0, 1)) // no insert id, 1 affected row
+ // expect order status update
+ mock.ExpectPrepare("UPDATE orders SET status").ExpectExec().
+ WithArgs(ORDER_CANCELLED, 1). // status, id
+ WillReturnResult(sqlmock.NewResult(0, 1)) // no insert id, 1 affected row
+ // expect a transaction commit
+ mock.ExpectCommit()
+
+ // run the cancel order function
+ err = cancelOrder(1, db)
+ if err != nil {
+ t.Errorf("Expected no error, but got %s instead", err)
+ }
+ // we make sure that all expectations were met
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+// will test order cancellation
+func TestShouldRollbackOnError(t *testing.T) {
+ // open database stub
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Errorf("An error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ // expect transaction begin
+ mock.ExpectBegin()
+ // expect query to fetch order and user, match it with regexp
+ mock.ExpectQuery("SELECT (.+) FROM orders AS o INNER JOIN users AS u (.+) FOR UPDATE").
+ WithArgs(1).
+ WillReturnError(fmt.Errorf("Some error"))
+ // should rollback since error was returned from query execution
+ mock.ExpectRollback()
+
+ // run the cancel order function
+ err = cancelOrder(1, db)
+ // error should return back
+ if err == nil {
+ t.Error("Expected error, but got none")
+ }
+ // we make sure that all expectations were met
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations.go
new file mode 100644
index 0000000..415759e
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations.go
@@ -0,0 +1,344 @@
+package sqlmock
+
+import (
+ "database/sql/driver"
+ "fmt"
+ "regexp"
+ "strings"
+ "sync"
+ "time"
+)
+
+// an expectation interface
+type expectation interface {
+ fulfilled() bool
+ Lock()
+ Unlock()
+ String() string
+}
+
+// common expectation struct
+// satisfies the expectation interface
+type commonExpectation struct {
+ sync.Mutex
+ triggered bool
+ err error
+}
+
+func (e *commonExpectation) fulfilled() bool {
+ return e.triggered
+}
+
+// ExpectedClose is used to manage *sql.DB.Close expectation
+// returned by *Sqlmock.ExpectClose.
+type ExpectedClose struct {
+ commonExpectation
+}
+
+// WillReturnError allows to set an error for *sql.DB.Close action
+func (e *ExpectedClose) WillReturnError(err error) *ExpectedClose {
+ e.err = err
+ return e
+}
+
+// String returns string representation
+func (e *ExpectedClose) String() string {
+ msg := "ExpectedClose => expecting database Close"
+ if e.err != nil {
+ msg += fmt.Sprintf(", which should return error: %s", e.err)
+ }
+ return msg
+}
+
+// ExpectedBegin is used to manage *sql.DB.Begin expectation
+// returned by *Sqlmock.ExpectBegin.
+type ExpectedBegin struct {
+ commonExpectation
+ delay time.Duration
+}
+
+// WillReturnError allows to set an error for *sql.DB.Begin action
+func (e *ExpectedBegin) WillReturnError(err error) *ExpectedBegin {
+ e.err = err
+ return e
+}
+
+// String returns string representation
+func (e *ExpectedBegin) String() string {
+ msg := "ExpectedBegin => expecting database transaction Begin"
+ if e.err != nil {
+ msg += fmt.Sprintf(", which should return error: %s", e.err)
+ }
+ return msg
+}
+
+// WillDelayFor allows to specify duration for which it will delay
+// result. May be used together with Context
+func (e *ExpectedBegin) WillDelayFor(duration time.Duration) *ExpectedBegin {
+ e.delay = duration
+ return e
+}
+
+// ExpectedCommit is used to manage *sql.Tx.Commit expectation
+// returned by *Sqlmock.ExpectCommit.
+type ExpectedCommit struct {
+ commonExpectation
+}
+
+// WillReturnError allows to set an error for *sql.Tx.Close action
+func (e *ExpectedCommit) WillReturnError(err error) *ExpectedCommit {
+ e.err = err
+ return e
+}
+
+// String returns string representation
+func (e *ExpectedCommit) String() string {
+ msg := "ExpectedCommit => expecting transaction Commit"
+ if e.err != nil {
+ msg += fmt.Sprintf(", which should return error: %s", e.err)
+ }
+ return msg
+}
+
+// ExpectedRollback is used to manage *sql.Tx.Rollback expectation
+// returned by *Sqlmock.ExpectRollback.
+type ExpectedRollback struct {
+ commonExpectation
+}
+
+// WillReturnError allows to set an error for *sql.Tx.Rollback action
+func (e *ExpectedRollback) WillReturnError(err error) *ExpectedRollback {
+ e.err = err
+ return e
+}
+
+// String returns string representation
+func (e *ExpectedRollback) String() string {
+ msg := "ExpectedRollback => expecting transaction Rollback"
+ if e.err != nil {
+ msg += fmt.Sprintf(", which should return error: %s", e.err)
+ }
+ return msg
+}
+
+// ExpectedQuery is used to manage *sql.DB.Query, *dql.DB.QueryRow, *sql.Tx.Query,
+// *sql.Tx.QueryRow, *sql.Stmt.Query or *sql.Stmt.QueryRow expectations.
+// Returned by *Sqlmock.ExpectQuery.
+type ExpectedQuery struct {
+ queryBasedExpectation
+ rows driver.Rows
+ delay time.Duration
+}
+
+// WithArgs will match given expected args to actual database query arguments.
+// if at least one argument does not match, it will return an error. For specific
+// arguments an sqlmock.Argument interface can be used to match an argument.
+func (e *ExpectedQuery) WithArgs(args ...driver.Value) *ExpectedQuery {
+ e.args = args
+ return e
+}
+
+// WillReturnError allows to set an error for expected database query
+func (e *ExpectedQuery) WillReturnError(err error) *ExpectedQuery {
+ e.err = err
+ return e
+}
+
+// WillDelayFor allows to specify duration for which it will delay
+// result. May be used together with Context
+func (e *ExpectedQuery) WillDelayFor(duration time.Duration) *ExpectedQuery {
+ e.delay = duration
+ return e
+}
+
+// String returns string representation
+func (e *ExpectedQuery) String() string {
+ msg := "ExpectedQuery => expecting Query or QueryRow which:"
+ msg += "\n - matches sql: '" + e.sqlRegex.String() + "'"
+
+ if len(e.args) == 0 {
+ msg += "\n - is without arguments"
+ } else {
+ msg += "\n - is with arguments:\n"
+ for i, arg := range e.args {
+ msg += fmt.Sprintf(" %d - %+v\n", i, arg)
+ }
+ msg = strings.TrimSpace(msg)
+ }
+
+ if e.rows != nil {
+ msg += fmt.Sprintf("\n - %s", e.rows)
+ }
+
+ if e.err != nil {
+ msg += fmt.Sprintf("\n - should return error: %s", e.err)
+ }
+
+ return msg
+}
+
+// ExpectedExec is used to manage *sql.DB.Exec, *sql.Tx.Exec or *sql.Stmt.Exec expectations.
+// Returned by *Sqlmock.ExpectExec.
+type ExpectedExec struct {
+ queryBasedExpectation
+ result driver.Result
+ delay time.Duration
+}
+
+// WithArgs will match given expected args to actual database exec operation arguments.
+// if at least one argument does not match, it will return an error. For specific
+// arguments an sqlmock.Argument interface can be used to match an argument.
+func (e *ExpectedExec) WithArgs(args ...driver.Value) *ExpectedExec {
+ e.args = args
+ return e
+}
+
+// WillReturnError allows to set an error for expected database exec action
+func (e *ExpectedExec) WillReturnError(err error) *ExpectedExec {
+ e.err = err
+ return e
+}
+
+// WillDelayFor allows to specify duration for which it will delay
+// result. May be used together with Context
+func (e *ExpectedExec) WillDelayFor(duration time.Duration) *ExpectedExec {
+ e.delay = duration
+ return e
+}
+
+// String returns string representation
+func (e *ExpectedExec) String() string {
+ msg := "ExpectedExec => expecting Exec which:"
+ msg += "\n - matches sql: '" + e.sqlRegex.String() + "'"
+
+ if len(e.args) == 0 {
+ msg += "\n - is without arguments"
+ } else {
+ msg += "\n - is with arguments:\n"
+ var margs []string
+ for i, arg := range e.args {
+ margs = append(margs, fmt.Sprintf(" %d - %+v", i, arg))
+ }
+ msg += strings.Join(margs, "\n")
+ }
+
+ if e.result != nil {
+ res, _ := e.result.(*result)
+ msg += "\n - should return Result having:"
+ msg += fmt.Sprintf("\n LastInsertId: %d", res.insertID)
+ msg += fmt.Sprintf("\n RowsAffected: %d", res.rowsAffected)
+ if res.err != nil {
+ msg += fmt.Sprintf("\n Error: %s", res.err)
+ }
+ }
+
+ if e.err != nil {
+ msg += fmt.Sprintf("\n - should return error: %s", e.err)
+ }
+
+ return msg
+}
+
+// WillReturnResult arranges for an expected Exec() to return a particular
+// result, there is sqlmock.NewResult(lastInsertID int64, affectedRows int64) method
+// to build a corresponding result. Or if actions needs to be tested against errors
+// sqlmock.NewErrorResult(err error) to return a given error.
+func (e *ExpectedExec) WillReturnResult(result driver.Result) *ExpectedExec {
+ e.result = result
+ return e
+}
+
+// ExpectedPrepare is used to manage *sql.DB.Prepare or *sql.Tx.Prepare expectations.
+// Returned by *Sqlmock.ExpectPrepare.
+type ExpectedPrepare struct {
+ commonExpectation
+ mock *sqlmock
+ sqlRegex *regexp.Regexp
+ statement driver.Stmt
+ closeErr error
+ delay time.Duration
+}
+
+// WillReturnError allows to set an error for the expected *sql.DB.Prepare or *sql.Tx.Prepare action.
+func (e *ExpectedPrepare) WillReturnError(err error) *ExpectedPrepare {
+ e.err = err
+ return e
+}
+
+// WillReturnCloseError allows to set an error for this prapared statement Close action
+func (e *ExpectedPrepare) WillReturnCloseError(err error) *ExpectedPrepare {
+ e.closeErr = err
+ return e
+}
+
+// WillDelayFor allows to specify duration for which it will delay
+// result. May be used together with Context
+func (e *ExpectedPrepare) WillDelayFor(duration time.Duration) *ExpectedPrepare {
+ e.delay = duration
+ return e
+}
+
+// ExpectQuery allows to expect Query() or QueryRow() on this prepared statement.
+// this method is convenient in order to prevent duplicating sql query string matching.
+func (e *ExpectedPrepare) ExpectQuery() *ExpectedQuery {
+ eq := &ExpectedQuery{}
+ eq.sqlRegex = e.sqlRegex
+ e.mock.expected = append(e.mock.expected, eq)
+ return eq
+}
+
+// ExpectExec allows to expect Exec() on this prepared statement.
+// this method is convenient in order to prevent duplicating sql query string matching.
+func (e *ExpectedPrepare) ExpectExec() *ExpectedExec {
+ eq := &ExpectedExec{}
+ eq.sqlRegex = e.sqlRegex
+ e.mock.expected = append(e.mock.expected, eq)
+ return eq
+}
+
+// String returns string representation
+func (e *ExpectedPrepare) String() string {
+ msg := "ExpectedPrepare => expecting Prepare statement which:"
+ msg += "\n - matches sql: '" + e.sqlRegex.String() + "'"
+
+ if e.err != nil {
+ msg += fmt.Sprintf("\n - should return error: %s", e.err)
+ }
+
+ if e.closeErr != nil {
+ msg += fmt.Sprintf("\n - should return error on Close: %s", e.closeErr)
+ }
+
+ return msg
+}
+
+// query based expectation
+// adds a query matching logic
+type queryBasedExpectation struct {
+ commonExpectation
+ sqlRegex *regexp.Regexp
+ args []driver.Value
+}
+
+func (e *queryBasedExpectation) attemptMatch(sql string, args []namedValue) (err error) {
+ if !e.queryMatches(sql) {
+ return fmt.Errorf(`could not match sql: "%s" with expected regexp "%s"`, sql, e.sqlRegex.String())
+ }
+
+ // catch panic
+ defer func() {
+ if e := recover(); e != nil {
+ _, ok := e.(error)
+ if !ok {
+ err = fmt.Errorf(e.(string))
+ }
+ }
+ }()
+
+ err = e.argsMatches(args)
+ return
+}
+
+func (e *queryBasedExpectation) queryMatches(sql string) bool {
+ return e.sqlRegex.MatchString(sql)
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_before_go18.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_before_go18.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_before_go18.go
new file mode 100644
index 0000000..146f240
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_before_go18.go
@@ -0,0 +1,52 @@
+// +build !go1.8
+
+package sqlmock
+
+import (
+ "database/sql/driver"
+ "fmt"
+ "reflect"
+)
+
+// WillReturnRows specifies the set of resulting rows that will be returned
+// by the triggered query
+func (e *ExpectedQuery) WillReturnRows(rows *Rows) *ExpectedQuery {
+ e.rows = &rowSets{sets: []*Rows{rows}}
+ return e
+}
+
+func (e *queryBasedExpectation) argsMatches(args []namedValue) error {
+ if nil == e.args {
+ return nil
+ }
+ if len(args) != len(e.args) {
+ return fmt.Errorf("expected %d, but got %d arguments", len(e.args), len(args))
+ }
+ for k, v := range args {
+ // custom argument matcher
+ matcher, ok := e.args[k].(Argument)
+ if ok {
+ // @TODO: does it make sense to pass value instead of named value?
+ if !matcher.Match(v.Value) {
+ return fmt.Errorf("matcher %T could not match %d argument %T - %+v", matcher, k, args[k], args[k])
+ }
+ continue
+ }
+
+ dval := e.args[k]
+ // convert to driver converter
+ darg, err := driver.DefaultParameterConverter.ConvertValue(dval)
+ if err != nil {
+ return fmt.Errorf("could not convert %d argument %T - %+v to driver value: %s", k, e.args[k], e.args[k], err)
+ }
+
+ if !driver.IsValue(darg) {
+ return fmt.Errorf("argument %d: non-subset type %T returned from Value", k, darg)
+ }
+
+ if !reflect.DeepEqual(darg, v.Value) {
+ return fmt.Errorf("argument %d expected [%T - %+v] does not match actual [%T - %+v]", k, darg, darg, v.Value, v.Value)
+ }
+ }
+ return nil
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18.go
new file mode 100644
index 0000000..2b4b44e
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18.go
@@ -0,0 +1,66 @@
+// +build go1.8
+
+package sqlmock
+
+import (
+ "database/sql"
+ "database/sql/driver"
+ "fmt"
+ "reflect"
+)
+
+// WillReturnRows specifies the set of resulting rows that will be returned
+// by the triggered query
+func (e *ExpectedQuery) WillReturnRows(rows ...*Rows) *ExpectedQuery {
+ sets := make([]*Rows, len(rows))
+ for i, r := range rows {
+ sets[i] = r
+ }
+ e.rows = &rowSets{sets: sets}
+ return e
+}
+
+func (e *queryBasedExpectation) argsMatches(args []namedValue) error {
+ if nil == e.args {
+ return nil
+ }
+ if len(args) != len(e.args) {
+ return fmt.Errorf("expected %d, but got %d arguments", len(e.args), len(args))
+ }
+ // @TODO should we assert either all args are named or ordinal?
+ for k, v := range args {
+ // custom argument matcher
+ matcher, ok := e.args[k].(Argument)
+ if ok {
+ if !matcher.Match(v.Value) {
+ return fmt.Errorf("matcher %T could not match %d argument %T - %+v", matcher, k, args[k], args[k])
+ }
+ continue
+ }
+
+ dval := e.args[k]
+ if named, isNamed := dval.(sql.NamedArg); isNamed {
+ dval = named.Value
+ if v.Name != named.Name {
+ return fmt.Errorf("named argument %d: name: \"%s\" does not match expected: \"%s\"", k, v.Name, named.Name)
+ }
+ } else if k+1 != v.Ordinal {
+ return fmt.Errorf("argument %d: ordinal position: %d does not match expected: %d", k, k+1, v.Ordinal)
+ }
+
+ // convert to driver converter
+ darg, err := driver.DefaultParameterConverter.ConvertValue(dval)
+ if err != nil {
+ return fmt.Errorf("could not convert %d argument %T - %+v to driver value: %s", k, e.args[k], e.args[k], err)
+ }
+
+ if !driver.IsValue(darg) {
+ return fmt.Errorf("argument %d: non-subset type %T returned from Value", k, darg)
+ }
+
+ if !reflect.DeepEqual(darg, v.Value) {
+ return fmt.Errorf("argument %d expected [%T - %+v] does not match actual [%T - %+v]", k, darg, darg, v.Value, v.Value)
+ }
+ }
+ return nil
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18_test.go
new file mode 100644
index 0000000..5f30d2f
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18_test.go
@@ -0,0 +1,64 @@
+// +build go1.8
+
+package sqlmock
+
+import (
+ "database/sql"
+ "database/sql/driver"
+ "testing"
+)
+
+func TestQueryExpectationNamedArgComparison(t *testing.T) {
+ e := &queryBasedExpectation{}
+ against := []namedValue{{Value: int64(5), Name: "id"}}
+ if err := e.argsMatches(against); err != nil {
+ t.Errorf("arguments should match, since the no expectation was set, but got err: %s", err)
+ }
+
+ e.args = []driver.Value{
+ sql.Named("id", 5),
+ sql.Named("s", "str"),
+ }
+
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments should not match, since the size is not the same")
+ }
+
+ against = []namedValue{
+ {Value: int64(5), Name: "id"},
+ {Value: "str", Name: "s"},
+ }
+
+ if err := e.argsMatches(against); err != nil {
+ t.Errorf("arguments should have matched, but it did not: %v", err)
+ }
+
+ against = []namedValue{
+ {Value: int64(5), Name: "id"},
+ {Value: "str", Name: "username"},
+ }
+
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments matched, but it should have not due to Name")
+ }
+
+ e.args = []driver.Value{int64(5), "str"}
+
+ against = []namedValue{
+ {Value: int64(5), Ordinal: 0},
+ {Value: "str", Ordinal: 1},
+ }
+
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments matched, but it should have not due to wrong Ordinal position")
+ }
+
+ against = []namedValue{
+ {Value: int64(5), Ordinal: 1},
+ {Value: "str", Ordinal: 2},
+ }
+
+ if err := e.argsMatches(against); err != nil {
+ t.Errorf("arguments should have matched, but it did not: %v", err)
+ }
+}
[28/43] incubator-trafficcontrol git commit: Add TO Golang access log
for proxied requests
Posted by de...@apache.org.
Add TO Golang access log for proxied requests
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/9d24e39f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/9d24e39f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/9d24e39f
Branch: refs/heads/master
Commit: 9d24e39fb3a7e6f4d6b71d5817697b7da70607e3
Parents: d50d93e
Author: Robert Butts <ro...@gmail.com>
Authored: Wed Jul 26 17:49:38 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/traffic_ops_golang/routes.go | 4 +++-
traffic_ops/traffic_ops_golang/wrappers.go | 19 +++++++++++++------
2 files changed, 16 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/9d24e39f/traffic_ops/traffic_ops_golang/routes.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/routes.go b/traffic_ops/traffic_ops_golang/routes.go
index e744086..8ad994e 100644
--- a/traffic_ops/traffic_ops_golang/routes.go
+++ b/traffic_ops/traffic_ops_golang/routes.go
@@ -46,7 +46,9 @@ func getRootHandler(d ServerData) http.Handler {
}
rp := httputil.NewSingleHostReverseProxy(d.TOURL)
rp.Transport = tr
- return rp
+
+ loggingProxyHandler := wrapAccessLog(d.TOSecret, rp)
+ return loggingProxyHandler
}
// GetRoutes returns the map of regex routes, and a catchall route for when no regex matches.
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/9d24e39f/traffic_ops/traffic_ops_golang/wrappers.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/wrappers.go b/traffic_ops/traffic_ops_golang/wrappers.go
index 17f3e1c..5a5cfce 100644
--- a/traffic_ops/traffic_ops_golang/wrappers.go
+++ b/traffic_ops/traffic_ops_golang/wrappers.go
@@ -90,15 +90,22 @@ func wrapAuth(h RegexHandlerFunc, noAuth bool, secret string, privLevelStmt *sql
const AccessLogTimeFormat = "02/Jan/2006:15:04:05 -0700"
-func wrapLogTime(h RegexHandlerFunc) RegexHandlerFunc {
- return func(w http.ResponseWriter, r *http.Request, p ParamMap) {
- start := time.Now()
+func wrapAccessLog(secret string, h http.Handler) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
iw := &Interceptor{w: w}
+ user := "-"
+ cookie, err := r.Cookie(tocookie.Name)
+ if err == nil && cookie != nil {
+ cookie, err := tocookie.Parse(secret, cookie.Value)
+ if err == nil {
+ user = cookie.AuthData
+ }
+ }
+ start := time.Now()
defer func() {
- user := "-" // TODO fix
- log.EventfRaw(`%s - %s [%s] "%v %v HTTP/1.1" %v 0 0 "%v"\n`, r.RemoteAddr, user, time.Now().Format(AccessLogTimeFormat), r.Method, r.URL.Path, iw.code, time.Now().Sub(start)/time.Millisecond, iw.byteCount, r.UserAgent())
+ log.EventfRaw(`%s - %s [%s] "%v %v HTTP/1.1" %v %v %v "%v"`, r.RemoteAddr, user, time.Now().Format(AccessLogTimeFormat), r.Method, r.URL.Path, iw.code, iw.byteCount, int(time.Now().Sub(start)/time.Millisecond), r.UserAgent())
}()
- h(iw, r, p)
+ h.ServeHTTP(iw, r)
}
}
[04/43] incubator-trafficcontrol git commit: Vendor TO GOlang
go-sqlmock
Posted by de...@apache.org.
Vendor TO GOlang go-sqlmock
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/f9f7cfa0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/f9f7cfa0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/f9f7cfa0
Branch: refs/heads/master
Commit: f9f7cfa06217d5b3d4c1ba4bd026982b8d8fcaba
Parents: 4fd7feb
Author: Robert Butts <ro...@gmail.com>
Authored: Mon Jul 17 21:53:50 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:02 2017 -0600
----------------------------------------------------------------------
.../vendor/gopkg.in/DATA-DOG/go-sqlmock/LICENSE | 28 +
.../gopkg.in/DATA-DOG/go-sqlmock/README.md | 223 +++++
.../gopkg.in/DATA-DOG/go-sqlmock/argument.go | 24 +
.../DATA-DOG/go-sqlmock/argument_test.go | 58 ++
.../gopkg.in/DATA-DOG/go-sqlmock/driver.go | 78 ++
.../gopkg.in/DATA-DOG/go-sqlmock/driver_test.go | 112 +++
.../DATA-DOG/go-sqlmock/examples/basic/basic.go | 40 +
.../go-sqlmock/examples/basic/basic_test.go | 58 ++
.../DATA-DOG/go-sqlmock/examples/blog/blog.go | 81 ++
.../go-sqlmock/examples/blog/blog_test.go | 102 ++
.../DATA-DOG/go-sqlmock/examples/doc.go | 1 +
.../go-sqlmock/examples/orders/orders.go | 121 +++
.../go-sqlmock/examples/orders/orders_test.go | 108 ++
.../DATA-DOG/go-sqlmock/expectations.go | 344 +++++++
.../go-sqlmock/expectations_before_go18.go | 52 +
.../DATA-DOG/go-sqlmock/expectations_go18.go | 66 ++
.../go-sqlmock/expectations_go18_test.go | 64 ++
.../DATA-DOG/go-sqlmock/expectations_test.go | 154 +++
.../gopkg.in/DATA-DOG/go-sqlmock/result.go | 39 +
.../gopkg.in/DATA-DOG/go-sqlmock/result_test.go | 62 ++
.../vendor/gopkg.in/DATA-DOG/go-sqlmock/rows.go | 144 +++
.../gopkg.in/DATA-DOG/go-sqlmock/rows_go18.go | 20 +
.../DATA-DOG/go-sqlmock/rows_go18_test.go | 92 ++
.../gopkg.in/DATA-DOG/go-sqlmock/rows_test.go | 265 +++++
.../gopkg.in/DATA-DOG/go-sqlmock/sqlmock.go | 525 ++++++++++
.../DATA-DOG/go-sqlmock/sqlmock_go18.go | 101 ++
.../DATA-DOG/go-sqlmock/sqlmock_go18_test.go | 426 ++++++++
.../DATA-DOG/go-sqlmock/sqlmock_test.go | 998 +++++++++++++++++++
.../gopkg.in/DATA-DOG/go-sqlmock/statement.go | 27 +
.../DATA-DOG/go-sqlmock/statement_test.go | 33 +
.../gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go | 76 ++
.../vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go | 13 +
.../gopkg.in/DATA-DOG/go-sqlmock/util_test.go | 21 +
33 files changed, 4556 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/LICENSE
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/LICENSE b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/LICENSE
new file mode 100644
index 0000000..7f8bedf
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/LICENSE
@@ -0,0 +1,28 @@
+The three clause BSD license (http://en.wikipedia.org/wiki/BSD_licenses)
+
+Copyright (c) 2013-2017, DATA-DOG team
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* The name DataDog.lt may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/README.md
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/README.md b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/README.md
new file mode 100644
index 0000000..f3d5487
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/README.md
@@ -0,0 +1,223 @@
+[](https://travis-ci.org/DATA-DOG/go-sqlmock)
+[](https://godoc.org/github.com/DATA-DOG/go-sqlmock)
+[](https://codecov.io/github/DATA-DOG/go-sqlmock)
+
+# Sql driver mock for Golang
+
+**sqlmock** is a mock library implementing [sql/driver](https://godoc.org/database/sql/driver). Which has one and only
+purpose - to simulate any **sql** driver behavior in tests, without needing a real database connection. It helps to
+maintain correct **TDD** workflow.
+
+- this library is now complete and stable. (you may not find new changes for this reason)
+- supports concurrency and multiple connections.
+- supports **go1.8** Context related feature mocking and Named sql parameters.
+- does not require any modifications to your source code.
+- the driver allows to mock any sql driver method behavior.
+- has strict by default expectation order matching.
+- has no third party dependencies.
+
+## Install
+
+ go get gopkg.in/DATA-DOG/go-sqlmock.v1
+
+## Documentation and Examples
+
+Visit [godoc](http://godoc.org/github.com/DATA-DOG/go-sqlmock) for general examples and public api reference.
+See **.travis.yml** for supported **go** versions.
+Different use case, is to functionally test with a real database - [go-txdb](https://github.com/DATA-DOG/go-txdb)
+all database related actions are isolated within a single transaction so the database can remain in the same state.
+
+See implementation examples:
+
+- [blog API server](https://github.com/DATA-DOG/go-sqlmock/tree/master/examples/blog)
+- [the same orders example](https://github.com/DATA-DOG/go-sqlmock/tree/master/examples/orders)
+
+### Something you may want to test
+
+``` go
+package main
+
+import "database/sql"
+
+func recordStats(db *sql.DB, userID, productID int64) (err error) {
+ tx, err := db.Begin()
+ if err != nil {
+ return
+ }
+
+ defer func() {
+ switch err {
+ case nil:
+ err = tx.Commit()
+ default:
+ tx.Rollback()
+ }
+ }()
+
+ if _, err = tx.Exec("UPDATE products SET views = views + 1"); err != nil {
+ return
+ }
+ if _, err = tx.Exec("INSERT INTO product_viewers (user_id, product_id) VALUES (?, ?)", userID, productID); err != nil {
+ return
+ }
+ return
+}
+
+func main() {
+ // @NOTE: the real connection is not required for tests
+ db, err := sql.Open("mysql", "root@/blog")
+ if err != nil {
+ panic(err)
+ }
+ defer db.Close()
+
+ if err = recordStats(db, 1 /*some user id*/, 5 /*some product id*/); err != nil {
+ panic(err)
+ }
+}
+```
+
+### Tests with sqlmock
+
+``` go
+package main
+
+import (
+ "fmt"
+ "testing"
+
+ "gopkg.in/DATA-DOG/go-sqlmock.v1"
+)
+
+// a successful case
+func TestShouldUpdateStats(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectBegin()
+ mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))
+ mock.ExpectExec("INSERT INTO product_viewers").WithArgs(2, 3).WillReturnResult(sqlmock.NewResult(1, 1))
+ mock.ExpectCommit()
+
+ // now we execute our method
+ if err = recordStats(db, 2, 3); err != nil {
+ t.Errorf("error was not expected while updating stats: %s", err)
+ }
+
+ // we make sure that all expectations were met
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+// a failing test case
+func TestShouldRollbackStatUpdatesOnFailure(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectBegin()
+ mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))
+ mock.ExpectExec("INSERT INTO product_viewers").
+ WithArgs(2, 3).
+ WillReturnError(fmt.Errorf("some error"))
+ mock.ExpectRollback()
+
+ // now we execute our method
+ if err = recordStats(db, 2, 3); err == nil {
+ t.Errorf("was expecting an error, but there was none")
+ }
+
+ // we make sure that all expectations were met
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+```
+
+## Matching arguments like time.Time
+
+There may be arguments which are of `struct` type and cannot be compared easily by value like `time.Time`. In this case
+**sqlmock** provides an [Argument](https://godoc.org/github.com/DATA-DOG/go-sqlmock#Argument) interface which
+can be used in more sophisticated matching. Here is a simple example of time argument matching:
+
+``` go
+type AnyTime struct{}
+
+// Match satisfies sqlmock.Argument interface
+func (a AnyTime) Match(v driver.Value) bool {
+ _, ok := v.(time.Time)
+ return ok
+}
+
+func TestAnyTimeArgument(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectExec("INSERT INTO users").
+ WithArgs("john", AnyTime{}).
+ WillReturnResult(NewResult(1, 1))
+
+ _, err = db.Exec("INSERT INTO users(name, created_at) VALUES (?, ?)", "john", time.Now())
+ if err != nil {
+ t.Errorf("error '%s' was not expected, while inserting a row", err)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+```
+
+It only asserts that argument is of `time.Time` type.
+
+## Run tests
+
+ go test -race
+
+## Change Log
+
+- **2017-02-09** - implemented support for **go1.8** features. **Rows** interface was changed to struct
+ but contains all methods as before and should maintain backwards compatibility. **ExpectedQuery.WillReturnRows** may now
+ accept multiple row sets.
+- **2016-11-02** - `db.Prepare()` was not validating expected prepare SQL
+ query. It should still be validated even if Exec or Query is not
+ executed on that prepared statement.
+- **2016-02-23** - added **sqlmock.AnyArg()** function to provide any kind
+ of argument matcher.
+- **2016-02-23** - convert expected arguments to driver.Value as natural
+ driver does, the change may affect time.Time comparison and will be
+ stricter. See [issue](https://github.com/DATA-DOG/go-sqlmock/issues/31).
+- **2015-08-27** - **v1** api change, concurrency support, all known issues fixed.
+- **2014-08-16** instead of **panic** during reflect type mismatch when comparing query arguments - now return error
+- **2014-08-14** added **sqlmock.NewErrorResult** which gives an option to return driver.Result with errors for
+interface methods, see [issue](https://github.com/DATA-DOG/go-sqlmock/issues/5)
+- **2014-05-29** allow to match arguments in more sophisticated ways, by providing an **sqlmock.Argument** interface
+- **2014-04-21** introduce **sqlmock.New()** to open a mock database connection for tests. This method
+calls sql.DB.Ping to ensure that connection is open, see [issue](https://github.com/DATA-DOG/go-sqlmock/issues/4).
+This way on Close it will surely assert if all expectations are met, even if database was not triggered at all.
+The old way is still available, but it is advisable to call db.Ping manually before asserting with db.Close.
+- **2014-02-14** RowsFromCSVString is now a part of Rows interface named as FromCSVString.
+It has changed to allow more ways to construct rows and to easily extend this API in future.
+See [issue 1](https://github.com/DATA-DOG/go-sqlmock/issues/1)
+**RowsFromCSVString** is deprecated and will be removed in future
+
+## Contributions
+
+Feel free to open a pull request. Note, if you wish to contribute an extension to public (exported methods or types) -
+please open an issue before, to discuss whether these changes can be accepted. All backward incompatible changes are
+and will be treated cautiously
+
+## License
+
+The [three clause BSD license](http://en.wikipedia.org/wiki/BSD_licenses)
+
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument.go
new file mode 100644
index 0000000..7727481
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument.go
@@ -0,0 +1,24 @@
+package sqlmock
+
+import "database/sql/driver"
+
+// Argument interface allows to match
+// any argument in specific way when used with
+// ExpectedQuery and ExpectedExec expectations.
+type Argument interface {
+ Match(driver.Value) bool
+}
+
+// AnyArg will return an Argument which can
+// match any kind of arguments.
+//
+// Useful for time.Time or similar kinds of arguments.
+func AnyArg() Argument {
+ return anyArgument{}
+}
+
+type anyArgument struct{}
+
+func (a anyArgument) Match(_ driver.Value) bool {
+ return true
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument_test.go
new file mode 100644
index 0000000..3088ed4
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/argument_test.go
@@ -0,0 +1,58 @@
+package sqlmock
+
+import (
+ "database/sql/driver"
+ "testing"
+ "time"
+)
+
+type AnyTime struct{}
+
+// Match satisfies sqlmock.Argument interface
+func (a AnyTime) Match(v driver.Value) bool {
+ _, ok := v.(time.Time)
+ return ok
+}
+
+func TestAnyTimeArgument(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectExec("INSERT INTO users").
+ WithArgs("john", AnyTime{}).
+ WillReturnResult(NewResult(1, 1))
+
+ _, err = db.Exec("INSERT INTO users(name, created_at) VALUES (?, ?)", "john", time.Now())
+ if err != nil {
+ t.Errorf("error '%s' was not expected, while inserting a row", err)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestByteSliceArgument(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ username := []byte("user")
+ mock.ExpectExec("INSERT INTO users").WithArgs(username).WillReturnResult(NewResult(1, 1))
+
+ _, err = db.Exec("INSERT INTO users(username) VALUES (?)", username)
+ if err != nil {
+ t.Errorf("error '%s' was not expected, while inserting a row", err)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver.go
new file mode 100644
index 0000000..2a480fe
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver.go
@@ -0,0 +1,78 @@
+package sqlmock
+
+import (
+ "database/sql"
+ "database/sql/driver"
+ "fmt"
+ "sync"
+)
+
+var pool *mockDriver
+
+func init() {
+ pool = &mockDriver{
+ conns: make(map[string]*sqlmock),
+ }
+ sql.Register("sqlmock", pool)
+}
+
+type mockDriver struct {
+ sync.Mutex
+ counter int
+ conns map[string]*sqlmock
+}
+
+func (d *mockDriver) Open(dsn string) (driver.Conn, error) {
+ d.Lock()
+ defer d.Unlock()
+
+ c, ok := d.conns[dsn]
+ if !ok {
+ return c, fmt.Errorf("expected a connection to be available, but it is not")
+ }
+
+ c.opened++
+ return c, nil
+}
+
+// New creates sqlmock database connection
+// and a mock to manage expectations.
+// Pings db so that all expectations could be
+// asserted.
+func New() (*sql.DB, Sqlmock, error) {
+ pool.Lock()
+ dsn := fmt.Sprintf("sqlmock_db_%d", pool.counter)
+ pool.counter++
+
+ smock := &sqlmock{dsn: dsn, drv: pool, ordered: true}
+ pool.conns[dsn] = smock
+ pool.Unlock()
+
+ return smock.open()
+}
+
+// NewWithDSN creates sqlmock database connection
+// with a specific DSN and a mock to manage expectations.
+// Pings db so that all expectations could be asserted.
+//
+// This method is introduced because of sql abstraction
+// libraries, which do not provide a way to initialize
+// with sql.DB instance. For example GORM library.
+//
+// Note, it will error if attempted to create with an
+// already used dsn
+//
+// It is not recommended to use this method, unless you
+// really need it and there is no other way around.
+func NewWithDSN(dsn string) (*sql.DB, Sqlmock, error) {
+ pool.Lock()
+ if _, ok := pool.conns[dsn]; ok {
+ pool.Unlock()
+ return nil, nil, fmt.Errorf("cannot create a new mock database with the same dsn: %s", dsn)
+ }
+ smock := &sqlmock{dsn: dsn, drv: pool, ordered: true}
+ pool.conns[dsn] = smock
+ pool.Unlock()
+
+ return smock.open()
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver_test.go
new file mode 100644
index 0000000..1a65c1c
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/driver_test.go
@@ -0,0 +1,112 @@
+package sqlmock
+
+import (
+ "fmt"
+ "testing"
+)
+
+type void struct{}
+
+func (void) Print(...interface{}) {}
+
+func ExampleNew() {
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("expected no error, but got:", err)
+ return
+ }
+ defer db.Close()
+ // now we can expect operations performed on db
+ mock.ExpectBegin().WillReturnError(fmt.Errorf("an error will occur on db.Begin() call"))
+}
+
+func TestShouldOpenConnectionIssue15(t *testing.T) {
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("expected no error, but got: %s", err)
+ }
+ if len(pool.conns) != 1 {
+ t.Errorf("expected 1 connection in pool, but there is: %d", len(pool.conns))
+ }
+
+ smock, _ := mock.(*sqlmock)
+ if smock.opened != 1 {
+ t.Errorf("expected 1 connection on mock to be opened, but there is: %d", smock.opened)
+ }
+
+ // defer so the rows gets closed first
+ defer func() {
+ if smock.opened != 0 {
+ t.Errorf("expected no connections on mock to be opened, but there is: %d", smock.opened)
+ }
+ }()
+
+ mock.ExpectQuery("SELECT").WillReturnRows(NewRows([]string{"one", "two"}).AddRow("val1", "val2"))
+ rows, err := db.Query("SELECT")
+ if err != nil {
+ t.Errorf("unexpected error: %s", err)
+ }
+ defer rows.Close()
+
+ mock.ExpectExec("UPDATE").WillReturnResult(NewResult(1, 1))
+ if _, err = db.Exec("UPDATE"); err != nil {
+ t.Errorf("unexpected error: %s", err)
+ }
+
+ // now there should be two connections open
+ if smock.opened != 2 {
+ t.Errorf("expected 2 connection on mock to be opened, but there is: %d", smock.opened)
+ }
+
+ mock.ExpectClose()
+ if err = db.Close(); err != nil {
+ t.Errorf("expected no error on close, but got: %s", err)
+ }
+
+ // one is still reserved for rows
+ if smock.opened != 1 {
+ t.Errorf("expected 1 connection on mock to be still reserved for rows, but there is: %d", smock.opened)
+ }
+}
+
+func TestTwoOpenConnectionsOnTheSameDSN(t *testing.T) {
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("expected no error, but got: %s", err)
+ }
+ db2, mock2, err := New()
+ if err != nil {
+ t.Errorf("expected no error, but got: %s", err)
+ }
+ if len(pool.conns) != 2 {
+ t.Errorf("expected 2 connection in pool, but there is: %d", len(pool.conns))
+ }
+
+ if db == db2 {
+ t.Errorf("expected not the same database instance, but it is the same")
+ }
+ if mock == mock2 {
+ t.Errorf("expected not the same mock instance, but it is the same")
+ }
+}
+
+func TestWrongDSN(t *testing.T) {
+ t.Parallel()
+ db, _, _ := New()
+ defer db.Close()
+ if _, err := db.Driver().Open("wrong_dsn"); err == nil {
+ t.Error("expected error on Open")
+ }
+}
+
+func TestNewDSN(t *testing.T) {
+ if _, _, err := NewWithDSN("sqlmock_db_99"); err != nil {
+ t.Errorf("expected no error on NewWithDSN, but got: %s", err)
+ }
+}
+
+func TestDuplicateNewDSN(t *testing.T) {
+ if _, _, err := NewWithDSN("sqlmock_db_1"); err == nil {
+ t.Error("expected error on NewWithDSN")
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic.go
new file mode 100644
index 0000000..0fbf98d
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic.go
@@ -0,0 +1,40 @@
+package main
+
+import "database/sql"
+
+func recordStats(db *sql.DB, userID, productID int64) (err error) {
+ tx, err := db.Begin()
+ if err != nil {
+ return
+ }
+
+ defer func() {
+ switch err {
+ case nil:
+ err = tx.Commit()
+ default:
+ tx.Rollback()
+ }
+ }()
+
+ if _, err = tx.Exec("UPDATE products SET views = views + 1"); err != nil {
+ return
+ }
+ if _, err = tx.Exec("INSERT INTO product_viewers (user_id, product_id) VALUES (?, ?)", userID, productID); err != nil {
+ return
+ }
+ return
+}
+
+func main() {
+ // @NOTE: the real connection is not required for tests
+ db, err := sql.Open("mysql", "root@/blog")
+ if err != nil {
+ panic(err)
+ }
+ defer db.Close()
+
+ if err = recordStats(db, 1 /*some user id*/, 5 /*some product id*/); err != nil {
+ panic(err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic_test.go
new file mode 100644
index 0000000..0825f90
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/basic/basic_test.go
@@ -0,0 +1,58 @@
+package main
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/DATA-DOG/go-sqlmock"
+)
+
+// a successful case
+func TestShouldUpdateStats(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectBegin()
+ mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))
+ mock.ExpectExec("INSERT INTO product_viewers").WithArgs(2, 3).WillReturnResult(sqlmock.NewResult(1, 1))
+ mock.ExpectCommit()
+
+ // now we execute our method
+ if err = recordStats(db, 2, 3); err != nil {
+ t.Errorf("error was not expected while updating stats: %s", err)
+ }
+
+ // we make sure that all expectations were met
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+// a failing test case
+func TestShouldRollbackStatUpdatesOnFailure(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectBegin()
+ mock.ExpectExec("UPDATE products").WillReturnResult(sqlmock.NewResult(1, 1))
+ mock.ExpectExec("INSERT INTO product_viewers").
+ WithArgs(2, 3).
+ WillReturnError(fmt.Errorf("some error"))
+ mock.ExpectRollback()
+
+ // now we execute our method
+ if err = recordStats(db, 2, 3); err == nil {
+ t.Errorf("was expecting an error, but there was none")
+ }
+
+ // we make sure that all expectations were met
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog.go
new file mode 100644
index 0000000..c4aec06
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog.go
@@ -0,0 +1,81 @@
+package main
+
+import (
+ "database/sql"
+ "encoding/json"
+ "net/http"
+)
+
+type api struct {
+ db *sql.DB
+}
+
+type post struct {
+ ID int
+ Title string
+ Body string
+}
+
+func (a *api) posts(w http.ResponseWriter, r *http.Request) {
+ rows, err := a.db.Query("SELECT id, title, body FROM posts")
+ if err != nil {
+ a.fail(w, "failed to fetch posts: "+err.Error(), 500)
+ return
+ }
+ defer rows.Close()
+
+ var posts []*post
+ for rows.Next() {
+ p := &post{}
+ if err := rows.Scan(&p.ID, &p.Title, &p.Body); err != nil {
+ a.fail(w, "failed to scan post: "+err.Error(), 500)
+ return
+ }
+ posts = append(posts, p)
+ }
+ if rows.Err() != nil {
+ a.fail(w, "failed to read all posts: "+rows.Err().Error(), 500)
+ return
+ }
+
+ data := struct {
+ Posts []*post
+ }{posts}
+
+ a.ok(w, data)
+}
+
+func main() {
+ // @NOTE: the real connection is not required for tests
+ db, err := sql.Open("mysql", "root@/blog")
+ if err != nil {
+ panic(err)
+ }
+ app := &api{db: db}
+ http.HandleFunc("/posts", app.posts)
+ http.ListenAndServe(":8080", nil)
+}
+
+func (a *api) fail(w http.ResponseWriter, msg string, status int) {
+ w.Header().Set("Content-Type", "application/json")
+
+ data := struct {
+ Error string
+ }{Error: msg}
+
+ resp, _ := json.Marshal(data)
+ w.WriteHeader(status)
+ w.Write(resp)
+}
+
+func (a *api) ok(w http.ResponseWriter, data interface{}) {
+ w.Header().Set("Content-Type", "application/json")
+
+ resp, err := json.Marshal(data)
+ if err != nil {
+ w.WriteHeader(http.StatusInternalServerError)
+ a.fail(w, "oops something evil has happened", 500)
+ return
+ }
+ w.Write(resp)
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog_test.go
new file mode 100644
index 0000000..aa1881a
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/blog/blog_test.go
@@ -0,0 +1,102 @@
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/DATA-DOG/go-sqlmock"
+)
+
+func (a *api) assertJSON(actual []byte, data interface{}, t *testing.T) {
+ expected, err := json.Marshal(data)
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when marshaling expected json data", err)
+ }
+
+ if bytes.Compare(expected, actual) != 0 {
+ t.Errorf("the expected json: %s is different from actual %s", expected, actual)
+ }
+}
+
+func TestShouldGetPosts(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ // create app with mocked db, request and response to test
+ app := &api{db}
+ req, err := http.NewRequest("GET", "http://localhost/posts", nil)
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected while creating request", err)
+ }
+ w := httptest.NewRecorder()
+
+ // before we actually execute our api function, we need to expect required DB actions
+ rows := sqlmock.NewRows([]string{"id", "title", "body"}).
+ AddRow(1, "post 1", "hello").
+ AddRow(2, "post 2", "world")
+
+ mock.ExpectQuery("^SELECT (.+) FROM posts$").WillReturnRows(rows)
+
+ // now we execute our request
+ app.posts(w, req)
+
+ if w.Code != 200 {
+ t.Fatalf("expected status code to be 200, but got: %d", w.Code)
+ }
+
+ data := struct {
+ Posts []*post
+ }{Posts: []*post{
+ {ID: 1, Title: "post 1", Body: "hello"},
+ {ID: 2, Title: "post 2", Body: "world"},
+ }}
+ app.assertJSON(w.Body.Bytes(), data, t)
+
+ // we make sure that all expectations were met
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestShouldRespondWithErrorOnFailure(t *testing.T) {
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ // create app with mocked db, request and response to test
+ app := &api{db}
+ req, err := http.NewRequest("GET", "http://localhost/posts", nil)
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected while creating request", err)
+ }
+ w := httptest.NewRecorder()
+
+ // before we actually execute our api function, we need to expect required DB actions
+ mock.ExpectQuery("^SELECT (.+) FROM posts$").WillReturnError(fmt.Errorf("some error"))
+
+ // now we execute our request
+ app.posts(w, req)
+
+ if w.Code != 500 {
+ t.Fatalf("expected status code to be 500, but got: %d", w.Code)
+ }
+
+ data := struct {
+ Error string
+ }{"failed to fetch posts: some error"}
+ app.assertJSON(w.Body.Bytes(), data, t)
+
+ // we make sure that all expectations were met
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/doc.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/doc.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/doc.go
new file mode 100644
index 0000000..c7842af
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/doc.go
@@ -0,0 +1 @@
+package examples
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders.go
new file mode 100644
index 0000000..fb7e47e
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders.go
@@ -0,0 +1,121 @@
+package main
+
+import (
+ "database/sql"
+ "fmt"
+ "log"
+
+ "github.com/kisielk/sqlstruct"
+)
+
+const ORDER_PENDING = 0
+const ORDER_CANCELLED = 1
+
+type User struct {
+ Id int `sql:"id"`
+ Username string `sql:"username"`
+ Balance float64 `sql:"balance"`
+}
+
+type Order struct {
+ Id int `sql:"id"`
+ Value float64 `sql:"value"`
+ ReservedFee float64 `sql:"reserved_fee"`
+ Status int `sql:"status"`
+}
+
+func cancelOrder(id int, db *sql.DB) (err error) {
+ tx, err := db.Begin()
+ if err != nil {
+ return
+ }
+
+ var order Order
+ var user User
+ sql := fmt.Sprintf(`
+SELECT %s, %s
+FROM orders AS o
+INNER JOIN users AS u ON o.buyer_id = u.id
+WHERE o.id = ?
+FOR UPDATE`,
+ sqlstruct.ColumnsAliased(order, "o"),
+ sqlstruct.ColumnsAliased(user, "u"))
+
+ // fetch order to cancel
+ rows, err := tx.Query(sql, id)
+ if err != nil {
+ tx.Rollback()
+ return
+ }
+
+ defer rows.Close()
+ // no rows, nothing to do
+ if !rows.Next() {
+ tx.Rollback()
+ return
+ }
+
+ // read order
+ err = sqlstruct.ScanAliased(&order, rows, "o")
+ if err != nil {
+ tx.Rollback()
+ return
+ }
+
+ // ensure order status
+ if order.Status != ORDER_PENDING {
+ tx.Rollback()
+ return
+ }
+
+ // read user
+ err = sqlstruct.ScanAliased(&user, rows, "u")
+ if err != nil {
+ tx.Rollback()
+ return
+ }
+ rows.Close() // manually close before other prepared statements
+
+ // refund order value
+ sql = "UPDATE users SET balance = balance + ? WHERE id = ?"
+ refundStmt, err := tx.Prepare(sql)
+ if err != nil {
+ tx.Rollback()
+ return
+ }
+ defer refundStmt.Close()
+ _, err = refundStmt.Exec(order.Value+order.ReservedFee, user.Id)
+ if err != nil {
+ tx.Rollback()
+ return
+ }
+
+ // update order status
+ order.Status = ORDER_CANCELLED
+ sql = "UPDATE orders SET status = ?, updated = NOW() WHERE id = ?"
+ orderUpdStmt, err := tx.Prepare(sql)
+ if err != nil {
+ tx.Rollback()
+ return
+ }
+ defer orderUpdStmt.Close()
+ _, err = orderUpdStmt.Exec(order.Status, order.Id)
+ if err != nil {
+ tx.Rollback()
+ return
+ }
+ return tx.Commit()
+}
+
+func main() {
+ // @NOTE: the real connection is not required for tests
+ db, err := sql.Open("mysql", "root:@/orders")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer db.Close()
+ err = cancelOrder(1, db)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders_test.go
new file mode 100644
index 0000000..7562b8f
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/examples/orders/orders_test.go
@@ -0,0 +1,108 @@
+package main
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/DATA-DOG/go-sqlmock"
+)
+
+// will test that order with a different status, cannot be cancelled
+func TestShouldNotCancelOrderWithNonPendingStatus(t *testing.T) {
+ // open database stub
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Errorf("An error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ // columns are prefixed with "o" since we used sqlstruct to generate them
+ columns := []string{"o_id", "o_status"}
+ // expect transaction begin
+ mock.ExpectBegin()
+ // expect query to fetch order and user, match it with regexp
+ mock.ExpectQuery("SELECT (.+) FROM orders AS o INNER JOIN users AS u (.+) FOR UPDATE").
+ WithArgs(1).
+ WillReturnRows(sqlmock.NewRows(columns).FromCSVString("1,1"))
+ // expect transaction rollback, since order status is "cancelled"
+ mock.ExpectRollback()
+
+ // run the cancel order function
+ err = cancelOrder(1, db)
+ if err != nil {
+ t.Errorf("Expected no error, but got %s instead", err)
+ }
+ // we make sure that all expectations were met
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+// will test order cancellation
+func TestShouldRefundUserWhenOrderIsCancelled(t *testing.T) {
+ // open database stub
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Errorf("An error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ // columns are prefixed with "o" since we used sqlstruct to generate them
+ columns := []string{"o_id", "o_status", "o_value", "o_reserved_fee", "u_id", "u_balance"}
+ // expect transaction begin
+ mock.ExpectBegin()
+ // expect query to fetch order and user, match it with regexp
+ mock.ExpectQuery("SELECT (.+) FROM orders AS o INNER JOIN users AS u (.+) FOR UPDATE").
+ WithArgs(1).
+ WillReturnRows(sqlmock.NewRows(columns).AddRow(1, 0, 25.75, 3.25, 2, 10.00))
+ // expect user balance update
+ mock.ExpectPrepare("UPDATE users SET balance").ExpectExec().
+ WithArgs(25.75+3.25, 2). // refund amount, user id
+ WillReturnResult(sqlmock.NewResult(0, 1)) // no insert id, 1 affected row
+ // expect order status update
+ mock.ExpectPrepare("UPDATE orders SET status").ExpectExec().
+ WithArgs(ORDER_CANCELLED, 1). // status, id
+ WillReturnResult(sqlmock.NewResult(0, 1)) // no insert id, 1 affected row
+ // expect a transaction commit
+ mock.ExpectCommit()
+
+ // run the cancel order function
+ err = cancelOrder(1, db)
+ if err != nil {
+ t.Errorf("Expected no error, but got %s instead", err)
+ }
+ // we make sure that all expectations were met
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+// will test order cancellation
+func TestShouldRollbackOnError(t *testing.T) {
+ // open database stub
+ db, mock, err := sqlmock.New()
+ if err != nil {
+ t.Errorf("An error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ // expect transaction begin
+ mock.ExpectBegin()
+ // expect query to fetch order and user, match it with regexp
+ mock.ExpectQuery("SELECT (.+) FROM orders AS o INNER JOIN users AS u (.+) FOR UPDATE").
+ WithArgs(1).
+ WillReturnError(fmt.Errorf("Some error"))
+ // should rollback since error was returned from query execution
+ mock.ExpectRollback()
+
+ // run the cancel order function
+ err = cancelOrder(1, db)
+ // error should return back
+ if err == nil {
+ t.Error("Expected error, but got none")
+ }
+ // we make sure that all expectations were met
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations.go
new file mode 100644
index 0000000..415759e
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations.go
@@ -0,0 +1,344 @@
+package sqlmock
+
+import (
+ "database/sql/driver"
+ "fmt"
+ "regexp"
+ "strings"
+ "sync"
+ "time"
+)
+
+// an expectation interface
+type expectation interface {
+ fulfilled() bool
+ Lock()
+ Unlock()
+ String() string
+}
+
+// common expectation struct
+// satisfies the expectation interface
+type commonExpectation struct {
+ sync.Mutex
+ triggered bool
+ err error
+}
+
+func (e *commonExpectation) fulfilled() bool {
+ return e.triggered
+}
+
+// ExpectedClose is used to manage *sql.DB.Close expectation
+// returned by *Sqlmock.ExpectClose.
+type ExpectedClose struct {
+ commonExpectation
+}
+
+// WillReturnError allows to set an error for *sql.DB.Close action
+func (e *ExpectedClose) WillReturnError(err error) *ExpectedClose {
+ e.err = err
+ return e
+}
+
+// String returns string representation
+func (e *ExpectedClose) String() string {
+ msg := "ExpectedClose => expecting database Close"
+ if e.err != nil {
+ msg += fmt.Sprintf(", which should return error: %s", e.err)
+ }
+ return msg
+}
+
+// ExpectedBegin is used to manage *sql.DB.Begin expectation
+// returned by *Sqlmock.ExpectBegin.
+type ExpectedBegin struct {
+ commonExpectation
+ delay time.Duration
+}
+
+// WillReturnError allows to set an error for *sql.DB.Begin action
+func (e *ExpectedBegin) WillReturnError(err error) *ExpectedBegin {
+ e.err = err
+ return e
+}
+
+// String returns string representation
+func (e *ExpectedBegin) String() string {
+ msg := "ExpectedBegin => expecting database transaction Begin"
+ if e.err != nil {
+ msg += fmt.Sprintf(", which should return error: %s", e.err)
+ }
+ return msg
+}
+
+// WillDelayFor allows to specify duration for which it will delay
+// result. May be used together with Context
+func (e *ExpectedBegin) WillDelayFor(duration time.Duration) *ExpectedBegin {
+ e.delay = duration
+ return e
+}
+
+// ExpectedCommit is used to manage *sql.Tx.Commit expectation
+// returned by *Sqlmock.ExpectCommit.
+type ExpectedCommit struct {
+ commonExpectation
+}
+
+// WillReturnError allows to set an error for *sql.Tx.Close action
+func (e *ExpectedCommit) WillReturnError(err error) *ExpectedCommit {
+ e.err = err
+ return e
+}
+
+// String returns string representation
+func (e *ExpectedCommit) String() string {
+ msg := "ExpectedCommit => expecting transaction Commit"
+ if e.err != nil {
+ msg += fmt.Sprintf(", which should return error: %s", e.err)
+ }
+ return msg
+}
+
+// ExpectedRollback is used to manage *sql.Tx.Rollback expectation
+// returned by *Sqlmock.ExpectRollback.
+type ExpectedRollback struct {
+ commonExpectation
+}
+
+// WillReturnError allows to set an error for *sql.Tx.Rollback action
+func (e *ExpectedRollback) WillReturnError(err error) *ExpectedRollback {
+ e.err = err
+ return e
+}
+
+// String returns string representation
+func (e *ExpectedRollback) String() string {
+ msg := "ExpectedRollback => expecting transaction Rollback"
+ if e.err != nil {
+ msg += fmt.Sprintf(", which should return error: %s", e.err)
+ }
+ return msg
+}
+
+// ExpectedQuery is used to manage *sql.DB.Query, *dql.DB.QueryRow, *sql.Tx.Query,
+// *sql.Tx.QueryRow, *sql.Stmt.Query or *sql.Stmt.QueryRow expectations.
+// Returned by *Sqlmock.ExpectQuery.
+type ExpectedQuery struct {
+ queryBasedExpectation
+ rows driver.Rows
+ delay time.Duration
+}
+
+// WithArgs will match given expected args to actual database query arguments.
+// if at least one argument does not match, it will return an error. For specific
+// arguments an sqlmock.Argument interface can be used to match an argument.
+func (e *ExpectedQuery) WithArgs(args ...driver.Value) *ExpectedQuery {
+ e.args = args
+ return e
+}
+
+// WillReturnError allows to set an error for expected database query
+func (e *ExpectedQuery) WillReturnError(err error) *ExpectedQuery {
+ e.err = err
+ return e
+}
+
+// WillDelayFor allows to specify duration for which it will delay
+// result. May be used together with Context
+func (e *ExpectedQuery) WillDelayFor(duration time.Duration) *ExpectedQuery {
+ e.delay = duration
+ return e
+}
+
+// String returns string representation
+func (e *ExpectedQuery) String() string {
+ msg := "ExpectedQuery => expecting Query or QueryRow which:"
+ msg += "\n - matches sql: '" + e.sqlRegex.String() + "'"
+
+ if len(e.args) == 0 {
+ msg += "\n - is without arguments"
+ } else {
+ msg += "\n - is with arguments:\n"
+ for i, arg := range e.args {
+ msg += fmt.Sprintf(" %d - %+v\n", i, arg)
+ }
+ msg = strings.TrimSpace(msg)
+ }
+
+ if e.rows != nil {
+ msg += fmt.Sprintf("\n - %s", e.rows)
+ }
+
+ if e.err != nil {
+ msg += fmt.Sprintf("\n - should return error: %s", e.err)
+ }
+
+ return msg
+}
+
+// ExpectedExec is used to manage *sql.DB.Exec, *sql.Tx.Exec or *sql.Stmt.Exec expectations.
+// Returned by *Sqlmock.ExpectExec.
+type ExpectedExec struct {
+ queryBasedExpectation
+ result driver.Result
+ delay time.Duration
+}
+
+// WithArgs will match given expected args to actual database exec operation arguments.
+// if at least one argument does not match, it will return an error. For specific
+// arguments an sqlmock.Argument interface can be used to match an argument.
+func (e *ExpectedExec) WithArgs(args ...driver.Value) *ExpectedExec {
+ e.args = args
+ return e
+}
+
+// WillReturnError allows to set an error for expected database exec action
+func (e *ExpectedExec) WillReturnError(err error) *ExpectedExec {
+ e.err = err
+ return e
+}
+
+// WillDelayFor allows to specify duration for which it will delay
+// result. May be used together with Context
+func (e *ExpectedExec) WillDelayFor(duration time.Duration) *ExpectedExec {
+ e.delay = duration
+ return e
+}
+
+// String returns string representation
+func (e *ExpectedExec) String() string {
+ msg := "ExpectedExec => expecting Exec which:"
+ msg += "\n - matches sql: '" + e.sqlRegex.String() + "'"
+
+ if len(e.args) == 0 {
+ msg += "\n - is without arguments"
+ } else {
+ msg += "\n - is with arguments:\n"
+ var margs []string
+ for i, arg := range e.args {
+ margs = append(margs, fmt.Sprintf(" %d - %+v", i, arg))
+ }
+ msg += strings.Join(margs, "\n")
+ }
+
+ if e.result != nil {
+ res, _ := e.result.(*result)
+ msg += "\n - should return Result having:"
+ msg += fmt.Sprintf("\n LastInsertId: %d", res.insertID)
+ msg += fmt.Sprintf("\n RowsAffected: %d", res.rowsAffected)
+ if res.err != nil {
+ msg += fmt.Sprintf("\n Error: %s", res.err)
+ }
+ }
+
+ if e.err != nil {
+ msg += fmt.Sprintf("\n - should return error: %s", e.err)
+ }
+
+ return msg
+}
+
+// WillReturnResult arranges for an expected Exec() to return a particular
+// result, there is sqlmock.NewResult(lastInsertID int64, affectedRows int64) method
+// to build a corresponding result. Or if actions needs to be tested against errors
+// sqlmock.NewErrorResult(err error) to return a given error.
+func (e *ExpectedExec) WillReturnResult(result driver.Result) *ExpectedExec {
+ e.result = result
+ return e
+}
+
+// ExpectedPrepare is used to manage *sql.DB.Prepare or *sql.Tx.Prepare expectations.
+// Returned by *Sqlmock.ExpectPrepare.
+type ExpectedPrepare struct {
+ commonExpectation
+ mock *sqlmock
+ sqlRegex *regexp.Regexp
+ statement driver.Stmt
+ closeErr error
+ delay time.Duration
+}
+
+// WillReturnError allows to set an error for the expected *sql.DB.Prepare or *sql.Tx.Prepare action.
+func (e *ExpectedPrepare) WillReturnError(err error) *ExpectedPrepare {
+ e.err = err
+ return e
+}
+
+// WillReturnCloseError allows to set an error for this prapared statement Close action
+func (e *ExpectedPrepare) WillReturnCloseError(err error) *ExpectedPrepare {
+ e.closeErr = err
+ return e
+}
+
+// WillDelayFor allows to specify duration for which it will delay
+// result. May be used together with Context
+func (e *ExpectedPrepare) WillDelayFor(duration time.Duration) *ExpectedPrepare {
+ e.delay = duration
+ return e
+}
+
+// ExpectQuery allows to expect Query() or QueryRow() on this prepared statement.
+// this method is convenient in order to prevent duplicating sql query string matching.
+func (e *ExpectedPrepare) ExpectQuery() *ExpectedQuery {
+ eq := &ExpectedQuery{}
+ eq.sqlRegex = e.sqlRegex
+ e.mock.expected = append(e.mock.expected, eq)
+ return eq
+}
+
+// ExpectExec allows to expect Exec() on this prepared statement.
+// this method is convenient in order to prevent duplicating sql query string matching.
+func (e *ExpectedPrepare) ExpectExec() *ExpectedExec {
+ eq := &ExpectedExec{}
+ eq.sqlRegex = e.sqlRegex
+ e.mock.expected = append(e.mock.expected, eq)
+ return eq
+}
+
+// String returns string representation
+func (e *ExpectedPrepare) String() string {
+ msg := "ExpectedPrepare => expecting Prepare statement which:"
+ msg += "\n - matches sql: '" + e.sqlRegex.String() + "'"
+
+ if e.err != nil {
+ msg += fmt.Sprintf("\n - should return error: %s", e.err)
+ }
+
+ if e.closeErr != nil {
+ msg += fmt.Sprintf("\n - should return error on Close: %s", e.closeErr)
+ }
+
+ return msg
+}
+
+// query based expectation
+// adds a query matching logic
+type queryBasedExpectation struct {
+ commonExpectation
+ sqlRegex *regexp.Regexp
+ args []driver.Value
+}
+
+func (e *queryBasedExpectation) attemptMatch(sql string, args []namedValue) (err error) {
+ if !e.queryMatches(sql) {
+ return fmt.Errorf(`could not match sql: "%s" with expected regexp "%s"`, sql, e.sqlRegex.String())
+ }
+
+ // catch panic
+ defer func() {
+ if e := recover(); e != nil {
+ _, ok := e.(error)
+ if !ok {
+ err = fmt.Errorf(e.(string))
+ }
+ }
+ }()
+
+ err = e.argsMatches(args)
+ return
+}
+
+func (e *queryBasedExpectation) queryMatches(sql string) bool {
+ return e.sqlRegex.MatchString(sql)
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_before_go18.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_before_go18.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_before_go18.go
new file mode 100644
index 0000000..146f240
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_before_go18.go
@@ -0,0 +1,52 @@
+// +build !go1.8
+
+package sqlmock
+
+import (
+ "database/sql/driver"
+ "fmt"
+ "reflect"
+)
+
+// WillReturnRows specifies the set of resulting rows that will be returned
+// by the triggered query
+func (e *ExpectedQuery) WillReturnRows(rows *Rows) *ExpectedQuery {
+ e.rows = &rowSets{sets: []*Rows{rows}}
+ return e
+}
+
+func (e *queryBasedExpectation) argsMatches(args []namedValue) error {
+ if nil == e.args {
+ return nil
+ }
+ if len(args) != len(e.args) {
+ return fmt.Errorf("expected %d, but got %d arguments", len(e.args), len(args))
+ }
+ for k, v := range args {
+ // custom argument matcher
+ matcher, ok := e.args[k].(Argument)
+ if ok {
+ // @TODO: does it make sense to pass value instead of named value?
+ if !matcher.Match(v.Value) {
+ return fmt.Errorf("matcher %T could not match %d argument %T - %+v", matcher, k, args[k], args[k])
+ }
+ continue
+ }
+
+ dval := e.args[k]
+ // convert to driver converter
+ darg, err := driver.DefaultParameterConverter.ConvertValue(dval)
+ if err != nil {
+ return fmt.Errorf("could not convert %d argument %T - %+v to driver value: %s", k, e.args[k], e.args[k], err)
+ }
+
+ if !driver.IsValue(darg) {
+ return fmt.Errorf("argument %d: non-subset type %T returned from Value", k, darg)
+ }
+
+ if !reflect.DeepEqual(darg, v.Value) {
+ return fmt.Errorf("argument %d expected [%T - %+v] does not match actual [%T - %+v]", k, darg, darg, v.Value, v.Value)
+ }
+ }
+ return nil
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18.go
new file mode 100644
index 0000000..2b4b44e
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18.go
@@ -0,0 +1,66 @@
+// +build go1.8
+
+package sqlmock
+
+import (
+ "database/sql"
+ "database/sql/driver"
+ "fmt"
+ "reflect"
+)
+
+// WillReturnRows specifies the set of resulting rows that will be returned
+// by the triggered query
+func (e *ExpectedQuery) WillReturnRows(rows ...*Rows) *ExpectedQuery {
+ sets := make([]*Rows, len(rows))
+ for i, r := range rows {
+ sets[i] = r
+ }
+ e.rows = &rowSets{sets: sets}
+ return e
+}
+
+func (e *queryBasedExpectation) argsMatches(args []namedValue) error {
+ if nil == e.args {
+ return nil
+ }
+ if len(args) != len(e.args) {
+ return fmt.Errorf("expected %d, but got %d arguments", len(e.args), len(args))
+ }
+ // @TODO should we assert either all args are named or ordinal?
+ for k, v := range args {
+ // custom argument matcher
+ matcher, ok := e.args[k].(Argument)
+ if ok {
+ if !matcher.Match(v.Value) {
+ return fmt.Errorf("matcher %T could not match %d argument %T - %+v", matcher, k, args[k], args[k])
+ }
+ continue
+ }
+
+ dval := e.args[k]
+ if named, isNamed := dval.(sql.NamedArg); isNamed {
+ dval = named.Value
+ if v.Name != named.Name {
+ return fmt.Errorf("named argument %d: name: \"%s\" does not match expected: \"%s\"", k, v.Name, named.Name)
+ }
+ } else if k+1 != v.Ordinal {
+ return fmt.Errorf("argument %d: ordinal position: %d does not match expected: %d", k, k+1, v.Ordinal)
+ }
+
+ // convert to driver converter
+ darg, err := driver.DefaultParameterConverter.ConvertValue(dval)
+ if err != nil {
+ return fmt.Errorf("could not convert %d argument %T - %+v to driver value: %s", k, e.args[k], e.args[k], err)
+ }
+
+ if !driver.IsValue(darg) {
+ return fmt.Errorf("argument %d: non-subset type %T returned from Value", k, darg)
+ }
+
+ if !reflect.DeepEqual(darg, v.Value) {
+ return fmt.Errorf("argument %d expected [%T - %+v] does not match actual [%T - %+v]", k, darg, darg, v.Value, v.Value)
+ }
+ }
+ return nil
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18_test.go
new file mode 100644
index 0000000..5f30d2f
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_go18_test.go
@@ -0,0 +1,64 @@
+// +build go1.8
+
+package sqlmock
+
+import (
+ "database/sql"
+ "database/sql/driver"
+ "testing"
+)
+
+func TestQueryExpectationNamedArgComparison(t *testing.T) {
+ e := &queryBasedExpectation{}
+ against := []namedValue{{Value: int64(5), Name: "id"}}
+ if err := e.argsMatches(against); err != nil {
+ t.Errorf("arguments should match, since the no expectation was set, but got err: %s", err)
+ }
+
+ e.args = []driver.Value{
+ sql.Named("id", 5),
+ sql.Named("s", "str"),
+ }
+
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments should not match, since the size is not the same")
+ }
+
+ against = []namedValue{
+ {Value: int64(5), Name: "id"},
+ {Value: "str", Name: "s"},
+ }
+
+ if err := e.argsMatches(against); err != nil {
+ t.Errorf("arguments should have matched, but it did not: %v", err)
+ }
+
+ against = []namedValue{
+ {Value: int64(5), Name: "id"},
+ {Value: "str", Name: "username"},
+ }
+
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments matched, but it should have not due to Name")
+ }
+
+ e.args = []driver.Value{int64(5), "str"}
+
+ against = []namedValue{
+ {Value: int64(5), Ordinal: 0},
+ {Value: "str", Ordinal: 1},
+ }
+
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments matched, but it should have not due to wrong Ordinal position")
+ }
+
+ against = []namedValue{
+ {Value: int64(5), Ordinal: 1},
+ {Value: "str", Ordinal: 2},
+ }
+
+ if err := e.argsMatches(against); err != nil {
+ t.Errorf("arguments should have matched, but it did not: %v", err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_test.go
new file mode 100644
index 0000000..2e3c097
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_test.go
@@ -0,0 +1,154 @@
+package sqlmock
+
+import (
+ "database/sql/driver"
+ "fmt"
+ "regexp"
+ "testing"
+ "time"
+)
+
+func TestQueryExpectationArgComparison(t *testing.T) {
+ e := &queryBasedExpectation{}
+ against := []namedValue{{Value: int64(5), Ordinal: 1}}
+ if err := e.argsMatches(against); err != nil {
+ t.Errorf("arguments should match, since the no expectation was set, but got err: %s", err)
+ }
+
+ e.args = []driver.Value{5, "str"}
+
+ against = []namedValue{{Value: int64(5), Ordinal: 1}}
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments should not match, since the size is not the same")
+ }
+
+ against = []namedValue{
+ {Value: int64(3), Ordinal: 1},
+ {Value: "str", Ordinal: 2},
+ }
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments should not match, since the first argument (int value) is different")
+ }
+
+ against = []namedValue{
+ {Value: int64(5), Ordinal: 1},
+ {Value: "st", Ordinal: 2},
+ }
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments should not match, since the second argument (string value) is different")
+ }
+
+ against = []namedValue{
+ {Value: int64(5), Ordinal: 1},
+ {Value: "str", Ordinal: 2},
+ }
+ if err := e.argsMatches(against); err != nil {
+ t.Errorf("arguments should match, but it did not: %s", err)
+ }
+
+ const longForm = "Jan 2, 2006 at 3:04pm (MST)"
+ tm, _ := time.Parse(longForm, "Feb 3, 2013 at 7:54pm (PST)")
+ e.args = []driver.Value{5, tm}
+
+ against = []namedValue{
+ {Value: int64(5), Ordinal: 1},
+ {Value: tm, Ordinal: 2},
+ }
+ if err := e.argsMatches(against); err != nil {
+ t.Error("arguments should match, but it did not")
+ }
+
+ e.args = []driver.Value{5, AnyArg()}
+ if err := e.argsMatches(against); err != nil {
+ t.Errorf("arguments should match, but it did not: %s", err)
+ }
+}
+
+func TestQueryExpectationArgComparisonBool(t *testing.T) {
+ var e *queryBasedExpectation
+
+ e = &queryBasedExpectation{args: []driver.Value{true}}
+ against := []namedValue{
+ {Value: true, Ordinal: 1},
+ }
+ if err := e.argsMatches(against); err != nil {
+ t.Error("arguments should match, since arguments are the same")
+ }
+
+ e = &queryBasedExpectation{args: []driver.Value{false}}
+ against = []namedValue{
+ {Value: false, Ordinal: 1},
+ }
+ if err := e.argsMatches(against); err != nil {
+ t.Error("arguments should match, since argument are the same")
+ }
+
+ e = &queryBasedExpectation{args: []driver.Value{true}}
+ against = []namedValue{
+ {Value: false, Ordinal: 1},
+ }
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments should not match, since argument is different")
+ }
+
+ e = &queryBasedExpectation{args: []driver.Value{false}}
+ against = []namedValue{
+ {Value: true, Ordinal: 1},
+ }
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments should not match, since argument is different")
+ }
+}
+
+func TestQueryExpectationSqlMatch(t *testing.T) {
+ e := &ExpectedExec{}
+
+ e.sqlRegex = regexp.MustCompile("SELECT x FROM")
+ if !e.queryMatches("SELECT x FROM someting") {
+ t.Errorf("Sql must have matched the query")
+ }
+
+ e.sqlRegex = regexp.MustCompile("SELECT COUNT\\(x\\) FROM")
+ if !e.queryMatches("SELECT COUNT(x) FROM someting") {
+ t.Errorf("Sql must have matched the query")
+ }
+}
+
+func ExampleExpectedExec() {
+ db, mock, _ := New()
+ result := NewErrorResult(fmt.Errorf("some error"))
+ mock.ExpectExec("^INSERT (.+)").WillReturnResult(result)
+ res, _ := db.Exec("INSERT something")
+ _, err := res.LastInsertId()
+ fmt.Println(err)
+ // Output: some error
+}
+
+func TestBuildQuery(t *testing.T) {
+ db, mock, _ := New()
+ query := `
+ SELECT
+ name,
+ email,
+ address,
+ anotherfield
+ FROM user
+ where
+ name = 'John'
+ and
+ address = 'Jakarta'
+
+ `
+
+ mock.ExpectQuery(query)
+ mock.ExpectExec(query)
+ mock.ExpectPrepare(query)
+
+ db.QueryRow(query)
+ db.Exec(query)
+ db.Prepare(query)
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Error(err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result.go
new file mode 100644
index 0000000..a63e72b
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result.go
@@ -0,0 +1,39 @@
+package sqlmock
+
+import (
+ "database/sql/driver"
+)
+
+// Result satisfies sql driver Result, which
+// holds last insert id and rows affected
+// by Exec queries
+type result struct {
+ insertID int64
+ rowsAffected int64
+ err error
+}
+
+// NewResult creates a new sql driver Result
+// for Exec based query mocks.
+func NewResult(lastInsertID int64, rowsAffected int64) driver.Result {
+ return &result{
+ insertID: lastInsertID,
+ rowsAffected: rowsAffected,
+ }
+}
+
+// NewErrorResult creates a new sql driver Result
+// which returns an error given for both interface methods
+func NewErrorResult(err error) driver.Result {
+ return &result{
+ err: err,
+ }
+}
+
+func (r *result) LastInsertId() (int64, error) {
+ return r.insertID, r.err
+}
+
+func (r *result) RowsAffected() (int64, error) {
+ return r.rowsAffected, r.err
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result_test.go
new file mode 100644
index 0000000..08d47c9
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result_test.go
@@ -0,0 +1,62 @@
+package sqlmock
+
+import (
+ "fmt"
+ "testing"
+)
+
+// used for examples
+var mock = &sqlmock{}
+
+func ExampleNewErrorResult() {
+ db, mock, _ := New()
+ result := NewErrorResult(fmt.Errorf("some error"))
+ mock.ExpectExec("^INSERT (.+)").WillReturnResult(result)
+ res, _ := db.Exec("INSERT something")
+ _, err := res.LastInsertId()
+ fmt.Println(err)
+ // Output: some error
+}
+
+func ExampleNewResult() {
+ var lastInsertID, affected int64
+ result := NewResult(lastInsertID, affected)
+ mock.ExpectExec("^INSERT (.+)").WillReturnResult(result)
+ fmt.Println(mock.ExpectationsWereMet())
+ // Output: there is a remaining expectation which was not matched: ExpectedExec => expecting Exec which:
+ // - matches sql: '^INSERT (.+)'
+ // - is without arguments
+ // - should return Result having:
+ // LastInsertId: 0
+ // RowsAffected: 0
+}
+
+func TestShouldReturnValidSqlDriverResult(t *testing.T) {
+ result := NewResult(1, 2)
+ id, err := result.LastInsertId()
+ if 1 != id {
+ t.Errorf("Expected last insert id to be 1, but got: %d", id)
+ }
+ if err != nil {
+ t.Errorf("expected no error, but got: %s", err)
+ }
+ affected, err := result.RowsAffected()
+ if 2 != affected {
+ t.Errorf("Expected affected rows to be 2, but got: %d", affected)
+ }
+ if err != nil {
+ t.Errorf("expected no error, but got: %s", err)
+ }
+}
+
+func TestShouldReturnErroeSqlDriverResult(t *testing.T) {
+ result := NewErrorResult(fmt.Errorf("some error"))
+ _, err := result.LastInsertId()
+ if err == nil {
+ t.Error("expected error, but got none")
+ }
+ _, err = result.RowsAffected()
+ if err == nil {
+ t.Error("expected error, but got none")
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows.go
new file mode 100644
index 0000000..39f9f83
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows.go
@@ -0,0 +1,144 @@
+package sqlmock
+
+import (
+ "database/sql/driver"
+ "encoding/csv"
+ "fmt"
+ "io"
+ "strings"
+)
+
+// CSVColumnParser is a function which converts trimmed csv
+// column string to a []byte representation. currently
+// transforms NULL to nil
+var CSVColumnParser = func(s string) []byte {
+ switch {
+ case strings.ToLower(s) == "null":
+ return nil
+ }
+ return []byte(s)
+}
+
+type rowSets struct {
+ sets []*Rows
+ pos int
+}
+
+func (rs *rowSets) Columns() []string {
+ return rs.sets[rs.pos].cols
+}
+
+func (rs *rowSets) Close() error {
+ return rs.sets[rs.pos].closeErr
+}
+
+// advances to next row
+func (rs *rowSets) Next(dest []driver.Value) error {
+ r := rs.sets[rs.pos]
+ r.pos++
+ if r.pos > len(r.rows) {
+ return io.EOF // per interface spec
+ }
+
+ for i, col := range r.rows[r.pos-1] {
+ dest[i] = col
+ }
+
+ return r.nextErr[r.pos-1]
+}
+
+// transforms to debuggable printable string
+func (rs *rowSets) String() string {
+ msg := "should return rows:\n"
+ if len(rs.sets) == 1 {
+ for n, row := range rs.sets[0].rows {
+ msg += fmt.Sprintf(" row %d - %+v\n", n, row)
+ }
+ return strings.TrimSpace(msg)
+ }
+ for i, set := range rs.sets {
+ msg += fmt.Sprintf(" result set: %d\n", i)
+ for n, row := range set.rows {
+ msg += fmt.Sprintf(" row %d - %+v\n", n, row)
+ }
+ }
+ return strings.TrimSpace(msg)
+}
+
+// Rows is a mocked collection of rows to
+// return for Query result
+type Rows struct {
+ cols []string
+ rows [][]driver.Value
+ pos int
+ nextErr map[int]error
+ closeErr error
+}
+
+// NewRows allows Rows to be created from a
+// sql driver.Value slice or from the CSV string and
+// to be used as sql driver.Rows
+func NewRows(columns []string) *Rows {
+ return &Rows{cols: columns, nextErr: make(map[int]error)}
+}
+
+// CloseError allows to set an error
+// which will be returned by rows.Close
+// function.
+//
+// The close error will be triggered only in cases
+// when rows.Next() EOF was not yet reached, that is
+// a default sql library behavior
+func (r *Rows) CloseError(err error) *Rows {
+ r.closeErr = err
+ return r
+}
+
+// RowError allows to set an error
+// which will be returned when a given
+// row number is read
+func (r *Rows) RowError(row int, err error) *Rows {
+ r.nextErr[row] = err
+ return r
+}
+
+// AddRow composed from database driver.Value slice
+// return the same instance to perform subsequent actions.
+// Note that the number of values must match the number
+// of columns
+func (r *Rows) AddRow(values ...driver.Value) *Rows {
+ if len(values) != len(r.cols) {
+ panic("Expected number of values to match number of columns")
+ }
+
+ row := make([]driver.Value, len(r.cols))
+ for i, v := range values {
+ row[i] = v
+ }
+
+ r.rows = append(r.rows, row)
+ return r
+}
+
+// FromCSVString build rows from csv string.
+// return the same instance to perform subsequent actions.
+// Note that the number of values must match the number
+// of columns
+func (r *Rows) FromCSVString(s string) *Rows {
+ res := strings.NewReader(strings.TrimSpace(s))
+ csvReader := csv.NewReader(res)
+
+ for {
+ res, err := csvReader.Read()
+ if err != nil || res == nil {
+ break
+ }
+
+ row := make([]driver.Value, len(r.cols))
+ for i, v := range res {
+ row[i] = CSVColumnParser(strings.TrimSpace(v))
+ }
+ r.rows = append(r.rows, row)
+ }
+ return r
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18.go
new file mode 100644
index 0000000..4ecf84e
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18.go
@@ -0,0 +1,20 @@
+// +build go1.8
+
+package sqlmock
+
+import "io"
+
+// Implement the "RowsNextResultSet" interface
+func (rs *rowSets) HasNextResultSet() bool {
+ return rs.pos+1 < len(rs.sets)
+}
+
+// Implement the "RowsNextResultSet" interface
+func (rs *rowSets) NextResultSet() error {
+ if !rs.HasNextResultSet() {
+ return io.EOF
+ }
+
+ rs.pos++
+ return nil
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18_test.go
new file mode 100644
index 0000000..297e7c0
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18_test.go
@@ -0,0 +1,92 @@
+// +build go1.8
+
+package sqlmock
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestQueryMultiRows(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs1 := NewRows([]string{"id", "title"}).AddRow(5, "hello world")
+ rs2 := NewRows([]string{"name"}).AddRow("gopher").AddRow("john").AddRow("jane").RowError(2, fmt.Errorf("error"))
+
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = \\?;SELECT name FROM users").
+ WithArgs(5).
+ WillReturnRows(rs1, rs2)
+
+ rows, err := db.Query("SELECT id, title FROM articles WHERE id = ?;SELECT name FROM users", 5)
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+ defer rows.Close()
+
+ if !rows.Next() {
+ t.Error("expected a row to be available in first result set")
+ }
+
+ var id int
+ var name string
+
+ err = rows.Scan(&id, &name)
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if id != 5 || name != "hello world" {
+ t.Errorf("unexpected row values id: %v name: %v", id, name)
+ }
+
+ if rows.Next() {
+ t.Error("was not expecting next row in first result set")
+ }
+
+ if !rows.NextResultSet() {
+ t.Error("had to have next result set")
+ }
+
+ if !rows.Next() {
+ t.Error("expected a row to be available in second result set")
+ }
+
+ err = rows.Scan(&name)
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if name != "gopher" {
+ t.Errorf("unexpected row name: %v", name)
+ }
+
+ if !rows.Next() {
+ t.Error("expected a row to be available in second result set")
+ }
+
+ err = rows.Scan(&name)
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if name != "john" {
+ t.Errorf("unexpected row name: %v", name)
+ }
+
+ if rows.Next() {
+ t.Error("expected next row to produce error")
+ }
+
+ if rows.Err() == nil {
+ t.Error("expected an error, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f9f7cfa0/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_test.go
new file mode 100644
index 0000000..56e834e
--- /dev/null
+++ b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_test.go
@@ -0,0 +1,265 @@
+package sqlmock
+
+import (
+ "database/sql"
+ "fmt"
+ "testing"
+)
+
+func ExampleRows() {
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("failed to open sqlmock database:", err)
+ }
+ defer db.Close()
+
+ rows := NewRows([]string{"id", "title"}).
+ AddRow(1, "one").
+ AddRow(2, "two")
+
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ rs, _ := db.Query("SELECT")
+ defer rs.Close()
+
+ for rs.Next() {
+ var id int
+ var title string
+ rs.Scan(&id, &title)
+ fmt.Println("scanned id:", id, "and title:", title)
+ }
+
+ if rs.Err() != nil {
+ fmt.Println("got rows error:", rs.Err())
+ }
+ // Output: scanned id: 1 and title: one
+ // scanned id: 2 and title: two
+}
+
+func ExampleRows_rowError() {
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("failed to open sqlmock database:", err)
+ }
+ defer db.Close()
+
+ rows := NewRows([]string{"id", "title"}).
+ AddRow(0, "one").
+ AddRow(1, "two").
+ RowError(1, fmt.Errorf("row error"))
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ rs, _ := db.Query("SELECT")
+ defer rs.Close()
+
+ for rs.Next() {
+ var id int
+ var title string
+ rs.Scan(&id, &title)
+ fmt.Println("scanned id:", id, "and title:", title)
+ }
+
+ if rs.Err() != nil {
+ fmt.Println("got rows error:", rs.Err())
+ }
+ // Output: scanned id: 0 and title: one
+ // got rows error: row error
+}
+
+func ExampleRows_closeError() {
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("failed to open sqlmock database:", err)
+ }
+ defer db.Close()
+
+ rows := NewRows([]string{"id", "title"}).CloseError(fmt.Errorf("close error"))
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ rs, _ := db.Query("SELECT")
+
+ // Note: that close will return error only before rows EOF
+ // that is a default sql package behavior. If you run rs.Next()
+ // it will handle the error internally and return nil bellow
+ if err := rs.Close(); err != nil {
+ fmt.Println("got error:", err)
+ }
+
+ // Output: got error: close error
+}
+
+func TestAllowsToSetRowsErrors(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rows := NewRows([]string{"id", "title"}).
+ AddRow(0, "one").
+ AddRow(1, "two").
+ RowError(1, fmt.Errorf("error"))
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ rs, err := db.Query("SELECT")
+ if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ defer rs.Close()
+
+ if !rs.Next() {
+ t.Fatal("expected the first row to be available")
+ }
+ if rs.Err() != nil {
+ t.Fatalf("unexpected error: %s", rs.Err())
+ }
+
+ if rs.Next() {
+ t.Fatal("was not expecting the second row, since there should be an error")
+ }
+ if rs.Err() == nil {
+ t.Fatal("expected an error, but got none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestRowsCloseError(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rows := NewRows([]string{"id"}).CloseError(fmt.Errorf("close error"))
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ rs, err := db.Query("SELECT")
+ if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+
+ if err := rs.Close(); err == nil {
+ t.Fatal("expected a close error")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestQuerySingleRow(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rows := NewRows([]string{"id"}).
+ AddRow(1).
+ AddRow(2)
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ var id int
+ if err := db.QueryRow("SELECT").Scan(&id); err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+
+ mock.ExpectQuery("SELECT").WillReturnRows(NewRows([]string{"id"}))
+ if err := db.QueryRow("SELECT").Scan(&id); err != sql.ErrNoRows {
+ t.Fatal("expected sql no rows error")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestRowsScanError(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ r := NewRows([]string{"col1", "col2"}).AddRow("one", "two").AddRow("one", nil)
+ mock.ExpectQuery("SELECT").WillReturnRows(r)
+
+ rs, err := db.Query("SELECT")
+ if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ defer rs.Close()
+
+ var one, two string
+ if !rs.Next() || rs.Err() != nil || rs.Scan(&one, &two) != nil {
+ t.Fatal("unexpected error on first row scan")
+ }
+
+ if !rs.Next() || rs.Err() != nil {
+ t.Fatal("unexpected error on second row read")
+ }
+
+ err = rs.Scan(&one, &two)
+ if err == nil {
+ t.Fatal("expected an error for scan, but got none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestCSVRowParser(t *testing.T) {
+ t.Parallel()
+ rs := NewRows([]string{"col1", "col2"}).FromCSVString("a,NULL")
+ db, mock, err := New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectQuery("SELECT").WillReturnRows(rs)
+
+ rw, err := db.Query("SELECT")
+ if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ defer rw.Close()
+ var col1 string
+ var col2 []byte
+
+ rw.Next()
+ if err = rw.Scan(&col1, &col2); err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ if col1 != "a" {
+ t.Fatalf("expected col1 to be 'a', but got [%T]:%+v", col1, col1)
+ }
+ if col2 != nil {
+ t.Fatalf("expected col2 to be nil, but got [%T]:%+v", col2, col2)
+ }
+}
+
+func TestWrongNumberOfValues(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ defer db.Close()
+ defer func() {
+ recover()
+ }()
+ mock.ExpectQuery("SELECT ID FROM TABLE").WithArgs(101).WillReturnRows(NewRows([]string{"ID"}).AddRow(101, "Hello"))
+ db.Query("SELECT ID FROM TABLE", 101)
+ // shouldn't reach here
+ t.Error("expected panic from query")
+}
[15/43] incubator-trafficcontrol git commit: Add TO Golang
configurable logging
Posted by de...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_test.go
new file mode 100644
index 0000000..2e3c097
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/expectations_test.go
@@ -0,0 +1,154 @@
+package sqlmock
+
+import (
+ "database/sql/driver"
+ "fmt"
+ "regexp"
+ "testing"
+ "time"
+)
+
+func TestQueryExpectationArgComparison(t *testing.T) {
+ e := &queryBasedExpectation{}
+ against := []namedValue{{Value: int64(5), Ordinal: 1}}
+ if err := e.argsMatches(against); err != nil {
+ t.Errorf("arguments should match, since the no expectation was set, but got err: %s", err)
+ }
+
+ e.args = []driver.Value{5, "str"}
+
+ against = []namedValue{{Value: int64(5), Ordinal: 1}}
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments should not match, since the size is not the same")
+ }
+
+ against = []namedValue{
+ {Value: int64(3), Ordinal: 1},
+ {Value: "str", Ordinal: 2},
+ }
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments should not match, since the first argument (int value) is different")
+ }
+
+ against = []namedValue{
+ {Value: int64(5), Ordinal: 1},
+ {Value: "st", Ordinal: 2},
+ }
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments should not match, since the second argument (string value) is different")
+ }
+
+ against = []namedValue{
+ {Value: int64(5), Ordinal: 1},
+ {Value: "str", Ordinal: 2},
+ }
+ if err := e.argsMatches(against); err != nil {
+ t.Errorf("arguments should match, but it did not: %s", err)
+ }
+
+ const longForm = "Jan 2, 2006 at 3:04pm (MST)"
+ tm, _ := time.Parse(longForm, "Feb 3, 2013 at 7:54pm (PST)")
+ e.args = []driver.Value{5, tm}
+
+ against = []namedValue{
+ {Value: int64(5), Ordinal: 1},
+ {Value: tm, Ordinal: 2},
+ }
+ if err := e.argsMatches(against); err != nil {
+ t.Error("arguments should match, but it did not")
+ }
+
+ e.args = []driver.Value{5, AnyArg()}
+ if err := e.argsMatches(against); err != nil {
+ t.Errorf("arguments should match, but it did not: %s", err)
+ }
+}
+
+func TestQueryExpectationArgComparisonBool(t *testing.T) {
+ var e *queryBasedExpectation
+
+ e = &queryBasedExpectation{args: []driver.Value{true}}
+ against := []namedValue{
+ {Value: true, Ordinal: 1},
+ }
+ if err := e.argsMatches(against); err != nil {
+ t.Error("arguments should match, since arguments are the same")
+ }
+
+ e = &queryBasedExpectation{args: []driver.Value{false}}
+ against = []namedValue{
+ {Value: false, Ordinal: 1},
+ }
+ if err := e.argsMatches(against); err != nil {
+ t.Error("arguments should match, since argument are the same")
+ }
+
+ e = &queryBasedExpectation{args: []driver.Value{true}}
+ against = []namedValue{
+ {Value: false, Ordinal: 1},
+ }
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments should not match, since argument is different")
+ }
+
+ e = &queryBasedExpectation{args: []driver.Value{false}}
+ against = []namedValue{
+ {Value: true, Ordinal: 1},
+ }
+ if err := e.argsMatches(against); err == nil {
+ t.Error("arguments should not match, since argument is different")
+ }
+}
+
+func TestQueryExpectationSqlMatch(t *testing.T) {
+ e := &ExpectedExec{}
+
+ e.sqlRegex = regexp.MustCompile("SELECT x FROM")
+ if !e.queryMatches("SELECT x FROM someting") {
+ t.Errorf("Sql must have matched the query")
+ }
+
+ e.sqlRegex = regexp.MustCompile("SELECT COUNT\\(x\\) FROM")
+ if !e.queryMatches("SELECT COUNT(x) FROM someting") {
+ t.Errorf("Sql must have matched the query")
+ }
+}
+
+func ExampleExpectedExec() {
+ db, mock, _ := New()
+ result := NewErrorResult(fmt.Errorf("some error"))
+ mock.ExpectExec("^INSERT (.+)").WillReturnResult(result)
+ res, _ := db.Exec("INSERT something")
+ _, err := res.LastInsertId()
+ fmt.Println(err)
+ // Output: some error
+}
+
+func TestBuildQuery(t *testing.T) {
+ db, mock, _ := New()
+ query := `
+ SELECT
+ name,
+ email,
+ address,
+ anotherfield
+ FROM user
+ where
+ name = 'John'
+ and
+ address = 'Jakarta'
+
+ `
+
+ mock.ExpectQuery(query)
+ mock.ExpectExec(query)
+ mock.ExpectPrepare(query)
+
+ db.QueryRow(query)
+ db.Exec(query)
+ db.Prepare(query)
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Error(err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result.go
new file mode 100644
index 0000000..a63e72b
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result.go
@@ -0,0 +1,39 @@
+package sqlmock
+
+import (
+ "database/sql/driver"
+)
+
+// Result satisfies sql driver Result, which
+// holds last insert id and rows affected
+// by Exec queries
+type result struct {
+ insertID int64
+ rowsAffected int64
+ err error
+}
+
+// NewResult creates a new sql driver Result
+// for Exec based query mocks.
+func NewResult(lastInsertID int64, rowsAffected int64) driver.Result {
+ return &result{
+ insertID: lastInsertID,
+ rowsAffected: rowsAffected,
+ }
+}
+
+// NewErrorResult creates a new sql driver Result
+// which returns an error given for both interface methods
+func NewErrorResult(err error) driver.Result {
+ return &result{
+ err: err,
+ }
+}
+
+func (r *result) LastInsertId() (int64, error) {
+ return r.insertID, r.err
+}
+
+func (r *result) RowsAffected() (int64, error) {
+ return r.rowsAffected, r.err
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result_test.go
new file mode 100644
index 0000000..08d47c9
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/result_test.go
@@ -0,0 +1,62 @@
+package sqlmock
+
+import (
+ "fmt"
+ "testing"
+)
+
+// used for examples
+var mock = &sqlmock{}
+
+func ExampleNewErrorResult() {
+ db, mock, _ := New()
+ result := NewErrorResult(fmt.Errorf("some error"))
+ mock.ExpectExec("^INSERT (.+)").WillReturnResult(result)
+ res, _ := db.Exec("INSERT something")
+ _, err := res.LastInsertId()
+ fmt.Println(err)
+ // Output: some error
+}
+
+func ExampleNewResult() {
+ var lastInsertID, affected int64
+ result := NewResult(lastInsertID, affected)
+ mock.ExpectExec("^INSERT (.+)").WillReturnResult(result)
+ fmt.Println(mock.ExpectationsWereMet())
+ // Output: there is a remaining expectation which was not matched: ExpectedExec => expecting Exec which:
+ // - matches sql: '^INSERT (.+)'
+ // - is without arguments
+ // - should return Result having:
+ // LastInsertId: 0
+ // RowsAffected: 0
+}
+
+func TestShouldReturnValidSqlDriverResult(t *testing.T) {
+ result := NewResult(1, 2)
+ id, err := result.LastInsertId()
+ if 1 != id {
+ t.Errorf("Expected last insert id to be 1, but got: %d", id)
+ }
+ if err != nil {
+ t.Errorf("expected no error, but got: %s", err)
+ }
+ affected, err := result.RowsAffected()
+ if 2 != affected {
+ t.Errorf("Expected affected rows to be 2, but got: %d", affected)
+ }
+ if err != nil {
+ t.Errorf("expected no error, but got: %s", err)
+ }
+}
+
+func TestShouldReturnErroeSqlDriverResult(t *testing.T) {
+ result := NewErrorResult(fmt.Errorf("some error"))
+ _, err := result.LastInsertId()
+ if err == nil {
+ t.Error("expected error, but got none")
+ }
+ _, err = result.RowsAffected()
+ if err == nil {
+ t.Error("expected error, but got none")
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows.go
new file mode 100644
index 0000000..39f9f83
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows.go
@@ -0,0 +1,144 @@
+package sqlmock
+
+import (
+ "database/sql/driver"
+ "encoding/csv"
+ "fmt"
+ "io"
+ "strings"
+)
+
+// CSVColumnParser is a function which converts trimmed csv
+// column string to a []byte representation. currently
+// transforms NULL to nil
+var CSVColumnParser = func(s string) []byte {
+ switch {
+ case strings.ToLower(s) == "null":
+ return nil
+ }
+ return []byte(s)
+}
+
+type rowSets struct {
+ sets []*Rows
+ pos int
+}
+
+func (rs *rowSets) Columns() []string {
+ return rs.sets[rs.pos].cols
+}
+
+func (rs *rowSets) Close() error {
+ return rs.sets[rs.pos].closeErr
+}
+
+// advances to next row
+func (rs *rowSets) Next(dest []driver.Value) error {
+ r := rs.sets[rs.pos]
+ r.pos++
+ if r.pos > len(r.rows) {
+ return io.EOF // per interface spec
+ }
+
+ for i, col := range r.rows[r.pos-1] {
+ dest[i] = col
+ }
+
+ return r.nextErr[r.pos-1]
+}
+
+// transforms to debuggable printable string
+func (rs *rowSets) String() string {
+ msg := "should return rows:\n"
+ if len(rs.sets) == 1 {
+ for n, row := range rs.sets[0].rows {
+ msg += fmt.Sprintf(" row %d - %+v\n", n, row)
+ }
+ return strings.TrimSpace(msg)
+ }
+ for i, set := range rs.sets {
+ msg += fmt.Sprintf(" result set: %d\n", i)
+ for n, row := range set.rows {
+ msg += fmt.Sprintf(" row %d - %+v\n", n, row)
+ }
+ }
+ return strings.TrimSpace(msg)
+}
+
+// Rows is a mocked collection of rows to
+// return for Query result
+type Rows struct {
+ cols []string
+ rows [][]driver.Value
+ pos int
+ nextErr map[int]error
+ closeErr error
+}
+
+// NewRows allows Rows to be created from a
+// sql driver.Value slice or from the CSV string and
+// to be used as sql driver.Rows
+func NewRows(columns []string) *Rows {
+ return &Rows{cols: columns, nextErr: make(map[int]error)}
+}
+
+// CloseError allows to set an error
+// which will be returned by rows.Close
+// function.
+//
+// The close error will be triggered only in cases
+// when rows.Next() EOF was not yet reached, that is
+// a default sql library behavior
+func (r *Rows) CloseError(err error) *Rows {
+ r.closeErr = err
+ return r
+}
+
+// RowError allows to set an error
+// which will be returned when a given
+// row number is read
+func (r *Rows) RowError(row int, err error) *Rows {
+ r.nextErr[row] = err
+ return r
+}
+
+// AddRow composed from database driver.Value slice
+// return the same instance to perform subsequent actions.
+// Note that the number of values must match the number
+// of columns
+func (r *Rows) AddRow(values ...driver.Value) *Rows {
+ if len(values) != len(r.cols) {
+ panic("Expected number of values to match number of columns")
+ }
+
+ row := make([]driver.Value, len(r.cols))
+ for i, v := range values {
+ row[i] = v
+ }
+
+ r.rows = append(r.rows, row)
+ return r
+}
+
+// FromCSVString build rows from csv string.
+// return the same instance to perform subsequent actions.
+// Note that the number of values must match the number
+// of columns
+func (r *Rows) FromCSVString(s string) *Rows {
+ res := strings.NewReader(strings.TrimSpace(s))
+ csvReader := csv.NewReader(res)
+
+ for {
+ res, err := csvReader.Read()
+ if err != nil || res == nil {
+ break
+ }
+
+ row := make([]driver.Value, len(r.cols))
+ for i, v := range res {
+ row[i] = CSVColumnParser(strings.TrimSpace(v))
+ }
+ r.rows = append(r.rows, row)
+ }
+ return r
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18.go
new file mode 100644
index 0000000..4ecf84e
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18.go
@@ -0,0 +1,20 @@
+// +build go1.8
+
+package sqlmock
+
+import "io"
+
+// Implement the "RowsNextResultSet" interface
+func (rs *rowSets) HasNextResultSet() bool {
+ return rs.pos+1 < len(rs.sets)
+}
+
+// Implement the "RowsNextResultSet" interface
+func (rs *rowSets) NextResultSet() error {
+ if !rs.HasNextResultSet() {
+ return io.EOF
+ }
+
+ rs.pos++
+ return nil
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18_test.go
new file mode 100644
index 0000000..297e7c0
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_go18_test.go
@@ -0,0 +1,92 @@
+// +build go1.8
+
+package sqlmock
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestQueryMultiRows(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs1 := NewRows([]string{"id", "title"}).AddRow(5, "hello world")
+ rs2 := NewRows([]string{"name"}).AddRow("gopher").AddRow("john").AddRow("jane").RowError(2, fmt.Errorf("error"))
+
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = \\?;SELECT name FROM users").
+ WithArgs(5).
+ WillReturnRows(rs1, rs2)
+
+ rows, err := db.Query("SELECT id, title FROM articles WHERE id = ?;SELECT name FROM users", 5)
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+ defer rows.Close()
+
+ if !rows.Next() {
+ t.Error("expected a row to be available in first result set")
+ }
+
+ var id int
+ var name string
+
+ err = rows.Scan(&id, &name)
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if id != 5 || name != "hello world" {
+ t.Errorf("unexpected row values id: %v name: %v", id, name)
+ }
+
+ if rows.Next() {
+ t.Error("was not expecting next row in first result set")
+ }
+
+ if !rows.NextResultSet() {
+ t.Error("had to have next result set")
+ }
+
+ if !rows.Next() {
+ t.Error("expected a row to be available in second result set")
+ }
+
+ err = rows.Scan(&name)
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if name != "gopher" {
+ t.Errorf("unexpected row name: %v", name)
+ }
+
+ if !rows.Next() {
+ t.Error("expected a row to be available in second result set")
+ }
+
+ err = rows.Scan(&name)
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if name != "john" {
+ t.Errorf("unexpected row name: %v", name)
+ }
+
+ if rows.Next() {
+ t.Error("expected next row to produce error")
+ }
+
+ if rows.Err() == nil {
+ t.Error("expected an error, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_test.go
new file mode 100644
index 0000000..56e834e
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_test.go
@@ -0,0 +1,265 @@
+package sqlmock
+
+import (
+ "database/sql"
+ "fmt"
+ "testing"
+)
+
+func ExampleRows() {
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("failed to open sqlmock database:", err)
+ }
+ defer db.Close()
+
+ rows := NewRows([]string{"id", "title"}).
+ AddRow(1, "one").
+ AddRow(2, "two")
+
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ rs, _ := db.Query("SELECT")
+ defer rs.Close()
+
+ for rs.Next() {
+ var id int
+ var title string
+ rs.Scan(&id, &title)
+ fmt.Println("scanned id:", id, "and title:", title)
+ }
+
+ if rs.Err() != nil {
+ fmt.Println("got rows error:", rs.Err())
+ }
+ // Output: scanned id: 1 and title: one
+ // scanned id: 2 and title: two
+}
+
+func ExampleRows_rowError() {
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("failed to open sqlmock database:", err)
+ }
+ defer db.Close()
+
+ rows := NewRows([]string{"id", "title"}).
+ AddRow(0, "one").
+ AddRow(1, "two").
+ RowError(1, fmt.Errorf("row error"))
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ rs, _ := db.Query("SELECT")
+ defer rs.Close()
+
+ for rs.Next() {
+ var id int
+ var title string
+ rs.Scan(&id, &title)
+ fmt.Println("scanned id:", id, "and title:", title)
+ }
+
+ if rs.Err() != nil {
+ fmt.Println("got rows error:", rs.Err())
+ }
+ // Output: scanned id: 0 and title: one
+ // got rows error: row error
+}
+
+func ExampleRows_closeError() {
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("failed to open sqlmock database:", err)
+ }
+ defer db.Close()
+
+ rows := NewRows([]string{"id", "title"}).CloseError(fmt.Errorf("close error"))
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ rs, _ := db.Query("SELECT")
+
+ // Note: that close will return error only before rows EOF
+ // that is a default sql package behavior. If you run rs.Next()
+ // it will handle the error internally and return nil bellow
+ if err := rs.Close(); err != nil {
+ fmt.Println("got error:", err)
+ }
+
+ // Output: got error: close error
+}
+
+func TestAllowsToSetRowsErrors(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rows := NewRows([]string{"id", "title"}).
+ AddRow(0, "one").
+ AddRow(1, "two").
+ RowError(1, fmt.Errorf("error"))
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ rs, err := db.Query("SELECT")
+ if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ defer rs.Close()
+
+ if !rs.Next() {
+ t.Fatal("expected the first row to be available")
+ }
+ if rs.Err() != nil {
+ t.Fatalf("unexpected error: %s", rs.Err())
+ }
+
+ if rs.Next() {
+ t.Fatal("was not expecting the second row, since there should be an error")
+ }
+ if rs.Err() == nil {
+ t.Fatal("expected an error, but got none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestRowsCloseError(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rows := NewRows([]string{"id"}).CloseError(fmt.Errorf("close error"))
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ rs, err := db.Query("SELECT")
+ if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+
+ if err := rs.Close(); err == nil {
+ t.Fatal("expected a close error")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestQuerySingleRow(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rows := NewRows([]string{"id"}).
+ AddRow(1).
+ AddRow(2)
+ mock.ExpectQuery("SELECT").WillReturnRows(rows)
+
+ var id int
+ if err := db.QueryRow("SELECT").Scan(&id); err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+
+ mock.ExpectQuery("SELECT").WillReturnRows(NewRows([]string{"id"}))
+ if err := db.QueryRow("SELECT").Scan(&id); err != sql.ErrNoRows {
+ t.Fatal("expected sql no rows error")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestRowsScanError(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ r := NewRows([]string{"col1", "col2"}).AddRow("one", "two").AddRow("one", nil)
+ mock.ExpectQuery("SELECT").WillReturnRows(r)
+
+ rs, err := db.Query("SELECT")
+ if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ defer rs.Close()
+
+ var one, two string
+ if !rs.Next() || rs.Err() != nil || rs.Scan(&one, &two) != nil {
+ t.Fatal("unexpected error on first row scan")
+ }
+
+ if !rs.Next() || rs.Err() != nil {
+ t.Fatal("unexpected error on second row read")
+ }
+
+ err = rs.Scan(&one, &two)
+ if err == nil {
+ t.Fatal("expected an error for scan, but got none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestCSVRowParser(t *testing.T) {
+ t.Parallel()
+ rs := NewRows([]string{"col1", "col2"}).FromCSVString("a,NULL")
+ db, mock, err := New()
+ if err != nil {
+ t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectQuery("SELECT").WillReturnRows(rs)
+
+ rw, err := db.Query("SELECT")
+ if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ defer rw.Close()
+ var col1 string
+ var col2 []byte
+
+ rw.Next()
+ if err = rw.Scan(&col1, &col2); err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ if col1 != "a" {
+ t.Fatalf("expected col1 to be 'a', but got [%T]:%+v", col1, col1)
+ }
+ if col2 != nil {
+ t.Fatalf("expected col2 to be nil, but got [%T]:%+v", col2, col2)
+ }
+}
+
+func TestWrongNumberOfValues(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ defer db.Close()
+ defer func() {
+ recover()
+ }()
+ mock.ExpectQuery("SELECT ID FROM TABLE").WithArgs(101).WillReturnRows(NewRows([]string{"ID"}).AddRow(101, "Hello"))
+ db.Query("SELECT ID FROM TABLE", 101)
+ // shouldn't reach here
+ t.Error("expected panic from query")
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock.go
new file mode 100644
index 0000000..b906a3f
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock.go
@@ -0,0 +1,525 @@
+/*
+Package sqlmock is a mock library implementing sql driver. Which has one and only
+purpose - to simulate any sql driver behavior in tests, without needing a real
+database connection. It helps to maintain correct **TDD** workflow.
+
+It does not require any modifications to your source code in order to test
+and mock database operations. Supports concurrency and multiple database mocking.
+
+The driver allows to mock any sql driver method behavior.
+*/
+package sqlmock
+
+import (
+ "database/sql"
+ "database/sql/driver"
+ "fmt"
+ "regexp"
+ "time"
+)
+
+// Sqlmock interface serves to create expectations
+// for any kind of database action in order to mock
+// and test real database behavior.
+type Sqlmock interface {
+
+ // ExpectClose queues an expectation for this database
+ // action to be triggered. the *ExpectedClose allows
+ // to mock database response
+ ExpectClose() *ExpectedClose
+
+ // ExpectationsWereMet checks whether all queued expectations
+ // were met in order. If any of them was not met - an error is returned.
+ ExpectationsWereMet() error
+
+ // ExpectPrepare expects Prepare() to be called with sql query
+ // which match sqlRegexStr given regexp.
+ // the *ExpectedPrepare allows to mock database response.
+ // Note that you may expect Query() or Exec() on the *ExpectedPrepare
+ // statement to prevent repeating sqlRegexStr
+ ExpectPrepare(sqlRegexStr string) *ExpectedPrepare
+
+ // ExpectQuery expects Query() or QueryRow() to be called with sql query
+ // which match sqlRegexStr given regexp.
+ // the *ExpectedQuery allows to mock database response.
+ ExpectQuery(sqlRegexStr string) *ExpectedQuery
+
+ // ExpectExec expects Exec() to be called with sql query
+ // which match sqlRegexStr given regexp.
+ // the *ExpectedExec allows to mock database response
+ ExpectExec(sqlRegexStr string) *ExpectedExec
+
+ // ExpectBegin expects *sql.DB.Begin to be called.
+ // the *ExpectedBegin allows to mock database response
+ ExpectBegin() *ExpectedBegin
+
+ // ExpectCommit expects *sql.Tx.Commit to be called.
+ // the *ExpectedCommit allows to mock database response
+ ExpectCommit() *ExpectedCommit
+
+ // ExpectRollback expects *sql.Tx.Rollback to be called.
+ // the *ExpectedRollback allows to mock database response
+ ExpectRollback() *ExpectedRollback
+
+ // MatchExpectationsInOrder gives an option whether to match all
+ // expectations in the order they were set or not.
+ //
+ // By default it is set to - true. But if you use goroutines
+ // to parallelize your query executation, that option may
+ // be handy.
+ //
+ // This option may be turned on anytime during tests. As soon
+ // as it is switched to false, expectations will be matched
+ // in any order. Or otherwise if switched to true, any unmatched
+ // expectations will be expected in order
+ MatchExpectationsInOrder(bool)
+}
+
+type sqlmock struct {
+ ordered bool
+ dsn string
+ opened int
+ drv *mockDriver
+
+ expected []expectation
+}
+
+func (c *sqlmock) open() (*sql.DB, Sqlmock, error) {
+ db, err := sql.Open("sqlmock", c.dsn)
+ if err != nil {
+ return db, c, err
+ }
+ return db, c, db.Ping()
+}
+
+func (c *sqlmock) ExpectClose() *ExpectedClose {
+ e := &ExpectedClose{}
+ c.expected = append(c.expected, e)
+ return e
+}
+
+func (c *sqlmock) MatchExpectationsInOrder(b bool) {
+ c.ordered = b
+}
+
+// Close a mock database driver connection. It may or may not
+// be called depending on the sircumstances, but if it is called
+// there must be an *ExpectedClose expectation satisfied.
+// meets http://golang.org/pkg/database/sql/driver/#Conn interface
+func (c *sqlmock) Close() error {
+ c.drv.Lock()
+ defer c.drv.Unlock()
+
+ c.opened--
+ if c.opened == 0 {
+ delete(c.drv.conns, c.dsn)
+ }
+
+ var expected *ExpectedClose
+ var fulfilled int
+ var ok bool
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if expected, ok = next.(*ExpectedClose); ok {
+ break
+ }
+
+ next.Unlock()
+ if c.ordered {
+ return fmt.Errorf("call to database Close, was not expected, next expectation is: %s", next)
+ }
+ }
+
+ if expected == nil {
+ msg := "call to database Close was not expected"
+ if fulfilled == len(c.expected) {
+ msg = "all expectations were already fulfilled, " + msg
+ }
+ return fmt.Errorf(msg)
+ }
+
+ expected.triggered = true
+ expected.Unlock()
+ return expected.err
+}
+
+func (c *sqlmock) ExpectationsWereMet() error {
+ for _, e := range c.expected {
+ if !e.fulfilled() {
+ return fmt.Errorf("there is a remaining expectation which was not matched: %s", e)
+ }
+ }
+ return nil
+}
+
+// Begin meets http://golang.org/pkg/database/sql/driver/#Conn interface
+func (c *sqlmock) Begin() (driver.Tx, error) {
+ ex, err := c.begin()
+ if err != nil {
+ return nil, err
+ }
+
+ time.Sleep(ex.delay)
+ return c, nil
+}
+
+func (c *sqlmock) begin() (*ExpectedBegin, error) {
+ var expected *ExpectedBegin
+ var ok bool
+ var fulfilled int
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if expected, ok = next.(*ExpectedBegin); ok {
+ break
+ }
+
+ next.Unlock()
+ if c.ordered {
+ return nil, fmt.Errorf("call to database transaction Begin, was not expected, next expectation is: %s", next)
+ }
+ }
+ if expected == nil {
+ msg := "call to database transaction Begin was not expected"
+ if fulfilled == len(c.expected) {
+ msg = "all expectations were already fulfilled, " + msg
+ }
+ return nil, fmt.Errorf(msg)
+ }
+
+ expected.triggered = true
+ expected.Unlock()
+
+ return expected, expected.err
+}
+
+func (c *sqlmock) ExpectBegin() *ExpectedBegin {
+ e := &ExpectedBegin{}
+ c.expected = append(c.expected, e)
+ return e
+}
+
+// Exec meets http://golang.org/pkg/database/sql/driver/#Execer
+func (c *sqlmock) Exec(query string, args []driver.Value) (driver.Result, error) {
+ namedArgs := make([]namedValue, len(args))
+ for i, v := range args {
+ namedArgs[i] = namedValue{
+ Ordinal: i + 1,
+ Value: v,
+ }
+ }
+
+ ex, err := c.exec(query, namedArgs)
+ if err != nil {
+ return nil, err
+ }
+
+ time.Sleep(ex.delay)
+ return ex.result, nil
+}
+
+func (c *sqlmock) exec(query string, args []namedValue) (*ExpectedExec, error) {
+ query = stripQuery(query)
+ var expected *ExpectedExec
+ var fulfilled int
+ var ok bool
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if c.ordered {
+ if expected, ok = next.(*ExpectedExec); ok {
+ break
+ }
+ next.Unlock()
+ return nil, fmt.Errorf("call to exec query '%s' with args %+v, was not expected, next expectation is: %s", query, args, next)
+ }
+ if exec, ok := next.(*ExpectedExec); ok {
+ if err := exec.attemptMatch(query, args); err == nil {
+ expected = exec
+ break
+ }
+ }
+ next.Unlock()
+ }
+ if expected == nil {
+ msg := "call to exec '%s' query with args %+v was not expected"
+ if fulfilled == len(c.expected) {
+ msg = "all expectations were already fulfilled, " + msg
+ }
+ return nil, fmt.Errorf(msg, query, args)
+ }
+ defer expected.Unlock()
+
+ if !expected.queryMatches(query) {
+ return nil, fmt.Errorf("exec query '%s', does not match regex '%s'", query, expected.sqlRegex.String())
+ }
+
+ if err := expected.argsMatches(args); err != nil {
+ return nil, fmt.Errorf("exec query '%s', arguments do not match: %s", query, err)
+ }
+
+ expected.triggered = true
+ if expected.err != nil {
+ return nil, expected.err // mocked to return error
+ }
+
+ if expected.result == nil {
+ return nil, fmt.Errorf("exec query '%s' with args %+v, must return a database/sql/driver.result, but it was not set for expectation %T as %+v", query, args, expected, expected)
+ }
+
+ return expected, nil
+}
+
+func (c *sqlmock) ExpectExec(sqlRegexStr string) *ExpectedExec {
+ e := &ExpectedExec{}
+ sqlRegexStr = stripQuery(sqlRegexStr)
+ e.sqlRegex = regexp.MustCompile(sqlRegexStr)
+ c.expected = append(c.expected, e)
+ return e
+}
+
+// Prepare meets http://golang.org/pkg/database/sql/driver/#Conn interface
+func (c *sqlmock) Prepare(query string) (driver.Stmt, error) {
+ ex, err := c.prepare(query)
+ if err != nil {
+ return nil, err
+ }
+
+ time.Sleep(ex.delay)
+ return &statement{c, query, ex.closeErr}, nil
+}
+
+func (c *sqlmock) prepare(query string) (*ExpectedPrepare, error) {
+ var expected *ExpectedPrepare
+ var fulfilled int
+ var ok bool
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if expected, ok = next.(*ExpectedPrepare); ok {
+ break
+ }
+
+ next.Unlock()
+ if c.ordered {
+ return nil, fmt.Errorf("call to Prepare statement with query '%s', was not expected, next expectation is: %s", query, next)
+ }
+ }
+
+ query = stripQuery(query)
+ if expected == nil {
+ msg := "call to Prepare '%s' query was not expected"
+ if fulfilled == len(c.expected) {
+ msg = "all expectations were already fulfilled, " + msg
+ }
+ return nil, fmt.Errorf(msg, query)
+ }
+ defer expected.Unlock()
+ if !expected.sqlRegex.MatchString(query) {
+ return nil, fmt.Errorf("query '%s', does not match regex [%s]", query, expected.sqlRegex.String())
+ }
+
+ expected.triggered = true
+ return expected, expected.err
+}
+
+func (c *sqlmock) ExpectPrepare(sqlRegexStr string) *ExpectedPrepare {
+ sqlRegexStr = stripQuery(sqlRegexStr)
+ e := &ExpectedPrepare{sqlRegex: regexp.MustCompile(sqlRegexStr), mock: c}
+ c.expected = append(c.expected, e)
+ return e
+}
+
+type namedValue struct {
+ Name string
+ Ordinal int
+ Value driver.Value
+}
+
+// Query meets http://golang.org/pkg/database/sql/driver/#Queryer
+func (c *sqlmock) Query(query string, args []driver.Value) (driver.Rows, error) {
+ namedArgs := make([]namedValue, len(args))
+ for i, v := range args {
+ namedArgs[i] = namedValue{
+ Ordinal: i + 1,
+ Value: v,
+ }
+ }
+
+ ex, err := c.query(query, namedArgs)
+ if err != nil {
+ return nil, err
+ }
+
+ time.Sleep(ex.delay)
+ return ex.rows, nil
+}
+
+func (c *sqlmock) query(query string, args []namedValue) (*ExpectedQuery, error) {
+ query = stripQuery(query)
+ var expected *ExpectedQuery
+ var fulfilled int
+ var ok bool
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if c.ordered {
+ if expected, ok = next.(*ExpectedQuery); ok {
+ break
+ }
+ next.Unlock()
+ return nil, fmt.Errorf("call to query '%s' with args %+v, was not expected, next expectation is: %s", query, args, next)
+ }
+ if qr, ok := next.(*ExpectedQuery); ok {
+ if err := qr.attemptMatch(query, args); err == nil {
+ expected = qr
+ break
+ }
+ }
+ next.Unlock()
+ }
+
+ if expected == nil {
+ msg := "call to query '%s' with args %+v was not expected"
+ if fulfilled == len(c.expected) {
+ msg = "all expectations were already fulfilled, " + msg
+ }
+ return nil, fmt.Errorf(msg, query, args)
+ }
+
+ defer expected.Unlock()
+
+ if !expected.queryMatches(query) {
+ return nil, fmt.Errorf("query '%s', does not match regex [%s]", query, expected.sqlRegex.String())
+ }
+
+ if err := expected.argsMatches(args); err != nil {
+ return nil, fmt.Errorf("exec query '%s', arguments do not match: %s", query, err)
+ }
+
+ expected.triggered = true
+ if expected.err != nil {
+ return nil, expected.err // mocked to return error
+ }
+
+ if expected.rows == nil {
+ return nil, fmt.Errorf("query '%s' with args %+v, must return a database/sql/driver.rows, but it was not set for expectation %T as %+v", query, args, expected, expected)
+ }
+ return expected, nil
+}
+
+func (c *sqlmock) ExpectQuery(sqlRegexStr string) *ExpectedQuery {
+ e := &ExpectedQuery{}
+ sqlRegexStr = stripQuery(sqlRegexStr)
+ e.sqlRegex = regexp.MustCompile(sqlRegexStr)
+ c.expected = append(c.expected, e)
+ return e
+}
+
+func (c *sqlmock) ExpectCommit() *ExpectedCommit {
+ e := &ExpectedCommit{}
+ c.expected = append(c.expected, e)
+ return e
+}
+
+func (c *sqlmock) ExpectRollback() *ExpectedRollback {
+ e := &ExpectedRollback{}
+ c.expected = append(c.expected, e)
+ return e
+}
+
+// Commit meets http://golang.org/pkg/database/sql/driver/#Tx
+func (c *sqlmock) Commit() error {
+ var expected *ExpectedCommit
+ var fulfilled int
+ var ok bool
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if expected, ok = next.(*ExpectedCommit); ok {
+ break
+ }
+
+ next.Unlock()
+ if c.ordered {
+ return fmt.Errorf("call to commit transaction, was not expected, next expectation is: %s", next)
+ }
+ }
+ if expected == nil {
+ msg := "call to commit transaction was not expected"
+ if fulfilled == len(c.expected) {
+ msg = "all expectations were already fulfilled, " + msg
+ }
+ return fmt.Errorf(msg)
+ }
+
+ expected.triggered = true
+ expected.Unlock()
+ return expected.err
+}
+
+// Rollback meets http://golang.org/pkg/database/sql/driver/#Tx
+func (c *sqlmock) Rollback() error {
+ var expected *ExpectedRollback
+ var fulfilled int
+ var ok bool
+ for _, next := range c.expected {
+ next.Lock()
+ if next.fulfilled() {
+ next.Unlock()
+ fulfilled++
+ continue
+ }
+
+ if expected, ok = next.(*ExpectedRollback); ok {
+ break
+ }
+
+ next.Unlock()
+ if c.ordered {
+ return fmt.Errorf("call to rollback transaction, was not expected, next expectation is: %s", next)
+ }
+ }
+ if expected == nil {
+ msg := "call to rollback transaction was not expected"
+ if fulfilled == len(c.expected) {
+ msg = "all expectations were already fulfilled, " + msg
+ }
+ return fmt.Errorf(msg)
+ }
+
+ expected.triggered = true
+ expected.Unlock()
+ return expected.err
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18.go
new file mode 100644
index 0000000..c49429c
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18.go
@@ -0,0 +1,101 @@
+// +build go1.8
+
+package sqlmock
+
+import (
+ "context"
+ "database/sql/driver"
+ "errors"
+ "time"
+)
+
+var ErrCancelled = errors.New("canceling query due to user request")
+
+// Implement the "QueryerContext" interface
+func (c *sqlmock) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
+ namedArgs := make([]namedValue, len(args))
+ for i, nv := range args {
+ namedArgs[i] = namedValue(nv)
+ }
+
+ ex, err := c.query(query, namedArgs)
+ if err != nil {
+ return nil, err
+ }
+
+ select {
+ case <-time.After(ex.delay):
+ return ex.rows, nil
+ case <-ctx.Done():
+ return nil, ErrCancelled
+ }
+}
+
+// Implement the "ExecerContext" interface
+func (c *sqlmock) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
+ namedArgs := make([]namedValue, len(args))
+ for i, nv := range args {
+ namedArgs[i] = namedValue(nv)
+ }
+
+ ex, err := c.exec(query, namedArgs)
+ if err != nil {
+ return nil, err
+ }
+
+ select {
+ case <-time.After(ex.delay):
+ return ex.result, nil
+ case <-ctx.Done():
+ return nil, ErrCancelled
+ }
+}
+
+// Implement the "ConnBeginTx" interface
+func (c *sqlmock) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
+ ex, err := c.begin()
+ if err != nil {
+ return nil, err
+ }
+
+ select {
+ case <-time.After(ex.delay):
+ return c, nil
+ case <-ctx.Done():
+ return nil, ErrCancelled
+ }
+}
+
+// Implement the "ConnPrepareContext" interface
+func (c *sqlmock) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
+ ex, err := c.prepare(query)
+ if err != nil {
+ return nil, err
+ }
+
+ select {
+ case <-time.After(ex.delay):
+ return &statement{c, query, ex.closeErr}, nil
+ case <-ctx.Done():
+ return nil, ErrCancelled
+ }
+}
+
+// Implement the "Pinger" interface
+// for now we do not have a Ping expectation
+// may be something for the future
+func (c *sqlmock) Ping(ctx context.Context) error {
+ return nil
+}
+
+// Implement the "StmtExecContext" interface
+func (stmt *statement) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
+ return stmt.conn.ExecContext(ctx, stmt.query, args)
+}
+
+// Implement the "StmtQueryContext" interface
+func (stmt *statement) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
+ return stmt.conn.QueryContext(ctx, stmt.query, args)
+}
+
+// @TODO maybe add ExpectedBegin.WithOptions(driver.TxOptions)
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18_test.go
new file mode 100644
index 0000000..9eadcb5
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18_test.go
@@ -0,0 +1,426 @@
+// +build go1.8
+
+package sqlmock
+
+import (
+ "context"
+ "database/sql"
+ "testing"
+ "time"
+)
+
+func TestContextExecCancel(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectExec("DELETE FROM users").
+ WillDelayFor(time.Second).
+ WillReturnResult(NewResult(1, 1))
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ _, err = db.ExecContext(ctx, "DELETE FROM users")
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = db.ExecContext(ctx, "DELETE FROM users")
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestPreparedStatementContextExecCancel(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectPrepare("DELETE FROM users").
+ ExpectExec().
+ WillDelayFor(time.Second).
+ WillReturnResult(NewResult(1, 1))
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ stmt, err := db.Prepare("DELETE FROM users")
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ _, err = stmt.ExecContext(ctx)
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = stmt.ExecContext(ctx)
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextExecWithNamedArg(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectExec("DELETE FROM users").
+ WithArgs(sql.Named("id", 5)).
+ WillDelayFor(time.Second).
+ WillReturnResult(NewResult(1, 1))
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ _, err = db.ExecContext(ctx, "DELETE FROM users WHERE id = :id", sql.Named("id", 5))
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = db.ExecContext(ctx, "DELETE FROM users WHERE id = :id", sql.Named("id", 5))
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextExec(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectExec("DELETE FROM users").
+ WillReturnResult(NewResult(1, 1))
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ res, err := db.ExecContext(ctx, "DELETE FROM users")
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ affected, err := res.RowsAffected()
+ if affected != 1 {
+ t.Errorf("expected affected rows 1, but got %v", affected)
+ }
+
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextQueryCancel(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs := NewRows([]string{"id", "title"}).AddRow(5, "hello world")
+
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+ WithArgs(5).
+ WillDelayFor(time.Second).
+ WillReturnRows(rs)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ _, err = db.QueryContext(ctx, "SELECT id, title FROM articles WHERE id = ?", 5)
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = db.QueryContext(ctx, "SELECT id, title FROM articles WHERE id = ?", 5)
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestPreparedStatementContextQueryCancel(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs := NewRows([]string{"id", "title"}).AddRow(5, "hello world")
+
+ mock.ExpectPrepare("SELECT (.+) FROM articles WHERE id = ?").
+ ExpectQuery().
+ WithArgs(5).
+ WillDelayFor(time.Second).
+ WillReturnRows(rs)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ stmt, err := db.Prepare("SELECT id, title FROM articles WHERE id = ?")
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ _, err = stmt.QueryContext(ctx, 5)
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = stmt.QueryContext(ctx, 5)
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextQuery(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs := NewRows([]string{"id", "title"}).AddRow(5, "hello world")
+
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id =").
+ WithArgs(sql.Named("id", 5)).
+ WillDelayFor(time.Millisecond * 3).
+ WillReturnRows(rs)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ rows, err := db.QueryContext(ctx, "SELECT id, title FROM articles WHERE id = :id", sql.Named("id", 5))
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if !rows.Next() {
+ t.Error("expected one row, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextBeginCancel(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectBegin().WillDelayFor(time.Second)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ _, err = db.BeginTx(ctx, nil)
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = db.BeginTx(ctx, nil)
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextBegin(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectBegin().WillDelayFor(time.Millisecond * 3)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ tx, err := db.BeginTx(ctx, nil)
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if tx == nil {
+ t.Error("expected tx, but there was nil")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextPrepareCancel(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectPrepare("SELECT").WillDelayFor(time.Second)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ _, err = db.PrepareContext(ctx, "SELECT")
+ if err == nil {
+ t.Error("error was expected, but there was none")
+ }
+
+ if err != ErrCancelled {
+ t.Errorf("was expecting cancel error, but got: %v", err)
+ }
+
+ _, err = db.PrepareContext(ctx, "SELECT")
+ if err != context.Canceled {
+ t.Error("error was expected since context was already done, but there was none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestContextPrepare(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectPrepare("SELECT").WillDelayFor(time.Millisecond * 3)
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ time.Sleep(time.Millisecond * 10)
+ cancel()
+ }()
+
+ stmt, err := db.PrepareContext(ctx, "SELECT")
+ if err != nil {
+ t.Errorf("error was not expected, but got: %v", err)
+ }
+
+ if stmt == nil {
+ t.Error("expected stmt, but there was nil")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_test.go
new file mode 100644
index 0000000..fe4924b
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_test.go
@@ -0,0 +1,998 @@
+package sqlmock
+
+import (
+ "database/sql"
+ "fmt"
+ "strconv"
+ "sync"
+ "testing"
+ "time"
+)
+
+func cancelOrder(db *sql.DB, orderID int) error {
+ tx, _ := db.Begin()
+ _, _ = tx.Query("SELECT * FROM orders {0} FOR UPDATE", orderID)
+ err := tx.Rollback()
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func Example() {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ // columns to be used for result
+ columns := []string{"id", "status"}
+ // expect transaction begin
+ mock.ExpectBegin()
+ // expect query to fetch order, match it with regexp
+ mock.ExpectQuery("SELECT (.+) FROM orders (.+) FOR UPDATE").
+ WithArgs(1).
+ WillReturnRows(NewRows(columns).AddRow(1, 1))
+ // expect transaction rollback, since order status is "cancelled"
+ mock.ExpectRollback()
+
+ // run the cancel order function
+ someOrderID := 1
+ // call a function which executes expected database operations
+ err = cancelOrder(db, someOrderID)
+ if err != nil {
+ fmt.Printf("unexpected error: %s", err)
+ return
+ }
+
+ // ensure all expectations have been met
+ if err = mock.ExpectationsWereMet(); err != nil {
+ fmt.Printf("unmet expectation error: %s", err)
+ }
+ // Output:
+}
+
+func TestIssue14EscapeSQL(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+ mock.ExpectExec("INSERT INTO mytable\\(a, b\\)").
+ WithArgs("A", "B").
+ WillReturnResult(NewResult(1, 1))
+
+ _, err = db.Exec("INSERT INTO mytable(a, b) VALUES (?, ?)", "A", "B")
+ if err != nil {
+ t.Errorf("error '%s' was not expected, while inserting a row", err)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+// test the case when db is not triggered and expectations
+// are not asserted on close
+func TestIssue4(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectQuery("some sql query which will not be called").
+ WillReturnRows(NewRows([]string{"id"}))
+
+ if err := mock.ExpectationsWereMet(); err == nil {
+ t.Errorf("was expecting an error since query was not triggered")
+ }
+}
+
+func TestMockQuery(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs := NewRows([]string{"id", "title"}).FromCSVString("5,hello world")
+
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+ WithArgs(5).
+ WillReturnRows(rs)
+
+ rows, err := db.Query("SELECT (.+) FROM articles WHERE id = ?", 5)
+ if err != nil {
+ t.Errorf("error '%s' was not expected while retrieving mock rows", err)
+ }
+
+ defer func() {
+ if er := rows.Close(); er != nil {
+ t.Error("Unexpected error while trying to close rows")
+ }
+ }()
+
+ if !rows.Next() {
+ t.Error("it must have had one row as result, but got empty result set instead")
+ }
+
+ var id int
+ var title string
+
+ err = rows.Scan(&id, &title)
+ if err != nil {
+ t.Errorf("error '%s' was not expected while trying to scan row", err)
+ }
+
+ if id != 5 {
+ t.Errorf("expected mocked id to be 5, but got %d instead", id)
+ }
+
+ if title != "hello world" {
+ t.Errorf("expected mocked title to be 'hello world', but got '%s' instead", title)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestMockQueryTypes(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ columns := []string{"id", "timestamp", "sold"}
+
+ timestamp := time.Now()
+ rs := NewRows(columns)
+ rs.AddRow(5, timestamp, true)
+
+ mock.ExpectQuery("SELECT (.+) FROM sales WHERE id = ?").
+ WithArgs(5).
+ WillReturnRows(rs)
+
+ rows, err := db.Query("SELECT (.+) FROM sales WHERE id = ?", 5)
+ if err != nil {
+ t.Errorf("error '%s' was not expected while retrieving mock rows", err)
+ }
+ defer func() {
+ if er := rows.Close(); er != nil {
+ t.Error("Unexpected error while trying to close rows")
+ }
+ }()
+ if !rows.Next() {
+ t.Error("it must have had one row as result, but got empty result set instead")
+ }
+
+ var id int
+ var time time.Time
+ var sold bool
+
+ err = rows.Scan(&id, &time, &sold)
+ if err != nil {
+ t.Errorf("error '%s' was not expected while trying to scan row", err)
+ }
+
+ if id != 5 {
+ t.Errorf("expected mocked id to be 5, but got %d instead", id)
+ }
+
+ if time != timestamp {
+ t.Errorf("expected mocked time to be %s, but got '%s' instead", timestamp, time)
+ }
+
+ if sold != true {
+ t.Errorf("expected mocked boolean to be true, but got %v instead", sold)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestTransactionExpectations(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ // begin and commit
+ mock.ExpectBegin()
+ mock.ExpectCommit()
+
+ tx, err := db.Begin()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when beginning a transaction", err)
+ }
+
+ err = tx.Commit()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when committing a transaction", err)
+ }
+
+ // begin and rollback
+ mock.ExpectBegin()
+ mock.ExpectRollback()
+
+ tx, err = db.Begin()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when beginning a transaction", err)
+ }
+
+ err = tx.Rollback()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when rolling back a transaction", err)
+ }
+
+ // begin with an error
+ mock.ExpectBegin().WillReturnError(fmt.Errorf("some err"))
+
+ tx, err = db.Begin()
+ if err == nil {
+ t.Error("an error was expected when beginning a transaction, but got none")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestPrepareExpectations(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectPrepare("SELECT (.+) FROM articles WHERE id = ?")
+
+ stmt, err := db.Prepare("SELECT (.+) FROM articles WHERE id = ?")
+ if err != nil {
+ t.Errorf("error '%s' was not expected while creating a prepared statement", err)
+ }
+ if stmt == nil {
+ t.Errorf("stmt was expected while creating a prepared statement")
+ }
+
+ // expect something else, w/o ExpectPrepare()
+ var id int
+ var title string
+ rs := NewRows([]string{"id", "title"}).FromCSVString("5,hello world")
+
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+ WithArgs(5).
+ WillReturnRows(rs)
+
+ err = stmt.QueryRow(5).Scan(&id, &title)
+ if err != nil {
+ t.Errorf("error '%s' was not expected while retrieving mock rows", err)
+ }
+
+ mock.ExpectPrepare("SELECT (.+) FROM articles WHERE id = ?").
+ WillReturnError(fmt.Errorf("Some DB error occurred"))
+
+ stmt, err = db.Prepare("SELECT id FROM articles WHERE id = ?")
+ if err == nil {
+ t.Error("error was expected while creating a prepared statement")
+ }
+ if stmt != nil {
+ t.Errorf("stmt was not expected while creating a prepared statement returning error")
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestPreparedQueryExecutions(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectPrepare("SELECT (.+) FROM articles WHERE id = ?")
+
+ rs1 := NewRows([]string{"id", "title"}).FromCSVString("5,hello world")
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+ WithArgs(5).
+ WillReturnRows(rs1)
+
+ rs2 := NewRows([]string{"id", "title"}).FromCSVString("2,whoop")
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+ WithArgs(2).
+ WillReturnRows(rs2)
+
+ stmt, err := db.Prepare("SELECT id, title FROM articles WHERE id = ?")
+ if err != nil {
+ t.Errorf("error '%s' was not expected while creating a prepared statement", err)
+ }
+
+ var id int
+ var title string
+ err = stmt.QueryRow(5).Scan(&id, &title)
+ if err != nil {
+ t.Errorf("error '%s' was not expected querying row from statement and scanning", err)
+ }
+
+ if id != 5 {
+ t.Errorf("expected mocked id to be 5, but got %d instead", id)
+ }
+
+ if title != "hello world" {
+ t.Errorf("expected mocked title to be 'hello world', but got '%s' instead", title)
+ }
+
+ err = stmt.QueryRow(2).Scan(&id, &title)
+ if err != nil {
+ t.Errorf("error '%s' was not expected querying row from statement and scanning", err)
+ }
+
+ if id != 2 {
+ t.Errorf("expected mocked id to be 2, but got %d instead", id)
+ }
+
+ if title != "whoop" {
+ t.Errorf("expected mocked title to be 'whoop', but got '%s' instead", title)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestUnexpectedOperations(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectPrepare("SELECT (.+) FROM articles WHERE id = ?")
+ stmt, err := db.Prepare("SELECT id, title FROM articles WHERE id = ?")
+ if err != nil {
+ t.Errorf("error '%s' was not expected while creating a prepared statement", err)
+ }
+
+ var id int
+ var title string
+
+ err = stmt.QueryRow(5).Scan(&id, &title)
+ if err == nil {
+ t.Error("error was expected querying row, since there was no such expectation")
+ }
+
+ mock.ExpectRollback()
+
+ if err := mock.ExpectationsWereMet(); err == nil {
+ t.Errorf("was expecting an error since query was not triggered")
+ }
+}
+
+func TestWrongExpectations(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectBegin()
+
+ rs1 := NewRows([]string{"id", "title"}).FromCSVString("5,hello world")
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+ WithArgs(5).
+ WillReturnRows(rs1)
+
+ mock.ExpectCommit().WillReturnError(fmt.Errorf("deadlock occurred"))
+ mock.ExpectRollback() // won't be triggered
+
+ var id int
+ var title string
+
+ err = db.QueryRow("SELECT id, title FROM articles WHERE id = ? FOR UPDATE", 5).Scan(&id, &title)
+ if err == nil {
+ t.Error("error was expected while querying row, since there begin transaction expectation is not fulfilled")
+ }
+
+ // lets go around and start transaction
+ tx, err := db.Begin()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when beginning a transaction", err)
+ }
+
+ err = db.QueryRow("SELECT id, title FROM articles WHERE id = ? FOR UPDATE", 5).Scan(&id, &title)
+ if err != nil {
+ t.Errorf("error '%s' was not expected while querying row, since transaction was started", err)
+ }
+
+ err = tx.Commit()
+ if err == nil {
+ t.Error("a deadlock error was expected when committing a transaction", err)
+ }
+
+ if err := mock.ExpectationsWereMet(); err == nil {
+ t.Errorf("was expecting an error since query was not triggered")
+ }
+}
+
+func TestExecExpectations(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ result := NewResult(1, 1)
+ mock.ExpectExec("^INSERT INTO articles").
+ WithArgs("hello").
+ WillReturnResult(result)
+
+ res, err := db.Exec("INSERT INTO articles (title) VALUES (?)", "hello")
+ if err != nil {
+ t.Errorf("error '%s' was not expected, while inserting a row", err)
+ }
+
+ id, err := res.LastInsertId()
+ if err != nil {
+ t.Errorf("error '%s' was not expected, while getting a last insert id", err)
+ }
+
+ affected, err := res.RowsAffected()
+ if err != nil {
+ t.Errorf("error '%s' was not expected, while getting affected rows", err)
+ }
+
+ if id != 1 {
+ t.Errorf("expected last insert id to be 1, but got %d instead", id)
+ }
+
+ if affected != 1 {
+ t.Errorf("expected affected rows to be 1, but got %d instead", affected)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestRowBuilderAndNilTypes(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs := NewRows([]string{"id", "active", "created", "status"}).
+ AddRow(1, true, time.Now(), 5).
+ AddRow(2, false, nil, nil)
+
+ mock.ExpectQuery("SELECT (.+) FROM sales").WillReturnRows(rs)
+
+ rows, err := db.Query("SELECT * FROM sales")
+ if err != nil {
+ t.Errorf("error '%s' was not expected while retrieving mock rows", err)
+ }
+ defer func() {
+ if er := rows.Close(); er != nil {
+ t.Error("Unexpected error while trying to close rows")
+ }
+ }()
+
+ // NullTime and NullInt are used from stubs_test.go
+ var (
+ id int
+ active bool
+ created NullTime
+ status NullInt
+ )
+
+ if !rows.Next() {
+ t.Error("it must have had row in rows, but got empty result set instead")
+ }
+
+ err = rows.Scan(&id, &active, &created, &status)
+ if err != nil {
+ t.Errorf("error '%s' was not expected while trying to scan row", err)
+ }
+
+ if id != 1 {
+ t.Errorf("expected mocked id to be 1, but got %d instead", id)
+ }
+
+ if !active {
+ t.Errorf("expected 'active' to be 'true', but got '%v' instead", active)
+ }
+
+ if !created.Valid {
+ t.Errorf("expected 'created' to be valid, but it %+v is not", created)
+ }
+
+ if !status.Valid {
+ t.Errorf("expected 'status' to be valid, but it %+v is not", status)
+ }
+
+ if status.Integer != 5 {
+ t.Errorf("expected 'status' to be '5', but got '%d'", status.Integer)
+ }
+
+ // test second row
+ if !rows.Next() {
+ t.Error("it must have had row in rows, but got empty result set instead")
+ }
+
+ err = rows.Scan(&id, &active, &created, &status)
+ if err != nil {
+ t.Errorf("error '%s' was not expected while trying to scan row", err)
+ }
+
+ if id != 2 {
+ t.Errorf("expected mocked id to be 2, but got %d instead", id)
+ }
+
+ if active {
+ t.Errorf("expected 'active' to be 'false', but got '%v' instead", active)
+ }
+
+ if created.Valid {
+ t.Errorf("expected 'created' to be invalid, but it %+v is not", created)
+ }
+
+ if status.Valid {
+ t.Errorf("expected 'status' to be invalid, but it %+v is not", status)
+ }
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestArgumentReflectValueTypeError(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs := NewRows([]string{"id"}).AddRow(1)
+
+ mock.ExpectQuery("SELECT (.+) FROM sales").WithArgs(5.5).WillReturnRows(rs)
+
+ _, err = db.Query("SELECT * FROM sales WHERE x = ?", 5)
+ if err == nil {
+ t.Error("Expected error, but got none")
+ }
+}
+
+func TestGoroutineExecutionWithUnorderedExpectationMatching(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ // note this line is important for unordered expectation matching
+ mock.MatchExpectationsInOrder(false)
+
+ result := NewResult(1, 1)
+
+ mock.ExpectExec("^UPDATE one").WithArgs("one").WillReturnResult(result)
+ mock.ExpectExec("^UPDATE two").WithArgs("one", "two").WillReturnResult(result)
+ mock.ExpectExec("^UPDATE three").WithArgs("one", "two", "three").WillReturnResult(result)
+
+ var wg sync.WaitGroup
+ queries := map[string][]interface{}{
+ "one": []interface{}{"one"},
+ "two": []interface{}{"one", "two"},
+ "three": []interface{}{"one", "two", "three"},
+ }
+
+ wg.Add(len(queries))
+ for table, args := range queries {
+ go func(tbl string, a []interface{}) {
+ if _, err := db.Exec("UPDATE "+tbl, a...); err != nil {
+ t.Errorf("error was not expected: %s", err)
+ }
+ wg.Done()
+ }(table, args)
+ }
+
+ wg.Wait()
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func ExampleSqlmock_goroutines() {
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("failed to open sqlmock database:", err)
+ }
+ defer db.Close()
+
+ // note this line is important for unordered expectation matching
+ mock.MatchExpectationsInOrder(false)
+
+ result := NewResult(1, 1)
+
+ mock.ExpectExec("^UPDATE one").WithArgs("one").WillReturnResult(result)
+ mock.ExpectExec("^UPDATE two").WithArgs("one", "two").WillReturnResult(result)
+ mock.ExpectExec("^UPDATE three").WithArgs("one", "two", "three").WillReturnResult(result)
+
+ var wg sync.WaitGroup
+ queries := map[string][]interface{}{
+ "one": []interface{}{"one"},
+ "two": []interface{}{"one", "two"},
+ "three": []interface{}{"one", "two", "three"},
+ }
+
+ wg.Add(len(queries))
+ for table, args := range queries {
+ go func(tbl string, a []interface{}) {
+ if _, err := db.Exec("UPDATE "+tbl, a...); err != nil {
+ fmt.Println("error was not expected:", err)
+ }
+ wg.Done()
+ }(table, args)
+ }
+
+ wg.Wait()
+
+ if err := mock.ExpectationsWereMet(); err != nil {
+ fmt.Println("there were unfulfilled expections:", err)
+ }
+ // Output:
+}
+
+// False Positive - passes despite mismatched Exec
+// see #37 issue
+func TestRunExecsWithOrderedShouldNotMeetAllExpectations(t *testing.T) {
+ db, dbmock, _ := New()
+ dbmock.ExpectExec("THE FIRST EXEC")
+ dbmock.ExpectExec("THE SECOND EXEC")
+
+ _, _ = db.Exec("THE FIRST EXEC")
+ _, _ = db.Exec("THE WRONG EXEC")
+
+ err := dbmock.ExpectationsWereMet()
+ if err == nil {
+ t.Fatal("was expecting an error, but there wasn't any")
+ }
+}
+
+// False Positive - passes despite mismatched Exec
+// see #37 issue
+func TestRunQueriesWithOrderedShouldNotMeetAllExpectations(t *testing.T) {
+ db, dbmock, _ := New()
+ dbmock.ExpectQuery("THE FIRST QUERY")
+ dbmock.ExpectQuery("THE SECOND QUERY")
+
+ _, _ = db.Query("THE FIRST QUERY")
+ _, _ = db.Query("THE WRONG QUERY")
+
+ err := dbmock.ExpectationsWereMet()
+ if err == nil {
+ t.Fatal("was expecting an error, but there wasn't any")
+ }
+}
+
+func TestRunExecsWithExpectedErrorMeetsExpectations(t *testing.T) {
+ db, dbmock, _ := New()
+ dbmock.ExpectExec("THE FIRST EXEC").WillReturnError(fmt.Errorf("big bad bug"))
+ dbmock.ExpectExec("THE SECOND EXEC").WillReturnResult(NewResult(0, 0))
+
+ _, _ = db.Exec("THE FIRST EXEC")
+ _, _ = db.Exec("THE SECOND EXEC")
+
+ err := dbmock.ExpectationsWereMet()
+ if err != nil {
+ t.Fatalf("all expectations should be met: %s", err)
+ }
+}
+
+func TestRunQueryWithExpectedErrorMeetsExpectations(t *testing.T) {
+ db, dbmock, _ := New()
+ dbmock.ExpectQuery("THE FIRST QUERY").WillReturnError(fmt.Errorf("big bad bug"))
+ dbmock.ExpectQuery("THE SECOND QUERY").WillReturnRows(NewRows([]string{"col"}).AddRow(1))
+
+ _, _ = db.Query("THE FIRST QUERY")
+ _, _ = db.Query("THE SECOND QUERY")
+
+ err := dbmock.ExpectationsWereMet()
+ if err != nil {
+ t.Fatalf("all expectations should be met: %s", err)
+ }
+}
+
+func TestEmptyRowSet(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ rs := NewRows([]string{"id", "title"})
+
+ mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
+ WithArgs(5).
+ WillReturnRows(rs)
+
+ rows, err := db.Query("SELECT (.+) FROM articles WHERE id = ?", 5)
+ if err != nil {
+ t.Errorf("error '%s' was not expected while retrieving mock rows", err)
+ }
+
+ defer func() {
+ if er := rows.Close(); er != nil {
+ t.Error("Unexpected error while trying to close rows")
+ }
+ }()
+
+ if rows.Next() {
+ t.Error("expected no rows but got one")
+ }
+
+ err = mock.ExpectationsWereMet()
+ if err != nil {
+ t.Fatalf("all expectations should be met: %s", err)
+ }
+}
+
+// Based on issue #50
+func TestPrepareExpectationNotFulfilled(t *testing.T) {
+ t.Parallel()
+ db, mock, err := New()
+ if err != nil {
+ t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
+ }
+ defer db.Close()
+
+ mock.ExpectPrepare("^BADSELECT$")
+
+ if _, err := db.Prepare("SELECT"); err == nil {
+ t.Fatal("prepare should not match expected query string")
+ }
+
+ if err := mock.ExpectationsWereMet(); err == nil {
+ t.Errorf("was expecting an error, since prepared statement query does not match, but there was none")
+ }
+}
+
+func TestRollbackThrow(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ // columns to be used for result
+ columns := []string{"id", "status"}
+ // expect transaction begin
+ mock.ExpectBegin()
+ // expect query to fetch order, match it with regexp
+ mock.ExpectQuery("SELECT (.+) FROM orders (.+) FOR UPDATE").
+ WithArgs(1).
+ WillReturnRows(NewRows(columns).AddRow(1, 1))
+ // expect transaction rollback, since order status is "cancelled"
+ mock.ExpectRollback().WillReturnError(fmt.Errorf("rollback failed"))
+
+ // run the cancel order function
+ someOrderID := 1
+ // call a function which executes expected database operations
+ err = cancelOrder(db, someOrderID)
+ if err == nil {
+ t.Error("an error was expected when rolling back transaction, but got none")
+ }
+
+ // ensure all expectations have been met
+ if err = mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("unmet expectation error: %s", err)
+ }
+ // Output:
+}
+
+func TestUnexpectedCommit(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ mock.ExpectBegin()
+ tx, _ := db.Begin()
+ if err := tx.Commit(); err == nil {
+ t.Error("an error was expected when calling commit, but got none")
+ }
+}
+
+func TestUnexpectedCommitOrder(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ mock.ExpectBegin()
+ mock.ExpectRollback().WillReturnError(fmt.Errorf("Rollback failed"))
+ tx, _ := db.Begin()
+ if err := tx.Commit(); err == nil {
+ t.Error("an error was expected when calling commit, but got none")
+ }
+}
+
+func TestExpectedCommitOrder(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ mock.ExpectCommit().WillReturnError(fmt.Errorf("Commit failed"))
+ if _, err := db.Begin(); err == nil {
+ t.Error("an error was expected when calling begin, but got none")
+ }
+}
+
+func TestUnexpectedRollback(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ mock.ExpectBegin()
+ tx, _ := db.Begin()
+ if err := tx.Rollback(); err == nil {
+ t.Error("an error was expected when calling rollback, but got none")
+ }
+}
+
+func TestUnexpectedRollbackOrder(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ mock.ExpectBegin()
+
+ tx, _ := db.Begin()
+ if err := tx.Rollback(); err == nil {
+ t.Error("an error was expected when calling rollback, but got none")
+ }
+}
+
+func TestPrepareExec(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ defer db.Close()
+ mock.ExpectBegin()
+ ep := mock.ExpectPrepare("INSERT INTO ORDERS\\(ID, STATUS\\) VALUES \\(\\?, \\?\\)")
+ for i := 0; i < 3; i++ {
+ ep.ExpectExec().WillReturnResult(NewResult(1, 1))
+ }
+ mock.ExpectCommit()
+ tx, _ := db.Begin()
+ stmt, err := tx.Prepare("INSERT INTO ORDERS(ID, STATUS) VALUES (?, ?)")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer stmt.Close()
+ for i := 0; i < 3; i++ {
+ _, err := stmt.Exec(i, "Hello"+strconv.Itoa(i))
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ tx.Commit()
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestPrepareQuery(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ defer db.Close()
+ mock.ExpectBegin()
+ ep := mock.ExpectPrepare("SELECT ID, STATUS FROM ORDERS WHERE ID = \\?")
+ ep.ExpectQuery().WithArgs(101).WillReturnRows(NewRows([]string{"ID", "STATUS"}).AddRow(101, "Hello"))
+ mock.ExpectCommit()
+ tx, _ := db.Begin()
+ stmt, err := tx.Prepare("SELECT ID, STATUS FROM ORDERS WHERE ID = ?")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer stmt.Close()
+ rows, err := stmt.Query(101)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer rows.Close()
+ for rows.Next() {
+ var (
+ id int
+ status string
+ )
+ if rows.Scan(&id, &status); id != 101 || status != "Hello" {
+ t.Fatal("wrong query results")
+ }
+
+ }
+ tx.Commit()
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestExpectedCloseError(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ mock.ExpectClose().WillReturnError(fmt.Errorf("Close failed"))
+ if err := db.Close(); err == nil {
+ t.Error("an error was expected when calling close, but got none")
+ }
+ if err := mock.ExpectationsWereMet(); err != nil {
+ t.Errorf("there were unfulfilled expections: %s", err)
+ }
+}
+
+func TestExpectedCloseOrder(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ defer db.Close()
+ mock.ExpectClose().WillReturnError(fmt.Errorf("Close failed"))
+ db.Begin()
+ if err := mock.ExpectationsWereMet(); err == nil {
+ t.Error("expected error on ExpectationsWereMet")
+ }
+}
+
+func TestExpectedBeginOrder(t *testing.T) {
+ // Open new mock database
+ db, mock, err := New()
+ if err != nil {
+ fmt.Println("error creating mock database")
+ return
+ }
+ mock.ExpectBegin().WillReturnError(fmt.Errorf("Begin failed"))
+ if err := db.Close(); err == nil {
+ t.Error("an error was expected when calling close, but got none")
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement.go
new file mode 100644
index 0000000..df73740
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement.go
@@ -0,0 +1,27 @@
+package sqlmock
+
+import (
+ "database/sql/driver"
+)
+
+type statement struct {
+ conn *sqlmock
+ query string
+ err error
+}
+
+func (stmt *statement) Close() error {
+ return stmt.err
+}
+
+func (stmt *statement) NumInput() int {
+ return -1
+}
+
+func (stmt *statement) Exec(args []driver.Value) (driver.Result, error) {
+ return stmt.conn.Exec(stmt.query, args)
+}
+
+func (stmt *statement) Query(args []driver.Value) (driver.Rows, error) {
+ return stmt.conn.Query(stmt.query, args)
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement_test.go
new file mode 100644
index 0000000..f951f63
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement_test.go
@@ -0,0 +1,33 @@
+// +build go1.6
+
+package sqlmock
+
+import (
+ "errors"
+ "testing"
+)
+
+func TestExpectedPreparedStatemtCloseError(t *testing.T) {
+ conn, mock, err := New()
+ if err != nil {
+ t.Fatal("failed to open sqlmock database:", err)
+ }
+
+ mock.ExpectBegin()
+ want := errors.New("STMT ERROR")
+ mock.ExpectPrepare("SELECT").WillReturnCloseError(want)
+
+ txn, err := conn.Begin()
+ if err != nil {
+ t.Fatal("unexpected error while opening transaction:", err)
+ }
+
+ stmt, err := txn.Prepare("SELECT")
+ if err != nil {
+ t.Fatal("unexpected error while preparing a statement:", err)
+ }
+
+ if err := stmt.Close(); err != want {
+ t.Fatalf("Got = %v, want = %v", err, want)
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go
new file mode 100644
index 0000000..d3c6003
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go
@@ -0,0 +1,76 @@
+package sqlmock
+
+import (
+ "database/sql/driver"
+ "fmt"
+ "strconv"
+ "time"
+)
+
+type NullTime struct {
+ Time time.Time
+ Valid bool // Valid is true if Time is not NULL
+}
+
+type NullInt struct {
+ Integer int
+ Valid bool
+}
+
+// Satisfy sql.Scanner interface
+func (ni *NullInt) Scan(value interface{}) (err error) {
+ if value == nil {
+ ni.Integer, ni.Valid = 0, false
+ return
+ }
+
+ switch v := value.(type) {
+ case int, int8, int16, int32, int64:
+ ni.Integer, ni.Valid = v.(int), true
+ return
+ case []byte:
+ ni.Integer, err = strconv.Atoi(string(v))
+ ni.Valid = (err == nil)
+ return
+ case string:
+ ni.Integer, err = strconv.Atoi(v)
+ ni.Valid = (err == nil)
+ return
+ }
+
+ ni.Valid = false
+ return fmt.Errorf("Can't convert %T to integer", value)
+}
+
+// Satisfy sql.Valuer interface.
+func (ni NullInt) Value() (driver.Value, error) {
+ if !ni.Valid {
+ return nil, nil
+ }
+ return ni.Integer, nil
+}
+
+// Satisfy sql.Scanner interface
+func (nt *NullTime) Scan(value interface{}) (err error) {
+ if value == nil {
+ nt.Time, nt.Valid = time.Time{}, false
+ return
+ }
+
+ switch v := value.(type) {
+ case time.Time:
+ nt.Time, nt.Valid = v, true
+ return
+ }
+
+ nt.Valid = false
+ return fmt.Errorf("Can't convert %T to time.Time", value)
+}
+
+// Satisfy sql.Valuer interface.
+func (nt NullTime) Value() (driver.Value, error) {
+ if !nt.Valid {
+ return nil, nil
+ }
+ return nt.Time, nil
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go
new file mode 100644
index 0000000..072e380
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go
@@ -0,0 +1,13 @@
+package sqlmock
+
+import (
+ "regexp"
+ "strings"
+)
+
+var re = regexp.MustCompile("\\s+")
+
+// strip out new lines and trim spaces
+func stripQuery(q string) (s string) {
+ return strings.TrimSpace(re.ReplaceAllString(q, " "))
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util_test.go b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util_test.go
new file mode 100644
index 0000000..c4b3974
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util_test.go
@@ -0,0 +1,21 @@
+package sqlmock
+
+import (
+ "testing"
+)
+
+func TestQueryStringStripping(t *testing.T) {
+ assert := func(actual, expected string) {
+ if res := stripQuery(actual); res != expected {
+ t.Errorf("Expected '%s' to be '%s', but got '%s'", actual, expected, res)
+ }
+ }
+
+ assert(" SELECT 1", "SELECT 1")
+ assert("SELECT 1 FROM d", "SELECT 1 FROM d")
+ assert(`
+ SELECT c
+ FROM D
+`, "SELECT c FROM D")
+ assert("UPDATE (.+) SET ", "UPDATE (.+) SET")
+}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops/traffic_ops_golang/wrappers.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/wrappers.go b/traffic_ops/traffic_ops_golang/wrappers.go
index f986d2f..30c36b4 100644
--- a/traffic_ops/traffic_ops_golang/wrappers.go
+++ b/traffic_ops/traffic_ops_golang/wrappers.go
@@ -22,8 +22,8 @@ package main
import (
"database/sql"
"fmt"
+ "github.com/apache/incubator-trafficcontrol/traffic_monitor_golang/common/log"
"github.com/apache/incubator-trafficcontrol/traffic_ops/experimental/tocookie"
- "log" // TODO change to traffic_monitor_golang/common/log
"net/http"
"time"
)
@@ -33,8 +33,16 @@ func wrapAuth(h RegexHandlerFunc, noAuth bool, secret string, privLevelStmt *sql
return h
}
return func(w http.ResponseWriter, r *http.Request, p ParamMap) {
+ // TODO remove, and make username available to wrapLogTime
+ start := time.Now()
+ iw := &Interceptor{w: w}
+ w = iw
+ username := "-"
+ defer func() {
+ log.Infof(`%s - %s [%s] "%v %v HTTP/1.1" %v 0 0 "%v"\n`, r.RemoteAddr, username, time.Now().Format(AccessLogTimeFormat), r.Method, r.URL.Path, iw.code, time.Now().Sub(start)/time.Millisecond, iw.byteCount, r.UserAgent())
+ }()
+
handleUnauthorized := func(reason string) {
- log.Printf("%v %v %v sent 401 - %v\n", time.Now(), r.RemoteAddr, r.URL.Path, reason)
status := http.StatusUnauthorized
w.WriteHeader(status)
fmt.Fprintf(w, http.StatusText(status))
@@ -57,7 +65,7 @@ func wrapAuth(h RegexHandlerFunc, noAuth bool, secret string, privLevelStmt *sql
return
}
- username := oldCookie.AuthData
+ username = oldCookie.AuthData
if !hasPrivLevel(privLevelStmt, username, privLevelRequired) {
handleUnauthorized("insufficient privileges")
return
@@ -65,17 +73,42 @@ func wrapAuth(h RegexHandlerFunc, noAuth bool, secret string, privLevelStmt *sql
newCookieVal := tocookie.Refresh(oldCookie, secret)
http.SetCookie(w, &http.Cookie{Name: tocookie.Name, Value: newCookieVal})
+
h(w, r, p)
}
}
+const AccessLogTimeFormat = "02/Jan/2006:15:04:05 -0700"
+
func wrapLogTime(h RegexHandlerFunc) RegexHandlerFunc {
return func(w http.ResponseWriter, r *http.Request, p ParamMap) {
start := time.Now()
+ iw := &Interceptor{w: w}
defer func() {
- now := time.Now()
- log.Printf("%v %v served %v in %v\n", now, r.RemoteAddr, r.URL.Path, now.Sub(start))
+ user := "-" // TODO fix
+ log.Infof(`%s - %s [%s] "%v %v HTTP/1.1" %v 0 0 "%v"\n`, r.RemoteAddr, user, time.Now().Format(AccessLogTimeFormat), r.Method, r.URL.Path, iw.code, time.Now().Sub(start)/time.Millisecond, iw.byteCount, r.UserAgent())
}()
- h(w, r, p)
+ h(iw, r, p)
}
}
+
+type Interceptor struct {
+ w http.ResponseWriter
+ code int
+ byteCount int
+}
+
+func (i *Interceptor) WriteHeader(rc int) {
+ i.w.WriteHeader(rc)
+ i.code = rc
+}
+
+func (i *Interceptor) Write(b []byte) (int, error) {
+ wi, werr := i.w.Write(b)
+ i.byteCount += wi
+ return wi, werr
+}
+
+func (i *Interceptor) Header() http.Header {
+ return i.w.Header()
+}
[13/43] incubator-trafficcontrol git commit: Add TO Golang
configurable logging
Posted by de...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_test.go
deleted file mode 100644
index 56e834e..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/rows_test.go
+++ /dev/null
@@ -1,265 +0,0 @@
-package sqlmock
-
-import (
- "database/sql"
- "fmt"
- "testing"
-)
-
-func ExampleRows() {
- db, mock, err := New()
- if err != nil {
- fmt.Println("failed to open sqlmock database:", err)
- }
- defer db.Close()
-
- rows := NewRows([]string{"id", "title"}).
- AddRow(1, "one").
- AddRow(2, "two")
-
- mock.ExpectQuery("SELECT").WillReturnRows(rows)
-
- rs, _ := db.Query("SELECT")
- defer rs.Close()
-
- for rs.Next() {
- var id int
- var title string
- rs.Scan(&id, &title)
- fmt.Println("scanned id:", id, "and title:", title)
- }
-
- if rs.Err() != nil {
- fmt.Println("got rows error:", rs.Err())
- }
- // Output: scanned id: 1 and title: one
- // scanned id: 2 and title: two
-}
-
-func ExampleRows_rowError() {
- db, mock, err := New()
- if err != nil {
- fmt.Println("failed to open sqlmock database:", err)
- }
- defer db.Close()
-
- rows := NewRows([]string{"id", "title"}).
- AddRow(0, "one").
- AddRow(1, "two").
- RowError(1, fmt.Errorf("row error"))
- mock.ExpectQuery("SELECT").WillReturnRows(rows)
-
- rs, _ := db.Query("SELECT")
- defer rs.Close()
-
- for rs.Next() {
- var id int
- var title string
- rs.Scan(&id, &title)
- fmt.Println("scanned id:", id, "and title:", title)
- }
-
- if rs.Err() != nil {
- fmt.Println("got rows error:", rs.Err())
- }
- // Output: scanned id: 0 and title: one
- // got rows error: row error
-}
-
-func ExampleRows_closeError() {
- db, mock, err := New()
- if err != nil {
- fmt.Println("failed to open sqlmock database:", err)
- }
- defer db.Close()
-
- rows := NewRows([]string{"id", "title"}).CloseError(fmt.Errorf("close error"))
- mock.ExpectQuery("SELECT").WillReturnRows(rows)
-
- rs, _ := db.Query("SELECT")
-
- // Note: that close will return error only before rows EOF
- // that is a default sql package behavior. If you run rs.Next()
- // it will handle the error internally and return nil bellow
- if err := rs.Close(); err != nil {
- fmt.Println("got error:", err)
- }
-
- // Output: got error: close error
-}
-
-func TestAllowsToSetRowsErrors(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- rows := NewRows([]string{"id", "title"}).
- AddRow(0, "one").
- AddRow(1, "two").
- RowError(1, fmt.Errorf("error"))
- mock.ExpectQuery("SELECT").WillReturnRows(rows)
-
- rs, err := db.Query("SELECT")
- if err != nil {
- t.Fatalf("unexpected error: %s", err)
- }
- defer rs.Close()
-
- if !rs.Next() {
- t.Fatal("expected the first row to be available")
- }
- if rs.Err() != nil {
- t.Fatalf("unexpected error: %s", rs.Err())
- }
-
- if rs.Next() {
- t.Fatal("was not expecting the second row, since there should be an error")
- }
- if rs.Err() == nil {
- t.Fatal("expected an error, but got none")
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestRowsCloseError(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- rows := NewRows([]string{"id"}).CloseError(fmt.Errorf("close error"))
- mock.ExpectQuery("SELECT").WillReturnRows(rows)
-
- rs, err := db.Query("SELECT")
- if err != nil {
- t.Fatalf("unexpected error: %s", err)
- }
-
- if err := rs.Close(); err == nil {
- t.Fatal("expected a close error")
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestQuerySingleRow(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- rows := NewRows([]string{"id"}).
- AddRow(1).
- AddRow(2)
- mock.ExpectQuery("SELECT").WillReturnRows(rows)
-
- var id int
- if err := db.QueryRow("SELECT").Scan(&id); err != nil {
- t.Fatalf("unexpected error: %s", err)
- }
-
- mock.ExpectQuery("SELECT").WillReturnRows(NewRows([]string{"id"}))
- if err := db.QueryRow("SELECT").Scan(&id); err != sql.ErrNoRows {
- t.Fatal("expected sql no rows error")
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestRowsScanError(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- r := NewRows([]string{"col1", "col2"}).AddRow("one", "two").AddRow("one", nil)
- mock.ExpectQuery("SELECT").WillReturnRows(r)
-
- rs, err := db.Query("SELECT")
- if err != nil {
- t.Fatalf("unexpected error: %s", err)
- }
- defer rs.Close()
-
- var one, two string
- if !rs.Next() || rs.Err() != nil || rs.Scan(&one, &two) != nil {
- t.Fatal("unexpected error on first row scan")
- }
-
- if !rs.Next() || rs.Err() != nil {
- t.Fatal("unexpected error on second row read")
- }
-
- err = rs.Scan(&one, &two)
- if err == nil {
- t.Fatal("expected an error for scan, but got none")
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestCSVRowParser(t *testing.T) {
- t.Parallel()
- rs := NewRows([]string{"col1", "col2"}).FromCSVString("a,NULL")
- db, mock, err := New()
- if err != nil {
- t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectQuery("SELECT").WillReturnRows(rs)
-
- rw, err := db.Query("SELECT")
- if err != nil {
- t.Fatalf("unexpected error: %s", err)
- }
- defer rw.Close()
- var col1 string
- var col2 []byte
-
- rw.Next()
- if err = rw.Scan(&col1, &col2); err != nil {
- t.Fatalf("unexpected error: %s", err)
- }
- if col1 != "a" {
- t.Fatalf("expected col1 to be 'a', but got [%T]:%+v", col1, col1)
- }
- if col2 != nil {
- t.Fatalf("expected col2 to be nil, but got [%T]:%+v", col2, col2)
- }
-}
-
-func TestWrongNumberOfValues(t *testing.T) {
- // Open new mock database
- db, mock, err := New()
- if err != nil {
- fmt.Println("error creating mock database")
- return
- }
- defer db.Close()
- defer func() {
- recover()
- }()
- mock.ExpectQuery("SELECT ID FROM TABLE").WithArgs(101).WillReturnRows(NewRows([]string{"ID"}).AddRow(101, "Hello"))
- db.Query("SELECT ID FROM TABLE", 101)
- // shouldn't reach here
- t.Error("expected panic from query")
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock.go
deleted file mode 100644
index b906a3f..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock.go
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
-Package sqlmock is a mock library implementing sql driver. Which has one and only
-purpose - to simulate any sql driver behavior in tests, without needing a real
-database connection. It helps to maintain correct **TDD** workflow.
-
-It does not require any modifications to your source code in order to test
-and mock database operations. Supports concurrency and multiple database mocking.
-
-The driver allows to mock any sql driver method behavior.
-*/
-package sqlmock
-
-import (
- "database/sql"
- "database/sql/driver"
- "fmt"
- "regexp"
- "time"
-)
-
-// Sqlmock interface serves to create expectations
-// for any kind of database action in order to mock
-// and test real database behavior.
-type Sqlmock interface {
-
- // ExpectClose queues an expectation for this database
- // action to be triggered. the *ExpectedClose allows
- // to mock database response
- ExpectClose() *ExpectedClose
-
- // ExpectationsWereMet checks whether all queued expectations
- // were met in order. If any of them was not met - an error is returned.
- ExpectationsWereMet() error
-
- // ExpectPrepare expects Prepare() to be called with sql query
- // which match sqlRegexStr given regexp.
- // the *ExpectedPrepare allows to mock database response.
- // Note that you may expect Query() or Exec() on the *ExpectedPrepare
- // statement to prevent repeating sqlRegexStr
- ExpectPrepare(sqlRegexStr string) *ExpectedPrepare
-
- // ExpectQuery expects Query() or QueryRow() to be called with sql query
- // which match sqlRegexStr given regexp.
- // the *ExpectedQuery allows to mock database response.
- ExpectQuery(sqlRegexStr string) *ExpectedQuery
-
- // ExpectExec expects Exec() to be called with sql query
- // which match sqlRegexStr given regexp.
- // the *ExpectedExec allows to mock database response
- ExpectExec(sqlRegexStr string) *ExpectedExec
-
- // ExpectBegin expects *sql.DB.Begin to be called.
- // the *ExpectedBegin allows to mock database response
- ExpectBegin() *ExpectedBegin
-
- // ExpectCommit expects *sql.Tx.Commit to be called.
- // the *ExpectedCommit allows to mock database response
- ExpectCommit() *ExpectedCommit
-
- // ExpectRollback expects *sql.Tx.Rollback to be called.
- // the *ExpectedRollback allows to mock database response
- ExpectRollback() *ExpectedRollback
-
- // MatchExpectationsInOrder gives an option whether to match all
- // expectations in the order they were set or not.
- //
- // By default it is set to - true. But if you use goroutines
- // to parallelize your query executation, that option may
- // be handy.
- //
- // This option may be turned on anytime during tests. As soon
- // as it is switched to false, expectations will be matched
- // in any order. Or otherwise if switched to true, any unmatched
- // expectations will be expected in order
- MatchExpectationsInOrder(bool)
-}
-
-type sqlmock struct {
- ordered bool
- dsn string
- opened int
- drv *mockDriver
-
- expected []expectation
-}
-
-func (c *sqlmock) open() (*sql.DB, Sqlmock, error) {
- db, err := sql.Open("sqlmock", c.dsn)
- if err != nil {
- return db, c, err
- }
- return db, c, db.Ping()
-}
-
-func (c *sqlmock) ExpectClose() *ExpectedClose {
- e := &ExpectedClose{}
- c.expected = append(c.expected, e)
- return e
-}
-
-func (c *sqlmock) MatchExpectationsInOrder(b bool) {
- c.ordered = b
-}
-
-// Close a mock database driver connection. It may or may not
-// be called depending on the sircumstances, but if it is called
-// there must be an *ExpectedClose expectation satisfied.
-// meets http://golang.org/pkg/database/sql/driver/#Conn interface
-func (c *sqlmock) Close() error {
- c.drv.Lock()
- defer c.drv.Unlock()
-
- c.opened--
- if c.opened == 0 {
- delete(c.drv.conns, c.dsn)
- }
-
- var expected *ExpectedClose
- var fulfilled int
- var ok bool
- for _, next := range c.expected {
- next.Lock()
- if next.fulfilled() {
- next.Unlock()
- fulfilled++
- continue
- }
-
- if expected, ok = next.(*ExpectedClose); ok {
- break
- }
-
- next.Unlock()
- if c.ordered {
- return fmt.Errorf("call to database Close, was not expected, next expectation is: %s", next)
- }
- }
-
- if expected == nil {
- msg := "call to database Close was not expected"
- if fulfilled == len(c.expected) {
- msg = "all expectations were already fulfilled, " + msg
- }
- return fmt.Errorf(msg)
- }
-
- expected.triggered = true
- expected.Unlock()
- return expected.err
-}
-
-func (c *sqlmock) ExpectationsWereMet() error {
- for _, e := range c.expected {
- if !e.fulfilled() {
- return fmt.Errorf("there is a remaining expectation which was not matched: %s", e)
- }
- }
- return nil
-}
-
-// Begin meets http://golang.org/pkg/database/sql/driver/#Conn interface
-func (c *sqlmock) Begin() (driver.Tx, error) {
- ex, err := c.begin()
- if err != nil {
- return nil, err
- }
-
- time.Sleep(ex.delay)
- return c, nil
-}
-
-func (c *sqlmock) begin() (*ExpectedBegin, error) {
- var expected *ExpectedBegin
- var ok bool
- var fulfilled int
- for _, next := range c.expected {
- next.Lock()
- if next.fulfilled() {
- next.Unlock()
- fulfilled++
- continue
- }
-
- if expected, ok = next.(*ExpectedBegin); ok {
- break
- }
-
- next.Unlock()
- if c.ordered {
- return nil, fmt.Errorf("call to database transaction Begin, was not expected, next expectation is: %s", next)
- }
- }
- if expected == nil {
- msg := "call to database transaction Begin was not expected"
- if fulfilled == len(c.expected) {
- msg = "all expectations were already fulfilled, " + msg
- }
- return nil, fmt.Errorf(msg)
- }
-
- expected.triggered = true
- expected.Unlock()
-
- return expected, expected.err
-}
-
-func (c *sqlmock) ExpectBegin() *ExpectedBegin {
- e := &ExpectedBegin{}
- c.expected = append(c.expected, e)
- return e
-}
-
-// Exec meets http://golang.org/pkg/database/sql/driver/#Execer
-func (c *sqlmock) Exec(query string, args []driver.Value) (driver.Result, error) {
- namedArgs := make([]namedValue, len(args))
- for i, v := range args {
- namedArgs[i] = namedValue{
- Ordinal: i + 1,
- Value: v,
- }
- }
-
- ex, err := c.exec(query, namedArgs)
- if err != nil {
- return nil, err
- }
-
- time.Sleep(ex.delay)
- return ex.result, nil
-}
-
-func (c *sqlmock) exec(query string, args []namedValue) (*ExpectedExec, error) {
- query = stripQuery(query)
- var expected *ExpectedExec
- var fulfilled int
- var ok bool
- for _, next := range c.expected {
- next.Lock()
- if next.fulfilled() {
- next.Unlock()
- fulfilled++
- continue
- }
-
- if c.ordered {
- if expected, ok = next.(*ExpectedExec); ok {
- break
- }
- next.Unlock()
- return nil, fmt.Errorf("call to exec query '%s' with args %+v, was not expected, next expectation is: %s", query, args, next)
- }
- if exec, ok := next.(*ExpectedExec); ok {
- if err := exec.attemptMatch(query, args); err == nil {
- expected = exec
- break
- }
- }
- next.Unlock()
- }
- if expected == nil {
- msg := "call to exec '%s' query with args %+v was not expected"
- if fulfilled == len(c.expected) {
- msg = "all expectations were already fulfilled, " + msg
- }
- return nil, fmt.Errorf(msg, query, args)
- }
- defer expected.Unlock()
-
- if !expected.queryMatches(query) {
- return nil, fmt.Errorf("exec query '%s', does not match regex '%s'", query, expected.sqlRegex.String())
- }
-
- if err := expected.argsMatches(args); err != nil {
- return nil, fmt.Errorf("exec query '%s', arguments do not match: %s", query, err)
- }
-
- expected.triggered = true
- if expected.err != nil {
- return nil, expected.err // mocked to return error
- }
-
- if expected.result == nil {
- return nil, fmt.Errorf("exec query '%s' with args %+v, must return a database/sql/driver.result, but it was not set for expectation %T as %+v", query, args, expected, expected)
- }
-
- return expected, nil
-}
-
-func (c *sqlmock) ExpectExec(sqlRegexStr string) *ExpectedExec {
- e := &ExpectedExec{}
- sqlRegexStr = stripQuery(sqlRegexStr)
- e.sqlRegex = regexp.MustCompile(sqlRegexStr)
- c.expected = append(c.expected, e)
- return e
-}
-
-// Prepare meets http://golang.org/pkg/database/sql/driver/#Conn interface
-func (c *sqlmock) Prepare(query string) (driver.Stmt, error) {
- ex, err := c.prepare(query)
- if err != nil {
- return nil, err
- }
-
- time.Sleep(ex.delay)
- return &statement{c, query, ex.closeErr}, nil
-}
-
-func (c *sqlmock) prepare(query string) (*ExpectedPrepare, error) {
- var expected *ExpectedPrepare
- var fulfilled int
- var ok bool
- for _, next := range c.expected {
- next.Lock()
- if next.fulfilled() {
- next.Unlock()
- fulfilled++
- continue
- }
-
- if expected, ok = next.(*ExpectedPrepare); ok {
- break
- }
-
- next.Unlock()
- if c.ordered {
- return nil, fmt.Errorf("call to Prepare statement with query '%s', was not expected, next expectation is: %s", query, next)
- }
- }
-
- query = stripQuery(query)
- if expected == nil {
- msg := "call to Prepare '%s' query was not expected"
- if fulfilled == len(c.expected) {
- msg = "all expectations were already fulfilled, " + msg
- }
- return nil, fmt.Errorf(msg, query)
- }
- defer expected.Unlock()
- if !expected.sqlRegex.MatchString(query) {
- return nil, fmt.Errorf("query '%s', does not match regex [%s]", query, expected.sqlRegex.String())
- }
-
- expected.triggered = true
- return expected, expected.err
-}
-
-func (c *sqlmock) ExpectPrepare(sqlRegexStr string) *ExpectedPrepare {
- sqlRegexStr = stripQuery(sqlRegexStr)
- e := &ExpectedPrepare{sqlRegex: regexp.MustCompile(sqlRegexStr), mock: c}
- c.expected = append(c.expected, e)
- return e
-}
-
-type namedValue struct {
- Name string
- Ordinal int
- Value driver.Value
-}
-
-// Query meets http://golang.org/pkg/database/sql/driver/#Queryer
-func (c *sqlmock) Query(query string, args []driver.Value) (driver.Rows, error) {
- namedArgs := make([]namedValue, len(args))
- for i, v := range args {
- namedArgs[i] = namedValue{
- Ordinal: i + 1,
- Value: v,
- }
- }
-
- ex, err := c.query(query, namedArgs)
- if err != nil {
- return nil, err
- }
-
- time.Sleep(ex.delay)
- return ex.rows, nil
-}
-
-func (c *sqlmock) query(query string, args []namedValue) (*ExpectedQuery, error) {
- query = stripQuery(query)
- var expected *ExpectedQuery
- var fulfilled int
- var ok bool
- for _, next := range c.expected {
- next.Lock()
- if next.fulfilled() {
- next.Unlock()
- fulfilled++
- continue
- }
-
- if c.ordered {
- if expected, ok = next.(*ExpectedQuery); ok {
- break
- }
- next.Unlock()
- return nil, fmt.Errorf("call to query '%s' with args %+v, was not expected, next expectation is: %s", query, args, next)
- }
- if qr, ok := next.(*ExpectedQuery); ok {
- if err := qr.attemptMatch(query, args); err == nil {
- expected = qr
- break
- }
- }
- next.Unlock()
- }
-
- if expected == nil {
- msg := "call to query '%s' with args %+v was not expected"
- if fulfilled == len(c.expected) {
- msg = "all expectations were already fulfilled, " + msg
- }
- return nil, fmt.Errorf(msg, query, args)
- }
-
- defer expected.Unlock()
-
- if !expected.queryMatches(query) {
- return nil, fmt.Errorf("query '%s', does not match regex [%s]", query, expected.sqlRegex.String())
- }
-
- if err := expected.argsMatches(args); err != nil {
- return nil, fmt.Errorf("exec query '%s', arguments do not match: %s", query, err)
- }
-
- expected.triggered = true
- if expected.err != nil {
- return nil, expected.err // mocked to return error
- }
-
- if expected.rows == nil {
- return nil, fmt.Errorf("query '%s' with args %+v, must return a database/sql/driver.rows, but it was not set for expectation %T as %+v", query, args, expected, expected)
- }
- return expected, nil
-}
-
-func (c *sqlmock) ExpectQuery(sqlRegexStr string) *ExpectedQuery {
- e := &ExpectedQuery{}
- sqlRegexStr = stripQuery(sqlRegexStr)
- e.sqlRegex = regexp.MustCompile(sqlRegexStr)
- c.expected = append(c.expected, e)
- return e
-}
-
-func (c *sqlmock) ExpectCommit() *ExpectedCommit {
- e := &ExpectedCommit{}
- c.expected = append(c.expected, e)
- return e
-}
-
-func (c *sqlmock) ExpectRollback() *ExpectedRollback {
- e := &ExpectedRollback{}
- c.expected = append(c.expected, e)
- return e
-}
-
-// Commit meets http://golang.org/pkg/database/sql/driver/#Tx
-func (c *sqlmock) Commit() error {
- var expected *ExpectedCommit
- var fulfilled int
- var ok bool
- for _, next := range c.expected {
- next.Lock()
- if next.fulfilled() {
- next.Unlock()
- fulfilled++
- continue
- }
-
- if expected, ok = next.(*ExpectedCommit); ok {
- break
- }
-
- next.Unlock()
- if c.ordered {
- return fmt.Errorf("call to commit transaction, was not expected, next expectation is: %s", next)
- }
- }
- if expected == nil {
- msg := "call to commit transaction was not expected"
- if fulfilled == len(c.expected) {
- msg = "all expectations were already fulfilled, " + msg
- }
- return fmt.Errorf(msg)
- }
-
- expected.triggered = true
- expected.Unlock()
- return expected.err
-}
-
-// Rollback meets http://golang.org/pkg/database/sql/driver/#Tx
-func (c *sqlmock) Rollback() error {
- var expected *ExpectedRollback
- var fulfilled int
- var ok bool
- for _, next := range c.expected {
- next.Lock()
- if next.fulfilled() {
- next.Unlock()
- fulfilled++
- continue
- }
-
- if expected, ok = next.(*ExpectedRollback); ok {
- break
- }
-
- next.Unlock()
- if c.ordered {
- return fmt.Errorf("call to rollback transaction, was not expected, next expectation is: %s", next)
- }
- }
- if expected == nil {
- msg := "call to rollback transaction was not expected"
- if fulfilled == len(c.expected) {
- msg = "all expectations were already fulfilled, " + msg
- }
- return fmt.Errorf(msg)
- }
-
- expected.triggered = true
- expected.Unlock()
- return expected.err
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18.go
deleted file mode 100644
index c49429c..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18.go
+++ /dev/null
@@ -1,101 +0,0 @@
-// +build go1.8
-
-package sqlmock
-
-import (
- "context"
- "database/sql/driver"
- "errors"
- "time"
-)
-
-var ErrCancelled = errors.New("canceling query due to user request")
-
-// Implement the "QueryerContext" interface
-func (c *sqlmock) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
- namedArgs := make([]namedValue, len(args))
- for i, nv := range args {
- namedArgs[i] = namedValue(nv)
- }
-
- ex, err := c.query(query, namedArgs)
- if err != nil {
- return nil, err
- }
-
- select {
- case <-time.After(ex.delay):
- return ex.rows, nil
- case <-ctx.Done():
- return nil, ErrCancelled
- }
-}
-
-// Implement the "ExecerContext" interface
-func (c *sqlmock) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
- namedArgs := make([]namedValue, len(args))
- for i, nv := range args {
- namedArgs[i] = namedValue(nv)
- }
-
- ex, err := c.exec(query, namedArgs)
- if err != nil {
- return nil, err
- }
-
- select {
- case <-time.After(ex.delay):
- return ex.result, nil
- case <-ctx.Done():
- return nil, ErrCancelled
- }
-}
-
-// Implement the "ConnBeginTx" interface
-func (c *sqlmock) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
- ex, err := c.begin()
- if err != nil {
- return nil, err
- }
-
- select {
- case <-time.After(ex.delay):
- return c, nil
- case <-ctx.Done():
- return nil, ErrCancelled
- }
-}
-
-// Implement the "ConnPrepareContext" interface
-func (c *sqlmock) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
- ex, err := c.prepare(query)
- if err != nil {
- return nil, err
- }
-
- select {
- case <-time.After(ex.delay):
- return &statement{c, query, ex.closeErr}, nil
- case <-ctx.Done():
- return nil, ErrCancelled
- }
-}
-
-// Implement the "Pinger" interface
-// for now we do not have a Ping expectation
-// may be something for the future
-func (c *sqlmock) Ping(ctx context.Context) error {
- return nil
-}
-
-// Implement the "StmtExecContext" interface
-func (stmt *statement) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
- return stmt.conn.ExecContext(ctx, stmt.query, args)
-}
-
-// Implement the "StmtQueryContext" interface
-func (stmt *statement) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
- return stmt.conn.QueryContext(ctx, stmt.query, args)
-}
-
-// @TODO maybe add ExpectedBegin.WithOptions(driver.TxOptions)
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18_test.go
deleted file mode 100644
index 9eadcb5..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_go18_test.go
+++ /dev/null
@@ -1,426 +0,0 @@
-// +build go1.8
-
-package sqlmock
-
-import (
- "context"
- "database/sql"
- "testing"
- "time"
-)
-
-func TestContextExecCancel(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectExec("DELETE FROM users").
- WillDelayFor(time.Second).
- WillReturnResult(NewResult(1, 1))
-
- ctx, cancel := context.WithCancel(context.Background())
-
- go func() {
- time.Sleep(time.Millisecond * 10)
- cancel()
- }()
-
- _, err = db.ExecContext(ctx, "DELETE FROM users")
- if err == nil {
- t.Error("error was expected, but there was none")
- }
-
- if err != ErrCancelled {
- t.Errorf("was expecting cancel error, but got: %v", err)
- }
-
- _, err = db.ExecContext(ctx, "DELETE FROM users")
- if err != context.Canceled {
- t.Error("error was expected since context was already done, but there was none")
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestPreparedStatementContextExecCancel(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectPrepare("DELETE FROM users").
- ExpectExec().
- WillDelayFor(time.Second).
- WillReturnResult(NewResult(1, 1))
-
- ctx, cancel := context.WithCancel(context.Background())
-
- go func() {
- time.Sleep(time.Millisecond * 10)
- cancel()
- }()
-
- stmt, err := db.Prepare("DELETE FROM users")
- if err != nil {
- t.Errorf("error was not expected, but got: %v", err)
- }
-
- _, err = stmt.ExecContext(ctx)
- if err == nil {
- t.Error("error was expected, but there was none")
- }
-
- if err != ErrCancelled {
- t.Errorf("was expecting cancel error, but got: %v", err)
- }
-
- _, err = stmt.ExecContext(ctx)
- if err != context.Canceled {
- t.Error("error was expected since context was already done, but there was none")
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestContextExecWithNamedArg(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectExec("DELETE FROM users").
- WithArgs(sql.Named("id", 5)).
- WillDelayFor(time.Second).
- WillReturnResult(NewResult(1, 1))
-
- ctx, cancel := context.WithCancel(context.Background())
-
- go func() {
- time.Sleep(time.Millisecond * 10)
- cancel()
- }()
-
- _, err = db.ExecContext(ctx, "DELETE FROM users WHERE id = :id", sql.Named("id", 5))
- if err == nil {
- t.Error("error was expected, but there was none")
- }
-
- if err != ErrCancelled {
- t.Errorf("was expecting cancel error, but got: %v", err)
- }
-
- _, err = db.ExecContext(ctx, "DELETE FROM users WHERE id = :id", sql.Named("id", 5))
- if err != context.Canceled {
- t.Error("error was expected since context was already done, but there was none")
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestContextExec(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectExec("DELETE FROM users").
- WillReturnResult(NewResult(1, 1))
-
- ctx, cancel := context.WithCancel(context.Background())
-
- go func() {
- time.Sleep(time.Millisecond * 10)
- cancel()
- }()
-
- res, err := db.ExecContext(ctx, "DELETE FROM users")
- if err != nil {
- t.Errorf("error was not expected, but got: %v", err)
- }
-
- affected, err := res.RowsAffected()
- if affected != 1 {
- t.Errorf("expected affected rows 1, but got %v", affected)
- }
-
- if err != nil {
- t.Errorf("error was not expected, but got: %v", err)
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestContextQueryCancel(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- rs := NewRows([]string{"id", "title"}).AddRow(5, "hello world")
-
- mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
- WithArgs(5).
- WillDelayFor(time.Second).
- WillReturnRows(rs)
-
- ctx, cancel := context.WithCancel(context.Background())
-
- go func() {
- time.Sleep(time.Millisecond * 10)
- cancel()
- }()
-
- _, err = db.QueryContext(ctx, "SELECT id, title FROM articles WHERE id = ?", 5)
- if err == nil {
- t.Error("error was expected, but there was none")
- }
-
- if err != ErrCancelled {
- t.Errorf("was expecting cancel error, but got: %v", err)
- }
-
- _, err = db.QueryContext(ctx, "SELECT id, title FROM articles WHERE id = ?", 5)
- if err != context.Canceled {
- t.Error("error was expected since context was already done, but there was none")
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestPreparedStatementContextQueryCancel(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- rs := NewRows([]string{"id", "title"}).AddRow(5, "hello world")
-
- mock.ExpectPrepare("SELECT (.+) FROM articles WHERE id = ?").
- ExpectQuery().
- WithArgs(5).
- WillDelayFor(time.Second).
- WillReturnRows(rs)
-
- ctx, cancel := context.WithCancel(context.Background())
-
- go func() {
- time.Sleep(time.Millisecond * 10)
- cancel()
- }()
-
- stmt, err := db.Prepare("SELECT id, title FROM articles WHERE id = ?")
- if err != nil {
- t.Errorf("error was not expected, but got: %v", err)
- }
-
- _, err = stmt.QueryContext(ctx, 5)
- if err == nil {
- t.Error("error was expected, but there was none")
- }
-
- if err != ErrCancelled {
- t.Errorf("was expecting cancel error, but got: %v", err)
- }
-
- _, err = stmt.QueryContext(ctx, 5)
- if err != context.Canceled {
- t.Error("error was expected since context was already done, but there was none")
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestContextQuery(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- rs := NewRows([]string{"id", "title"}).AddRow(5, "hello world")
-
- mock.ExpectQuery("SELECT (.+) FROM articles WHERE id =").
- WithArgs(sql.Named("id", 5)).
- WillDelayFor(time.Millisecond * 3).
- WillReturnRows(rs)
-
- ctx, cancel := context.WithCancel(context.Background())
-
- go func() {
- time.Sleep(time.Millisecond * 10)
- cancel()
- }()
-
- rows, err := db.QueryContext(ctx, "SELECT id, title FROM articles WHERE id = :id", sql.Named("id", 5))
- if err != nil {
- t.Errorf("error was not expected, but got: %v", err)
- }
-
- if !rows.Next() {
- t.Error("expected one row, but there was none")
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestContextBeginCancel(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectBegin().WillDelayFor(time.Second)
-
- ctx, cancel := context.WithCancel(context.Background())
-
- go func() {
- time.Sleep(time.Millisecond * 10)
- cancel()
- }()
-
- _, err = db.BeginTx(ctx, nil)
- if err == nil {
- t.Error("error was expected, but there was none")
- }
-
- if err != ErrCancelled {
- t.Errorf("was expecting cancel error, but got: %v", err)
- }
-
- _, err = db.BeginTx(ctx, nil)
- if err != context.Canceled {
- t.Error("error was expected since context was already done, but there was none")
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestContextBegin(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectBegin().WillDelayFor(time.Millisecond * 3)
-
- ctx, cancel := context.WithCancel(context.Background())
-
- go func() {
- time.Sleep(time.Millisecond * 10)
- cancel()
- }()
-
- tx, err := db.BeginTx(ctx, nil)
- if err != nil {
- t.Errorf("error was not expected, but got: %v", err)
- }
-
- if tx == nil {
- t.Error("expected tx, but there was nil")
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestContextPrepareCancel(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectPrepare("SELECT").WillDelayFor(time.Second)
-
- ctx, cancel := context.WithCancel(context.Background())
-
- go func() {
- time.Sleep(time.Millisecond * 10)
- cancel()
- }()
-
- _, err = db.PrepareContext(ctx, "SELECT")
- if err == nil {
- t.Error("error was expected, but there was none")
- }
-
- if err != ErrCancelled {
- t.Errorf("was expecting cancel error, but got: %v", err)
- }
-
- _, err = db.PrepareContext(ctx, "SELECT")
- if err != context.Canceled {
- t.Error("error was expected since context was already done, but there was none")
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestContextPrepare(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectPrepare("SELECT").WillDelayFor(time.Millisecond * 3)
-
- ctx, cancel := context.WithCancel(context.Background())
-
- go func() {
- time.Sleep(time.Millisecond * 10)
- cancel()
- }()
-
- stmt, err := db.PrepareContext(ctx, "SELECT")
- if err != nil {
- t.Errorf("error was not expected, but got: %v", err)
- }
-
- if stmt == nil {
- t.Error("expected stmt, but there was nil")
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_test.go
deleted file mode 100644
index fe4924b..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/sqlmock_test.go
+++ /dev/null
@@ -1,998 +0,0 @@
-package sqlmock
-
-import (
- "database/sql"
- "fmt"
- "strconv"
- "sync"
- "testing"
- "time"
-)
-
-func cancelOrder(db *sql.DB, orderID int) error {
- tx, _ := db.Begin()
- _, _ = tx.Query("SELECT * FROM orders {0} FOR UPDATE", orderID)
- err := tx.Rollback()
- if err != nil {
- return err
- }
- return nil
-}
-
-func Example() {
- // Open new mock database
- db, mock, err := New()
- if err != nil {
- fmt.Println("error creating mock database")
- return
- }
- // columns to be used for result
- columns := []string{"id", "status"}
- // expect transaction begin
- mock.ExpectBegin()
- // expect query to fetch order, match it with regexp
- mock.ExpectQuery("SELECT (.+) FROM orders (.+) FOR UPDATE").
- WithArgs(1).
- WillReturnRows(NewRows(columns).AddRow(1, 1))
- // expect transaction rollback, since order status is "cancelled"
- mock.ExpectRollback()
-
- // run the cancel order function
- someOrderID := 1
- // call a function which executes expected database operations
- err = cancelOrder(db, someOrderID)
- if err != nil {
- fmt.Printf("unexpected error: %s", err)
- return
- }
-
- // ensure all expectations have been met
- if err = mock.ExpectationsWereMet(); err != nil {
- fmt.Printf("unmet expectation error: %s", err)
- }
- // Output:
-}
-
-func TestIssue14EscapeSQL(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
- mock.ExpectExec("INSERT INTO mytable\\(a, b\\)").
- WithArgs("A", "B").
- WillReturnResult(NewResult(1, 1))
-
- _, err = db.Exec("INSERT INTO mytable(a, b) VALUES (?, ?)", "A", "B")
- if err != nil {
- t.Errorf("error '%s' was not expected, while inserting a row", err)
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-// test the case when db is not triggered and expectations
-// are not asserted on close
-func TestIssue4(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectQuery("some sql query which will not be called").
- WillReturnRows(NewRows([]string{"id"}))
-
- if err := mock.ExpectationsWereMet(); err == nil {
- t.Errorf("was expecting an error since query was not triggered")
- }
-}
-
-func TestMockQuery(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- rs := NewRows([]string{"id", "title"}).FromCSVString("5,hello world")
-
- mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
- WithArgs(5).
- WillReturnRows(rs)
-
- rows, err := db.Query("SELECT (.+) FROM articles WHERE id = ?", 5)
- if err != nil {
- t.Errorf("error '%s' was not expected while retrieving mock rows", err)
- }
-
- defer func() {
- if er := rows.Close(); er != nil {
- t.Error("Unexpected error while trying to close rows")
- }
- }()
-
- if !rows.Next() {
- t.Error("it must have had one row as result, but got empty result set instead")
- }
-
- var id int
- var title string
-
- err = rows.Scan(&id, &title)
- if err != nil {
- t.Errorf("error '%s' was not expected while trying to scan row", err)
- }
-
- if id != 5 {
- t.Errorf("expected mocked id to be 5, but got %d instead", id)
- }
-
- if title != "hello world" {
- t.Errorf("expected mocked title to be 'hello world', but got '%s' instead", title)
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestMockQueryTypes(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- columns := []string{"id", "timestamp", "sold"}
-
- timestamp := time.Now()
- rs := NewRows(columns)
- rs.AddRow(5, timestamp, true)
-
- mock.ExpectQuery("SELECT (.+) FROM sales WHERE id = ?").
- WithArgs(5).
- WillReturnRows(rs)
-
- rows, err := db.Query("SELECT (.+) FROM sales WHERE id = ?", 5)
- if err != nil {
- t.Errorf("error '%s' was not expected while retrieving mock rows", err)
- }
- defer func() {
- if er := rows.Close(); er != nil {
- t.Error("Unexpected error while trying to close rows")
- }
- }()
- if !rows.Next() {
- t.Error("it must have had one row as result, but got empty result set instead")
- }
-
- var id int
- var time time.Time
- var sold bool
-
- err = rows.Scan(&id, &time, &sold)
- if err != nil {
- t.Errorf("error '%s' was not expected while trying to scan row", err)
- }
-
- if id != 5 {
- t.Errorf("expected mocked id to be 5, but got %d instead", id)
- }
-
- if time != timestamp {
- t.Errorf("expected mocked time to be %s, but got '%s' instead", timestamp, time)
- }
-
- if sold != true {
- t.Errorf("expected mocked boolean to be true, but got %v instead", sold)
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestTransactionExpectations(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- // begin and commit
- mock.ExpectBegin()
- mock.ExpectCommit()
-
- tx, err := db.Begin()
- if err != nil {
- t.Errorf("an error '%s' was not expected when beginning a transaction", err)
- }
-
- err = tx.Commit()
- if err != nil {
- t.Errorf("an error '%s' was not expected when committing a transaction", err)
- }
-
- // begin and rollback
- mock.ExpectBegin()
- mock.ExpectRollback()
-
- tx, err = db.Begin()
- if err != nil {
- t.Errorf("an error '%s' was not expected when beginning a transaction", err)
- }
-
- err = tx.Rollback()
- if err != nil {
- t.Errorf("an error '%s' was not expected when rolling back a transaction", err)
- }
-
- // begin with an error
- mock.ExpectBegin().WillReturnError(fmt.Errorf("some err"))
-
- tx, err = db.Begin()
- if err == nil {
- t.Error("an error was expected when beginning a transaction, but got none")
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestPrepareExpectations(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectPrepare("SELECT (.+) FROM articles WHERE id = ?")
-
- stmt, err := db.Prepare("SELECT (.+) FROM articles WHERE id = ?")
- if err != nil {
- t.Errorf("error '%s' was not expected while creating a prepared statement", err)
- }
- if stmt == nil {
- t.Errorf("stmt was expected while creating a prepared statement")
- }
-
- // expect something else, w/o ExpectPrepare()
- var id int
- var title string
- rs := NewRows([]string{"id", "title"}).FromCSVString("5,hello world")
-
- mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
- WithArgs(5).
- WillReturnRows(rs)
-
- err = stmt.QueryRow(5).Scan(&id, &title)
- if err != nil {
- t.Errorf("error '%s' was not expected while retrieving mock rows", err)
- }
-
- mock.ExpectPrepare("SELECT (.+) FROM articles WHERE id = ?").
- WillReturnError(fmt.Errorf("Some DB error occurred"))
-
- stmt, err = db.Prepare("SELECT id FROM articles WHERE id = ?")
- if err == nil {
- t.Error("error was expected while creating a prepared statement")
- }
- if stmt != nil {
- t.Errorf("stmt was not expected while creating a prepared statement returning error")
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestPreparedQueryExecutions(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectPrepare("SELECT (.+) FROM articles WHERE id = ?")
-
- rs1 := NewRows([]string{"id", "title"}).FromCSVString("5,hello world")
- mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
- WithArgs(5).
- WillReturnRows(rs1)
-
- rs2 := NewRows([]string{"id", "title"}).FromCSVString("2,whoop")
- mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
- WithArgs(2).
- WillReturnRows(rs2)
-
- stmt, err := db.Prepare("SELECT id, title FROM articles WHERE id = ?")
- if err != nil {
- t.Errorf("error '%s' was not expected while creating a prepared statement", err)
- }
-
- var id int
- var title string
- err = stmt.QueryRow(5).Scan(&id, &title)
- if err != nil {
- t.Errorf("error '%s' was not expected querying row from statement and scanning", err)
- }
-
- if id != 5 {
- t.Errorf("expected mocked id to be 5, but got %d instead", id)
- }
-
- if title != "hello world" {
- t.Errorf("expected mocked title to be 'hello world', but got '%s' instead", title)
- }
-
- err = stmt.QueryRow(2).Scan(&id, &title)
- if err != nil {
- t.Errorf("error '%s' was not expected querying row from statement and scanning", err)
- }
-
- if id != 2 {
- t.Errorf("expected mocked id to be 2, but got %d instead", id)
- }
-
- if title != "whoop" {
- t.Errorf("expected mocked title to be 'whoop', but got '%s' instead", title)
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestUnexpectedOperations(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectPrepare("SELECT (.+) FROM articles WHERE id = ?")
- stmt, err := db.Prepare("SELECT id, title FROM articles WHERE id = ?")
- if err != nil {
- t.Errorf("error '%s' was not expected while creating a prepared statement", err)
- }
-
- var id int
- var title string
-
- err = stmt.QueryRow(5).Scan(&id, &title)
- if err == nil {
- t.Error("error was expected querying row, since there was no such expectation")
- }
-
- mock.ExpectRollback()
-
- if err := mock.ExpectationsWereMet(); err == nil {
- t.Errorf("was expecting an error since query was not triggered")
- }
-}
-
-func TestWrongExpectations(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectBegin()
-
- rs1 := NewRows([]string{"id", "title"}).FromCSVString("5,hello world")
- mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
- WithArgs(5).
- WillReturnRows(rs1)
-
- mock.ExpectCommit().WillReturnError(fmt.Errorf("deadlock occurred"))
- mock.ExpectRollback() // won't be triggered
-
- var id int
- var title string
-
- err = db.QueryRow("SELECT id, title FROM articles WHERE id = ? FOR UPDATE", 5).Scan(&id, &title)
- if err == nil {
- t.Error("error was expected while querying row, since there begin transaction expectation is not fulfilled")
- }
-
- // lets go around and start transaction
- tx, err := db.Begin()
- if err != nil {
- t.Errorf("an error '%s' was not expected when beginning a transaction", err)
- }
-
- err = db.QueryRow("SELECT id, title FROM articles WHERE id = ? FOR UPDATE", 5).Scan(&id, &title)
- if err != nil {
- t.Errorf("error '%s' was not expected while querying row, since transaction was started", err)
- }
-
- err = tx.Commit()
- if err == nil {
- t.Error("a deadlock error was expected when committing a transaction", err)
- }
-
- if err := mock.ExpectationsWereMet(); err == nil {
- t.Errorf("was expecting an error since query was not triggered")
- }
-}
-
-func TestExecExpectations(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- result := NewResult(1, 1)
- mock.ExpectExec("^INSERT INTO articles").
- WithArgs("hello").
- WillReturnResult(result)
-
- res, err := db.Exec("INSERT INTO articles (title) VALUES (?)", "hello")
- if err != nil {
- t.Errorf("error '%s' was not expected, while inserting a row", err)
- }
-
- id, err := res.LastInsertId()
- if err != nil {
- t.Errorf("error '%s' was not expected, while getting a last insert id", err)
- }
-
- affected, err := res.RowsAffected()
- if err != nil {
- t.Errorf("error '%s' was not expected, while getting affected rows", err)
- }
-
- if id != 1 {
- t.Errorf("expected last insert id to be 1, but got %d instead", id)
- }
-
- if affected != 1 {
- t.Errorf("expected affected rows to be 1, but got %d instead", affected)
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestRowBuilderAndNilTypes(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- rs := NewRows([]string{"id", "active", "created", "status"}).
- AddRow(1, true, time.Now(), 5).
- AddRow(2, false, nil, nil)
-
- mock.ExpectQuery("SELECT (.+) FROM sales").WillReturnRows(rs)
-
- rows, err := db.Query("SELECT * FROM sales")
- if err != nil {
- t.Errorf("error '%s' was not expected while retrieving mock rows", err)
- }
- defer func() {
- if er := rows.Close(); er != nil {
- t.Error("Unexpected error while trying to close rows")
- }
- }()
-
- // NullTime and NullInt are used from stubs_test.go
- var (
- id int
- active bool
- created NullTime
- status NullInt
- )
-
- if !rows.Next() {
- t.Error("it must have had row in rows, but got empty result set instead")
- }
-
- err = rows.Scan(&id, &active, &created, &status)
- if err != nil {
- t.Errorf("error '%s' was not expected while trying to scan row", err)
- }
-
- if id != 1 {
- t.Errorf("expected mocked id to be 1, but got %d instead", id)
- }
-
- if !active {
- t.Errorf("expected 'active' to be 'true', but got '%v' instead", active)
- }
-
- if !created.Valid {
- t.Errorf("expected 'created' to be valid, but it %+v is not", created)
- }
-
- if !status.Valid {
- t.Errorf("expected 'status' to be valid, but it %+v is not", status)
- }
-
- if status.Integer != 5 {
- t.Errorf("expected 'status' to be '5', but got '%d'", status.Integer)
- }
-
- // test second row
- if !rows.Next() {
- t.Error("it must have had row in rows, but got empty result set instead")
- }
-
- err = rows.Scan(&id, &active, &created, &status)
- if err != nil {
- t.Errorf("error '%s' was not expected while trying to scan row", err)
- }
-
- if id != 2 {
- t.Errorf("expected mocked id to be 2, but got %d instead", id)
- }
-
- if active {
- t.Errorf("expected 'active' to be 'false', but got '%v' instead", active)
- }
-
- if created.Valid {
- t.Errorf("expected 'created' to be invalid, but it %+v is not", created)
- }
-
- if status.Valid {
- t.Errorf("expected 'status' to be invalid, but it %+v is not", status)
- }
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestArgumentReflectValueTypeError(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- rs := NewRows([]string{"id"}).AddRow(1)
-
- mock.ExpectQuery("SELECT (.+) FROM sales").WithArgs(5.5).WillReturnRows(rs)
-
- _, err = db.Query("SELECT * FROM sales WHERE x = ?", 5)
- if err == nil {
- t.Error("Expected error, but got none")
- }
-}
-
-func TestGoroutineExecutionWithUnorderedExpectationMatching(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- // note this line is important for unordered expectation matching
- mock.MatchExpectationsInOrder(false)
-
- result := NewResult(1, 1)
-
- mock.ExpectExec("^UPDATE one").WithArgs("one").WillReturnResult(result)
- mock.ExpectExec("^UPDATE two").WithArgs("one", "two").WillReturnResult(result)
- mock.ExpectExec("^UPDATE three").WithArgs("one", "two", "three").WillReturnResult(result)
-
- var wg sync.WaitGroup
- queries := map[string][]interface{}{
- "one": []interface{}{"one"},
- "two": []interface{}{"one", "two"},
- "three": []interface{}{"one", "two", "three"},
- }
-
- wg.Add(len(queries))
- for table, args := range queries {
- go func(tbl string, a []interface{}) {
- if _, err := db.Exec("UPDATE "+tbl, a...); err != nil {
- t.Errorf("error was not expected: %s", err)
- }
- wg.Done()
- }(table, args)
- }
-
- wg.Wait()
-
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func ExampleSqlmock_goroutines() {
- db, mock, err := New()
- if err != nil {
- fmt.Println("failed to open sqlmock database:", err)
- }
- defer db.Close()
-
- // note this line is important for unordered expectation matching
- mock.MatchExpectationsInOrder(false)
-
- result := NewResult(1, 1)
-
- mock.ExpectExec("^UPDATE one").WithArgs("one").WillReturnResult(result)
- mock.ExpectExec("^UPDATE two").WithArgs("one", "two").WillReturnResult(result)
- mock.ExpectExec("^UPDATE three").WithArgs("one", "two", "three").WillReturnResult(result)
-
- var wg sync.WaitGroup
- queries := map[string][]interface{}{
- "one": []interface{}{"one"},
- "two": []interface{}{"one", "two"},
- "three": []interface{}{"one", "two", "three"},
- }
-
- wg.Add(len(queries))
- for table, args := range queries {
- go func(tbl string, a []interface{}) {
- if _, err := db.Exec("UPDATE "+tbl, a...); err != nil {
- fmt.Println("error was not expected:", err)
- }
- wg.Done()
- }(table, args)
- }
-
- wg.Wait()
-
- if err := mock.ExpectationsWereMet(); err != nil {
- fmt.Println("there were unfulfilled expections:", err)
- }
- // Output:
-}
-
-// False Positive - passes despite mismatched Exec
-// see #37 issue
-func TestRunExecsWithOrderedShouldNotMeetAllExpectations(t *testing.T) {
- db, dbmock, _ := New()
- dbmock.ExpectExec("THE FIRST EXEC")
- dbmock.ExpectExec("THE SECOND EXEC")
-
- _, _ = db.Exec("THE FIRST EXEC")
- _, _ = db.Exec("THE WRONG EXEC")
-
- err := dbmock.ExpectationsWereMet()
- if err == nil {
- t.Fatal("was expecting an error, but there wasn't any")
- }
-}
-
-// False Positive - passes despite mismatched Exec
-// see #37 issue
-func TestRunQueriesWithOrderedShouldNotMeetAllExpectations(t *testing.T) {
- db, dbmock, _ := New()
- dbmock.ExpectQuery("THE FIRST QUERY")
- dbmock.ExpectQuery("THE SECOND QUERY")
-
- _, _ = db.Query("THE FIRST QUERY")
- _, _ = db.Query("THE WRONG QUERY")
-
- err := dbmock.ExpectationsWereMet()
- if err == nil {
- t.Fatal("was expecting an error, but there wasn't any")
- }
-}
-
-func TestRunExecsWithExpectedErrorMeetsExpectations(t *testing.T) {
- db, dbmock, _ := New()
- dbmock.ExpectExec("THE FIRST EXEC").WillReturnError(fmt.Errorf("big bad bug"))
- dbmock.ExpectExec("THE SECOND EXEC").WillReturnResult(NewResult(0, 0))
-
- _, _ = db.Exec("THE FIRST EXEC")
- _, _ = db.Exec("THE SECOND EXEC")
-
- err := dbmock.ExpectationsWereMet()
- if err != nil {
- t.Fatalf("all expectations should be met: %s", err)
- }
-}
-
-func TestRunQueryWithExpectedErrorMeetsExpectations(t *testing.T) {
- db, dbmock, _ := New()
- dbmock.ExpectQuery("THE FIRST QUERY").WillReturnError(fmt.Errorf("big bad bug"))
- dbmock.ExpectQuery("THE SECOND QUERY").WillReturnRows(NewRows([]string{"col"}).AddRow(1))
-
- _, _ = db.Query("THE FIRST QUERY")
- _, _ = db.Query("THE SECOND QUERY")
-
- err := dbmock.ExpectationsWereMet()
- if err != nil {
- t.Fatalf("all expectations should be met: %s", err)
- }
-}
-
-func TestEmptyRowSet(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- rs := NewRows([]string{"id", "title"})
-
- mock.ExpectQuery("SELECT (.+) FROM articles WHERE id = ?").
- WithArgs(5).
- WillReturnRows(rs)
-
- rows, err := db.Query("SELECT (.+) FROM articles WHERE id = ?", 5)
- if err != nil {
- t.Errorf("error '%s' was not expected while retrieving mock rows", err)
- }
-
- defer func() {
- if er := rows.Close(); er != nil {
- t.Error("Unexpected error while trying to close rows")
- }
- }()
-
- if rows.Next() {
- t.Error("expected no rows but got one")
- }
-
- err = mock.ExpectationsWereMet()
- if err != nil {
- t.Fatalf("all expectations should be met: %s", err)
- }
-}
-
-// Based on issue #50
-func TestPrepareExpectationNotFulfilled(t *testing.T) {
- t.Parallel()
- db, mock, err := New()
- if err != nil {
- t.Errorf("an error '%s' was not expected when opening a stub database connection", err)
- }
- defer db.Close()
-
- mock.ExpectPrepare("^BADSELECT$")
-
- if _, err := db.Prepare("SELECT"); err == nil {
- t.Fatal("prepare should not match expected query string")
- }
-
- if err := mock.ExpectationsWereMet(); err == nil {
- t.Errorf("was expecting an error, since prepared statement query does not match, but there was none")
- }
-}
-
-func TestRollbackThrow(t *testing.T) {
- // Open new mock database
- db, mock, err := New()
- if err != nil {
- fmt.Println("error creating mock database")
- return
- }
- // columns to be used for result
- columns := []string{"id", "status"}
- // expect transaction begin
- mock.ExpectBegin()
- // expect query to fetch order, match it with regexp
- mock.ExpectQuery("SELECT (.+) FROM orders (.+) FOR UPDATE").
- WithArgs(1).
- WillReturnRows(NewRows(columns).AddRow(1, 1))
- // expect transaction rollback, since order status is "cancelled"
- mock.ExpectRollback().WillReturnError(fmt.Errorf("rollback failed"))
-
- // run the cancel order function
- someOrderID := 1
- // call a function which executes expected database operations
- err = cancelOrder(db, someOrderID)
- if err == nil {
- t.Error("an error was expected when rolling back transaction, but got none")
- }
-
- // ensure all expectations have been met
- if err = mock.ExpectationsWereMet(); err != nil {
- t.Errorf("unmet expectation error: %s", err)
- }
- // Output:
-}
-
-func TestUnexpectedCommit(t *testing.T) {
- // Open new mock database
- db, mock, err := New()
- if err != nil {
- fmt.Println("error creating mock database")
- return
- }
- mock.ExpectBegin()
- tx, _ := db.Begin()
- if err := tx.Commit(); err == nil {
- t.Error("an error was expected when calling commit, but got none")
- }
-}
-
-func TestUnexpectedCommitOrder(t *testing.T) {
- // Open new mock database
- db, mock, err := New()
- if err != nil {
- fmt.Println("error creating mock database")
- return
- }
- mock.ExpectBegin()
- mock.ExpectRollback().WillReturnError(fmt.Errorf("Rollback failed"))
- tx, _ := db.Begin()
- if err := tx.Commit(); err == nil {
- t.Error("an error was expected when calling commit, but got none")
- }
-}
-
-func TestExpectedCommitOrder(t *testing.T) {
- // Open new mock database
- db, mock, err := New()
- if err != nil {
- fmt.Println("error creating mock database")
- return
- }
- mock.ExpectCommit().WillReturnError(fmt.Errorf("Commit failed"))
- if _, err := db.Begin(); err == nil {
- t.Error("an error was expected when calling begin, but got none")
- }
-}
-
-func TestUnexpectedRollback(t *testing.T) {
- // Open new mock database
- db, mock, err := New()
- if err != nil {
- fmt.Println("error creating mock database")
- return
- }
- mock.ExpectBegin()
- tx, _ := db.Begin()
- if err := tx.Rollback(); err == nil {
- t.Error("an error was expected when calling rollback, but got none")
- }
-}
-
-func TestUnexpectedRollbackOrder(t *testing.T) {
- // Open new mock database
- db, mock, err := New()
- if err != nil {
- fmt.Println("error creating mock database")
- return
- }
- mock.ExpectBegin()
-
- tx, _ := db.Begin()
- if err := tx.Rollback(); err == nil {
- t.Error("an error was expected when calling rollback, but got none")
- }
-}
-
-func TestPrepareExec(t *testing.T) {
- // Open new mock database
- db, mock, err := New()
- if err != nil {
- fmt.Println("error creating mock database")
- return
- }
- defer db.Close()
- mock.ExpectBegin()
- ep := mock.ExpectPrepare("INSERT INTO ORDERS\\(ID, STATUS\\) VALUES \\(\\?, \\?\\)")
- for i := 0; i < 3; i++ {
- ep.ExpectExec().WillReturnResult(NewResult(1, 1))
- }
- mock.ExpectCommit()
- tx, _ := db.Begin()
- stmt, err := tx.Prepare("INSERT INTO ORDERS(ID, STATUS) VALUES (?, ?)")
- if err != nil {
- t.Fatal(err)
- }
- defer stmt.Close()
- for i := 0; i < 3; i++ {
- _, err := stmt.Exec(i, "Hello"+strconv.Itoa(i))
- if err != nil {
- t.Fatal(err)
- }
- }
- tx.Commit()
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestPrepareQuery(t *testing.T) {
- // Open new mock database
- db, mock, err := New()
- if err != nil {
- fmt.Println("error creating mock database")
- return
- }
- defer db.Close()
- mock.ExpectBegin()
- ep := mock.ExpectPrepare("SELECT ID, STATUS FROM ORDERS WHERE ID = \\?")
- ep.ExpectQuery().WithArgs(101).WillReturnRows(NewRows([]string{"ID", "STATUS"}).AddRow(101, "Hello"))
- mock.ExpectCommit()
- tx, _ := db.Begin()
- stmt, err := tx.Prepare("SELECT ID, STATUS FROM ORDERS WHERE ID = ?")
- if err != nil {
- t.Fatal(err)
- }
- defer stmt.Close()
- rows, err := stmt.Query(101)
- if err != nil {
- t.Fatal(err)
- }
- defer rows.Close()
- for rows.Next() {
- var (
- id int
- status string
- )
- if rows.Scan(&id, &status); id != 101 || status != "Hello" {
- t.Fatal("wrong query results")
- }
-
- }
- tx.Commit()
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestExpectedCloseError(t *testing.T) {
- // Open new mock database
- db, mock, err := New()
- if err != nil {
- fmt.Println("error creating mock database")
- return
- }
- mock.ExpectClose().WillReturnError(fmt.Errorf("Close failed"))
- if err := db.Close(); err == nil {
- t.Error("an error was expected when calling close, but got none")
- }
- if err := mock.ExpectationsWereMet(); err != nil {
- t.Errorf("there were unfulfilled expections: %s", err)
- }
-}
-
-func TestExpectedCloseOrder(t *testing.T) {
- // Open new mock database
- db, mock, err := New()
- if err != nil {
- fmt.Println("error creating mock database")
- return
- }
- defer db.Close()
- mock.ExpectClose().WillReturnError(fmt.Errorf("Close failed"))
- db.Begin()
- if err := mock.ExpectationsWereMet(); err == nil {
- t.Error("expected error on ExpectationsWereMet")
- }
-}
-
-func TestExpectedBeginOrder(t *testing.T) {
- // Open new mock database
- db, mock, err := New()
- if err != nil {
- fmt.Println("error creating mock database")
- return
- }
- mock.ExpectBegin().WillReturnError(fmt.Errorf("Begin failed"))
- if err := db.Close(); err == nil {
- t.Error("an error was expected when calling close, but got none")
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement.go
deleted file mode 100644
index df73740..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package sqlmock
-
-import (
- "database/sql/driver"
-)
-
-type statement struct {
- conn *sqlmock
- query string
- err error
-}
-
-func (stmt *statement) Close() error {
- return stmt.err
-}
-
-func (stmt *statement) NumInput() int {
- return -1
-}
-
-func (stmt *statement) Exec(args []driver.Value) (driver.Result, error) {
- return stmt.conn.Exec(stmt.query, args)
-}
-
-func (stmt *statement) Query(args []driver.Value) (driver.Rows, error) {
- return stmt.conn.Query(stmt.query, args)
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement_test.go
deleted file mode 100644
index f951f63..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/statement_test.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// +build go1.6
-
-package sqlmock
-
-import (
- "errors"
- "testing"
-)
-
-func TestExpectedPreparedStatemtCloseError(t *testing.T) {
- conn, mock, err := New()
- if err != nil {
- t.Fatal("failed to open sqlmock database:", err)
- }
-
- mock.ExpectBegin()
- want := errors.New("STMT ERROR")
- mock.ExpectPrepare("SELECT").WillReturnCloseError(want)
-
- txn, err := conn.Begin()
- if err != nil {
- t.Fatal("unexpected error while opening transaction:", err)
- }
-
- stmt, err := txn.Prepare("SELECT")
- if err != nil {
- t.Fatal("unexpected error while preparing a statement:", err)
- }
-
- if err := stmt.Close(); err != want {
- t.Fatalf("Got = %v, want = %v", err, want)
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go
deleted file mode 100644
index d3c6003..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package sqlmock
-
-import (
- "database/sql/driver"
- "fmt"
- "strconv"
- "time"
-)
-
-type NullTime struct {
- Time time.Time
- Valid bool // Valid is true if Time is not NULL
-}
-
-type NullInt struct {
- Integer int
- Valid bool
-}
-
-// Satisfy sql.Scanner interface
-func (ni *NullInt) Scan(value interface{}) (err error) {
- if value == nil {
- ni.Integer, ni.Valid = 0, false
- return
- }
-
- switch v := value.(type) {
- case int, int8, int16, int32, int64:
- ni.Integer, ni.Valid = v.(int), true
- return
- case []byte:
- ni.Integer, err = strconv.Atoi(string(v))
- ni.Valid = (err == nil)
- return
- case string:
- ni.Integer, err = strconv.Atoi(v)
- ni.Valid = (err == nil)
- return
- }
-
- ni.Valid = false
- return fmt.Errorf("Can't convert %T to integer", value)
-}
-
-// Satisfy sql.Valuer interface.
-func (ni NullInt) Value() (driver.Value, error) {
- if !ni.Valid {
- return nil, nil
- }
- return ni.Integer, nil
-}
-
-// Satisfy sql.Scanner interface
-func (nt *NullTime) Scan(value interface{}) (err error) {
- if value == nil {
- nt.Time, nt.Valid = time.Time{}, false
- return
- }
-
- switch v := value.(type) {
- case time.Time:
- nt.Time, nt.Valid = v, true
- return
- }
-
- nt.Valid = false
- return fmt.Errorf("Can't convert %T to time.Time", value)
-}
-
-// Satisfy sql.Valuer interface.
-func (nt NullTime) Value() (driver.Value, error) {
- if !nt.Valid {
- return nil, nil
- }
- return nt.Time, nil
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go
deleted file mode 100644
index 072e380..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package sqlmock
-
-import (
- "regexp"
- "strings"
-)
-
-var re = regexp.MustCompile("\\s+")
-
-// strip out new lines and trim spaces
-func stripQuery(q string) (s string) {
- return strings.TrimSpace(re.ReplaceAllString(q, " "))
-}
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/b5fa231b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util_test.go b/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util_test.go
deleted file mode 100644
index c4b3974..0000000
--- a/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/util_test.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package sqlmock
-
-import (
- "testing"
-)
-
-func TestQueryStringStripping(t *testing.T) {
- assert := func(actual, expected string) {
- if res := stripQuery(actual); res != expected {
- t.Errorf("Expected '%s' to be '%s', but got '%s'", actual, expected, res)
- }
- }
-
- assert(" SELECT 1", "SELECT 1")
- assert("SELECT 1 FROM d", "SELECT 1 FROM d")
- assert(`
- SELECT c
- FROM D
-`, "SELECT c FROM D")
- assert("UPDATE (.+) SET ", "UPDATE (.+) SET")
-}
[10/43] incubator-trafficcontrol git commit: Add TO Golang Set-Cookie
to CORS allow headers
Posted by de...@apache.org.
Add TO Golang Set-Cookie to CORS allow headers
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/128c6a2d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/128c6a2d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/128c6a2d
Branch: refs/heads/master
Commit: 128c6a2d88daf230ac9c87083d71a2d24206c15d
Parents: 89491c1
Author: Robert Butts <ro...@gmail.com>
Authored: Thu Jul 27 10:54:10 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/traffic_ops_golang/wrappers.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/128c6a2d/traffic_ops/traffic_ops_golang/wrappers.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/wrappers.go b/traffic_ops/traffic_ops_golang/wrappers.go
index 386e278..39137ac 100644
--- a/traffic_ops/traffic_ops_golang/wrappers.go
+++ b/traffic_ops/traffic_ops_golang/wrappers.go
@@ -33,7 +33,7 @@ const ServerName = "traffic_ops_golang" + "/" + Version
func wrapHeaders(h RegexHandlerFunc) RegexHandlerFunc {
return func(w http.ResponseWriter, r *http.Request, p ParamMap) {
w.Header().Set("Access-Control-Allow-Credentials", "true")
- w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
+ w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Set-Cookie, Cookie")
w.Header().Set("Access-Control-Allow-Methods", "POST,GET,OPTIONS,PUT,DELETE")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("X-Server-Name", ServerName)
[40/43] incubator-trafficcontrol git commit: Fix TO Golang
monitoring.json capitalisation
Posted by de...@apache.org.
Fix TO Golang monitoring.json capitalisation
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/fbd81092
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/fbd81092
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/fbd81092
Branch: refs/heads/master
Commit: fbd81092e9fca076f75dec88c6de7a5deaacc096
Parents: d728b59
Author: Robert Butts <ro...@gmail.com>
Authored: Tue Aug 8 16:42:25 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/traffic_ops_golang/monitoring.go | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/fbd81092/traffic_ops/traffic_ops_golang/monitoring.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/monitoring.go b/traffic_ops/traffic_ops_golang/monitoring.go
index 62d356c..3804e75 100644
--- a/traffic_ops/traffic_ops_golang/monitoring.go
+++ b/traffic_ops/traffic_ops_golang/monitoring.go
@@ -47,7 +47,7 @@ type BasicServer struct {
IP6 string `json:"ip6"`
Port int `json:"port"`
Cachegroup string `json:"cachegroup"`
- HostName string `json:"hostName"`
+ HostName string `json:"hostname"`
FQDN string `json:"fqdn"`
}
@@ -57,9 +57,9 @@ type Monitor struct {
type Cache struct {
BasicServer
- InterfaceName string `json:"interfaceName"`
+ InterfaceName string `json:"interfacename"`
Type string `json:"type"`
- HashID string `json:"hashId"`
+ HashID string `json:"hashid"`
}
type Cachegroup struct {
[38/43] incubator-trafficcontrol git commit: Fix TO Golang docs
config file name
Posted by de...@apache.org.
Fix TO Golang docs config file name
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/8e8383eb
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/8e8383eb
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/8e8383eb
Branch: refs/heads/master
Commit: 8e8383eb64987a77aae3c0cc7235711b9b79a8d6
Parents: 10a410a
Author: Robert Butts <ro...@gmail.com>
Authored: Tue Aug 1 18:04:44 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
docs/source/admin/traffic_ops/configuration.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/8e8383eb/docs/source/admin/traffic_ops/configuration.rst
----------------------------------------------------------------------
diff --git a/docs/source/admin/traffic_ops/configuration.rst b/docs/source/admin/traffic_ops/configuration.rst
index 66158d9..45b952b 100644
--- a/docs/source/admin/traffic_ops/configuration.rst
+++ b/docs/source/admin/traffic_ops/configuration.rst
@@ -300,4 +300,4 @@ Configuring the Go Application
=======================
Traffic Ops is in the process of migrating from Perl to Go, and currently runs as two applications. The Go application serves all endpoints which have been rewritten in the Go language, and transparently proxies all other requests to the old Perl application. Both applications are installed by the RPM, and both run as a single service. When the project has fully migrated to Go, the Perl application will be removed, and the RPM and service will consist solely of the Go application.
-By default, the postinstall script configures the Go application to behave and transparently serve as the old Perl Traffic Ops did in previous versions. This includes reading the old ``cdn.conf`` and ``database.conf`` config files, and logging to the old ``access.log`` location. However, if you wish to customize the Go Traffic Ops application, you can do so by running it with the ``-oldcfg=false`` argument. By default, it will then look for a config file in ``/opt/traffic_ops/conf/traffic_ops_golang.json``. The new config file location may also be customized via the ``-cfg`` flag. A sample config file is installed by the RPM at ``/opt/traffic_ops/conf/traffic_ops_golang.json``. If you wish to run the new Go Traffic Ops application as a service with a new config file, the ``-oldcfg=false`` and ``-cfg`` flags may be added to the ``start`` function in the service file, located by default at ``etc/init.d/traffic_ops``.
+By default, the postinstall script configures the Go application to behave and transparently serve as the old Perl Traffic Ops did in previous versions. This includes reading the old ``cdn.conf`` and ``database.conf`` config files, and logging to the old ``access.log`` location. However, if you wish to customize the Go Traffic Ops application, you can do so by running it with the ``-oldcfg=false`` argument. By default, it will then look for a config file in ``/opt/traffic_ops/conf/traffic_ops_golang.config``. The new config file location may also be customized via the ``-cfg`` flag. A sample config file is installed by the RPM at ``/opt/traffic_ops/conf/traffic_ops_golang.config``. If you wish to run the new Go Traffic Ops application as a service with a new config file, the ``-oldcfg=false`` and ``-cfg`` flags may be added to the ``start`` function in the service file, located by default at ``etc/init.d/traffic_ops``.
[39/43] incubator-trafficcontrol git commit: Fix TO Golang build spec
needing TO client
Posted by de...@apache.org.
Fix TO Golang build spec needing TO client
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/57c1a13a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/57c1a13a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/57c1a13a
Branch: refs/heads/master
Commit: 57c1a13a59d6c08c4926d7fe256d3d804f4a3f21
Parents: 722915a
Author: Robert Butts <ro...@gmail.com>
Authored: Thu Aug 3 10:33:50 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/build/traffic_ops.spec | 9 +++++++++
1 file changed, 9 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/57c1a13a/traffic_ops/build/traffic_ops.spec
----------------------------------------------------------------------
diff --git a/traffic_ops/build/traffic_ops.spec b/traffic_ops/build/traffic_ops.spec
index 26d19e8..f723490 100644
--- a/traffic_ops/build/traffic_ops.spec
+++ b/traffic_ops/build/traffic_ops.spec
@@ -77,6 +77,15 @@ Built: %(date) by %{getenv: USER}
go get -v \
) || { echo "Could not build go log at $(pwd): $!"; exit 1; }
+ # build TO client (dependencies within traffic_control will fail to `go get` unless prebuilt)
+ godir=src/github.com/apache/incubator-trafficcontrol/traffic_ops/client
+ ( mkdir -p "$godir" && \
+ cd "$godir" && \
+ cp -r "$TC_DIR"/traffic_ops/client/* . && \
+ echo "go getting log at $(pwd)" && \
+ go get -v \
+ ) || { echo "Could not build go Traffic Ops client at $(pwd): $!"; exit 1; }
+
# build traffic_ops_golang binary
godir=src/github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang
oldpwd=$(pwd)
[24/43] incubator-trafficcontrol git commit: Fix TO Golang perlcfg
test
Posted by de...@apache.org.
Fix TO Golang perlcfg test
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/29c1593a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/29c1593a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/29c1593a
Branch: refs/heads/master
Commit: 29c1593ae91b96d6df307c5c8424790bc6af60df
Parents: 4a3f7db
Author: Robert Butts <ro...@gmail.com>
Authored: Tue Jul 25 10:38:14 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_ops/traffic_ops_golang/perlconfig_test.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/29c1593a/traffic_ops/traffic_ops_golang/perlconfig_test.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/perlconfig_test.go b/traffic_ops/traffic_ops_golang/perlconfig_test.go
index 8242d5c..d3cffe4 100644
--- a/traffic_ops/traffic_ops_golang/perlconfig_test.go
+++ b/traffic_ops/traffic_ops_golang/perlconfig_test.go
@@ -146,8 +146,8 @@ func TestGetPerlConfigsFromStrs(t *testing.T) {
KeyPath: "/etc/pki/tls/private/localhost.key",
LogLocationError: NewLogPath,
LogLocationWarning: NewLogPath,
- LogLocationInfo: OldAccessLogPath,
- LogLocationEvent: NewLogPath,
+ LogLocationInfo: NewLogPath,
+ LogLocationEvent: OldAccessLogPath,
LogLocationDebug: log.LogLocationNull,
}
err := error(nil)
[35/43] incubator-trafficcontrol git commit: Add licenses go-sqlmock
refs
Posted by de...@apache.org.
Add licenses go-sqlmock refs
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/f212661d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/f212661d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/f212661d
Branch: refs/heads/master
Commit: f212661da75a32614b04c4f781fe07e1d62ffa64
Parents: b4ccbb1
Author: Robert Butts <ro...@gmail.com>
Authored: Tue Aug 1 17:33:09 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
LICENSE | 4 ++++
1 file changed, 4 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/f212661d/LICENSE
----------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
index f7653ef..e6c1e6f 100644
--- a/LICENSE
+++ b/LICENSE
@@ -382,3 +382,7 @@ For the seelog component:
The invalid_passwords.txt file is from the Projects/OWASP SecLists Project provided under a CC-A-SA license:
@traffic_ops/app/conf/invalid_passwords.txt
./licenses/CC_A_SA_3
+
+For the go-sqlmock component:
+@traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/*
+./traffic_ops/traffic_ops_golang/vendor/gopkg.in/DATA-DOG/go-sqlmock/LICENSE
[23/43] incubator-trafficcontrol git commit: Fix TO Golang access.log
text
Posted by de...@apache.org.
Fix TO Golang access.log text
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/4a3f7db7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/4a3f7db7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/4a3f7db7
Branch: refs/heads/master
Commit: 4a3f7db7d3ffa7d3a5dd97da95d1caa3b6efb56e
Parents: 8b0ac5f
Author: Robert Butts <ro...@gmail.com>
Authored: Mon Jul 24 21:53:33 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
traffic_monitor_golang/common/log/log.go | 5 +++++
traffic_ops/traffic_ops_golang/perlconfig.go | 4 ++--
traffic_ops/traffic_ops_golang/wrappers.go | 7 +++++--
3 files changed, 12 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4a3f7db7/traffic_monitor_golang/common/log/log.go
----------------------------------------------------------------------
diff --git a/traffic_monitor_golang/common/log/log.go b/traffic_monitor_golang/common/log/log.go
index dd63892..a5204b5 100644
--- a/traffic_monitor_golang/common/log/log.go
+++ b/traffic_monitor_golang/common/log/log.go
@@ -134,6 +134,11 @@ func Eventf(t time.Time, format string, v ...interface{}) {
Event.Printf("%.3f %s", float64(t.Unix())+(float64(t.Nanosecond())/1e9), fmt.Sprintf(format, v...))
}
+// EventfRaw writes to the event log with no prefix.
+func EventfRaw(format string, v ...interface{}) {
+ Event.Printf(format, v...)
+}
+
// Close calls `Close()` on the given Closer, and logs any error. On error, the context is logged, followed by a colon, the error message, and a newline. This is primarily designed to be used in `defer`, for example, `defer log.Close(resp.Body, "readData fetching /foo/bar")`.
func Close(c io.Closer, context string) {
err := c.Close()
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4a3f7db7/traffic_ops/traffic_ops_golang/perlconfig.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/perlconfig.go b/traffic_ops/traffic_ops_golang/perlconfig.go
index c7abf64..a3013dc 100644
--- a/traffic_ops/traffic_ops_golang/perlconfig.go
+++ b/traffic_ops/traffic_ops_golang/perlconfig.go
@@ -65,10 +65,10 @@ func getPerlConfigsFromStrs(cdnConfBytes string, dbConfBytes string) (Config, er
cfg.DBServer += ":" + dbconf.Port
}
- cfg.LogLocationInfo = OldAccessLogPath
+ cfg.LogLocationInfo = NewLogPath
cfg.LogLocationError = NewLogPath
cfg.LogLocationWarning = NewLogPath
- cfg.LogLocationEvent = NewLogPath
+ cfg.LogLocationEvent = OldAccessLogPath
cfg.LogLocationDebug = log.LogLocationNull
return cfg, nil
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/4a3f7db7/traffic_ops/traffic_ops_golang/wrappers.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/wrappers.go b/traffic_ops/traffic_ops_golang/wrappers.go
index 64afeff..b20cd53 100644
--- a/traffic_ops/traffic_ops_golang/wrappers.go
+++ b/traffic_ops/traffic_ops_golang/wrappers.go
@@ -49,7 +49,7 @@ func wrapAuth(h RegexHandlerFunc, noAuth bool, secret string, privLevelStmt *sql
w = iw
username := "-"
defer func() {
- log.Infof(`%s - %s [%s] "%v %v HTTP/1.1" %v 0 0 "%v"\n`, r.RemoteAddr, username, time.Now().Format(AccessLogTimeFormat), r.Method, r.URL.Path, iw.code, time.Now().Sub(start)/time.Millisecond, iw.byteCount, r.UserAgent())
+ log.EventfRaw(`%s - %s [%s] "%v %v HTTP/1.1" %v %v %v "%v"`, r.RemoteAddr, username, time.Now().Format(AccessLogTimeFormat), r.Method, r.URL.Path, iw.code, int(time.Now().Sub(start)/time.Millisecond), iw.byteCount, r.UserAgent())
}()
handleUnauthorized := func(reason string) {
@@ -96,7 +96,7 @@ func wrapLogTime(h RegexHandlerFunc) RegexHandlerFunc {
iw := &Interceptor{w: w}
defer func() {
user := "-" // TODO fix
- log.Infof(`%s - %s [%s] "%v %v HTTP/1.1" %v 0 0 "%v"\n`, r.RemoteAddr, user, time.Now().Format(AccessLogTimeFormat), r.Method, r.URL.Path, iw.code, time.Now().Sub(start)/time.Millisecond, iw.byteCount, r.UserAgent())
+ log.EventfRaw(`%s - %s [%s] "%v %v HTTP/1.1" %v 0 0 "%v"\n`, r.RemoteAddr, user, time.Now().Format(AccessLogTimeFormat), r.Method, r.URL.Path, iw.code, time.Now().Sub(start)/time.Millisecond, iw.byteCount, r.UserAgent())
}()
h(iw, r, p)
}
@@ -116,6 +116,9 @@ func (i *Interceptor) WriteHeader(rc int) {
func (i *Interceptor) Write(b []byte) (int, error) {
wi, werr := i.w.Write(b)
i.byteCount += wi
+ if i.code == 0 {
+ i.code = 200
+ }
return wi, werr
}
[30/43] incubator-trafficcontrol git commit: This closes #729
Posted by de...@apache.org.
This closes #729
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/77c0dae3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/77c0dae3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/77c0dae3
Branch: refs/heads/master
Commit: 77c0dae32b79e1d9affdd50ab4c50b49f86d86a8
Parents: fbd8109
Author: Dewayne Richardson <de...@apache.org>
Authored: Thu Aug 10 09:46:03 2017 -0600
Committer: Dewayne Richardson <de...@apache.org>
Committed: Thu Aug 10 09:46:03 2017 -0600
----------------------------------------------------------------------
----------------------------------------------------------------------