You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by mi...@apache.org on 2018/06/18 16:25:49 UTC

[trafficcontrol] branch master updated: Fix TO Go DS update to omit sslkeys for anymap

This is an automated email from the ASF dual-hosted git repository.

mitchell852 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git


The following commit(s) were added to refs/heads/master by this push:
     new 9a44efb  Fix TO Go DS update to omit sslkeys for anymap
9a44efb is described below

commit 9a44efb25529bf803bcfe515b7f2aea3e1d861d5
Author: Robert Butts <ro...@apache.org>
AuthorDate: Mon Jun 11 10:52:55 2018 -0600

    Fix TO Go DS update to omit sslkeys for anymap
---
 lib/go-tc/deliveryservices.go                      |  12 +-
 lib/go-tc/enum.go                                  | 223 +++++++++++++++++++--
 traffic_monitor/datareq/dsstatfilter.go            |  14 +-
 traffic_monitor/todata/todata.go                   |  12 +-
 .../deliveryservice/deliveryservicesv12.go         |   7 +-
 .../deliveryservice/deliveryservicesv13.go         |  89 +++++---
 6 files changed, 289 insertions(+), 68 deletions(-)

diff --git a/lib/go-tc/deliveryservices.go b/lib/go-tc/deliveryservices.go
index 7990998..e7e8614 100644
--- a/lib/go-tc/deliveryservices.go
+++ b/lib/go-tc/deliveryservices.go
@@ -21,6 +21,8 @@ import (
    limitations under the License.
 */
 
+const DefaultRoutingName = "cdn"
+
 //
 // GetDeliveryServiceResponse is deprecated use DeliveryServicesResponse...
 type GetDeliveryServiceResponse struct {
@@ -107,7 +109,7 @@ type DeliveryService struct {
 	RoutingName          string                 `json:"routingName"`
 	SigningAlgorithm     string                 `json:"signingAlgorithm" db:"signing_algorithm"`
 	TypeID               int                    `json:"typeId"`
-	Type                 string                 `json:"type"`
+	Type                 DSType                 `json:"type"`
 	TRResponseHeaders    string                 `json:"trResponseHeaders"`
 	TenantID             int                    `json:"tenantId,omitempty"`
 	XMLID                string                 `json:"xmlId"`
@@ -184,7 +186,7 @@ type DeliveryServiceNullable struct {
 	Signed               bool                    `json:"signed"`
 	SSLKeyVersion        *int                    `json:"sslKeyVersion" db:"ssl_key_version"`
 	TenantID             *int                    `json:"tenantId" db:"tenant_id"`
-	Type                 *string                 `json:"type"`
+	Type                 *DSType                 `json:"type"`
 	TypeID               *int                    `json:"typeId" db:"type"`
 	XMLID                *string                 `json:"xmlId" db:"xml_id"`
 	ExampleURLs          []string                `json:"exampleURLs"`
@@ -224,9 +226,9 @@ func (d *DeliveryServiceNullable) Scan(src interface{}) error {
 
 // DeliveryServiceMatch ...
 type DeliveryServiceMatch struct {
-	Type      string `json:"type"`
-	SetNumber int    `json:"setNumber"`
-	Pattern   string `json:"pattern"`
+	Type      DSMatchType `json:"type"`
+	SetNumber int         `json:"setNumber"`
+	Pattern   string      `json:"pattern"`
 }
 
 // DeliveryServiceAlert ...
diff --git a/lib/go-tc/enum.go b/lib/go-tc/enum.go
index d7991b7..7d203d5 100644
--- a/lib/go-tc/enum.go
+++ b/lib/go-tc/enum.go
@@ -98,40 +98,40 @@ func CacheTypeFromString(s string) CacheType {
 	return CacheTypeInvalid
 }
 
-// DSType is the Delivery Service type. HTTP, DNS, etc.
-type DSType string
+// DSTypeCategory is the Delivery Service type category: HTTP or DNS
+type DSTypeCategory string
 
 const (
-	// DSTypeHTTP represents an HTTP delivery service
-	DSTypeHTTP = DSType("http")
-	// DSTypeDNS represents a DNS delivery service
-	DSTypeDNS = DSType("dns")
-	// DSTypeInvalid represents an invalid delivery service type enumeration. Note this is the default construction for a DSType.
-	DSTypeInvalid = DSType("")
+	// DSTypeCategoryHTTP represents an HTTP delivery service
+	DSTypeCategoryHTTP = DSTypeCategory("http")
+	// DSTypeCategoryDNS represents a DNS delivery service
+	DSTypeCategoryDNS = DSTypeCategory("dns")
+	// DSTypeCategoryInvalid represents an invalid delivery service type enumeration. Note this is the default construction for a DSTypeCategory.
+	DSTypeCategoryInvalid = DSTypeCategory("")
 )
 
 // String returns a string representation of this delivery service type.
-func (t DSType) String() string {
+func (t DSTypeCategory) String() string {
 	switch t {
-	case DSTypeHTTP:
+	case DSTypeCategoryHTTP:
 		return "HTTP"
-	case DSTypeDNS:
+	case DSTypeCategoryDNS:
 		return "DNS"
 	default:
 		return "INVALIDDSTYPE"
 	}
 }
 
-// DSTypeFromString returns a delivery service type object from its string representation, or DSTypeInvalid if the string is not a valid type.
-func DSTypeFromString(s string) DSType {
+// DSTypeCategoryFromString returns a delivery service type object from its string representation, or DSTypeCategoryInvalid if the string is not a valid type.
+func DSTypeCategoryFromString(s string) DSTypeCategory {
 	s = strings.ToLower(s)
 	switch s {
 	case "http":
-		return DSTypeHTTP
+		return DSTypeCategoryHTTP
 	case "dns":
-		return DSTypeDNS
+		return DSTypeCategoryDNS
 	default:
-		return DSTypeInvalid
+		return DSTypeCategoryInvalid
 	}
 }
 
@@ -243,3 +243,194 @@ func (t *DeepCachingType) UnmarshalJSON(data []byte) error {
 func (t DeepCachingType) MarshalJSON() ([]byte, error) {
 	return json.Marshal(t.String())
 }
+
+// DSType is the Delivery Service type.
+type DSType string
+
+const (
+	DSTypeClientSteering   DSType = "CLIENT_STEERING"
+	DSTypeDNS              DSType = "DNS"
+	DSTypeDNSLive          DSType = "DNS_LIVE"
+	DSTypeDNSLiveNational  DSType = "DNS_LIVE_NATNL"
+	DSTypeHTTP             DSType = "HTTP"
+	DSTypeHTTPLive         DSType = "HTTP_LIVE"
+	DSTypeHTTPLiveNational DSType = "HTTP_LIVE_NATNL"
+	DSTypeHTTPNoCache      DSType = "HTTP_NO_CACHE"
+	DSTypeSteering         DSType = "STEERING"
+	DSTypeAnyMap           DSType = "ANY_MAP"
+	DSTypeInvalid          DSType = ""
+)
+
+// String returns a string representation of this delivery service type.
+func (t DSType) String() string {
+	switch t {
+	case DSTypeHTTPNoCache:
+		fallthrough
+	case DSTypeDNS:
+		fallthrough
+	case DSTypeDNSLive:
+		fallthrough
+	case DSTypeHTTP:
+		fallthrough
+	case DSTypeDNSLiveNational:
+		fallthrough
+	case DSTypeAnyMap:
+		fallthrough
+	case DSTypeHTTPLive:
+		fallthrough
+	case DSTypeSteering:
+		fallthrough
+	case DSTypeHTTPLiveNational:
+		fallthrough
+	case DSTypeClientSteering:
+		return string(t)
+	default:
+		return "INVALID"
+	}
+}
+
+// DSTypeFromString returns a delivery service type object from its string representation, or DSTypeInvalid if the string is not a valid type.
+func DSTypeFromString(s string) DSType {
+	s = strings.ToLower(strings.Replace(s, "_", "", -1))
+	switch s {
+	case "httpnocache":
+		return DSTypeHTTPNoCache
+	case "dns":
+		return DSTypeDNS
+	case "dnslive":
+		return DSTypeDNSLive
+	case "http":
+		return DSTypeHTTP
+	case "dnslivenatnl":
+		return DSTypeDNSLiveNational
+	case "anymap":
+		return DSTypeAnyMap
+	case "httplive":
+		return DSTypeHTTPLive
+	case "steering":
+		return DSTypeSteering
+	case "httplivenatnl":
+		return DSTypeHTTPLiveNational
+	case "clientsteering":
+		return DSTypeClientSteering
+	default:
+		return DSTypeInvalid
+	}
+}
+
+// IsHTTP returns whether the DSType is an HTTP category.
+func (t DSType) IsHTTP() bool {
+	switch t {
+	case DSTypeHTTP:
+		fallthrough
+	case DSTypeHTTPLive:
+		fallthrough
+	case DSTypeHTTPLiveNational:
+		fallthrough
+	case DSTypeHTTPNoCache:
+		return true
+	}
+	return false
+}
+
+// IsDNS returns whether the DSType is a DNS category.
+func (t DSType) IsDNS() bool {
+	switch t {
+	case DSTypeHTTPNoCache:
+		fallthrough
+	case DSTypeDNS:
+		fallthrough
+	case DSTypeDNSLive:
+		fallthrough
+	case DSTypeDNSLiveNational:
+		return true
+	}
+	return false
+}
+
+// IsSteering returns whether the DSType is a Steering category
+func (t DSType) IsSteering() bool {
+	switch t {
+	case DSTypeSteering:
+		fallthrough
+	case DSTypeClientSteering:
+		fallthrough
+	case DSTypeDNSLive:
+		return true
+	}
+	return false
+}
+
+// HasSSLKeys returns whether delivery services of this type have SSL keys.
+func (t DSType) HasSSLKeys() bool {
+	return t.IsHTTP() || t.IsDNS() || t.IsSteering()
+}
+
+// IsLive returns whether delivery services of this type are "live".
+func (t DSType) IsLive() bool {
+	switch t {
+	case DSTypeDNSLive:
+		fallthrough
+	case DSTypeDNSLiveNational:
+		fallthrough
+	case DSTypeHTTPLive:
+		fallthrough
+	case DSTypeHTTPLiveNational:
+		return true
+	}
+	return false
+}
+
+// IsLive returns whether delivery services of this type are "national".
+func (t DSType) IsNational() bool {
+	switch t {
+	case DSTypeDNSLiveNational:
+		fallthrough
+	case DSTypeHTTPLiveNational:
+		return true
+	}
+	return false
+}
+
+type DSMatchType string
+
+const (
+	DSMatchTypeHostRegex     DSMatchType = "HOST_REGEXP"
+	DSMatchTypePathRegex     DSMatchType = "PATH_REGEXP"
+	DSMatchTypeSteeringRegex DSMatchType = "STEERING_REGEXP"
+	DSMatchTypeHeaderRegex   DSMatchType = "HEADER_REGEXP"
+	DSMatchTypeInvalid       DSMatchType = ""
+)
+
+// String returns a string representation of this delivery service match type.
+func (t DSMatchType) String() string {
+	switch t {
+	case DSMatchTypeHostRegex:
+		fallthrough
+	case DSMatchTypePathRegex:
+		fallthrough
+	case DSMatchTypeSteeringRegex:
+		fallthrough
+	case DSMatchTypeHeaderRegex:
+		return string(t)
+	default:
+		return "INVALID_MATCH_TYPE"
+	}
+}
+
+// DSMatchTypeFromString returns a delivery service match type object from its string representation, or DSMatchTypeInvalid if the string is not a valid type.
+func DSMatchTypeFromString(s string) DSMatchType {
+	s = strings.ToLower(strings.Replace(s, "_", "", -1))
+	switch s {
+	case "hostregexp":
+		return DSMatchTypeHostRegex
+	case "pathregexp":
+		return DSMatchTypePathRegex
+	case "steeringregexp":
+		return DSMatchTypeSteeringRegex
+	case "headerregexp":
+		return DSMatchTypeHeaderRegex
+	default:
+		return DSMatchTypeInvalid
+	}
+}
diff --git a/traffic_monitor/datareq/dsstatfilter.go b/traffic_monitor/datareq/dsstatfilter.go
index d872027..91aadd9 100644
--- a/traffic_monitor/datareq/dsstatfilter.go
+++ b/traffic_monitor/datareq/dsstatfilter.go
@@ -34,9 +34,9 @@ type DSStatFilter struct {
 	historyCount     int
 	statsToUse       map[string]struct{}
 	wildcard         bool
-	dsType           tc.DSType
+	dsType           tc.DSTypeCategory
 	deliveryServices map[tc.DeliveryServiceName]struct{}
-	dsTypes          map[tc.DeliveryServiceName]tc.DSType
+	dsTypes          map[tc.DeliveryServiceName]tc.DSTypeCategory
 }
 
 // UseDeliveryService returns whether the given delivery service is in this filter.
@@ -44,7 +44,7 @@ func (f *DSStatFilter) UseDeliveryService(name tc.DeliveryServiceName) bool {
 	if _, inDSes := f.deliveryServices[name]; len(f.deliveryServices) != 0 && !inDSes {
 		return false
 	}
-	if f.dsType != tc.DSTypeInvalid && f.dsTypes[name] != f.dsType {
+	if f.dsType != tc.DSTypeCategoryInvalid && f.dsTypes[name] != f.dsType {
 		return false
 	}
 	return true
@@ -84,7 +84,7 @@ func (f *DSStatFilter) WithinStatHistoryMax(n int) bool {
 // If `stats` is empty, all stats are returned.
 // If `wildcard` is empty, `stats` is considered exact.
 // If `type` is empty, all types are returned.
-func NewDSStatFilter(path string, params url.Values, dsTypes map[tc.DeliveryServiceName]tc.DSType) (dsdata.Filter, error) {
+func NewDSStatFilter(path string, params url.Values, dsTypes map[tc.DeliveryServiceName]tc.DSTypeCategory) (dsdata.Filter, error) {
 	validParams := map[string]struct{}{"hc": struct{}{}, "stats": struct{}{}, "wildcard": struct{}{}, "type": struct{}{}, "deliveryservices": struct{}{}}
 	if len(params) > len(validParams) {
 		return nil, fmt.Errorf("invalid query parameters")
@@ -116,10 +116,10 @@ func NewDSStatFilter(path string, params url.Values, dsTypes map[tc.DeliveryServ
 		wildcard, _ = strconv.ParseBool(paramWildcard[0]) // ignore errors, error => false
 	}
 
-	dsType := tc.DSTypeInvalid
+	dsType := tc.DSTypeCategoryInvalid
 	if paramType, exists := params["type"]; exists && len(paramType) > 0 {
-		dsType = tc.DSTypeFromString(paramType[0])
-		if dsType == tc.DSTypeInvalid {
+		dsType = tc.DSTypeCategoryFromString(paramType[0])
+		if dsType == tc.DSTypeCategoryInvalid {
 			return nil, fmt.Errorf("invalid query parameter type '%v' - valid types are: {http, dns}", paramType[0])
 		}
 	}
diff --git a/traffic_monitor/todata/todata.go b/traffic_monitor/todata/todata.go
index f4b05b1..ef22332 100644
--- a/traffic_monitor/todata/todata.go
+++ b/traffic_monitor/todata/todata.go
@@ -68,7 +68,7 @@ type TOData struct {
 	DeliveryServiceServers map[tc.DeliveryServiceName][]tc.CacheName
 	ServerDeliveryServices map[tc.CacheName][]tc.DeliveryServiceName
 	ServerTypes            map[tc.CacheName]tc.CacheType
-	DeliveryServiceTypes   map[tc.DeliveryServiceName]tc.DSType
+	DeliveryServiceTypes   map[tc.DeliveryServiceName]tc.DSTypeCategory
 	DeliveryServiceRegexes Regexes
 	ServerCachegroups      map[tc.CacheName]tc.CacheGroupName
 }
@@ -79,7 +79,7 @@ func New() *TOData {
 		DeliveryServiceServers: map[tc.DeliveryServiceName][]tc.CacheName{},
 		ServerDeliveryServices: map[tc.CacheName][]tc.DeliveryServiceName{},
 		ServerTypes:            map[tc.CacheName]tc.CacheType{},
-		DeliveryServiceTypes:   map[tc.DeliveryServiceName]tc.DSType{},
+		DeliveryServiceTypes:   map[tc.DeliveryServiceName]tc.DSTypeCategory{},
 		DeliveryServiceRegexes: NewRegexes(),
 		ServerCachegroups:      map[tc.CacheName]tc.CacheGroupName{},
 	}
@@ -279,16 +279,16 @@ func getServerTypes(crc CRConfig) (map[tc.CacheName]tc.CacheType, error) {
 	return serverTypes, nil
 }
 
-func getDeliveryServiceTypes(crc CRConfig) (map[tc.DeliveryServiceName]tc.DSType, error) {
-	dsTypes := map[tc.DeliveryServiceName]tc.DSType{}
+func getDeliveryServiceTypes(crc CRConfig) (map[tc.DeliveryServiceName]tc.DSTypeCategory, error) {
+	dsTypes := map[tc.DeliveryServiceName]tc.DSTypeCategory{}
 
 	for dsName, dsData := range crc.DeliveryServices {
 		if len(dsData.Matchsets) < 1 {
 			return nil, fmt.Errorf("CRConfig missing protocol for '%s'", dsName)
 		}
 		dsTypeStr := dsData.Matchsets[0].Protocol
-		dsType := tc.DSTypeFromString(dsTypeStr)
-		if dsType == tc.DSTypeInvalid {
+		dsType := tc.DSTypeCategoryFromString(dsTypeStr)
+		if dsType == tc.DSTypeCategoryInvalid {
 			return nil, fmt.Errorf("CRConfig unknowng protocol for '%s': '%s'", dsName, dsTypeStr)
 		}
 		dsTypes[dsName] = dsType
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv12.go b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv12.go
index cdfc319..892ec00 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv12.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv12.go
@@ -104,6 +104,9 @@ func sanitizeV12(ds *tc.DeliveryServiceNullableV12) {
 	if ds.MidHeaderRewrite != nil && strings.TrimSpace(*ds.MidHeaderRewrite) == "" {
 		ds.MidHeaderRewrite = nil
 	}
+	if ds.RoutingName == nil || *ds.RoutingName == "" {
+		ds.RoutingName = utils.StrPtr(tc.DefaultRoutingName)
+	}
 }
 
 // getDSTenantIDByID returns the tenant ID, whether the delivery service exists, and any error.
@@ -345,10 +348,6 @@ func CreateV12(db *sqlx.DB, cfg config.Config) http.HandlerFunc {
 			return
 		}
 
-		if ds.RoutingName == nil || *ds.RoutingName == "" {
-			ds.RoutingName = utils.StrPtr("cdn")
-		}
-
 		if errs := validateV12(db, &ds); len(errs) > 0 {
 			api.HandleErr(w, r, http.StatusBadRequest, errors.New("invalid request: "+util.JoinErrs(errs).Error()), nil)
 			return
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv13.go b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv13.go
index 13fd993..a11b6c1 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv13.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservicesv13.go
@@ -39,7 +39,6 @@ import (
 	"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
 	"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/tenant"
 	"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/tovalidate"
-	"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/utils"
 
 	"github.com/go-ozzo/ozzo-validation"
 	"github.com/jmoiron/sqlx"
@@ -156,10 +155,6 @@ func CreateV13(db *sqlx.DB, cfg config.Config) http.HandlerFunc {
 			return
 		}
 
-		if ds.RoutingName == nil || *ds.RoutingName == "" {
-			ds.RoutingName = utils.StrPtr("cdn")
-		}
-
 		if errs := validateV13(db, &ds); len(errs) > 0 {
 			api.HandleErr(w, r, http.StatusBadRequest, errors.New("invalid request: "+util.JoinErrs(errs).Error()), nil)
 			return
@@ -229,7 +224,7 @@ func create(db *sql.DB, cfg config.Config, user *auth.CurrentUser, ds tc.Deliver
 	if ds.TypeID == nil {
 		return tc.DeliveryServiceNullableV13{}, http.StatusInternalServerError, nil, errors.New("missing type after insert")
 	}
-	dsType, err := getTypeNameFromID(*ds.TypeID, tx)
+	dsType, err := getTypeFromID(*ds.TypeID, tx)
 	if err != nil {
 		return tc.DeliveryServiceNullableV13{}, http.StatusInternalServerError, nil, errors.New("getting delivery service type: " + err.Error())
 	}
@@ -404,12 +399,16 @@ WHERE ds.id=$1
 `
 	xmlID := ""
 	protocol := (*int)(nil)
-	dsType := ""
+	dsTypeStr := ""
 	routingName := ""
 	cdnDomain := ""
-	if err := tx.QueryRow(q, id).Scan(&xmlID, &protocol, &dsType, &routingName, &cdnDomain); err != nil {
+	if err := tx.QueryRow(q, id).Scan(&xmlID, &protocol, &dsTypeStr, &routingName, &cdnDomain); err != nil {
 		return "", fmt.Errorf("querying delivery service %v host name: "+err.Error()+"\n", id)
 	}
+	dsType := tc.DSTypeFromString(dsTypeStr)
+	if dsType == tc.DSTypeInvalid {
+		return "", errors.New("getting delivery services matchlist: got invalid delivery service type '" + dsTypeStr + "'")
+	}
 	matchLists, err := readGetDeliveryServicesMatchLists([]string{xmlID}, tx)
 	if err != nil {
 		return "", errors.New("getting delivery services matchlist: " + err.Error())
@@ -425,13 +424,24 @@ WHERE ds.id=$1
 	return host, nil
 }
 
-func getTypeNameFromID(id int, tx *sql.Tx) (string, error) {
+func getTypeFromID(id int, tx *sql.Tx) (tc.DSType, error) {
 	// TODO combine with getOldHostName, to only make one query?
 	name := ""
 	if err := tx.QueryRow(`SELECT name FROM type WHERE id = $1`, id).Scan(&name); err != nil {
 		return "", fmt.Errorf("querying type ID %v: "+err.Error()+"\n", id)
 	}
-	return name, nil
+	return tc.DSTypeFromString(name), nil
+}
+
+func getDSType(tx *sql.Tx, xmlid string) (tc.DSType, bool, error) {
+	name := ""
+	if err := tx.QueryRow(`SELECT name FROM type WHERE id = (select type from deliveryservice where xml_id = $1)`, xmlid).Scan(&name); err != nil {
+		if err == sql.ErrNoRows {
+			return "", false, nil
+		}
+		return "", false, fmt.Errorf("querying deliveryservice type name: " + err.Error())
+	}
+	return tc.DSTypeFromString(name), true, nil
 }
 
 func UpdateV13(db *sqlx.DB, cfg config.Config) http.HandlerFunc {
@@ -500,9 +510,21 @@ func update(db *sql.DB, cfg config.Config, user auth.CurrentUser, ds *tc.Deliver
 		return tc.DeliveryServiceNullableV13{}, http.StatusBadRequest, errors.New("missing id"), nil
 	}
 
-	oldHostName, err := getOldHostName(*ds.ID, tx)
+	dsType, ok, err := getDSType(tx, *ds.XMLID)
+	if !ok {
+		return tc.DeliveryServiceNullableV13{}, http.StatusNotFound, errors.New("delivery service '" + *ds.XMLID + "' not found"), nil
+	}
 	if err != nil {
-		return tc.DeliveryServiceNullableV13{}, http.StatusInternalServerError, nil, errors.New("getting existing delivery service hostname: " + err.Error())
+		return tc.DeliveryServiceNullableV13{}, http.StatusInternalServerError, nil, errors.New("getting delivery service type during update: " + err.Error())
+	}
+
+	// oldHostName will be used to determine if SSL Keys need updating - this will be empty if the DS doesn't have SSL keys, because DS types without SSL keys may not have regexes, and thus will fail to get a host name.
+	oldHostName := ""
+	if dsType.HasSSLKeys() {
+		oldHostName, err = getOldHostName(*ds.ID, tx)
+		if err != nil {
+			return tc.DeliveryServiceNullableV13{}, http.StatusInternalServerError, nil, errors.New("getting existing delivery service hostname: " + err.Error())
+		}
 	}
 
 	// TODO change DeepCachingType to implement sql.Valuer and sql.Scanner, so sqlx struct scan can be used.
@@ -550,20 +572,24 @@ func update(db *sql.DB, cfg config.Config, user auth.CurrentUser, ds *tc.Deliver
 	if ds.RoutingName == nil {
 		return tc.DeliveryServiceNullableV13{}, http.StatusInternalServerError, nil, errors.New("missing routing name after update")
 	}
-	dsType, err := getTypeNameFromID(*ds.TypeID, tx)
+	newDSType, err := getTypeFromID(*ds.TypeID, tx)
 	if err != nil {
 		return tc.DeliveryServiceNullableV13{}, http.StatusInternalServerError, nil, errors.New("getting delivery service type after update: " + err.Error())
 	}
-	ds.Type = &dsType
+	ds.Type = &newDSType
 
 	cdnDomain, err := getCDNDomain(*ds.ID, db) // need to get the domain again, in case it changed.
 	if err != nil {
 		return tc.DeliveryServiceNullableV13{}, http.StatusInternalServerError, nil, errors.New("getting CDN domain after update: " + err.Error())
 	}
 
-	newHostName, err := getHostName(ds.Protocol, *ds.Type, *ds.RoutingName, *ds.MatchList, cdnDomain)
-	if err != nil {
-		return tc.DeliveryServiceNullableV13{}, http.StatusInternalServerError, nil, errors.New("getting hostname after update: " + err.Error())
+	// newHostName will be used to determine if SSL Keys need updating - this will be empty if the DS doesn't have SSL keys, because DS types without SSL keys may not have regexes, and thus will fail to get a host name.
+	newHostName := ""
+	if dsType.HasSSLKeys() {
+		newHostName, err = getHostName(ds.Protocol, *ds.Type, *ds.RoutingName, *ds.MatchList, cdnDomain)
+		if err != nil {
+			return tc.DeliveryServiceNullableV13{}, http.StatusInternalServerError, nil, errors.New("getting hostname after update: " + err.Error())
+		}
 	}
 
 	matchLists, err := readGetDeliveryServicesMatchLists([]string{*ds.XMLID}, tx)
@@ -576,7 +602,7 @@ func update(db *sql.DB, cfg config.Config, user auth.CurrentUser, ds *tc.Deliver
 		ds.MatchList = &ml
 	}
 
-	if oldHostName != newHostName {
+	if newDSType.HasSSLKeys() && oldHostName != newHostName {
 		if err := updateSSLKeys(ds, newHostName, db, cfg); err != nil {
 			return tc.DeliveryServiceNullableV13{}, http.StatusInternalServerError, nil, errors.New("updating delivery service " + *ds.XMLID + ": updating SSL keys: " + err.Error())
 		}
@@ -822,7 +848,7 @@ func updateSSLKeys(ds *tc.DeliveryServiceNullableV13, hostName string, db *sql.D
 }
 
 // getHostName gets the host name used for delivery service requests. The dsProtocol may be nil, if the delivery service type doesn't have a protocol (e.g. ANY_MAP).
-func getHostName(dsProtocol *int, dsType string, dsRoutingName string, dsMatchList []tc.DeliveryServiceMatch, cdnDomain string) (string, error) {
+func getHostName(dsProtocol *int, dsType tc.DSType, dsRoutingName string, dsMatchList []tc.DeliveryServiceMatch, cdnDomain string) (string, error) {
 	exampleURLs := makeExampleURLs(dsProtocol, dsType, dsRoutingName, dsMatchList, cdnDomain)
 
 	exampleURL := ""
@@ -839,7 +865,7 @@ func getHostName(dsProtocol *int, dsType string, dsRoutingName string, dsMatchLi
 	}
 
 	host := strings.NewReplacer(`http://`, ``, `https://`, ``).Replace(exampleURL)
-	if strings.HasPrefix(dsType, "HTTP") {
+	if dsType.IsHTTP() {
 		if firstDot := strings.Index(host, "."); firstDot == -1 {
 			host = "*" // TODO warn? error?
 		} else {
@@ -870,7 +896,7 @@ func getCDNNameDomainDNSSecEnabled(dsID int, tx *sql.Tx) (string, string, bool,
 }
 
 // makeExampleURLs creates the example URLs for a delivery service. The dsProtocol may be nil, if the delivery service type doesn't have a protocol (e.g. ANY_MAP).
-func makeExampleURLs(protocol *int, dsType string, routingName string, matchList []tc.DeliveryServiceMatch, cdnDomain string) []string {
+func makeExampleURLs(protocol *int, dsType tc.DSType, routingName string, matchList []tc.DeliveryServiceMatch, cdnDomain string) []string {
 	examples := []string{}
 	scheme := ""
 	scheme2 := ""
@@ -891,13 +917,10 @@ func makeExampleURLs(protocol *int, dsType string, routingName string, matchList
 	} else {
 		scheme = "http"
 	}
-	dsIsDNS := strings.HasPrefix(strings.ToLower(dsType), "DNS")
+	dsIsDNS := dsType.IsDNS()
 	regexReplacer := strings.NewReplacer(`\`, ``, `.*`, ``, `.`, ``)
 	for _, match := range matchList {
-		switch {
-		case dsIsDNS:
-			fallthrough
-		case match.Type == `HOST_REGEXP`:
+		if dsIsDNS || match.Type == tc.DSMatchTypeHostRegex {
 			host := regexReplacer.Replace(match.Pattern)
 			if match.SetNumber == 0 {
 				examples = append(examples, scheme+`://`+routingName+`.`+host+`.`+cdnDomain)
@@ -910,7 +933,7 @@ func makeExampleURLs(protocol *int, dsType string, routingName string, matchList
 			if scheme2 != "" {
 				examples = append(examples, scheme2+`://`+match.Pattern)
 			}
-		case match.Type == `PATH_REGEXP`:
+		} else if match.Type == tc.DSMatchTypePathRegex {
 			examples = append(examples, match.Pattern)
 		}
 	}
@@ -935,9 +958,15 @@ WHERE ds.xml_id = ANY($1)
 	for rows.Next() {
 		m := tc.DeliveryServiceMatch{}
 		dsName := ""
-		if err := rows.Scan(&dsName, &m.Type, &m.Pattern, &m.SetNumber); err != nil {
+		matchTypeStr := ""
+		if err := rows.Scan(&dsName, &matchTypeStr, &m.Pattern, &m.SetNumber); err != nil {
 			return nil, errors.New("scanning delivery service regexes: " + err.Error())
 		}
+		matchType := tc.DSMatchTypeFromString(matchTypeStr)
+		if matchType == tc.DSMatchTypeInvalid {
+			return nil, errors.New("getting delivery service regexes: got invalid delivery service match type '" + matchTypeStr + "'")
+		}
+		m.Type = matchType
 		matches[dsName] = append(matches[dsName], m)
 	}
 	return matches, nil
@@ -950,8 +979,8 @@ const (
 	edgeTier
 )
 
-func ensureHeaderRewriteParams(tx *sql.Tx, dsID int, xmlID string, hdrRW *string, tier tierType, dsType string) error {
-	if tier == midTier && strings.Contains(dsType, "LIVE") && !strings.Contains(dsType, "NATNL") {
+func ensureHeaderRewriteParams(tx *sql.Tx, dsID int, xmlID string, hdrRW *string, tier tierType, dsType tc.DSType) error {
+	if tier == midTier && dsType.IsLive() && !dsType.IsNational() {
 		return nil // live local DSes don't get remap rules
 	}
 	configFile := "hdr_rw_" + xmlID + ".config"

-- 
To stop receiving notification emails like this one, please contact
mitchell852@apache.org.