github.com/akamai/AkamaiOPEN-edgegrid-golang/v2@v2.17.0/pkg/configgtm/property.go (about)

     1  package gtm
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net/http"
     7  )
     8  
     9  //
    10  // Support gtm domain properties thru Edgegrid
    11  // Based on 1.4 Schema
    12  //
    13  
    14  // Properties contains operations available on a Property resource
    15  // See: https://developer.akamai.com/api/web_performance/global_traffic_management/v1.html
    16  type Properties interface {
    17  	// NewTrafficTarget is a method applied to a property object that instantiates a TrafficTarget object.
    18  	NewTrafficTarget(context.Context) *TrafficTarget
    19  	// NewStaticRRSet is a method applied to a property object that instantiates a StaticRRSet object.
    20  	NewStaticRRSet(context.Context) *StaticRRSet
    21  	// NewLivenessTest is a method applied to a property object that instantiates a LivenessTest object.
    22  	NewLivenessTest(context.Context, string, string, int, float32) *LivenessTest
    23  	// NewProperty creates a new Property object.
    24  	NewProperty(context.Context, string) *Property
    25  	// ListProperties retreieves all Properties for the provided domainName.
    26  	// See: https://developer.akamai.com/api/web_performance/global_traffic_management/v1.html#getproperties
    27  	ListProperties(context.Context, string) ([]*Property, error)
    28  	// GetProperty retrieves a Property with the given domain and property names.
    29  	// See: https://developer.akamai.com/api/web_performance/global_traffic_management/v1.html#getproperty
    30  	GetProperty(context.Context, string, string) (*Property, error)
    31  	// CreateProperty creates property
    32  	// See: https://developer.akamai.com/api/web_performance/global_traffic_management/v1.html#putproperty
    33  	CreateProperty(context.Context, *Property, string) (*PropertyResponse, error)
    34  	// DeleteProperty is a method applied to a property object resulting in removal.
    35  	// See: https://developer.akamai.com/api/web_performance/global_traffic_management/v1.html#deleteproperty
    36  	DeleteProperty(context.Context, *Property, string) (*ResponseStatus, error)
    37  	// UpdateProperty is a method applied to a property object resulting in an update.
    38  	// https://developer.akamai.com/api/web_performance/global_traffic_management/v1.html#putproperty
    39  	UpdateProperty(context.Context, *Property, string) (*ResponseStatus, error)
    40  }
    41  
    42  // TrafficTarget struct contains information about where to direct data center traffic
    43  type TrafficTarget struct {
    44  	DatacenterId int      `json:"datacenterId"`
    45  	Enabled      bool     `json:"enabled"`
    46  	Weight       float64  `json:"weight,omitempty"`
    47  	Servers      []string `json:"servers,omitempty"`
    48  	Name         string   `json:"name,omitempty"`
    49  	HandoutCName string   `json:"handoutCName,omitempty"`
    50  }
    51  
    52  // HttpHeader struct contains HTTP headers to send if the testObjectProtocol is http or https
    53  type HttpHeader struct {
    54  	Name  string `json:"name"`
    55  	Value string `json:"value"`
    56  }
    57  
    58  // LivenessTest contains configuration of liveness tests to determine whether your servers respond to requests
    59  type LivenessTest struct {
    60  	Name                          string        `json:"name"`
    61  	ErrorPenalty                  float64       `json:"errorPenalty,omitempty"`
    62  	PeerCertificateVerification   bool          `json:"peerCertificateVerification"`
    63  	TestInterval                  int           `json:"testInterval,omitempty"`
    64  	TestObject                    string        `json:"testObject,omitempty"`
    65  	Links                         []*Link       `json:"links,omitempty"`
    66  	RequestString                 string        `json:"requestString,omitempty"`
    67  	ResponseString                string        `json:"responseString,omitempty"`
    68  	HttpError3xx                  bool          `json:"httpError3xx"`
    69  	HttpError4xx                  bool          `json:"httpError4xx"`
    70  	HttpError5xx                  bool          `json:"httpError5xx"`
    71  	Disabled                      bool          `json:"disabled"`
    72  	TestObjectProtocol            string        `json:"testObjectProtocol,omitempty"`
    73  	TestObjectPassword            string        `json:"testObjectPassword,omitempty"`
    74  	TestObjectPort                int           `json:"testObjectPort,omitempty"`
    75  	SslClientPrivateKey           string        `json:"sslClientPrivateKey,omitempty"`
    76  	SslClientCertificate          string        `json:"sslClientCertificate,omitempty"`
    77  	DisableNonstandardPortWarning bool          `json:"disableNonstandardPortWarning"`
    78  	HttpHeaders                   []*HttpHeader `json:"httpHeaders,omitempty"`
    79  	TestObjectUsername            string        `json:"testObjectUsername,omitempty"`
    80  	TestTimeout                   float32       `json:"testTimeout,omitempty"`
    81  	TimeoutPenalty                float64       `json:"timeoutPenalty,omitempty"`
    82  	AnswersRequired               bool          `json:"answersRequired"`
    83  	ResourceType                  string        `json:"resourceType,omitempty"`
    84  	RecursionRequested            bool          `json:"recursionRequested"`
    85  }
    86  
    87  // StaticRRSet contains static recordset
    88  type StaticRRSet struct {
    89  	Type  string   `json:"type"`
    90  	TTL   int      `json:"ttl"`
    91  	Rdata []string `json:"rdata"`
    92  }
    93  
    94  // Property represents a GTM property
    95  type Property struct {
    96  	Name                      string           `json:"name"`
    97  	Type                      string           `json:"type"`
    98  	Ipv6                      bool             `json:"ipv6"`
    99  	ScoreAggregationType      string           `json:"scoreAggregationType"`
   100  	StickinessBonusPercentage int              `json:"stickinessBonusPercentage,omitempty"`
   101  	StickinessBonusConstant   int              `json:"stickinessBonusConstant,omitempty"`
   102  	HealthThreshold           float64          `json:"healthThreshold,omitempty"`
   103  	UseComputedTargets        bool             `json:"useComputedTargets"`
   104  	BackupIp                  string           `json:"backupIp,omitempty"`
   105  	BalanceByDownloadScore    bool             `json:"balanceByDownloadScore"`
   106  	StaticTTL                 int              `json:"staticTTL,omitempty"`
   107  	StaticRRSets              []*StaticRRSet   `json:"staticRRSets,omitempty"`
   108  	LastModified              string           `json:"lastModified"`
   109  	UnreachableThreshold      float64          `json:"unreachableThreshold,omitempty"`
   110  	MinLiveFraction           float64          `json:"minLiveFraction,omitempty"`
   111  	HealthMultiplier          float64          `json:"healthMultiplier,omitempty"`
   112  	DynamicTTL                int              `json:"dynamicTTL,omitempty"`
   113  	MaxUnreachablePenalty     int              `json:"maxUnreachablePenalty,omitempty"`
   114  	MapName                   string           `json:"mapName,omitempty"`
   115  	HandoutLimit              int              `json:"handoutLimit"`
   116  	HandoutMode               string           `json:"handoutMode"`
   117  	FailoverDelay             int              `json:"failoverDelay,omitempty"`
   118  	BackupCName               string           `json:"backupCName,omitempty"`
   119  	FailbackDelay             int              `json:"failbackDelay,omitempty"`
   120  	LoadImbalancePercentage   float64          `json:"loadImbalancePercentage,omitempty"`
   121  	HealthMax                 float64          `json:"healthMax,omitempty"`
   122  	GhostDemandReporting      bool             `json:"ghostDemandReporting"`
   123  	Comments                  string           `json:"comments,omitempty"`
   124  	CName                     string           `json:"cname,omitempty"`
   125  	WeightedHashBitsForIPv4   int              `json:"weightedHashBitsForIPv4,omitempty"`
   126  	WeightedHashBitsForIPv6   int              `json:"weightedHashBitsForIPv6,omitempty"`
   127  	TrafficTargets            []*TrafficTarget `json:"trafficTargets,omitempty"`
   128  	Links                     []*Link          `json:"links,omitempty"`
   129  	LivenessTests             []*LivenessTest  `json:"livenessTests,omitempty"`
   130  }
   131  
   132  // PropertyList contains a list of property items
   133  type PropertyList struct {
   134  	PropertyItems []*Property `json:"items"`
   135  }
   136  
   137  // Validate validates Property
   138  func (prop *Property) Validate() error {
   139  
   140  	if len(prop.Name) < 1 {
   141  		return fmt.Errorf("Property is missing Name")
   142  	}
   143  	if len(prop.Type) < 1 {
   144  		return fmt.Errorf("Property is missing Type")
   145  	}
   146  	if len(prop.ScoreAggregationType) < 1 {
   147  		return fmt.Errorf("Property is missing ScoreAggregationType")
   148  	}
   149  	if len(prop.HandoutMode) < 1 {
   150  		return fmt.Errorf("Property is missing HandoutMode")
   151  	}
   152  	// is zero a valid value? need to check and uncomment
   153  	//if prop.HandoutLimit == 0 {
   154  	//        return fmt.Errorf("Property is missing  handoutLimit"
   155  	//}
   156  
   157  	return nil
   158  }
   159  
   160  // NewTrafficTarget is a method applied to a property object that instantiates a TrafficTarget object.
   161  func (p *gtm) NewTrafficTarget(ctx context.Context) *TrafficTarget {
   162  
   163  	logger := p.Log(ctx)
   164  	logger.Debug("NewTrafficTarget")
   165  
   166  	return &TrafficTarget{}
   167  
   168  }
   169  
   170  // NewStaticRRSet is a method applied to a property object that instantiates a StaticRRSet object.
   171  func (p *gtm) NewStaticRRSet(ctx context.Context) *StaticRRSet {
   172  
   173  	logger := p.Log(ctx)
   174  	logger.Debug("NewStaticRRSet")
   175  
   176  	return &StaticRRSet{}
   177  
   178  }
   179  
   180  // NewHttpHeader is a method applied to a livenesstest object that instantiates an HttpHeader  object.
   181  func (lt *LivenessTest) NewHttpHeader() *HttpHeader {
   182  
   183  	return &HttpHeader{}
   184  
   185  }
   186  
   187  // NewLivenessTest is a method applied to a property object that instantiates a LivenessTest object.
   188  func (p *gtm) NewLivenessTest(ctx context.Context, name string, objproto string, interval int, timeout float32) *LivenessTest {
   189  
   190  	logger := p.Log(ctx)
   191  	logger.Debug("NewLivenessTest")
   192  
   193  	return &LivenessTest{Name: name, TestInterval: interval, TestObjectProtocol: objproto, TestTimeout: timeout}
   194  
   195  }
   196  
   197  // NewProperty creates a new Property object.
   198  func (p *gtm) NewProperty(ctx context.Context, name string) *Property {
   199  
   200  	logger := p.Log(ctx)
   201  	logger.Debug("NewProperty")
   202  
   203  	property := &Property{Name: name}
   204  	return property
   205  }
   206  
   207  // ListProperties retreieves all Properties for the provided domainName.
   208  func (p *gtm) ListProperties(ctx context.Context, domainName string) ([]*Property, error) {
   209  
   210  	logger := p.Log(ctx)
   211  	logger.Debug("ListProperties")
   212  
   213  	var properties PropertyList
   214  	getURL := fmt.Sprintf("/config-gtm/v1/domains/%s/properties", domainName)
   215  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, getURL, nil)
   216  	if err != nil {
   217  		return nil, fmt.Errorf("failed to create ListProperties request: %w", err)
   218  	}
   219  	setVersionHeader(req, schemaVersion)
   220  	resp, err := p.Exec(req, &properties)
   221  	if err != nil {
   222  		return nil, fmt.Errorf("ListProperties request failed: %w", err)
   223  	}
   224  
   225  	if resp.StatusCode != http.StatusOK {
   226  		return nil, p.Error(resp)
   227  	}
   228  
   229  	return properties.PropertyItems, nil
   230  }
   231  
   232  // GetProperty retrieves a Property with the given name.
   233  func (p *gtm) GetProperty(ctx context.Context, name, domainName string) (*Property, error) {
   234  
   235  	logger := p.Log(ctx)
   236  	logger.Debug("GetProperty")
   237  
   238  	var property Property
   239  	getURL := fmt.Sprintf("/config-gtm/v1/domains/%s/properties/%s", domainName, name)
   240  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, getURL, nil)
   241  	if err != nil {
   242  		return nil, fmt.Errorf("failed to create GetProperty request: %w", err)
   243  	}
   244  	setVersionHeader(req, schemaVersion)
   245  	resp, err := p.Exec(req, &property)
   246  	if err != nil {
   247  		return nil, fmt.Errorf("GetProperty request failed: %w", err)
   248  	}
   249  
   250  	if resp.StatusCode != http.StatusOK {
   251  		return nil, p.Error(resp)
   252  	}
   253  
   254  	return &property, nil
   255  }
   256  
   257  // Create the property in the receiver argument in the specified domain.
   258  func (p *gtm) CreateProperty(ctx context.Context, property *Property, domainName string) (*PropertyResponse, error) {
   259  
   260  	logger := p.Log(ctx)
   261  	logger.Debug("CreateProperty")
   262  
   263  	// Need do any validation?
   264  	return property.save(ctx, p, domainName)
   265  }
   266  
   267  // Update the property in the receiver argument in the specified domain.
   268  func (p *gtm) UpdateProperty(ctx context.Context, property *Property, domainName string) (*ResponseStatus, error) {
   269  
   270  	logger := p.Log(ctx)
   271  	logger.Debug("UpdateProperty")
   272  
   273  	// Need do any validation?
   274  	stat, err := property.save(ctx, p, domainName)
   275  	if err != nil {
   276  		return nil, err
   277  	}
   278  	return stat.Status, err
   279  
   280  }
   281  
   282  // Save Property updates method
   283  func (prop *Property) save(ctx context.Context, p *gtm, domainName string) (*PropertyResponse, error) {
   284  
   285  	if err := prop.Validate(); err != nil {
   286  		return nil, fmt.Errorf("Property validation failed. %w", err)
   287  	}
   288  
   289  	putURL := fmt.Sprintf("/config-gtm/v1/domains/%s/properties/%s", domainName, prop.Name)
   290  	req, err := http.NewRequestWithContext(ctx, http.MethodPut, putURL, nil)
   291  	if err != nil {
   292  		return nil, fmt.Errorf("failed to create Property request: %w", err)
   293  	}
   294  
   295  	var presp PropertyResponse
   296  	setVersionHeader(req, schemaVersion)
   297  	resp, err := p.Exec(req, &presp, prop)
   298  	if err != nil {
   299  		return nil, fmt.Errorf("Property request failed: %w", err)
   300  	}
   301  
   302  	if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
   303  		return nil, p.Error(resp)
   304  	}
   305  
   306  	return &presp, nil
   307  }
   308  
   309  // Delete the property identified by the receiver argument from the domain provided.
   310  func (p *gtm) DeleteProperty(ctx context.Context, property *Property, domainName string) (*ResponseStatus, error) {
   311  
   312  	logger := p.Log(ctx)
   313  	logger.Debug("DeleteProperty")
   314  
   315  	if err := property.Validate(); err != nil {
   316  		logger.Errorf("Property validation failed. %w", err)
   317  		return nil, fmt.Errorf("Property validation failed. %w", err)
   318  	}
   319  
   320  	delURL := fmt.Sprintf("/config-gtm/v1/domains/%s/properties/%s", domainName, property.Name)
   321  	req, err := http.NewRequestWithContext(ctx, http.MethodDelete, delURL, nil)
   322  	if err != nil {
   323  		return nil, fmt.Errorf("failed to create Property request: %w", err)
   324  	}
   325  
   326  	var presp ResponseBody
   327  	setVersionHeader(req, schemaVersion)
   328  	resp, err := p.Exec(req, &presp)
   329  	if err != nil {
   330  		return nil, fmt.Errorf("Property request failed: %w", err)
   331  	}
   332  
   333  	if resp.StatusCode != http.StatusOK {
   334  		return nil, p.Error(resp)
   335  	}
   336  
   337  	return presp.Status, nil
   338  }