You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@trafficcontrol.apache.org by GitBox <gi...@apache.org> on 2018/11/30 17:05:08 UTC

[GitHub] mitchell852 closed pull request #3060: enroller acts as http server and dir watcher

mitchell852 closed pull request #3060: enroller acts as http server and dir watcher
URL: https://github.com/apache/trafficcontrol/pull/3060
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/docs/source/admin/quick_howto/ciab.rst b/docs/source/admin/quick_howto/ciab.rst
index d02b311ee..bc5f51cf1 100644
--- a/docs/source/admin/quick_howto/ciab.rst
+++ b/docs/source/admin/quick_howto/ciab.rst
@@ -103,6 +103,13 @@ Advanced Usage
 ==============
 This section will be amended as functionality is added to the CDN in a Box project.
 
+The Enroller
+------------
+The "enroller" provides an efficient way for Traffic Ops to be populated with data as CDN in a Box starts up.  It connects to Traffic Ops as the admin user and processes files places in the docker volume shared between the containers.  The enroller watches each directory within the ``/shared/enroller`` directory for new ``.json`` files to be created there.  These files must follow the format outlined in the API guide for the ``POST`` method for each data type,  (e.g. for a ``tenant``, follow the guidelines for ``POST api/1.4/regions``).  Of note,  the ``enroller`` does not require fields that reference database ids for other objects within the database.
+
+The enroller runs within CDN in a Box using the ``-dir <dir>`` switch which provides the above behavior.  It can also be run using the ``-http :<port>`` switch to instead have it listen on the indicated port.  In this case, it accepts only POST requests with the JSON provided using the POST JSON method, e.g. ``curl -X POST https://enroller/api/1.4/regions -d @newregion.json``.   CDN in a Box does not currently use this method, but may be modified in the future to avoid using the shared volume approach.
+
+
 The Test Client
 ---------------
 The "testclient" service is an optional extension to CDN in a Box which provides several more user-friendly interfaces to the CDN network. Specifically it contains:
diff --git a/infrastructure/cdn-in-a-box/enroller/Dockerfile b/infrastructure/cdn-in-a-box/enroller/Dockerfile
index 9e4a71a20..e816dc205 100644
--- a/infrastructure/cdn-in-a-box/enroller/Dockerfile
+++ b/infrastructure/cdn-in-a-box/enroller/Dockerfile
@@ -22,21 +22,22 @@ COPY ./lib/ /go/src/github.com/apache/trafficcontrol/lib/
 COPY ./vendor/ /go/src/github.com/apache/trafficcontrol/vendor/
 COPY ./traffic_ops/client/ /go/src/github.com/apache/trafficcontrol/traffic_ops/client/
 COPY ./traffic_ops/vendor/ /go/src/github.com/apache/trafficcontrol/traffic_ops/vendor/
-COPY ./infrastructure/cdn-in-a-box/enroller/ /go/src/github.com/apache/trafficcontrol/infrastructure/cdn-in-a-box/enroller/
+COPY ./infrastructure/cdn-in-a-box/ /go/src/github.com/apache/trafficcontrol/infrastructure/cdn-in-a-box/
 
 WORKDIR /go/src/github.com/apache/trafficcontrol/infrastructure/cdn-in-a-box/enroller
-RUN go get -v && go build
+RUN go clean && go get -v && go build
 
-COPY ./infrastructure/cdn-in-a-box/ /go/src/github.com/apache/trafficcontrol/infrastructure/cdn-in-a-box/
-COPY ./infrastructure/cdn-in-a-box/enroller/server_template.json /
 
 
 FROM debian:stretch
 
-RUN apt-get update && apt-get install -y netcat curl dnsutils net-tools vim && apt-get clean
+RUN apt-get update && apt-get install -y netcat curl dnsutils net-tools && apt-get clean
 COPY --from=enroller-builder \
-   /go/src/github.com/apache/trafficcontrol/infrastructure/cdn-in-a-box \
-   /go/src/github.com/apache/trafficcontrol/infrastructure/cdn-in-a-box
-
-WORKDIR /go/src/github.com/apache/trafficcontrol/infrastructure/cdn-in-a-box/enroller
-CMD ./run.sh
+   /go/src/github.com/apache/trafficcontrol/infrastructure/cdn-in-a-box/enroller/enroller \
+   /go/src/github.com/apache/trafficcontrol/infrastructure/cdn-in-a-box/enroller/run.sh \
+   /go/src/github.com/apache/trafficcontrol/infrastructure/cdn-in-a-box/enroller/server_template.json \
+   /go/src/github.com/apache/trafficcontrol/infrastructure/cdn-in-a-box/traffic_ops/to-access.sh \
+   /
+
+WORKDIR /shared/enroller
+CMD /run.sh
diff --git a/infrastructure/cdn-in-a-box/enroller/enroller.go b/infrastructure/cdn-in-a-box/enroller/enroller.go
index 3c1c4ca76..b71dee6a4 100644
--- a/infrastructure/cdn-in-a-box/enroller/enroller.go
+++ b/infrastructure/cdn-in-a-box/enroller/enroller.go
@@ -21,20 +21,25 @@ import (
 	"bytes"
 	"encoding/json"
 	"errors"
+	"flag"
 	"fmt"
 	"io"
-	"log"
+	"net/http"
 	"net/url"
 	"os"
+	"path/filepath"
 	"strings"
 	"time"
 
+	log "github.com/apache/trafficcontrol/lib/go-log"
 	tc "github.com/apache/trafficcontrol/lib/go-tc"
 	client "github.com/apache/trafficcontrol/traffic_ops/client"
 	"github.com/kelseyhightower/envconfig"
 	"gopkg.in/fsnotify.v1"
 )
 
+var startedFile = "enroller-started"
+
 type session struct {
 	*client.Session
 }
@@ -49,7 +54,7 @@ func printJSON(label string, b interface{}) {
 	enc := json.NewEncoder(&buf)
 	enc.SetIndent(``, `  `)
 	enc.Encode(b)
-	fmt.Println(label, buf.String())
+	log.Infoln(label, buf.String())
 }
 
 func (s session) getParameterIDMatching(m tc.Parameter) (int, error) {
@@ -78,37 +83,23 @@ func (s session) getDeliveryServiceIDByXMLID(n string) (int, error) {
 	return dses[0].ID, err
 }
 
-var to struct {
-	URL      string `envconfig:"TO_URL"`
-	User     string `envconfig:"TO_USER"`
-	Password string `envconfig:"TO_PASSWORD"`
-}
-
 // enrollType takes a json file and creates a Type object using the TO API
-func enrollType(toSession *session, fn string) error {
-	fh, err := os.Open(fn)
-	if err != nil {
-		return err
-	}
-	defer func() {
-		fh.Close()
-	}()
-
-	dec := json.NewDecoder(fh)
+func enrollType(toSession *session, r io.Reader) error {
+	dec := json.NewDecoder(r)
 	var s tc.Type
-	err = dec.Decode(&s)
+	err := dec.Decode(&s)
 	if err != nil && err != io.EOF {
-		log.Printf("error decoding %s: %s\n", fn, err)
+		log.Infof("error decoding Type: %s\n", err)
 		return err
 	}
 
 	alerts, _, err := toSession.CreateType(s)
 	if err != nil {
 		if strings.Contains(err.Error(), "already exists") {
-			log.Printf("type %s already exists\n", s.Name)
+			log.Infof("type %s already exists\n", s.Name)
 			return nil
 		}
-		log.Printf("error creating from %s: %s\n", fn, err)
+		log.Infof("error creating Type: %s\n", err)
 		return err
 	}
 
@@ -120,30 +111,22 @@ func enrollType(toSession *session, fn string) error {
 }
 
 // enrollCDN takes a json file and creates a CDN object using the TO API
-func enrollCDN(toSession *session, fn string) error {
-	fh, err := os.Open(fn)
-	if err != nil {
-		return err
-	}
-	defer func() {
-		fh.Close()
-	}()
-
-	dec := json.NewDecoder(fh)
+func enrollCDN(toSession *session, r io.Reader) error {
+	dec := json.NewDecoder(r)
 	var s tc.CDN
-	err = dec.Decode(&s)
+	err := dec.Decode(&s)
 	if err != nil && err != io.EOF {
-		log.Printf("error decoding %s: %s\n", fn, err)
+		log.Infof("error decoding CDN: %s\n", err)
 		return err
 	}
 
 	alerts, _, err := toSession.CreateCDN(s)
 	if err != nil {
 		if strings.Contains(err.Error(), "already exists") {
-			log.Printf("cdn %s already exists\n", s.Name)
+			log.Infof("cdn %s already exists\n", s.Name)
 			return nil
 		}
-		log.Printf("error creating from %s: %s\n", fn, err)
+		log.Infof("error creating CDN: %s\n", err)
 		return err
 	}
 
@@ -154,30 +137,22 @@ func enrollCDN(toSession *session, fn string) error {
 	return err
 }
 
-func enrollASN(toSession *session, fn string) error {
-	fh, err := os.Open(fn)
-	if err != nil {
-		return err
-	}
-	defer func() {
-		fh.Close()
-	}()
-
-	dec := json.NewDecoder(fh)
+func enrollASN(toSession *session, r io.Reader) error {
+	dec := json.NewDecoder(r)
 	var s tc.ASN
-	err = dec.Decode(&s)
+	err := dec.Decode(&s)
 	if err != nil && err != io.EOF {
-		log.Printf("error decoding %s: %s\n", fn, err)
+		log.Infof("error decoding ASN: %s\n", err)
 		return err
 	}
 
 	alerts, _, err := toSession.CreateASN(s)
 	if err != nil {
 		if strings.Contains(err.Error(), "already exists") {
-			log.Printf("asn %d already exists\n", s.ASN)
+			log.Infof("asn %d already exists\n", s.ASN)
 			return nil
 		}
-		log.Printf("error creating from %s: %s\n", fn, err)
+		log.Infof("error creating ASN: %s\n", err)
 		return err
 	}
 
@@ -189,30 +164,22 @@ func enrollASN(toSession *session, fn string) error {
 }
 
 // enrollCachegroup takes a json file and creates a Cachegroup object using the TO API
-func enrollCachegroup(toSession *session, fn string) error {
-	fh, err := os.Open(fn)
-	if err != nil {
-		return err
-	}
-	defer func() {
-		fh.Close()
-	}()
-
-	dec := json.NewDecoder(fh)
+func enrollCachegroup(toSession *session, r io.Reader) error {
+	dec := json.NewDecoder(r)
 	var s tc.CacheGroupNullable
-	err = dec.Decode(&s)
+	err := dec.Decode(&s)
 	if err != nil && err != io.EOF {
-		log.Printf("error decoding %s: %s\n", fn, err)
+		log.Infof("error decoding Cachegroup: %s\n", err)
 		return err
 	}
 
 	alerts, _, err := toSession.CreateCacheGroupNullable(s)
 	if err != nil {
 		if strings.Contains(err.Error(), "already exists") {
-			log.Printf("cachegroup %s already exists\n", *s.Name)
+			log.Infof("cachegroup %s already exists\n", *s.Name)
 			return nil
 		}
-		log.Printf("error creating from %s: %s\n", fn, err)
+		log.Infof("error creating Cachegroup: %s\n", err)
 		return err
 	}
 
@@ -223,30 +190,22 @@ func enrollCachegroup(toSession *session, fn string) error {
 	return err
 }
 
-func enrollDeliveryService(toSession *session, fn string) error {
-	fh, err := os.Open(fn)
-	if err != nil {
-		return err
-	}
-	defer func() {
-		fh.Close()
-	}()
-
-	dec := json.NewDecoder(fh)
+func enrollDeliveryService(toSession *session, r io.Reader) error {
+	dec := json.NewDecoder(r)
 	var s tc.DeliveryServiceNullable
-	err = dec.Decode(&s)
+	err := dec.Decode(&s)
 	if err != nil && err != io.EOF {
-		log.Printf("error decoding %s: %s\n", fn, err)
+		log.Infof("error decoding DeliveryService: %s\n", err)
 		return err
 	}
 
 	alerts, err := toSession.CreateDeliveryServiceNullable(&s)
 	if err != nil {
 		if strings.Contains(err.Error(), "already exists") {
-			log.Printf("deliveryservice %s already exists\n", *s.XMLID)
+			log.Infof("deliveryservice %s already exists\n", *s.XMLID)
 			return nil
 		}
-		log.Printf("error creating from %s: %s\n", fn, err)
+		log.Infof("error creating DeliveryService: %s\n", err)
 		return err
 	}
 
@@ -257,22 +216,14 @@ func enrollDeliveryService(toSession *session, fn string) error {
 	return err
 }
 
-func enrollDeliveryServiceServer(toSession *session, fn string) error {
-	fh, err := os.Open(fn)
-	if err != nil {
-		return err
-	}
-	defer func() {
-		fh.Close()
-	}()
-
-	dec := json.NewDecoder(fh)
+func enrollDeliveryServiceServer(toSession *session, r io.Reader) error {
+	dec := json.NewDecoder(r)
 
 	// DeliveryServiceServers lists ds xmlid and array of server names.  Use that to create multiple DeliveryServiceServer objects
 	var dss tc.DeliveryServiceServers
-	err = dec.Decode(&dss)
+	err := dec.Decode(&dss)
 	if err != nil && err != io.EOF {
-		log.Printf("error decoding %s: %s\n", fn, err)
+		log.Infof("error decoding DeliveryServiceServer: %s\n", err)
 		return err
 	}
 
@@ -298,36 +249,28 @@ func enrollDeliveryServiceServer(toSession *session, fn string) error {
 	}
 	_, err = toSession.CreateDeliveryServiceServers(dsID, serverIDs, true)
 	if err != nil {
-		log.Printf("error creating from %s: %s\n", fn, err)
+		log.Infof("error creating DeliveryServiceServer: %s\n", err)
 	}
 
 	return err
 }
 
-func enrollDivision(toSession *session, fn string) error {
-	fh, err := os.Open(fn)
-	if err != nil {
-		return err
-	}
-	defer func() {
-		fh.Close()
-	}()
-
-	dec := json.NewDecoder(fh)
+func enrollDivision(toSession *session, r io.Reader) error {
+	dec := json.NewDecoder(r)
 	var s tc.Division
-	err = dec.Decode(&s)
+	err := dec.Decode(&s)
 	if err != nil && err != io.EOF {
-		log.Printf("error decoding %s: %s\n", fn, err)
+		log.Infof("error decoding Division: %s\n", err)
 		return err
 	}
 
 	alerts, _, err := toSession.CreateDivision(s)
 	if err != nil {
 		if strings.Contains(err.Error(), "already exists") {
-			log.Printf("division %s already exists\n", s.Name)
+			log.Infof("division %s already exists\n", s.Name)
 			return nil
 		}
-		log.Printf("error creating from %s: %s\n", fn, err)
+		log.Infof("error creating Division: %s\n", err)
 		return err
 	}
 
@@ -338,30 +281,22 @@ func enrollDivision(toSession *session, fn string) error {
 	return err
 }
 
-func enrollOrigin(toSession *session, fn string) error {
-	fh, err := os.Open(fn)
-	if err != nil {
-		return err
-	}
-	defer func() {
-		fh.Close()
-	}()
-
-	dec := json.NewDecoder(fh)
+func enrollOrigin(toSession *session, r io.Reader) error {
+	dec := json.NewDecoder(r)
 	var s tc.Origin
-	err = dec.Decode(&s)
+	err := dec.Decode(&s)
 	if err != nil && err != io.EOF {
-		log.Printf("error decoding %s: %s\n", fn, err)
+		log.Infof("error decoding Origin: %s\n", err)
 		return err
 	}
 
 	alerts, _, err := toSession.CreateOrigin(s)
 	if err != nil {
 		if strings.Contains(err.Error(), "already exists") {
-			log.Printf("origin %s already exists\n", *s.Name)
+			log.Infof("origin %s already exists\n", *s.Name)
 			return nil
 		}
-		log.Printf("error creating from %s: %s\n", fn, err)
+		log.Infof("error creating Origin: %s\n", err)
 		return err
 	}
 
@@ -372,20 +307,12 @@ func enrollOrigin(toSession *session, fn string) error {
 	return err
 }
 
-func enrollParameter(toSession *session, fn string) error {
-	fh, err := os.Open(fn)
-	if err != nil {
-		return err
-	}
-	defer func() {
-		fh.Close()
-	}()
-
-	dec := json.NewDecoder(fh)
+func enrollParameter(toSession *session, r io.Reader) error {
+	dec := json.NewDecoder(r)
 	var params []tc.Parameter
-	err = dec.Decode(&params)
+	err := dec.Decode(&params)
 	if err != nil && err != io.EOF {
-		log.Printf("error decoding %s: %s\n", fn, err)
+		log.Infof("error decoding Parameter: %s\n", err)
 		return err
 	}
 
@@ -396,17 +323,17 @@ func enrollParameter(toSession *session, fn string) error {
 			// existing param -- update
 			alerts, _, err = toSession.UpdateParameterByID(paramID, p)
 			if err != nil {
-				log.Printf("error updating parameter %d: %s with %+v ", paramID, err.Error(), p)
+				log.Infof("error updating parameter %d: %s with %+v ", paramID, err.Error(), p)
 				break
 			}
 		} else {
 			alerts, _, err = toSession.CreateParameter(p)
 			if err != nil {
 				if strings.Contains(err.Error(), "already exists") {
-					log.Printf("parameter %s already exists\n", p.Name)
+					log.Infof("parameter %s already exists\n", p.Name)
 					return nil
 				}
-				log.Printf("error creating from %s: %s\n", fn, err)
+				log.Infof("error creating parameter: %s from %+v\n", err.Error(), p)
 				return err
 			}
 		}
@@ -420,7 +347,7 @@ func enrollParameter(toSession *session, fn string) error {
 			var profiles []string
 			err = json.Unmarshal(p.Profiles, &profiles)
 			if err != nil {
-				log.Printf("%v", err)
+				log.Infof("%v", err)
 			}
 
 			for _, n := range profiles {
@@ -448,30 +375,22 @@ func enrollParameter(toSession *session, fn string) error {
 	return err
 }
 
-func enrollPhysLocation(toSession *session, fn string) error {
-	fh, err := os.Open(fn)
-	if err != nil {
-		return err
-	}
-	defer func() {
-		fh.Close()
-	}()
-
-	dec := json.NewDecoder(fh)
+func enrollPhysLocation(toSession *session, r io.Reader) error {
+	dec := json.NewDecoder(r)
 	var s tc.PhysLocation
-	err = dec.Decode(&s)
+	err := dec.Decode(&s)
 	if err != nil && err != io.EOF {
-		log.Printf("error decoding %s: %s\n", fn, err)
+		log.Infof("error decoding PhysLocation: %s\n", err)
 		return err
 	}
 
 	alerts, _, err := toSession.CreatePhysLocation(s)
 	if err != nil {
 		if strings.Contains(err.Error(), "already exists") {
-			log.Printf("physLocation %s already exists\n", s.Name)
+			log.Infof("physLocation %s already exists\n", s.Name)
 			return nil
 		}
-		log.Printf("error creating from %s: %s\n", fn, err)
+		log.Infof("error creating PhysLocation: %s\n", err)
 		return err
 	}
 
@@ -482,30 +401,22 @@ func enrollPhysLocation(toSession *session, fn string) error {
 	return err
 }
 
-func enrollRegion(toSession *session, fn string) error {
-	fh, err := os.Open(fn)
-	if err != nil {
-		return err
-	}
-	defer func() {
-		fh.Close()
-	}()
-
-	dec := json.NewDecoder(fh)
+func enrollRegion(toSession *session, r io.Reader) error {
+	dec := json.NewDecoder(r)
 	var s tc.Region
-	err = dec.Decode(&s)
+	err := dec.Decode(&s)
 	if err != nil && err != io.EOF {
-		log.Printf("error decoding %s: %s\n", fn, err)
+		log.Infof("error decoding Region: %s\n", err)
 		return err
 	}
 
 	alerts, _, err := toSession.CreateRegion(s)
 	if err != nil {
 		if strings.Contains(err.Error(), "already exists") {
-			log.Printf("region %s already exists\n", s.Name)
+			log.Infof("region %s already exists\n", s.Name)
 			return nil
 		}
-		log.Printf("error creating from %s: %s\n", fn, err)
+		log.Infof("error creating Region: %s\n", err)
 		return err
 	}
 
@@ -516,30 +427,22 @@ func enrollRegion(toSession *session, fn string) error {
 	return err
 }
 
-func enrollStatus(toSession *session, fn string) error {
-	fh, err := os.Open(fn)
-	if err != nil {
-		return err
-	}
-	defer func() {
-		fh.Close()
-	}()
-
-	dec := json.NewDecoder(fh)
+func enrollStatus(toSession *session, r io.Reader) error {
+	dec := json.NewDecoder(r)
 	var s tc.Status
-	err = dec.Decode(&s)
+	err := dec.Decode(&s)
 	if err != nil && err != io.EOF {
-		log.Printf("error decoding %s: %s\n", fn, err)
+		log.Infof("error decoding Status: %s\n", err)
 		return err
 	}
 
 	alerts, _, err := toSession.CreateStatus(s)
 	if err != nil {
 		if strings.Contains(err.Error(), "already exists") {
-			log.Printf("status %s already exists\n", s.Name)
+			log.Infof("status %s already exists\n", s.Name)
 			return nil
 		}
-		log.Printf("error creating from %s: %s\n", fn, err)
+		log.Infof("error creating Status: %s\n", err)
 		return err
 	}
 
@@ -550,30 +453,22 @@ func enrollStatus(toSession *session, fn string) error {
 	return err
 }
 
-func enrollTenant(toSession *session, fn string) error {
-	fh, err := os.Open(fn)
-	if err != nil {
-		return err
-	}
-	defer func() {
-		fh.Close()
-	}()
-
-	dec := json.NewDecoder(fh)
+func enrollTenant(toSession *session, r io.Reader) error {
+	dec := json.NewDecoder(r)
 	var s tc.Tenant
-	err = dec.Decode(&s)
+	err := dec.Decode(&s)
 	if err != nil && err != io.EOF {
-		log.Printf("error decoding %s: %s\n", fn, err)
+		log.Infof("error decoding Tenant: %s\n", err)
 		return err
 	}
 
 	alerts, err := toSession.CreateTenant(&s)
 	if err != nil {
 		if strings.Contains(err.Error(), "already exists") {
-			log.Printf("tenant %s already exists\n", s.Name)
+			log.Infof("tenant %s already exists\n", s.Name)
 			return nil
 		}
-		log.Printf("error creating from %s: %s\n", fn, err)
+		log.Infof("error creating Tenant: %s\n", err)
 		return err
 	}
 
@@ -584,31 +479,23 @@ func enrollTenant(toSession *session, fn string) error {
 	return err
 }
 
-func enrollUser(toSession *session, fn string) error {
-	fh, err := os.Open(fn)
-	if err != nil {
-		return err
-	}
-	defer func() {
-		fh.Close()
-	}()
-
-	dec := json.NewDecoder(fh)
+func enrollUser(toSession *session, r io.Reader) error {
+	dec := json.NewDecoder(r)
 	var s tc.User
-	err = dec.Decode(&s)
-	log.Printf("User is %++v\n", s)
+	err := dec.Decode(&s)
+	log.Infof("User is %++v\n", s)
 	if err != nil && err != io.EOF {
-		log.Printf("error decoding %s: %s\n", fn, err)
+		log.Infof("error decoding User: %s\n", err)
 		return err
 	}
 
 	alerts, _, err := toSession.CreateUser(&s)
 	if err != nil {
 		if strings.Contains(err.Error(), "already exists") {
-			log.Printf("user %s already exists\n", *s.Username)
+			log.Infof("user %s already exists\n", *s.Username)
 			return nil
 		}
-		log.Printf("error creating from %s: %s\n", fn, err)
+		log.Infof("error creating User: %s\n", err)
 		return err
 	}
 
@@ -626,21 +513,13 @@ type profileImport struct {
 }
 
 // enrollProfile takes a json file and creates a Profile object using the TO API
-func enrollProfile(toSession *session, fn string) error {
-	fh, err := os.Open(fn)
-	if err != nil {
-		return err
-	}
-	defer func() {
-		fh.Close()
-	}()
-
-	dec := json.NewDecoder(fh)
+func enrollProfile(toSession *session, r io.Reader) error {
+	dec := json.NewDecoder(r)
 	var profile tc.Profile
 
-	err = dec.Decode(&profile)
+	err := dec.Decode(&profile)
 	if err != nil && err != io.EOF {
-		log.Printf("error decoding %s: %s\n", fn, err)
+		log.Infof("error decoding Profile: %s\n", err)
 		return err
 	}
 
@@ -649,8 +528,8 @@ func enrollProfile(toSession *session, fn string) error {
 	enc.Encode(profile)
 
 	if len(profile.Name) == 0 {
-		log.Println("missing name on profile from " + fn)
-		return errors.New("missing name on profile from " + fn)
+		log.Infoln("missing name on profile")
+		return errors.New("missing name on profile")
 	}
 
 	profiles, _, err := toSession.GetProfileByName(profile.Name)
@@ -670,14 +549,14 @@ func enrollProfile(toSession *session, fn string) error {
 		alerts, _, err = toSession.CreateProfile(profile)
 		if err != nil {
 			if strings.Contains(err.Error(), "already exists") {
-				log.Printf("profile %s already exists\n", profile.Name)
+				log.Infof("profile %s already exists\n", profile.Name)
 			} else {
-				log.Printf("error creating profile from %+v: %s\n", profile, err.Error())
+				log.Infof("error creating profile from %+v: %s\n", profile, err.Error())
 			}
 		}
 		profiles, _, err = toSession.GetProfileByName(profile.Name)
 		if err != nil || len(profiles) == 0 {
-			log.Printf("error getting profile ID from %+v: %s\n", profile, err.Error())
+			log.Infof("error getting profile ID from %+v: %s\n", profile, err.Error())
 		}
 		profile.ID = profiles[0].ID
 		action = "creating"
@@ -687,11 +566,11 @@ func enrollProfile(toSession *session, fn string) error {
 	}
 
 	if err != nil {
-		log.Printf("error "+action+" from %s: %s\n", fn, err)
+		log.Infof("error "+action+" from %s: %s\n", err)
 		return err
 	}
 
-	//log.Printf("total profile is  %+v\n", profile)
+	//log.Infof("total profile is  %+v\n", profile)
 	for _, p := range profile.Parameters {
 		var name, configFile, value string
 		var secure bool
@@ -705,22 +584,22 @@ func enrollProfile(toSession *session, fn string) error {
 			value = *p.Value
 		}
 		param := tc.Parameter{ConfigFile: configFile, Name: name, Value: value, Secure: secure}
-		log.Printf("creating param %+v\n", param)
+		log.Infof("creating param %+v\n", param)
 		id, err := toSession.getParameterIDMatching(param)
 		if err != nil {
 			// create it
 			_, _, err = toSession.CreateParameter(param)
 			if err != nil {
 				if !strings.Contains(err.Error(), "already exists") {
-					log.Printf("can't create parameter %+v: %s\n", param, err.Error())
+					log.Infof("can't create parameter %+v: %s\n", param, err.Error())
 				}
 				continue
 			}
 			param.ID, err = toSession.getParameterIDMatching(param)
 			if err != nil {
-				log.Printf("error getting new parameter %+v\n", param)
+				log.Infof("error getting new parameter %+v\n", param)
 				param.ID, err = toSession.getParameterIDMatching(param)
-				log.Printf(err.Error())
+				log.Infof(err.Error())
 
 			}
 		} else {
@@ -729,14 +608,14 @@ func enrollProfile(toSession *session, fn string) error {
 		}
 
 		if param.ID < 1 {
-			panic(fmt.Sprintf("param ID not found for %v", param))
-
+			log.Infof("param ID not found for %v", param)
+			continue
 		}
 		pp := tc.ProfileParameter{ProfileID: profile.ID, ParameterID: param.ID}
 		_, _, err = toSession.CreateProfileParameter(pp)
 		if err != nil {
 			if !strings.Contains(err.Error(), "already exists") {
-				log.Printf("error creating profileparameter %+v: %s\n", pp, err.Error())
+				log.Infof("error creating profileparameter %+v: %s\n", pp, err.Error())
 			}
 			continue
 		}
@@ -750,26 +629,18 @@ func enrollProfile(toSession *session, fn string) error {
 }
 
 // enrollServer takes a json file and creates a Server object using the TO API
-func enrollServer(toSession *session, fn string) error {
-	fh, err := os.Open(fn)
-	if err != nil {
-		return err
-	}
-	defer func() {
-		fh.Close()
-	}()
-
-	dec := json.NewDecoder(fh)
+func enrollServer(toSession *session, r io.Reader) error {
+	dec := json.NewDecoder(r)
 	var s tc.Server
-	err = dec.Decode(&s)
+	err := dec.Decode(&s)
 	if err != nil && err != io.EOF {
-		log.Printf("error decoding %s: %s\n", fn, err)
+		log.Infof("error decoding Server: %s\n", err)
 		return err
 	}
 
 	alerts, _, err := toSession.CreateServer(s)
 	if err != nil {
-		log.Printf("error creating from %s: %s\n", fn, err)
+		log.Infof("error creating Server: %s\n", err)
 		return err
 	}
 
@@ -804,52 +675,53 @@ func newDirWatcher(toSession *session) (*dirWatcher, error) {
 			select {
 			case event, ok := <-dw.Events:
 				if !ok {
-					log.Printf("event not ok: %+v", event)
-					return
+					log.Infoln("event not ok")
+					continue
 				}
 
-				//log.Println("event:", event)
-				if event.Op&fsnotify.Create == fsnotify.Create {
-					if strings.HasSuffix(event.Name, processed) || strings.HasSuffix(event.Name, rejected) {
-						continue
-					}
-					i, err := os.Stat(event.Name)
-					if err != nil || i.IsDir() {
-						log.Println("skipping " + event.Name)
-						continue
-					}
-					log.Println("new file :", event.Name)
-					p := strings.IndexRune(event.Name, '/')
-					if p == -1 {
-						continue
-					}
-					dir := event.Name[:p]
-					suffix := rejected
-					if f, ok := dw.watched[dir]; ok {
-						log.Printf("creating from %s\n", event.Name)
-						// TODO: ensure file content is there before attempting to read
-						time.Sleep(100 * time.Millisecond)
-
-						err := f(toSession, event.Name)
-						if err != nil {
-							log.Printf("error creating %s from %s: %s\n", dir, event.Name, err.Error())
-						} else {
-							suffix = processed
-						}
-					} else {
-						log.Printf("no method for creating %s\n", dir)
-					}
-					// rename the file indicating if processed or rejected
-					err = os.Rename(event.Name, event.Name+suffix)
+				// ignore all but Create events
+				if event.Op&fsnotify.Create != fsnotify.Create {
+					continue
+				}
+
+				// skip already processed files
+				if strings.HasSuffix(event.Name, processed) || strings.HasSuffix(event.Name, rejected) {
+					continue
+				}
+
+				i, err := os.Stat(event.Name)
+				if err != nil || i.IsDir() {
+					log.Infoln("skipping " + event.Name)
+					continue
+				}
+				log.Infoln("new file :", event.Name)
+
+				// what directory is the file in?  Invoke the matching func
+				dir := filepath.Base(filepath.Dir(event.Name))
+				suffix := rejected
+				if f, ok := dw.watched[dir]; ok {
+					t := filepath.Base(dir)
+					log.Infoln("creating " + t + " from " + event.Name)
+					// TODO: ensure file content is there before attempting to read.  For now, this does the trick..
+					time.Sleep(100 * time.Millisecond)
+
+					err := f(toSession, event.Name)
 					if err != nil {
-						log.Printf("error renaming %s to %s: %s\n", event.Name, event.Name+suffix, err.Error())
+						log.Infof("error creating %s from %s: %s\n", dir, event.Name, err.Error())
+					} else {
+						suffix = processed
 					}
+				} else {
+					log.Infof("no method for creating %s\n", dir)
 				}
-			case err, ok := <-dw.Errors:
-				if !ok {
-					log.Printf("error not ok: %+v", err)
+				// rename the file indicating if processed or rejected
+				err = os.Rename(event.Name, event.Name+suffix)
+				if err != nil {
+					log.Infof("error renaming %s to %s: %s\n", event.Name, event.Name+suffix, err.Error())
 				}
-				log.Println("error:", err)
+			case err, ok := <-dw.Errors:
+				log.Infof("error from fsnotify: ok? %v;  error: %v\n", ok, err)
+				continue
 			}
 		}
 	}()
@@ -857,72 +729,160 @@ func newDirWatcher(toSession *session) (*dirWatcher, error) {
 }
 
 // watch starts f when a new file is created in dir
-func (dw *dirWatcher) watch(dir string, f func(*session, string) error) {
+func (dw *dirWatcher) watch(watchdir, t string, f func(*session, io.Reader) error) {
+	dir := watchdir + "/" + t
 	if stat, err := os.Stat(dir); err != nil || !stat.IsDir() {
 		// attempt to create dir
 		if err = os.Mkdir(dir, os.ModeDir|0700); err != nil {
-			log.Println("cannot watch " + dir + ": not a directory")
+			log.Infoln("cannot watch " + dir + ": not a directory")
 			return
 		}
 	}
-	log.Println("watching " + dir)
+
+	log.Infoln("watching " + dir)
 	dw.Add(dir)
-	dw.watched[dir] = f
+	dw.watched[t] = func(toSession *session, fn string) error {
+		fh, err := os.Open(fn)
+		if err != nil {
+			return err
+		}
+		defer fh.Close()
+		return f(toSession, fh)
+	}
+}
+
+func startWatching(watchDir string, toSession *session, dispatcher map[string]func(*session, io.Reader) error) (*dirWatcher, error) {
+	// watch for file creation in directories
+	dw, err := newDirWatcher(toSession)
+	if err == nil {
+		for d, f := range dispatcher {
+			dw.watch(watchDir, d, f)
+		}
+	}
+	return dw, err
+}
+
+func startServer(httpPort string, toSession *session, dispatcher map[string]func(*session, io.Reader) error) error {
+	baseEP := "/api/1.4/"
+	for d, f := range dispatcher {
+		http.HandleFunc(baseEP+d, func(w http.ResponseWriter, r *http.Request) {
+			defer r.Body.Close()
+			f(toSession, r.Body)
+		})
+	}
+
+	go func() {
+		server := &http.Server{
+			Addr:      httpPort,
+			TLSConfig: nil,
+			ErrorLog:  log.Error,
+		}
+		if err := server.ListenAndServe(); err != nil {
+			log.Errorf("stopping server: %v\n", err)
+			panic(err)
+		}
+	}()
+
+	log.Infoln("http service started on " + httpPort)
+	return nil
 }
 
-const startedFile = "enroller-started"
+// Set up the log config -- all messages go to stdout
+type logConfig struct{}
+
+func (cfg logConfig) ErrorLog() log.LogLocation {
+	return log.LogLocationStdout
+}
+func (cfg logConfig) WarningLog() log.LogLocation {
+	return log.LogLocationStdout
+}
+func (cfg logConfig) InfoLog() log.LogLocation {
+	return log.LogLocationStdout
+}
+func (cfg logConfig) DebugLog() log.LogLocation {
+	return log.LogLocationStdout
+}
+func (cfg logConfig) EventLog() log.LogLocation {
+	return log.LogLocationStdout
+}
 
 func main() {
-	watchDir := "."
-	if len(os.Args) > 1 {
-		watchDir = os.Args[1]
+	var watchDir, httpPort string
+
+	flag.StringVar(&startedFile, "started", startedFile, "file indicating service was started")
+	flag.StringVar(&watchDir, "dir", "", "base directory to watch")
+	flag.StringVar(&httpPort, "http", "", "act as http server for POST on this port (e.g. :7070)")
+	flag.Parse()
+
+	err := log.InitCfg(logConfig{})
+	if err != nil {
+		panic(err.Error())
 	}
-	if stat, err := os.Stat(watchDir); err != nil || !stat.IsDir() {
-		log.Fatalln("expected " + watchDir + " to be a directory")
+	if watchDir == "" && httpPort == "" {
+		// if neither -dir nor -http provided, default to watching the current dir
+		watchDir = "."
 	}
-	if err := os.Chdir(watchDir); err != nil {
-		log.Fatalf("cannot chdir to %s: %s", watchDir, err)
+
+	var toCreds struct {
+		URL      string `envconfig:"TO_URL"`
+		User     string `envconfig:"TO_USER"`
+		Password string `envconfig:"TO_PASSWORD"`
 	}
-	envconfig.Process("", &to)
+
+	envconfig.Process("", &toCreds)
 
 	reqTimeout := time.Second * time.Duration(60)
 
-	log.Println("Starting TrafficOps session")
-	toSession, err := newSession(reqTimeout, to.URL, to.User, to.Password)
-	if err != nil {
-		log.Fatalln("error starting TrafficOps session: " + err.Error())
+	log.Infoln("Starting TrafficOps session")
+	toSession, err := newSession(reqTimeout, toCreds.URL, toCreds.User, toCreds.Password)
+	if err != nil {
+		log.Errorln("error starting TrafficOps session: " + err.Error())
+	}
+	log.Infoln("TrafficOps session established")
+
+	// dispatcher maps an API endpoint name to a function to act on the JSON input Reader
+	dispatcher := map[string]func(*session, io.Reader) error{
+		"types":                   enrollType,
+		"cdns":                    enrollCDN,
+		"cachegroups":             enrollCachegroup,
+		"profiles":                enrollProfile,
+		"parameters":              enrollParameter,
+		"servers":                 enrollServer,
+		"asns":                    enrollASN,
+		"deliveryservices":        enrollDeliveryService,
+		"deliveryservice_servers": enrollDeliveryServiceServer,
+		"divisions":               enrollDivision,
+		"origins":                 enrollOrigin,
+		"phys_locations":          enrollPhysLocation,
+		"regions":                 enrollRegion,
+		"statuses":                enrollStatus,
+		"tenants":                 enrollTenant,
+		"users":                   enrollUser,
+	}
+
+	if len(httpPort) != 0 {
+		log.Infoln("Starting http server on " + httpPort)
+		err := startServer(httpPort, &toSession, dispatcher)
+		if err != nil {
+			log.Errorln("http server on " + httpPort + " failed: " + err.Error())
+		}
 	}
-	fmt.Println("TrafficOps session established")
 
-	// watch for file creation in directories
-	dw, err := newDirWatcher(&toSession)
-	if err != nil {
-		log.Fatalf("%v", err)
-	}
-	defer dw.Close()
-
-	dw.watch("types", enrollType)
-	dw.watch("cdns", enrollCDN)
-	dw.watch("cachegroups", enrollCachegroup)
-	dw.watch("profiles", enrollProfile)
-	dw.watch("parameters", enrollParameter)
-	dw.watch("servers", enrollServer)
-	dw.watch("asns", enrollASN)
-	dw.watch("deliveryservices", enrollDeliveryService)
-	dw.watch("deliveryservice_servers", enrollDeliveryServiceServer)
-	dw.watch("divisions", enrollDivision)
-	dw.watch("origins", enrollOrigin)
-	dw.watch("phys_locations", enrollPhysLocation)
-	dw.watch("regions", enrollRegion)
-	dw.watch("statuses", enrollStatus)
-	dw.watch("tenants", enrollTenant)
-	dw.watch("users", enrollUser)
+	if len(watchDir) != 0 {
+		log.Infoln("Watching directory " + watchDir)
+		dw, err := startWatching(watchDir, &toSession, dispatcher)
+		defer dw.Close()
+		if err != nil {
+			log.Errorf("dirwatcher on %s failed: %s", watchDir, err.Error())
+		}
+	}
 
 	// create this file to indicate the enroller is ready
 	f, err := os.Create(startedFile)
 	if err != nil {
 		panic(err)
 	}
+	log.Infoln("Created " + startedFile)
 	f.Close()
 
 	var waitforever chan struct{}
diff --git a/infrastructure/cdn-in-a-box/enroller/run.sh b/infrastructure/cdn-in-a-box/enroller/run.sh
index 0f35d1123..3f0bbef25 100755
--- a/infrastructure/cdn-in-a-box/enroller/run.sh
+++ b/infrastructure/cdn-in-a-box/enroller/run.sh
@@ -18,7 +18,8 @@
 # under the License.
 ############################################################
 
-. ../traffic_ops/to-access.sh
+set -x
+. /to-access.sh
 
 export TO_URL=https://$TO_FQDN:$TO_PORT
 export TO_USER=$TO_ADMIN_USER
@@ -53,4 +54,4 @@ fi
 # clear out the enroller dir first so no files left from previous run
 rm -rf ${ENROLLER_DIR}/*
 
-./enroller "$ENROLLER_DIR" || tail -f /dev/null
+/enroller -dir "$ENROLLER_DIR" || tail -f /dev/null


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services