A great deal of refactoring, fixing, and other improvements
diff --git a/README.md b/README.md
index 274d12c..c59f078 100644
--- a/README.md
+++ b/README.md
@@ -38,9 +38,10 @@
curl -i localhost:9000/deployments/current
curl -i -X POST localhost:9000/deployments/entityId -d '{ "status": "SUCCESS" }'
-The following have been exposed as configurable env vars:
+The following may be interesting env vars for configuration:
* APID_API_PORT
+* APID_GATEWAYDEPLOY_GITHUB_ACCESSTOKEN
## Running tests
diff --git a/api.go b/api.go
index 8728efe..6eb7212 100644
--- a/api.go
+++ b/api.go
@@ -1,19 +1,46 @@
package apiGatewayDeploy
import (
- "net/http"
"database/sql"
- "time"
- "io/ioutil"
"encoding/json"
"github.com/30x/apid"
+ "io/ioutil"
+ "net/http"
+ "strconv"
+ "time"
)
+// todo: add error codes where this is used
+const ERROR_CODE_TODO = 0
+
+type errorResponse struct {
+ ErrorCode int `json:"errorCode"`
+ Reason string `json:"reason"`
+}
+
func initAPI(services apid.Services) {
services.API().HandleFunc("/deployments/current", handleCurrentDeployment).Methods("GET")
services.API().HandleFunc("/deployments/{deploymentID}", respHandler).Methods("POST")
}
+func writeError(w http.ResponseWriter, status int, code int, reason string) {
+ e := errorResponse{
+ ErrorCode: code,
+ Reason: reason,
+ }
+ bytes, err := json.Marshal(e)
+ if err != nil {
+ log.Errorf("unable to marshal errorResponse: %v", err)
+ } else {
+ w.Write(bytes)
+ }
+ log.Debugf("sending (%d) error to client: %s", status, reason)
+ w.WriteHeader(status)
+}
+
+func writeDatabaseError(w http.ResponseWriter) {
+ writeError(w, http.StatusInternalServerError, ERROR_CODE_TODO, "database error")
+}
// todo: The following was basically just copied from old APID - needs review.
@@ -22,90 +49,84 @@
for {
select {
case msg := <-incoming:
- for sub := range subscribers {
+ for subscriber := range subscribers {
select {
- case sub <- msg:
- log.Info("Handling LP response for devId: ", msg)
+ case subscriber <- msg:
+ log.Debugf("Handling deploy response for: %s", msg)
default:
- log.Error("listener too far behind - message dropped")
+ log.Error("listener too far behind, message dropped")
}
}
- case sub := <-addSubscriber:
- log.Info("Add subscriber", sub)
- subscribers[sub] = struct{}{}
+ case subscriber := <-addSubscriber:
+ log.Debugf("Add subscriber: %s", subscriber)
+ subscribers[subscriber] = struct{}{}
}
}
}
func handleCurrentDeployment(w http.ResponseWriter, r *http.Request) {
- block := r.URL.Query()["block"] != nil
+ // If block greater than zero AND if request ETag header not empty AND if there is no new bundle list
+ // available, then block for up to the specified number of seconds until a new bundle list becomes
+ // available. If no new bundle list becomes available, then return an empty array.
+ b := r.URL.Query().Get("block")
+ var block int
+ if b != "" {
+ var err error
+ block, err = strconv.Atoi(b)
+ if err != nil {
+ writeError(w, http.StatusBadRequest, ERROR_CODE_TODO, "bad block value, must be number of seconds")
+ return
+ }
+ }
- /* Retrieve the args from the i/p arg */
- res := sendDeployInfo(w, r)
+ sent := sendDeployInfo(w, r, false)
- /*
- * If the call has nothing to return, check to see if the call is a
- * blocking request (Simulate Long Poll)
- */
- if res == false && block == true {
- log.Info("Blocking request... Waiting for new Deployments.")
- timeout := make(chan bool)
+ // todo: can we kill the timer & channel if client connection is lost?
+
+ // blocking request (Long Poll)
+ if sent == false && block > 0 && r.Header.Get("etag") != "" {
+ log.Debug("Blocking request... Waiting for new Deployments.")
newReq := make(chan string)
- /* Update channel of a new request (subscriber) */
+ // Update channel of a new request (subscriber)
addSubscriber <- newReq
- /* Start the timer for the blocking request */
- /* FIXME: 120 sec to be made configurable ? */
- go func() {
- time.Sleep(time.Second * 120)
- timeout <- true
- }()
+ // Block until timeout of new deployment
select {
- /*
- * This blocks till either of the two occurs
- * (1) - Timeout
- * (2) - A new deployment has occurred
- * FIXME: <-newReq has the DevId, this can be
- * used directly instead of getting it via
- * SQL query in GetDeployInfo()
- */
+ case depID := <-newReq:
+ // todo: depID could be used directly instead of getting it again in sendDeployInfo
+ log.Debugf("DeploymentID = %s", depID)
+ sendDeployInfo(w, r, false)
- case <-newReq:
- sendDeployInfo(w, r)
-
- case <-timeout:
- log.Debug("Blocking request Timed out. No new Deployments.")
+ case <-time.After(time.Duration(block) * time.Second):
+ log.Debug("Blocking deployment request timed out.")
+ sendDeployInfo(w, r, true)
}
}
}
func respHandler(w http.ResponseWriter, r *http.Request) {
- db, err := data.DB()
- if err != nil {
- log.Error("Error accessing database", err)
- return
- }
-
- // uri is /deployments/{deploymentID}
depID := apid.API().Vars(r)["deploymentID"]
if depID == "" {
log.Error("No deployment ID")
- w.WriteHeader(http.StatusBadRequest)
- w.Write([]byte("No deployment ID")) // todo: probably not a valid response per API spec
+ // todo: add error code
+ writeError(w, http.StatusBadRequest, 0, "Missing deployment ID")
return
}
var rsp gwBundleResponse
buf, _ := ioutil.ReadAll(r.Body)
- err = json.Unmarshal(buf, &rsp)
+ err := json.Unmarshal(buf, &rsp)
if err != nil {
log.Error("Resp Handler Json Unmarshal err: ", err)
+ // todo: add error code
+ writeError(w, http.StatusBadRequest, 0, "Malformed body")
return
}
+ // todo: validate request body
/*
* If the state of deployment was success, update state of bundles and
@@ -113,34 +134,44 @@
*/
txn, err := db.Begin()
if err != nil {
- log.Error("Unable to begin transaction: ", err)
+ log.Errorf("Unable to begin transaction: %s", err)
+ writeDatabaseError(w)
return
}
- var res bool
+ var updated bool
if rsp.Status == "SUCCESS" {
- res = updateDeploymentSuccess(depID, txn)
+ updated = updateDeploymentSuccess(depID, txn)
} else {
- res = updateDeploymentFailure(depID, rsp.GWbunRsp, txn)
+ updated = updateDeploymentFailure(depID, rsp.GWbunRsp, txn)
}
- if res == true {
- err = txn.Commit()
- } else {
+ log.Print("***** 1")
+ if !updated {
+ writeDatabaseError(w)
err = txn.Rollback()
- }
- if err != nil {
- log.Error("Unable to finish transaction: ", err)
+ if err != nil {
+ log.Errorf("Unable to rollback transaction: %s", err)
+ }
return
}
+ log.Print("***** 2")
+ err = txn.Commit()
+ if err != nil {
+ log.Errorf("Unable to commit transaction: %s", err)
+ writeDatabaseError(w)
+ }
+
+ log.Print("***** 3")
+
return
}
func updateDeploymentSuccess(depID string, txn *sql.Tx) bool {
- log.Infof("Marking deployment (%s) as SUCCEEDED", depID)
+ log.Debugf("Marking deployment (%s) as SUCCEEDED", depID)
var rows int64
res, err := txn.Exec("UPDATE BUNDLE_INFO SET deploy_status = ? WHERE deployment_id = ?;",
@@ -190,7 +221,8 @@
/* Iterate over Bundles, and update the errors */
for _, a := range rsp.ErrorDetails {
- res, err = txn.Exec("UPDATE BUNDLE_INFO SET deploy_status = ?, errorcode = ?, error_reason = ? WHERE id = ?;", DEPLOYMENT_STATE_ERR_GWY, a.ErrorCode, a.Reason, a.BundleId)
+ res, err = txn.Exec("UPDATE BUNDLE_INFO SET deploy_status = ?, errorcode = ?, error_reason = ? "+
+ "WHERE id = ?;", DEPLOYMENT_STATE_ERR_GWY, a.ErrorCode, a.Reason, a.BundleId)
if err != nil {
rows, err = res.RowsAffected()
}
diff --git a/api_test.go b/api_test.go
index e0dfcc0..afbbac9 100644
--- a/api_test.go
+++ b/api_test.go
@@ -1,50 +1,39 @@
package apiGatewayDeploy
import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ . "github.com/30x/apidApigeeSync" // for direct access to Payload types
+ "github.com/30x/keymaster/client"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
- . "github.com/30x/apidApigeeSync" // for direct access to Payload types
- "database/sql"
- "net/http/httptest"
"io/ioutil"
"net/http"
+ "net/http/httptest"
"net/url"
- "encoding/json"
"time"
- "fmt"
- "bytes"
- "github.com/30x/keymaster/client"
)
-const (
- currentDeploymentPath = "/deployments/current"
-)
+const currentDeploymentPath = "/deployments/current"
var _ = Describe("api", func() {
- var db *sql.DB
-
- BeforeEach(func() {
- var err error
- db, err = data.DB()
- Expect(err).NotTo(HaveOccurred())
- })
+ PIt("should deliver deployment events to long-poll waiters")
It("should get current deployment", func() {
- var (
- deployStatus int
- err error
- deploymentID = "api_test_1"
- )
-
+ deploymentID := "api_test_1"
insertTestDeployment(testServer, deploymentID)
- err = db.QueryRow("SELECT deploy_status from BUNDLE_INFO WHERE deployment_id = ?;", deploymentID).Scan(&deployStatus)
+ var deployStatus int
+ err := db.QueryRow("SELECT deploy_status from BUNDLE_INFO WHERE deployment_id = ?;",
+ deploymentID).Scan(&deployStatus)
Expect(err).ShouldNot(HaveOccurred())
Expect(deployStatus).Should(Equal(DEPLOYMENT_STATE_READY))
- err = db.QueryRow("SELECT deploy_status from BUNDLE_DEPLOYMENT WHERE id = ?;", deploymentID).Scan(&deployStatus)
+ err = db.QueryRow("SELECT deploy_status from BUNDLE_DEPLOYMENT WHERE id = ?;",
+ deploymentID).Scan(&deployStatus)
Expect(err).ShouldNot(HaveOccurred())
Expect(deployStatus).Should(Equal(DEPLOYMENT_STATE_READY))
@@ -59,7 +48,9 @@
body, err := ioutil.ReadAll(res.Body)
Expect(err).ShouldNot(HaveOccurred())
json.Unmarshal(body, &depRes)
+
Expect(depRes.DeploymentId).Should(Equal(deploymentID))
+ Expect(res.Header.Get("etag")).Should(Equal(deploymentID))
})
It("should mark a deployment as deployed", func() {
@@ -87,11 +78,13 @@
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
var deployStatus int
- err = db.QueryRow("SELECT deploy_status from BUNDLE_INFO WHERE deployment_id = ?;", deploymentID).Scan(&deployStatus)
+ err = db.QueryRow("SELECT deploy_status from BUNDLE_INFO WHERE deployment_id = ?;",
+ deploymentID).Scan(&deployStatus)
Expect(err).ShouldNot(HaveOccurred())
Expect(deployStatus).Should(Equal(DEPLOYMENT_STATE_SUCCESS))
- err = db.QueryRow("SELECT deploy_status from BUNDLE_DEPLOYMENT WHERE id = ?;", deploymentID).Scan(&deployStatus)
+ err = db.QueryRow("SELECT deploy_status from BUNDLE_DEPLOYMENT WHERE id = ?;",
+ deploymentID).Scan(&deployStatus)
Expect(err).ShouldNot(HaveOccurred())
Expect(deployStatus).Should(Equal(DEPLOYMENT_STATE_SUCCESS))
})
@@ -109,7 +102,7 @@
Status: client.StatusFail,
Error: &client.DeploymentError{
ErrorCode: 100,
- Reason: "bad juju",
+ Reason: "bad juju",
//BundleErrors: []client.BundleError{ // todo: add tests for bundle errors
// {
// BundleID: "",
@@ -132,7 +125,8 @@
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
var deployStatus int
- err = db.QueryRow("SELECT deploy_status from BUNDLE_DEPLOYMENT WHERE id = ?;", deploymentID).Scan(&deployStatus)
+ err = db.QueryRow("SELECT deploy_status from BUNDLE_DEPLOYMENT WHERE id = ?;",
+ deploymentID).Scan(&deployStatus)
Expect(err).ShouldNot(HaveOccurred())
Expect(deployStatus).Should(Equal(DEPLOYMENT_STATE_ERR_GWY))
})
@@ -162,14 +156,14 @@
Expect(err).ShouldNot(HaveOccurred())
payload := DataPayload{
- EntityType: "deployment",
- Operation: "create",
+ EntityType: "deployment",
+ Operation: "create",
EntityIdentifier: entityID,
PldCont: Payload{
CreatedAt: time.Now().Unix(),
- Manifest: string(bundleBytes),
+ Manifest: string(bundleBytes),
},
}
insertDeployment(payload)
-}
\ No newline at end of file
+}
diff --git a/apidGatewayDeploy-api.yaml b/apidGatewayDeploy-api.yaml
index aee10c2..0f55ab7 100644
--- a/apidGatewayDeploy-api.yaml
+++ b/apidGatewayDeploy-api.yaml
@@ -41,21 +41,21 @@
"deploymentId": "abc123",
"system" : {
"bundleId": "system-bundle-rev-3",
- "url": "file:///apid/bundles/system-bundle-rev-3.zip"
+ "uri": "file:///apid/bundles/system-bundle-rev-3.zip"
},
"bundles": [
{
"bundleId": "system-bundle-rev-3",
"authCode": "@#$nike#$#$stage&#$(^#",
- "url": "file:///apid/bundles/system-bundle-release-1-1233.zip"
+ "uri": "file:///apid/bundles/system-bundle-release-1-1233.zip"
},{
"bundleId": "bundleA-rev-9",
"authCode": "@#$nike#$#$prod&#$(^#",
- "url": "file:///apid/bundles/bundleA-rev-9-26372.zip"
+ "uri": "file:///apid/bundles/bundleA-rev-9-26372.zip"
},{
"bundleId": "bundleB-rev-1",
"authCode": "@#$nike#$#$test&#$(^#",
- "url": "file:///somewhere/bundles/bundleB-rev-1-72351.zip"
+ "uri": "file:///somewhere/bundles/bundleB-rev-1-72351.zip"
}
]
}
@@ -74,48 +74,14 @@
- name: _
in: body
required: true
- description: |
- Example: <pre>
- {
- "status": "SUCCESS|FAIL",
- #Optional
- "error": {
- "errorCode": 5,
- "reason": "Failed to restart NGINX"
- "bundleErrors": [
- {
- "bundleId": "system-bundle-rev-3",
- "errorCode": 5,
- "reason": "Invalid template parameter"
- },
- {
- "bundleId": "system-bundle-rev-9",
- "errorCode": 1,
- "reason": "Missing Virtual Host"
- }
- ]
- }
- }
- </pre>
+ description: Success or failure response
schema:
$ref: '#/definitions/DeploymentResult'
responses:
'200':
description: OK
default:
- description: |
- <pre>
- 4xx:
- {
- errorCode: "INVALID_REQUEST_PARAMS"
- reason: "Something wrong!"
- }
-
- 5xx:
- {
- errorCode: "SERVER_SUCKS"
- reason: "Server took too long"
- }</pre>
+ description: Error response
schema:
$ref: '#/definitions/ErrorResponse'
@@ -130,6 +96,10 @@
type: number
reason:
type: string
+ example: {
+ "errorCode": 601,
+ "reason": "Something's wrong"
+ }
DeploymentResponse:
type: object
diff --git a/apidGatewayDeploy_suite_test.go b/apidGatewayDeploy_suite_test.go
index 3919042..48a6d69 100644
--- a/apidGatewayDeploy_suite_test.go
+++ b/apidGatewayDeploy_suite_test.go
@@ -4,17 +4,17 @@
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
- "testing"
"github.com/30x/apid"
"github.com/30x/apid/factory"
"io/ioutil"
+ "net/http"
"net/http/httptest"
"os"
- "net/http"
+ "testing"
)
var (
- tmpDir string
+ tmpDir string
testServer *httptest.Server
)
@@ -49,7 +49,7 @@
var _ = AfterSuite(func() {
apid.Events().Close()
- if (testServer != nil) {
+ if testServer != nil {
testServer.Close()
}
os.RemoveAll(tmpDir)
diff --git a/cmd/apidGatewayDeploy/main.go b/cmd/apidGatewayDeploy/main.go
index 3e2f9fb..f972fad 100644
--- a/cmd/apidGatewayDeploy/main.go
+++ b/cmd/apidGatewayDeploy/main.go
@@ -1,13 +1,13 @@
package main
import (
+ "flag"
"github.com/30x/apid"
"github.com/30x/apid/factory"
- _ "github.com/30x/apidGatewayDeploy"
"github.com/30x/apidApigeeSync"
- "time"
+ _ "github.com/30x/apidGatewayDeploy"
"io/ioutil"
- "flag"
+ "time"
)
func main() {
@@ -75,12 +75,12 @@
event.Changes = []apidApigeeSync.ChangePayload{
{
Data: apidApigeeSync.DataPayload{
- EntityType: "deployment",
- Operation: "create",
+ EntityType: "deployment",
+ Operation: "create",
EntityIdentifier: "entityID",
PldCont: apidApigeeSync.Payload{
CreatedAt: now,
- Manifest: string(manifest),
+ Manifest: string(manifest),
},
},
},
diff --git a/deployments.go b/deployments.go
index 3a4e56b..c746d04 100644
--- a/deployments.go
+++ b/deployments.go
@@ -3,18 +3,20 @@
import (
"database/sql"
"encoding/json"
+ "fmt"
+ "github.com/30x/apidGatewayDeploy/github"
"io"
"net/http"
+ "net/url"
"os"
"strconv"
"time"
- "github.com/30x/apidGatewayDeploy/github"
- "net/url"
- "fmt"
)
// todo: The following was basically just copied from old APID - needs review.
+// todo: /current should return latest (regardless of status) if no ETag
+
/* All Global Constants go here */
const DEPLOYMENT_STATE_UNUSED = 0
const DEPLOYMENT_STATE_INPROG = 1
@@ -24,14 +26,13 @@
const DEPLOYMENT_STATE_ERR_GWY = 5
var (
- bundlePathAbs string
+ bundlePathAbs string
gitHubAccessToken string
- incoming = make(chan string)
+ incoming = make(chan string)
addSubscriber = make(chan chan string)
)
-
type systemBundle struct {
Uri string `json:"uri"`
}
@@ -88,7 +89,7 @@
// todo: temporary - if not a github url, just open it or call GET on it
if uri.Host != "github.com" {
// assume it's a file if no scheme
- if uri.Scheme == "" || uri.Scheme == "file"{
+ if uri.Scheme == "" || uri.Scheme == "file" {
f, err := os.Open(uri.Path)
if err != nil {
return nil, err
@@ -118,6 +119,7 @@
if typ == "sys" {
bundleID = typ + "_" + timeString
} else {
+ // todo: stop using org and env
bundleID = typ + "_" + org + "_" + env + "_" + timeString
}
locFile := depPath + "/" + bundleID + ".zip"
@@ -173,18 +175,13 @@
*/
func orchestrateDeployment() string {
- db, err := data.DB()
- if err != nil {
- log.Error("Error accessing database", err)
- return ""
- }
-
/* (1) Find the latest deployment, if none - get out */
status := DEPLOYMENT_STATE_READY
txn, _ := db.Begin()
var manifestString, deploymentID string
- err = db.QueryRow("SELECT id, manifest FROM BUNDLE_DEPLOYMENT WHERE deploy_status = ? ORDER BY created_at ASC LIMIT 1;", DEPLOYMENT_STATE_UNUSED).
+ err := db.QueryRow("SELECT id, manifest FROM BUNDLE_DEPLOYMENT WHERE deploy_status = ? "+
+ "ORDER BY created_at ASC LIMIT 1;", DEPLOYMENT_STATE_UNUSED).
Scan(&deploymentID, &manifestString)
switch {
@@ -271,17 +268,8 @@
*/
func createInitBundleDB(fileurl string, id string, cts int64, env string, org string, depid string, typ string, loc string, status int, txn *sql.Tx) bool {
- _, err := txn.Exec("INSERT INTO BUNDLE_INFO (id, deployment_id, org, env, url, type, deploy_status, created_at, file_url)VALUES(?,?,?,?,?,?,?,?,?);",
- id,
- depid,
- org,
- env,
- loc,
- typ,
- status,
- cts,
- fileurl,
- )
+ _, err := txn.Exec("INSERT INTO BUNDLE_INFO (id, deployment_id, org, env, url, type, deploy_status, "+
+ "created_at, file_url)VALUES(?,?,?,?,?,?,?,?,?);", id, depid, org, env, loc, typ, status, cts, fileurl)
if err != nil {
log.Error("INSERT BUNDLE_INFO Failed (id, dep id) : (", id, ", ", depid, ")", err)
@@ -314,29 +302,47 @@
}
-func (dr *deploymentResponse) addBundle(bd bundle) []bundle {
- dr.Bundles = append(dr.Bundles, bd)
- return dr.Bundles
-}
+func sendDeployInfo(w http.ResponseWriter, r *http.Request, sendEmpty bool) bool {
-func sendDeployInfo(w http.ResponseWriter, r *http.Request) bool {
+ // If If-None-Match header matches the ETag of current bundle list AND if the request does NOT have a 'block'
+ // query param > 0, the server returns a 304 Not Modified response indicating that the client already has the
+ // most recent bundle list.
+ ifNoneMatch := r.Header.Get("If-None-Match")
- db, err := data.DB()
+ // Pick the most recent deployment
+ var depID string
+ // todo: fix /current
+ err := db.QueryRow("SELECT id FROM BUNDLE_DEPLOYMENT WHERE deploy_status = ? ORDER BY created_at ASC LIMIT 1;",
+ DEPLOYMENT_STATE_READY).Scan(&depID)
+ //err = db.QueryRow("SELECT id FROM BUNDLE_DEPLOYMENT ORDER BY created_at ASC LIMIT 1;").Scan(&depID)
if err != nil {
- log.Error("Database error: ", err)
+ log.Errorf("Database error: %s", err)
return false
}
- /* Pick the most recent deployment that is ready */
- var depID string
- err = db.QueryRow("SELECT id FROM BUNDLE_DEPLOYMENT WHERE deploy_status = ? ORDER BY created_at ASC LIMIT 1;",
- DEPLOYMENT_STATE_READY).Scan(&depID)
+ // todo: is depID appropriate for eTag?
+ if depID == ifNoneMatch {
+ w.WriteHeader(http.StatusNotModified)
+ return true
+ }
+ w.Header().Set("ETag", depID)
var bundleID, fileUrl string
- err = db.QueryRow("SELECT file_url, id FROM BUNDLE_INFO WHERE deploy_status = ? AND deployment_id = ? AND type = 'sys';", DEPLOYMENT_STATE_READY, depID).Scan(&fileUrl, &bundleID)
+ // todo: fix /current
+ err = db.QueryRow("SELECT file_url, id FROM BUNDLE_INFO WHERE deploy_status = ? AND deployment_id = ? AND "+
+ "type = 'sys';", DEPLOYMENT_STATE_READY, depID).Scan(&fileUrl, &bundleID)
+ //err = db.QueryRow("SELECT file_url, id FROM BUNDLE_INFO WHERE deployment_id = ? AND " +
+ // "type = 'sys';", DEPLOYMENT_STATE_READY, depID).Scan(&fileUrl, &bundleID)
if err != nil {
- log.Error("No System Deployment ready: ", err)
- return false
+ if err == sql.ErrNoRows {
+ log.Debugf("No System Deployment ready: %s", err)
+ if !sendEmpty {
+ return false
+ }
+ } else {
+ log.Errorf("Database error: %s", err)
+ return false
+ }
}
chItems := []bundle{}
@@ -352,24 +358,29 @@
System: sysInfo,
}
- rows, err := db.Query("SELECT file_url, id FROM BUNDLE_INFO WHERE deploy_status = ? AND deployment_id = ? AND type = 'dep';",
- DEPLOYMENT_STATE_READY, depID)
+ // todo: fix /current
+ rows, err := db.Query("SELECT file_url, id FROM BUNDLE_INFO WHERE deploy_status = ? AND deployment_id = ? "+
+ "AND type = 'dep';", DEPLOYMENT_STATE_READY, depID)
+ //rows, err := db.Query("SELECT file_url, id FROM BUNDLE_INFO WHERE deployment_id = ? " +
+ // "AND type = 'dep';", depID)
if err != nil {
- log.Error("No Deployments ready: ", err)
- return false
+ log.Debugf("No Deployments ready: %s", err)
+ if !sendEmpty {
+ return false
+ }
}
for rows.Next() {
err = rows.Scan(&fileUrl, &bundleID)
if err != nil {
- log.Error("Deployments fetch failed. Err: ", err)
+ log.Errorf("Deployments fetch failed. Err: %s", err)
return false
}
bd := bundle{
- AuthCode: bundleID, /* FIXME */
+ AuthCode: bundleID, // todo: authCode
BundleId: bundleID,
URL: fileUrl,
}
- depResp.addBundle(bd)
+ depResp.Bundles = append(depResp.Bundles, bd)
}
b, err := json.Marshal(depResp)
w.Write(b)
diff --git a/github/github.go b/github/github.go
index 7ea8ef3..9abd321 100644
--- a/github/github.go
+++ b/github/github.go
@@ -5,6 +5,7 @@
"encoding/json"
"errors"
"fmt"
+ "github.com/30x/apid"
"io"
"io/ioutil"
"net/http"
@@ -13,7 +14,6 @@
"os"
"regexp"
"strings"
- "github.com/30x/apid"
)
var log apid.LogService
@@ -111,7 +111,7 @@
url := "https://api.github.com/repos/" + repo + "/contents" + parentPath + "?ref=" + ref
client := &http.Client{
- //CheckRedirect: redirectPolicyFunc,
+ //CheckRedirect: redirectPolicyFunc,
}
req, err := http.NewRequest("GET", url, nil)
if strings.HasPrefix(accessToken, "UPDATE_FROM_GITHUB_API") {
diff --git a/init.go b/init.go
index 6254b10..36ffea1 100644
--- a/init.go
+++ b/init.go
@@ -1,22 +1,21 @@
package apiGatewayDeploy
import (
+ "database/sql"
+ "github.com/30x/apid"
+ "github.com/30x/apidGatewayDeploy/github"
"os"
"path/filepath"
- "github.com/30x/apidApigeeSync"
- "github.com/30x/apid"
- "database/sql"
- "github.com/30x/apidGatewayDeploy/github"
)
const (
- configBundleDir = "gatewaydeploy_bundle_dir"
+ configBundleDir = "gatewaydeploy_bundle_dir"
configGithubAccessToken = "gatewaydeploy_github_accesstoken"
)
var (
log apid.LogService
- data apid.DataService
+ db *sql.DB
)
func init() {
@@ -32,9 +31,6 @@
config := services.Config()
config.SetDefault(configBundleDir, "/var/tmp")
- events := services.Events()
- data = services.Data()
-
var err error
bundleDir := config.GetString(configBundleDir)
if err := os.MkdirAll(bundleDir, 0700); err != nil {
@@ -48,25 +44,16 @@
gitHubAccessToken = config.GetString(configGithubAccessToken)
- db, err := data.DB()
+ db, err = services.Data().DB()
if err != nil {
log.Panic("Unable to access DB", err)
}
-
- var count int
- row := db.QueryRow("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='bundle_deployment';")
- if err := row.Scan(&count); err != nil {
- log.Panic("Unable to setup database", err)
- }
- if count == 0 {
- createTables(db)
- }
+ initDB()
go distributeEvents()
initAPI(services)
-
- events.Listen(apidApigeeSync.ApigeeSyncEventSelector, &apigeeSyncHandler{})
+ initListener(services)
orchestrateDeployment()
@@ -75,9 +62,16 @@
return nil
}
-func createTables(db *sql.DB) {
- _, err := db.Exec("CREATE TABLE bundle_deployment (org varchar(255), id varchar(255), uri varchar(255), env varchar(255), etag varchar(255), manifest text, created_at integer, modified_at integer, deploy_status integer, error_code varchar(255), PRIMARY KEY (id)); CREATE TABLE bundle_info (type integer, env varchar(255), org varchar(255), id varchar(255), url varchar(255), file_url varchar(255), created_at integer, modified_at integer, deployment_id varchar(255), etag varchar(255), custom_tag varchar(255), deploy_status integer, error_code integer, error_reason text, PRIMARY KEY (id), FOREIGN KEY (deployment_id) references BUNDLE_DEPLOYMENT(id) ON DELETE CASCADE);")
- if err != nil {
- log.Panic("Unable to initialize DB", err)
+func initDB() {
+ var count int
+ row := db.QueryRow("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='bundle_deployment';")
+ if err := row.Scan(&count); err != nil {
+ log.Panic("Unable to setup database", err)
+ }
+ if count == 0 {
+ _, err := db.Exec("CREATE TABLE bundle_deployment (org varchar(255), id varchar(255), uri varchar(255), env varchar(255), etag varchar(255), manifest text, created_at integer, modified_at integer, deploy_status integer, error_code varchar(255), PRIMARY KEY (id)); CREATE TABLE bundle_info (type integer, env varchar(255), org varchar(255), id varchar(255), url varchar(255), file_url varchar(255), created_at integer, modified_at integer, deployment_id varchar(255), etag varchar(255), custom_tag varchar(255), deploy_status integer, error_code integer, error_reason text, PRIMARY KEY (id), FOREIGN KEY (deployment_id) references BUNDLE_DEPLOYMENT(id) ON DELETE CASCADE);")
+ if err != nil {
+ log.Panic("Unable to initialize DB", err)
+ }
}
}
diff --git a/listener.go b/listener.go
index ba26ce1..eb9ab16 100644
--- a/listener.go
+++ b/listener.go
@@ -1,10 +1,14 @@
package apiGatewayDeploy
import (
- "github.com/30x/apidApigeeSync"
"github.com/30x/apid"
+ "github.com/30x/apidApigeeSync"
)
+func initListener(services apid.Services) {
+ services.Events().Listen(apidApigeeSync.ApigeeSyncEventSelector, &apigeeSyncHandler{})
+}
+
type apigeeSyncHandler struct {
}
@@ -28,8 +32,8 @@
}
switch payload.Data.Operation {
- case "create":
- insertDeployment(payload.Data)
+ case "create":
+ insertDeployment(payload.Data)
}
}
@@ -37,12 +41,7 @@
func insertDeployment(payload apidApigeeSync.DataPayload) {
- db, err := data.DB()
- if err != nil {
- panic("help me!") // todo: handle
- }
-
- _, err = db.Exec("INSERT INTO BUNDLE_DEPLOYMENT (id, manifest, created_at, deploy_status) VALUES (?,?,?,?);",
+ _, err := db.Exec("INSERT INTO BUNDLE_DEPLOYMENT (id, manifest, created_at, deploy_status) VALUES (?,?,?,?);",
payload.EntityIdentifier,
payload.PldCont.Manifest,
payload.PldCont.CreatedAt,
diff --git a/listener_test.go b/listener_test.go
index c9a4dd5..33b3eec 100644
--- a/listener_test.go
+++ b/listener_test.go
@@ -1,13 +1,13 @@
package apiGatewayDeploy
import (
+ "encoding/json"
"github.com/30x/apid"
. "github.com/30x/apidApigeeSync" // for direct access to Payload types
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
- "time"
- "encoding/json"
"net/url"
+ "time"
)
var _ = Describe("listener", func() {
@@ -25,7 +25,7 @@
},
DepBun: []dependantBundle{
{
- Uri: bundleUri,
+ Uri: bundleUri,
},
},
}
@@ -38,12 +38,12 @@
event.Changes = []ChangePayload{
{
Data: DataPayload{
- EntityType: "deployment",
- Operation: "create",
+ EntityType: "deployment",
+ Operation: "create",
EntityIdentifier: "entityID",
PldCont: Payload{
CreatedAt: now,
- Manifest: manifest,
+ Manifest: manifest,
},
},
},
@@ -59,9 +59,6 @@
return
}
- db, err := data.DB()
- Expect(err).NotTo(HaveOccurred())
-
// todo: should do a lot more checking here... maybe call another api instead?
var selectedManifest string
var createdAt int64
@@ -77,7 +74,7 @@
}
apid.Events().Listen(ApigeeSyncEventSelector, h)
- apid.Events().Emit(ApigeeSyncEventSelector, &event) // for standard listener
+ apid.Events().Emit(ApigeeSyncEventSelector, &event) // for standard listener
apid.Events().Emit(ApigeeSyncEventSelector, &ChangeSet{}) // for test listener
})