From 245cd69ccd8edb38aa32c72a00371f878eaf708e Mon Sep 17 00:00:00 2001 From: Sanjay Date: Sun, 12 Nov 2017 16:59:44 -0800 Subject: [PATCH 01/80] feat(): adding new features. --- bigip.go | 19 +- device.go | 236 +++++++++++++++ ltm.go | 841 +++++++++++++++++++++++++++++++++++++++++++++++++++-- sys.go | 339 +++++++++++++++++++++ utility.go | 150 ++++++++++ 5 files changed, 1567 insertions(+), 18 deletions(-) create mode 100644 device.go create mode 100644 sys.go create mode 100644 utility.go diff --git a/bigip.go b/bigip.go index 7bf958e..bcc33f5 100644 --- a/bigip.go +++ b/bigip.go @@ -213,7 +213,7 @@ func (b *BigIP) delete(path ...string) error { } func (b *BigIP) post(body interface{}, path ...string) error { - marshalJSON, err := jsonMarshal(body) + marshalJSON, err := json.Marshal(body) if err != nil { return err } @@ -246,6 +246,23 @@ func (b *BigIP) put(body interface{}, path ...string) error { return callErr } +func (b *BigIP) patch(body interface{}, path ...string) error { + marshalJSON, err := json.Marshal(body) + if err != nil { + return err + } + + req := &APIRequest{ + Method: "patch", + URL: b.iControlPath(path), + Body: string(marshalJSON), + ContentType: "application/json", + } + + _, callErr := b.APICall(req) + return callErr +} + //Get a url and populate an entity. If the entity does not exist (404) then the //passed entity will be untouched and false will be returned as the second parameter. //You can use this to distinguish between a missing entity or an actual error. diff --git a/device.go b/device.go new file mode 100644 index 0000000..d36d2de --- /dev/null +++ b/device.go @@ -0,0 +1,236 @@ +package bigip + +import "encoding/json" + +// LIC contains device license for BIG-IP system. +type LICs struct { + LIC []LIC `json:"items"` +} + +// VirtualAddress contains information about each individual virtual address. +type LIC struct { + DeviceAddress string + Username string + Password string +} + +type LicensePools struct { + LicensePool []LicensePool `json:"items"` +} + +type LicensePool struct { + Items []struct { + Uuid string `json:"Uuid,omitempty"` + } +} + +type LICDTO struct { + DeviceAddress string `json:"deviceAddress,omitempty"` + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` +} + +type Devicenames struct { + Devicenames []Devicename `json:"items"` +} + +type Devicename struct { + Command string `json:"command,omitempty"` + Name string `json:"name,omitempty"` + Target string `json:"target,omitempty"` +} + +type Devices struct { + Devices []Device `json:"items"` +} + +type Device struct { + ConfigsyncIp string `json:"configsyncIp,omitempty"` + Name string `json:"name,omitempty"` + MirrorIp string `json:"mirrorIp,omitempty"` + MirrorSecondaryIp string `json:"mirrorSecondaryIp,omitempty"` +} + +type Devicegroups struct { + Devicegroups []Devicegroup `json:"items"` +} + +type Devicegroup struct { + AutoSync string `json:"autoSync,omitempty"` + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` + FullLoadOnSync string `json:"fullLoadOnSync,omitempty"` +} + +// https://10.192.74.80/mgmt/cm/device/licensing/pool/purchased-pool/licenses +// The above command will spit out license uuid and which should be mapped uriUuid +const ( + uriMgmt = "mgmt" + uriCm = "cm" + uriDiv = "device" + uriLins = "licensing" + uriPoo = "pool" + uriPur = "purchased-pool" + uriLicn = "licenses" + uriMemb = "members" + uriUtility = "utility" + uriOfferings = "offerings" + uriF5BIGMSPBT10G = "f37c66e0-a80d-43e8-924b-3bbe9fe96bbe" +) + +func (p *LIC) MarshalJSON() ([]byte, error) { + var dto LICDTO + marshal(&dto, p) + return json.Marshal(dto) +} + +func (p *LIC) UnmarshalJSON(b []byte) error { + var dto LICDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + return marshal(p, &dto) +} + +func (b *BigIP) getLicensePool() (*LicensePool, error) { + var licensePool LicensePool + err, _ := b.getForEntity(&licensePool, uriMgmt, uriCm, uriDiv, uriLins, uriPoo, uriPur, uriLicn) + if err != nil { + return nil, err + } + // for loop over all returned license pools to check which one has available licenses + // getAvailablePool(member[index_of_array].Uuid) + // At the end change return statement to return only the UUID string of the one where license + // is availble + return &licensePool, nil +} + +// VirtualAddresses returns a list of virtual addresses. +func (b *BigIP) LIC() (*LIC, error) { + var va LIC + licensePool, licensePoolErr := b.getLicensePool() + if licensePoolErr != nil { + return nil, licensePoolErr + } + err, _ := b.getForEntity(&va, uriMgmt, uriCm, uriDiv, uriLins, uriPoo, uriPur, uriLicn, licensePool.Items[0].Uuid, uriMemb) + if err != nil { + return nil, err + } + return &va, nil +} + +func (b *BigIP) CreateLIC(deviceAddress string, username string, password string) error { + config := &LIC{ + DeviceAddress: deviceAddress, + Username: username, + Password: password, + } + + licensePool, licensePoolErr := b.getLicensePool() + if licensePoolErr != nil { + return licensePoolErr + } + + return b.post(config, uriMgmt, uriCm, uriDiv, uriLins, uriPoo, uriPur, uriLicn, licensePool.Items[0].Uuid, uriMemb) +} + +func (b *BigIP) ModifyLIC(config *LIC) error { + licensePool, licensePoolErr := b.getLicensePool() + if licensePoolErr != nil { + return licensePoolErr + } + return b.post(config, uriMgmt, uriCm, uriDiv, uriLins, uriPoo, uriPur, uriLicn, licensePool.Items[0].Uuid, uriMemb) +} + +func (b *BigIP) LICs() (*LIC, error) { + var members LIC + licensePool, licensePoolErr := b.getLicensePool() + if licensePoolErr != nil { + return nil, licensePoolErr + } + err, _ := b.getForEntity(&members, uriMgmt, uriCm, uriDiv, uriLins, uriPoo, uriPur, uriLicn, licensePool.Items[0].Uuid, uriMemb) + + if err != nil { + return nil, err + } + + return &members, nil +} + +func (b *BigIP) CreateDevicename(command, name, target string) error { + config := &Devicename{ + Command: command, + Name: name, + Target: target, + } + + return b.post(config, uriCm, uriDiv) +} + +func (b *BigIP) ModifyDevicename(config *Devicename) error { + return b.put(config, uriCm, uriDiv) +} + +func (b *BigIP) Devicenames() (*Devicename, error) { + var devicename Devicename + err, _ := b.getForEntity(&devicename, uriCm, uriDiv) + + if err != nil { + return nil, err + } + + return &devicename, nil +} + +func (b *BigIP) CreateDevice(name, configsyncIp, mirrorIp, mirrorSecondaryIp string) error { + config := &Device{ + Name: name, + ConfigsyncIp: configsyncIp, + MirrorIp: mirrorIp, + MirrorSecondaryIp: mirrorSecondaryIp, + } + + return b.post(config, uriCm, uriDiv) +} + +func (b *BigIP) ModifyDevice(config *Device) error { + return b.put(config, uriCm, uriDiv) +} + +func (b *BigIP) Devices() (*Device, error) { + var device Device + err, _ := b.getForEntity(&device, uriCm, uriDiv) + + if err != nil { + return nil, err + } + + return &device, nil +} + +func (b *BigIP) CreateDevicegroup(name, autoSync, typo, fullLoadOnSync string) error { + config := &Devicegroup{ + Name: name, + AutoSync: autoSync, + Type: typo, + FullLoadOnSync: fullLoadOnSync, + } + + return b.post(config, uriCm, uriDiv) +} + +func (b *BigIP) ModifyDevicegroup(config *Devicegroup) error { + return b.put(config, uriCm, uriDiv) +} + +func (b *BigIP) Devicegroups() (*Devicegroup, error) { + var devicegroup Devicegroup + err, _ := b.getForEntity(&devicegroup, uriCm, uriDiv) + + if err != nil { + return nil, err + } + + return &devicegroup, nil +} diff --git a/ltm.go b/ltm.go index fdd1acd..56827f0 100644 --- a/ltm.go +++ b/ltm.go @@ -3,6 +3,7 @@ package bigip import ( "encoding/json" "fmt" + "log" "strings" ) @@ -93,7 +94,7 @@ type ClientSSLProfile struct { CertLifespan int `json:"certLifespan,omitempty"` CertLookupByIpaddrPort string `json:"certLookupByIpaddrPort,omitempty"` Chain string `json:"chain,omitempty"` - Ciphers string `json:"ciphers,omitempty"` + Ciphers string `json:"Ciphers,omitempty"` ClientCertCa string `json:"clientCertCa,omitempty"` CrlFile string `json:"crlFile,omitempty"` DefaultsFrom string `json:"defaultsFrom,omitempty"` @@ -279,6 +280,48 @@ type PoolMember struct { State string `json:"state,omitempty"` } +// Pool transfer object so we can mask the bool data munging +type poolDTO struct { + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` + Generation int `json:"generation,omitempty"` + AllowNAT string `json:"allowNat,omitempty" bool:"yes"` + AllowSNAT string `json:"allowSnat,omitempty" bool:"yes"` + IgnorePersistedWeight string `json:"ignorePersistedWeight,omitempty" bool:"enabled"` + IPTOSToClient string `json:"ipTosToClient,omitempty"` + IPTOSToServer string `json:"ipTosToServer,omitempty"` + LinkQoSToClient string `json:"linkQosToClient,omitempty"` + LinkQoSToServer string `json:"linkQosToServer,omitempty"` + LoadBalancingMode string `json:"loadBalancingMode,omitempty"` + MinActiveMembers int `json:"minActiveMembers,omitempty"` + MinUpMembers int `json:"minUpMembers,omitempty"` + MinUpMembersAction string `json:"minUpMembersAction,omitempty"` + MinUpMembersChecking string `json:"minUpMembersChecking,omitempty"` + Monitor string `json:"monitor,omitempty"` + QueueDepthLimit int `json:"queueDepthLimit,omitempty"` + QueueOnConnectionLimit string `json:"queueOnConnectionLimit,omitempty"` + QueueTimeLimit int `json:"queueTimeLimit,omitempty"` + ReselectTries int `json:"reselectTries,omitempty"` + ServiceDownAction string `json:"serviceDownAction,omitempty"` + SlowRampTime int `json:"slowRampTime,omitempty"` +} + +func (p *Pool) MarshalJSON() ([]byte, error) { + var dto poolDTO + marshal(&dto, p) + return json.Marshal(dto) +} + +func (p *Pool) UnmarshalJSON(b []byte) error { + var dto poolDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + return marshal(p, &dto) +} + // VirtualServers contains a list of all virtual servers on the BIG-IP system. type VirtualServers struct { VirtualServers []VirtualServer `json:"items"` @@ -763,13 +806,255 @@ type monitorDTO struct { Username string `json:"username,omitempty"` } +type Profiles struct { + Profiles []Profile `json:"items"` +} + +type Profile struct { + Name string `json:"name,omitempty"` + FullPath string `json:"fullPath,omitempty"` + Partition string `json:"partition,omitempty"` + Context string `json:"context,omitempty"` +} + +type IRules struct { + IRules []IRule `json:"items"` +} + +type IRule struct { + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` + Rule string `json:"apiAnonymous,omitempty"` +} + +type oneconnectDTO struct { + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + IdleTimeoutOverride string `json:"idleTimeoutOverride,omitempty"` + MaxAge int `json:"maxAge,omitempty"` + MaxReuse int `json:"maxReuse,omitempty"` + MaxSize int `json:"maxSize,omitempty"` + SourceMask string `json:"sourceMask,omitempty"` + SharePools string `json:"sharePools,omitempty"` +} +type Oneconnects struct { + Oneconnects []Oneconnect `json:"items"` +} + +type Oneconnect struct { + Name string + Partition string + DefaultsFrom string + IdleTimeoutOverride string + MaxAge int + MaxReuse int + MaxSize int + SourceMask string + SharePools string +} + +type tcpDTO struct { + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + IdleTimeout int `json:"idleTimeout,omitempty"` + CloseWaitTimeout int `json:"closeWaitTimeout,omitempty"` + FinWait_2Timeout int `json:"finWait_2Timeout,omitempty"` + FinWaitTimeout int `json:"finWaitTimeout,omitempty"` + KeepAliveInterval int `json:"keepAliveInterval,omitempty"` + DeferredAccept string `json:"deferredAccept,omitempty"` + FastOpen string `json:"fastOpen,omitempty"` +} + +type Tcps struct { + Tcps []Tcp `json:"items"` +} + +type Tcp struct { + Name string + Partition string + DefaultsFrom string + IdleTimeout int + CloseWaitTimeout int + FinWait_2Timeout int + FinWaitTimeout int + KeepAliveInterval int + DeferredAccept string + FastOpen string +} + +type fasthttpDTO struct { + Name string `json:"name,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + IdleTimeout int `json:"idleTimeout,omitempty"` + ConnpoolIdleTimeoutOverride int `json:"connpoolIdleTimeoutOverride,omitempty"` + ConnpoolMaxReuse int `json:"connpoolMaxReuse,omitempty"` + ConnpoolMaxSize int `json:"connpoolMaxSize,omitempty"` + ConnpoolMinSize int `json:"connpoolMinSize,omitempty"` + ConnpoolReplenish string `json:"connpoolReplenish,omitempty"` + ConnpoolStep int `json:"deferredAccept,omitempty"` + ForceHttp_10Response string `json:"forceHttp_10Response,omitempty"` + MaxHeaderSize int `json:"maxHeaderSize,omitempty"` +} + +type Fasthttps struct { + Fasthttps []Fasthttp `json:"items"` +} + +type Fasthttp struct { + Name string + DefaultsFrom string + IdleTimeout int + ConnpoolIdleTimeoutOverride int + ConnpoolMaxReuse int + ConnpoolMaxSize int + ConnpoolMinSize int + ConnpoolReplenish string + ConnpoolStep int + ForceHttp_10Response string + MaxHeaderSize int +} + +type fastl4DTO struct { + Name string `json:"name,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + Partition string `json:"partition,omitempty"` + ExplicitFlowMigration string `json:"explicitFlowMigration,omitempty"` + HardwareSynCookie string `json:"hardwareSynCookie,omitem"` + IdleTimeout string `json:"idleTimeout,omitempty"` + ClientTimeout int `json:"clientTimeout,omitempty"` + IpTosToClient string `json:"ipTosToClient,omitempty"` + IpTosToServer string `json:"ipTosToServer,omitempty"` + KeepAliveInterval string `json:"keepAliveInterval,omitempty"` +} + +type Fastl4s struct { + Fastl4s []Fastl4 `json:"items"` +} + +type Fastl4 struct { + Name string + Partition string + DefaultsFrom string + ExplicitFlowMigration string + HardwareSynCookie string + IdleTimeout string + ClientTimeout int + IpTosToClient string + IpTosToServer string + KeepAliveInterval string +} + +type httpcompressDTO struct { + Name string `json:"name,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + UriExclude []string `json:"uriExclude,omitempty"` + UriInclude []string `json:"uriInclude,omitempty"` +} + +type Httpcompresss struct { + Httpcompresss []Httpcompress `json:"items"` +} + +type Httpcompress struct { + Name string + DefaultsFrom string + UriExclude []string + UriInclude []string +} + +type http2DTO struct { + Name string `json:"name,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + ConcurrentStreamsPerConnection int `json:"concurrentStreamsPerConnection,omitempty"` + ConnectionIdleTimeout int `json:"connectionIdleTimeout,omitempty"` + HeaderTableSize int `json:"headerTableSize,omitempty"` + ActivationModes []string `json:"activationModes,omitempty"` +} + +type Http2s struct { + Http2s []Http2 `json:"items"` +} + +type Http2 struct { + Name string + DefaultsFrom string + ConcurrentStreamsPerConnection int + ConnectionIdleTimeout int + HeaderTableSize int + ActivationModes []string +} + +type Recordss struct { + Recordss []Records `json:"items"` +} + +type Records struct { + Name string + Data string +} +type RecordsDTO struct { + Name string `json:"name,omitempty"` + Data string `json:"data,omitempty"` +} + +type Datagroup struct { + Name string + Type string + Records []Records +} + +type Datagroups struct { + Datagroups []Datagroup `json:"items"` +} + +type DatagroupDTO struct { + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` + Records struct { + Items []Records `json:"items,omitempty"` + } `json:"records,omitempty"` +} + +func (p *Datagroup) MarshalJSON() ([]byte, error) { + var dto DatagroupDTO + marshal(&dto, p) + return json.Marshal(dto) +} + +func (p *Datagroup) UnmarshalJSON(b []byte) error { + var dto DatagroupDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + return marshal(p, &dto) +} + +func (p *Records) MarshalJSON() ([]byte, error) { + var dto RecordsDTO + marshal(&dto, p) + return json.Marshal(dto) +} + +func (p *Records) UnmarshalJSON(b []byte) error { + var dto RecordsDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + return marshal(p, &dto) +} + func (p *Monitor) MarshalJSON() ([]byte, error) { var dto monitorDTO marshal(&dto, p) if strings.Contains(dto.SendString, "\r\n") { dto.SendString = strings.Replace(dto.SendString, "\r\n", "\\r\\n", -1) } - return jsonMarshal(dto) + return json.Marshal(dto) } func (p *Monitor) UnmarshalJSON(b []byte) error { @@ -781,26 +1066,176 @@ func (p *Monitor) UnmarshalJSON(b []byte) error { return marshal(p, &dto) } -type Profiles struct { - Profiles []Profile `json:"items"` +func (p *Oneconnect) MarshalJSON() ([]byte, error) { + var dto oneconnectDTO + marshal(&dto, p) + return json.Marshal(dto) } -type Profile struct { - Name string `json:"name,omitempty"` - FullPath string `json:"fullPath,omitempty"` - Partition string `json:"partition,omitempty"` - Context string `json:"context,omitempty"` +func (p *Oneconnect) UnmarshalJSON(b []byte) error { + var dto oneconnectDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + return marshal(p, &dto) } -type IRules struct { - IRules []IRule `json:"items"` +func (p *Tcp) MarshalJSON() ([]byte, error) { + var dto tcpDTO + marshal(&dto, p) + return json.Marshal(dto) } -type IRule struct { - Name string `json:"name,omitempty"` - Partition string `json:"partition,omitempty"` - FullPath string `json:"fullPath,omitempty"` - Rule string `json:"apiAnonymous,omitempty"` +func (p *Tcp) UnmarshalJSON(b []byte) error { + var dto tcpDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + return marshal(p, &dto) +} + +func (p *Fasthttp) MarshalJSON() ([]byte, error) { + var dto fasthttpDTO + marshal(&dto, p) + return json.Marshal(dto) +} + +func (p *Fasthttp) UnmarshalJSON(b []byte) error { + var dto fasthttpDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + return marshal(p, &dto) +} + +func (p *Fastl4) MarshalJSON() ([]byte, error) { + var dto fastl4DTO + marshal(&dto, p) + return json.Marshal(dto) +} + +func (p *Fastl4) UnmarshalJSON(b []byte) error { + var dto fastl4DTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + return marshal(p, &dto) +} + +func (p *Httpcompress) MarshalJSON() ([]byte, error) { + var dto httpcompressDTO + marshal(&dto, p) + return json.Marshal(dto) +} + +func (p *Httpcompress) UnmarshalJSON(b []byte) error { + var dto httpcompressDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + return marshal(p, &dto) +} + +func (p *Http2) MarshalJSON() ([]byte, error) { + var dto http2DTO + marshal(&dto, p) + return json.Marshal(dto) +} + +func (p *Http2) UnmarshalJSON(b []byte) error { + var dto http2DTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + return marshal(p, &dto) +} + +type Snats struct { + Snats []Snat `json:"items"` +} + +// VirtualAddress contains information about each individual virtual address. +type Snat struct { + Name string + Partition string + FullPath string + AutoLasthop string + Mirror bool + SourcePort string + Translation string + Snatpool string + VlansDisabled bool + Origins []string +} + +type snatDTO struct { + Name string `json:"name"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` + AutoLasthop string `json:"autoLastHop,omitempty"` + Mirror bool `json:"mirror,omitempty" bool:"disabled"` + SourcePort string `json:"sourePort,omitempty"` + Translation string `json:"translation,omitempty"` + Snatpool string `json:"snatpool,omitempty"` + VlansDisabled bool `json:"vlansDisabled,omitempty" bool:"disabled"` + Origins []string `json:"origins,omitempty"` +} + +func (p *Snat) MarshalJSON() ([]byte, error) { + var dto snatDTO + marshal(&dto, p) + return json.Marshal(dto) +} + +func (p *Snat) UnmarshalJSON(b []byte) error { + var dto snatDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + p.Origins = dto.Origins + //return marshal(p, &dto) + return nil +} + +type Snatpools struct { + Snatpools []Snatpool `json:"items"` +} + +// Snatpool structure +type Snatpool struct { + Name string + Partition string + Members []string +} + +type snatpoolDTO struct { + Name string `json:"name"` + Partition string `json:"partition,omitempty"` + Members []string `json:"members,omitempty"` +} + +func (p *Snatpool) MarshalJSON() ([]byte, error) { + var dto snatpoolDTO + marshal(&dto, p) + return json.Marshal(dto) +} + +func (p *Snatpool) UnmarshalJSON(b []byte) error { + var dto snatpoolDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + p.Members = dto.Members + //return marshal(p, &dto) + return nil } const ( @@ -816,14 +1251,22 @@ const ( uriSnatPool = "snatpool" uriMonitor = "monitor" uriIRule = "rule" - uriPolicy = "policy" uriDatagroup = "data-group" uriInternal = "internal" + uriPolicy = "policy" + uriOneconnect = "one-connect" ENABLED = "enable" DISABLED = "disable" CONTEXT_SERVER = "serverside" CONTEXT_CLIENT = "clientside" CONTEXT_ALL = "all" + uriTcp = "tcp" + uriFasthttp = "fasthttp" + uriFastl4 = "fastl4" + uriHttpcompress = "http-compression" + uriHttp2 = "http2" + uriSnat = "snat" + uriSnatpool = "snatpool" ) var cidr = map[string]string{ @@ -1603,3 +2046,367 @@ func (b *BigIP) UpdatePolicy(name string, p *Policy) error { func (b *BigIP) DeletePolicy(name string) error { return b.delete(uriLtm, uriPolicy, name) } + +// Oneconnect profile creation +func (b *BigIP) CreateOneconnect(name, idleTimeoutOverride, partition, defaultsFrom, sharePools, sourceMask string, maxAge, maxReuse, maxSize int) error { + oneconnect := &Oneconnect{ + Name: name, + IdleTimeoutOverride: idleTimeoutOverride, + Partition: partition, + DefaultsFrom: defaultsFrom, + SharePools: sharePools, + SourceMask: sourceMask, + MaxAge: maxAge, + MaxReuse: maxReuse, + MaxSize: maxSize, + } + return b.post(oneconnect, uriLtm, uriProfile, uriOneconnect) +} + +func (b *BigIP) Oneconnect(name string) (*Oneconnects, error) { + var oneconnects Oneconnects + err, _ := b.getForEntity(&oneconnects, uriLtm, uriProfile, uriOneconnect) + + if err != nil { + return nil, err + } + + return &oneconnects, nil +} + +// DeleteOneconnect removes an OneConnect profile from the system. +func (b *BigIP) DeleteOneconnect(name string) error { + return b.delete(uriLtm, uriProfile, uriOneconnect, name) +} + +// ModifyOneconnect updates the given Oneconnect profile with any changed values. +func (b *BigIP) ModifyOneconnect(name string, oneconnect *Oneconnect) error { + oneconnect.Name = name + return b.put(oneconnect, uriLtm, uriProfile, uriOneconnect, name) +} + +// Create TCP profile for WAN or LAN + +func (b *BigIP) CreateTcp(name, partition, defaultsFrom string, idleTimeout, closeWaitTimeout, finWait_2Timeout, finWaitTimeout, keepAliveInterval int, deferredAccept, fastOpen string) error { + tcp := &Tcp{ + Name: name, + Partition: partition, + DefaultsFrom: defaultsFrom, + IdleTimeout: idleTimeout, + CloseWaitTimeout: closeWaitTimeout, + FinWait_2Timeout: finWait_2Timeout, + FinWaitTimeout: finWaitTimeout, + KeepAliveInterval: keepAliveInterval, + DeferredAccept: deferredAccept, + FastOpen: fastOpen, + } + return b.post(tcp, uriLtm, uriProfile, uriTcp) +} + +// DeleteOneconnect removes an OneConnect profile from the system. +func (b *BigIP) DeleteTcp(name string) error { + return b.delete(uriLtm, uriProfile, uriTcp, name) +} + +// ModifyTcp updates the given Oneconnect profile with any changed values. +func (b *BigIP) ModifyTcp(name string, tcp *Tcp) error { + tcp.Name = name + return b.put(tcp, uriLtm, uriProfile, uriTcp, name) +} + +func (b *BigIP) Tcp(name string) (*Tcps, error) { + var tcps Tcps + err, _ := b.getForEntity(&tcps, uriLtm, uriProfile, uriTcp) + + if err != nil { + return nil, err + } + + return &tcps, nil +} + +func (b *BigIP) CreateFasthttp(name, defaultsFrom string, idleTimeout, connpoolIdleTimeoutOverride, connpoolMaxReuse, connpoolMaxSize, connpoolMinSize int, connpoolReplenish string, connpoolStep int, forceHttp_10Response string, maxHeaderSize int) error { + fasthttp := &Fasthttp{ + Name: name, + DefaultsFrom: defaultsFrom, + IdleTimeout: idleTimeout, + ConnpoolIdleTimeoutOverride: connpoolIdleTimeoutOverride, + ConnpoolMaxReuse: connpoolMaxReuse, + ConnpoolMaxSize: connpoolMaxSize, + ConnpoolMinSize: connpoolMinSize, + ConnpoolReplenish: connpoolReplenish, + ConnpoolStep: connpoolStep, + ForceHttp_10Response: forceHttp_10Response, + MaxHeaderSize: maxHeaderSize, + } + return b.post(fasthttp, uriLtm, uriProfile, uriFasthttp) +} + +// Delete Fast http removes an Fasthttp profile from the system. +func (b *BigIP) DeleteFasthttp(name string) error { + return b.delete(uriLtm, uriProfile, uriFasthttp, name) +} + +// ModifyFasthttp updates the given Fasthttp profile with any changed values. +func (b *BigIP) ModifyFasthttp(name string, fasthttp *Fasthttp) error { + fasthttp.Name = name + return b.put(fasthttp, uriLtm, uriProfile, uriFasthttp, name) +} + +func (b *BigIP) Fasthttp() (*Fasthttps, error) { + var fasthttps Fasthttps + err, _ := b.getForEntity(&fasthttps, uriLtm, uriProfile, uriFasthttp) + + if err != nil { + return nil, err + } + + return &fasthttps, nil +} + +func (b *BigIP) CreateFastl4(name, partition, defaultsFrom string, clientTimeout int, explicitFlowMigration, hardwareSynCookie string, idleTimeout string, ipTosToClient, ipTosToServer, keepAliveInterval string) error { + fastl4 := &Fastl4{ + Name: name, + Partition: partition, + DefaultsFrom: defaultsFrom, + ClientTimeout: clientTimeout, + ExplicitFlowMigration: explicitFlowMigration, + HardwareSynCookie: hardwareSynCookie, + IdleTimeout: idleTimeout, + IpTosToClient: ipTosToClient, + IpTosToServer: ipTosToServer, + KeepAliveInterval: keepAliveInterval, + } + return b.post(fastl4, uriLtm, uriProfile, uriFastl4) +} + +// Delete Fast http removes an Fasthttp profile from the system. +func (b *BigIP) DeleteFastl4(name string) error { + return b.delete(uriLtm, uriProfile, uriFastl4, name) +} + +// ModifyFastl4 updates the given Fastl4 profile with any changed values. +func (b *BigIP) ModifyFastl4(name string, fastl4 *Fastl4) error { + fastl4.Name = name + return b.put(fastl4, uriLtm, uriProfile, uriFastl4, name) +} + +func (b *BigIP) Fastl4(name string) (*Fastl4s, error) { + var fastl4s Fastl4s + err, _ := b.getForEntity(&fastl4s, uriLtm, uriProfile, uriFastl4) + + if err != nil { + return nil, err + } + + return &fastl4s, nil +} + +// =============== + +func (b *BigIP) CreateHttpcompress(name, defaultsFrom string, uriExclude, uriInclude []string) error { + httpcompress := &Httpcompress{ + Name: name, + DefaultsFrom: defaultsFrom, + UriExclude: uriExclude, + UriInclude: uriInclude, + } + return b.post(httpcompress, uriLtm, uriProfile, uriHttpcompress) +} + +// Delete Fast http removes an Fasthttp profile from the system. +func (b *BigIP) DeleteHttpcompress(name string) error { + return b.delete(uriLtm, uriProfile, uriHttpcompress, name) +} + +// ModifyFastl4 updates the given Fastl4 profile with any changed values. +func (b *BigIP) ModifyHttpcompress(name string, httpcompress *Httpcompress) error { + httpcompress.Name = name + return b.put(httpcompress, uriLtm, uriProfile, uriHttpcompress, name) +} + +func (b *BigIP) Httpcompress() (*Httpcompresss, error) { + var httpcompresss Httpcompresss + err, _ := b.getForEntity(&httpcompresss, uriLtm, uriProfile, uriHttpcompress) + + if err != nil { + return nil, err + } + + return &httpcompresss, nil +} + +func (b *BigIP) CreateHttp2(name, defaultsFrom string, concurrentStreamsPerConnection, connectionIdleTimeout, headerTableSize int, activationModes []string) error { + http2 := &Http2{ + Name: name, + DefaultsFrom: defaultsFrom, + ConcurrentStreamsPerConnection: concurrentStreamsPerConnection, + ConnectionIdleTimeout: connectionIdleTimeout, + HeaderTableSize: headerTableSize, + ActivationModes: activationModes, + } + return b.post(http2, uriLtm, uriProfile, uriHttp2) +} + +// Delete http2 removes an http2 profile from the system. +func (b *BigIP) DeleteHttp2(name string) error { + return b.delete(uriLtm, uriProfile, uriHttp2, name) +} + +// Modify http2 updates the given http2 profile with any changed values. +func (b *BigIP) ModifyHttp2(name string, http2 *Http2) error { + http2.Name = name + return b.put(http2, uriLtm, uriProfile, uriHttp2, name) +} + +func (b *BigIP) Http2() (*Http2s, error) { + var http2s Http2s + err, _ := b.getForEntity(&http2s, uriLtm, uriProfile, uriHttp2) + + if err != nil { + return nil, err + } + + return &http2s, nil +} + +// Datagroups returns a list of datagroups. +func (b *BigIP) Datagroups(name string) (*Datagroups, error) { + var datagroups Datagroups + err, _ := b.getForEntity(&datagroups, uriLtm, uriDatagroup, uriInternal, name) + + if err != nil { + return nil, err + } + + return &datagroups, nil +} + +// CreateDatagroup adds a new Datagroup to the BIG-IP system. +func (b *BigIP) CreateDatagroup(typo, name string, records []Records) error { + //func (b *BigIP) CreateDatagroup(typo, name string) error { + config := &Datagroup{ + Type: typo, + Name: name, + Records: records, + } + + return b.post(config, uriLtm, uriDatagroup, uriInternal) +} +func (b *BigIP) Records() (*Records, error) { + var records Records + err, _ := b.getForEntity(&records, uriLtm, uriDatagroup, uriInternal) + + if err != nil { + return nil, err + } + + return &records, nil +} +func (b *BigIP) DeleteDatagroup(name string) error { + + return b.delete(uriLtm, uriDatagroup, uriInternal, name) +} + +func (b *BigIP) AddRecords(name, rname, data string) error { + config := &Records{} + + config.Name = rname + config.Data = data + + return b.post(config, uriLtm, uriDatagroup, uriInternal, "records") +} + +// Snats returns a list of snat +func (b *BigIP) Snats(name string) (*Snats, error) { + var snats Snats + err, _ := b.getForEntity(&snats, uriLtm, uriSnat, name) + + if err != nil { + return nil, err + } + + return &snats, nil +} + +func (b *BigIP) CreateSnat(name, partition, autoLastHop, sourcePort, translation, snatpool string, vlansDisabled, mirror bool, origins []string) error { + snat := &Snat{ + Name: name, + Partition: partition, + AutoLasthop: autoLastHop, + SourcePort: sourcePort, + Translation: translation, + Snatpool: snatpool, + Mirror: mirror, + VlansDisabled: vlansDisabled, + Origins: origins, + } + log.Println("[INFO] Creating snat ", snat) + return b.post(snat, uriLtm, uriSnat) +} + +func (b *BigIP) ModifySnat(config *Snat) error { + return b.patch(config, uriLtm, uriSnat) +} + +// Get a Snat list by name. Returns nil if the node does not exist +func (b *BigIP) GetSnat(name string) (*Snat, error) { + var snat Snat + err, ok := b.getForEntity(&snat, uriLtm, uriSnat, name) + if err != nil { + return nil, err + } + if !ok { + return nil, nil + } + + return &snat, nil +} + +func (b *BigIP) DeleteSnat(name string) error { + return b.delete(uriLtm, uriSnat, name) +} + +// Snats returns a list of snat +func (b *BigIP) Snatpools(name string) (*Snatpools, error) { + var snatpools Snatpools + err, _ := b.getForEntity(&snatpools, uriLtm, uriSnatpool, name) + + if err != nil { + return nil, err + } + + return &snatpools, nil +} + +func (b *BigIP) CreateSnatpool(name, partition string, members []string) error { + snatpool := &Snatpool{ + Name: name, + Partition: partition, + Members: members, + } + log.Println("[INFO] Creating snatpool ", snatpool) + return b.post(snatpool, uriLtm, uriSnatpool) +} + +func (b *BigIP) ModifySnatpool(config *Snatpool) error { + return b.put(config, uriLtm, uriSnatpool) +} + +// Get a Snat list by name. Returns nil if the node does not exist +func (b *BigIP) GetSnatpool(name string) (*Snatpool, error) { + var snatpool Snatpool + err, ok := b.getForEntity(&snatpool, uriLtm, uriSnatpool, name) + if err != nil { + return nil, err + } + if !ok { + return nil, nil + } + + return &snatpool, nil +} + +func (b *BigIP) DeleteSnatpool(name string) error { + return b.delete(uriLtm, uriSnatpool, name) +} diff --git a/sys.go b/sys.go new file mode 100644 index 0000000..d4dcfbf --- /dev/null +++ b/sys.go @@ -0,0 +1,339 @@ +package bigip + +import "encoding/json" + +type NTPs struct { + NTPs []NTP `json:"items"` +} + +type NTP struct { + Description string `json:"description,omitempty"` + Servers []string `json:"servers,omitempty"` + Timezone string `json:"timezone,omitempty"` +} + +type DNSs struct { + DNSs []DNS `json:"items"` +} + +type DNS struct { + Description string `json:"description,omitempty"` + NameServers []string `json:"nameServers,omitempty"` + NumberOfDots int `json:"numberOfDots,omitempty"` + Search []string `json:"search,omitempty"` +} + +type Provisions struct { + Provisions []Provision `json:"items"` +} + +type Provision struct { + Name string `json:"name,omitempty"` + FullPath string `json:"fullPath,omitempty"` + CpuRatio int `json:"cpuRatio,omitempty"` + DiskRatio int `json:"diskRatio,omitempty"` + Level string `json:"level,omitempty"` + MemoryRatio int `json:"memoryRatio,omitempty"` +} + +type Syslogs struct { + Syslogs []Syslog `json:"items"` +} + +type Syslog struct { + AuthPrivFrom string + RemoteServers []RemoteServer +} + +type syslogDTO struct { + AuthPrivFrom string `json:"authPrivFrom,omitempty"` + RemoteServers struct { + Items []RemoteServer `json:"items,omitempty"` + } `json:"remoteServers,omitempty"` +} + +func (p *Syslog) MarshalJSON() ([]byte, error) { + var dto syslogDTO + return json.Marshal(dto) +} + +func (p *Syslog) UnmarshalJSON(b []byte) error { + var dto syslogDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + + p.AuthPrivFrom = dto.AuthPrivFrom + p.RemoteServers = dto.RemoteServers.Items + + return nil +} + +type RemoteServer struct { + Name string `json:"name,omitempty"` + Host string `json:"host,omitempty"` + RemotePort int `json:"remotePort,omitempty"` +} + +type remoteServerDTO struct { + Name string `json:"name,omitempty"` + Host string `json:"host,omitempty"` + RemotePort int `json:"remotePort,omitempty"` +} + +func (p *RemoteServer) MarshalJSON() ([]byte, error) { + return json.Marshal(remoteServerDTO{ + Name: p.Name, + Host: p.Host, + RemotePort: p.RemotePort, + }) +} + +func (p *RemoteServer) UnmarshalJSON(b []byte) error { + var dto remoteServerDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + + p.Name = dto.Name + p.Host = dto.Host + p.RemotePort = dto.RemotePort + + return nil +} + +type SNMPs struct { + SNMPs []SNMP `json:"items"` +} + +type SNMP struct { + SysContact string `json:"sysContact,omitempty"` + SysLocation string `json:"sysLocation,omitempty"` + AllowedAddresses []string `json:"allowedAddresses,omitempty"` +} + +type TRAPs struct { + SNMPs []SNMP `json:"items"` +} + +type TRAP struct { + Name string `json:"name,omitempty"` + AuthPasswordEncrypted string `json:"authPasswordEncrypted,omitempty"` + AuthProtocol string `json:"authProtocol,omitempty"` + Community string `json:"community,omitempty"` + Description string `json:"description,omitempty"` + EngineId string `json:"engineId,omitempty"` + Host string `json:"host,omitempty"` + Port int `json:"port,omitempty"` + PrivacyPassword string `json:"privacyPassword,omitempty"` + PrivacyPasswordEncrypted string `json:"privacyPasswordEncrypted,omitempty"` + PrivacyProtocol string `json:"privacyProtocol,omitempty"` + SecurityLevel string `json:"securityLevel,omitempty"` + SecurityName string `json:"SecurityName,omitempty"` + Version string `json:"version,omitempty"` +} + +const ( + uriSys = "sys" + uriNtp = "ntp" + uriDNS = "dns" + uriProvision = "provision" + uriAfm = "afm" + uriAsm = "asm" + uriApm = "apm" + uriGtm = "gtm" + uriAvr = "avr" + uriIlx = "ilx" + uriSyslog = "syslog" + uriSnmp = "snmp" + uriTraps = "traps" +) + +func (b *BigIP) CreateNTP(description string, servers []string, timezone string) error { + config := &NTP{ + Description: description, + Servers: servers, + Timezone: timezone, + } + + return b.patch(config, uriSys, uriNtp) +} + +func (b *BigIP) ModifyNTP(config *NTP) error { + return b.put(config, uriSys, uriNtp) +} + +func (b *BigIP) NTPs() (*NTP, error) { + var ntp NTP + err, _ := b.getForEntity(&ntp, uriSys, uriNtp) + + if err != nil { + return nil, err + } + + return &ntp, nil +} + +func (b *BigIP) CreateDNS(description string, nameservers []string, numberofdots int, search []string) error { + config := &DNS{ + Description: description, + NameServers: nameservers, + NumberOfDots: numberofdots, + Search: search, + } + + return b.patch(config, uriSys, uriDNS) +} + +func (b *BigIP) ModifyDNS(config *DNS) error { + return b.put(config, uriSys, uriDNS) +} + +func (b *BigIP) DNSs() (*DNS, error) { + var dns DNS + err, _ := b.getForEntity(&dns, uriSys, uriDNS) + + if err != nil { + return nil, err + } + + return &dns, nil +} + +func (b *BigIP) CreateProvision(name string, fullPath string, cpuRatio int, diskRatio int, level string, memoryRatio int) error { + config := &Provision{ + Name: name, + FullPath: fullPath, + CpuRatio: cpuRatio, + DiskRatio: diskRatio, + Level: level, + MemoryRatio: memoryRatio, + } + if name == "/Common/asm" { + return b.put(config, uriSys, uriProvision, uriAsm) + } + if name == "/Common/afm" { + return b.put(config, uriSys, uriProvision, uriAfm) + } + if name == "/Common/gtm" { + return b.put(config, uriSys, uriProvision, uriGtm) + } + + if name == "/Common/apm" { + return b.put(config, uriSys, uriProvision, uriApm) + } + + if name == "/Common/avr" { + return b.put(config, uriSys, uriProvision, uriAvr) + } + if name == "/Common/ilx" { + return b.put(config, uriSys, uriProvision, uriIlx) + } + return nil +} + +func (b *BigIP) ModifyProvision(config *Provision) error { + + return b.put(config, uriSys, uriProvision, uriAfm) +} + +func (b *BigIP) DeleteProvision(name string) error { + return b.delete(uriSys, uriProvision, uriIlx, name) +} + +func (b *BigIP) Provisions() (*Provision, error) { + var provision Provision + err, _ := b.getForEntity(&provision, uriProvision, uriAfm) + + if err != nil { + return nil, err + } + + return &provision, nil +} + +func (b *BigIP) Syslogs() (*Syslog, error) { + var syslog Syslog + err, _ := b.getForEntity(&syslog, uriSys, uriSyslog) + + if err != nil { + return nil, err + } + + return &syslog, nil +} + +func (b *BigIP) CreateSyslog(r *Syslog) error { + return b.patch(r, uriSys, uriSyslog) +} + +func (b *BigIP) ModifySyslog(r *Syslog) error { + return b.put(r, uriSys, uriSyslog) +} + +func (b *BigIP) CreateSNMP(sysContact string, sysLocation string, allowedAddresses []string) error { + config := &SNMP{ + SysContact: sysContact, + SysLocation: sysLocation, + AllowedAddresses: allowedAddresses, + } + + return b.patch(config, uriSys, uriSnmp) +} + +func (b *BigIP) ModifySNMP(config *SNMP) error { + return b.put(config, uriSys, uriSnmp) +} + +func (b *BigIP) SNMPs() (*SNMP, error) { + var snmp SNMP + err, _ := b.getForEntity(&snmp, uriSys, uriSnmp) + + if err != nil { + return nil, err + } + + return &snmp, nil +} + +func (b *BigIP) CreateTRAP(name string, authPasswordEncrypted string, authProtocol string, community string, description string, engineId string, host string, port int, privacyPassword string, privacyPasswordEncrypted string, privacyProtocol string, securityLevel string, securityName string, version string) error { + config := &TRAP{ + Name: name, + AuthPasswordEncrypted: authPasswordEncrypted, + AuthProtocol: authProtocol, + Community: community, + Description: description, + EngineId: engineId, + Host: host, + Port: port, + PrivacyPassword: privacyPassword, + PrivacyPasswordEncrypted: privacyPasswordEncrypted, + PrivacyProtocol: privacyProtocol, + SecurityLevel: securityLevel, + SecurityName: securityName, + Version: version, + } + + return b.post(config, uriSys, uriSnmp, uriTraps) +} + +func (b *BigIP) ModifyTRAP(config *TRAP) error { + return b.put(config, uriSys, uriSnmp, uriTraps) +} + +func (b *BigIP) TRAPs() (*TRAP, error) { + var traps TRAP + err, _ := b.getForEntity(&traps, uriSys, uriSnmp, uriTraps) + + if err != nil { + return nil, err + } + + return &traps, nil +} + +func (b *BigIP) DeleteTRAP(name string) error { + return b.delete(uriSys, uriSnmp, uriTraps, name) +} diff --git a/utility.go b/utility.go new file mode 100644 index 0000000..90354e1 --- /dev/null +++ b/utility.go @@ -0,0 +1,150 @@ +package bigip + +import "encoding/json" + +// LIC contains device license for BIG-IP system. +type ULICs struct { + LIC []LIC `json:"items"` +} + +// This is BIG-IP which needs to be licensed. +type ULIC struct { + DeviceAddress string + Username string + Password string + UnitOfMeasure string +} + +type UtilityPools struct { + UtilityPool []UtilityPool `json:"items"` +} + +type UtilityPool struct { + Items []struct { + RegKey string `json:"RegKey,omitempty"` + } +} + +type ULICDTO struct { + DeviceAddress string `json:"deviceAddress,omitempty"` + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + UnitOfMeasure string `json:"unitOfMeasure,omitempty"` +} + +/*GET https://10.192.74.92/mgmt/cm/device/licensing/pool/utility/licenses + +To view a particular utility license (exclude brackets) +GET https://10.192.74.92/mgmt/cm/device/licensing/pool/utility/licenses/{ reg key for license} +So for your license currently on box +GET https://10.192.74.92/mgmt/cm/device/licensing/pool/utility/licenses/FDKOC-UVGUE-FDURD-AYYDH-IXDSOYV + +To view the list of offerings for a utility license +GET https://10.192.74.92/mgmt/cm/device/licensing/pool/utility/licenses/FDKOC-UVGUE-FDURD-AYYDH-IXDSOYV/offerings + +To view the members of an offering +GET https://10.192.74.92/mgmt/cm/device/licensing/pool/utility/licenses/{RegKey}/offerings/{offering id}/members +So for your license currently on box +GET https://10.192.74.92/mgmt/cm/device/licensing/pool/utility/licenses/FDKOC-UVGUE-FDURD-AYYDH-IXDSOYV/offerings/fb7b7c65-5551-4ab2-a35a-659d47533e6b/members + +To assign a license a device the license from an offering you would POST to the members collection like you would for purchased pool licenses for managed devices. +POST https://10.192.74.92/mgmt/cm/device/licensing/pool/utility/licenses/FDKOC-UVGUE-FDURD-AYYDH-IXDSOYV/offerings/fb7b7c65-5551-4ab2-a35a-659d47533e6b/members +{ + + “unitOfMeasure”: “yearly” +} +UnitOfMeasure can be “hourly”,”daily”, “monthly”, “yearly”. + +*/ + +func (p *ULIC) MarshalJSON() ([]byte, error) { + var dto ULICDTO + marshal(&dto, p) + return json.Marshal(dto) +} + +func (p *ULIC) UnmarshalJSON(b []byte) error { + var dto ULICDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + return marshal(p, &dto) +} + +// Get the RegKey which is used to know what Bulk license is available on BIG-IQ +func (b *BigIP) getUtilityPool() (*UtilityPool, error) { + var utilityPool UtilityPool + err, _ := b.getForEntity(&utilityPool, uriMgmt, uriCm, uriDiv, uriLins, uriPoo, uriUtility, uriLicn) + if err != nil { + return nil, err + } + // for loop over all returned license pools to check which one has available licenses + // getAvailablePool(member[index_of_array].Uuid) + // At the end change return statement to return only the UUID string of the one where license + // is availble + return &utilityPool, nil +} + +// Function to get the RegKey +func (b *BigIP) ULIC() (*ULIC, error) { + var va ULIC + utilityPool, utilityPoolErr := b.getUtilityPool() + if utilityPoolErr != nil { + return nil, utilityPoolErr + } + err, _ := b.getForEntity(&va, uriMgmt, uriCm, uriDiv, uriLins, uriPoo, uriUtility, uriLicn, utilityPool.Items[0].RegKey) + if err != nil { + return nil, err + } + return &va, nil +} + +func (b *BigIP) CreateULIC(deviceAddress string, username string, password string, unitOfMeasure string) error { + config := &ULIC{ + DeviceAddress: deviceAddress, + Username: username, + Password: password, + UnitOfMeasure: unitOfMeasure, + } + + utilityPool, utilityPoolErr := b.getUtilityPool() + if utilityPoolErr != nil { + return utilityPoolErr + } + + return b.post(config, uriMgmt, uriCm, uriDiv, uriLins, uriPoo, uriUtility, uriLicn, utilityPool.Items[0].RegKey, uriOfferings, uriF5BIGMSPBT10G, uriMemb) +} + +func (b *BigIP) ModifyULIC(config *ULIC) error { + utilityPool, utilityPoolErr := b.getUtilityPool() + if utilityPoolErr != nil { + return utilityPoolErr + } + return b.patch(config, uriMgmt, uriCm, uriDiv, uriLins, uriPoo, uriUtility, uriLicn, utilityPool.Items[0].RegKey, uriMemb) +} + +func (b *BigIP) ULICs() (*ULIC, error) { + var members ULIC + utilityPool, utilityPoolErr := b.getUtilityPool() + if utilityPoolErr != nil { + return nil, utilityPoolErr + } + err, _ := b.getForEntity(&members, uriMgmt, uriCm, uriDiv, uriLins, uriPoo, uriUtility, uriLicn, utilityPool.Items[0].RegKey, uriMemb) + + if err != nil { + return nil, err + } + + return &members, nil +} + +func (b *BigIP) DeleteULIC(config *ULIC) error { + + utilityPool, utilityPoolErr := b.getUtilityPool() + if utilityPoolErr != nil { + return utilityPoolErr + } + + return b.delete(uriMgmt, uriCm, uriDiv, uriLins, uriPoo, uriUtility, uriLicn, utilityPool.Items[0].RegKey, uriOfferings, uriF5BIGMSPBT10G, uriMemb) +} From 94752996b250ccf4c04612ff15f7c3a2cc322faa Mon Sep 17 00:00:00 2001 From: Sanjay Date: Thu, 16 Nov 2017 16:19:47 -0800 Subject: [PATCH 02/80] created gtm.go for GTM --- .gitignore | 1 + gtm.go | 231 +++++++++++++++++++++++++++++++++++++++++++++++++++++ ltm.go | 4 +- net.go | 5 +- sys.go | 4 +- 5 files changed, 239 insertions(+), 6 deletions(-) create mode 100644 gtm.go diff --git a/.gitignore b/.gitignore index c38fa4e..7d4df8a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea *.iml +*.back diff --git a/gtm.go b/gtm.go new file mode 100644 index 0000000..41c199d --- /dev/null +++ b/gtm.go @@ -0,0 +1,231 @@ +package bigip + +import "encoding/json" +import "log" + + + +type Datacenters struct { + Datacenters []Datacenter `json:"items"` +} + +type Datacenter struct { + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + Contact string `json:"contact,omitempty"` + App_service string `json:"appService,omitempty"` + Disabled bool `json:"disabled,omitempty"` + Enabled bool `json:"enabled,omitempty"` + Prober_pool string `json:"proberPool,omitempty"` +} + + +type Gtmmonitors struct { + Gtmmonitors []Gtmmonitor `json:"items"` +} + + +type Gtmmonitor struct { + Name string `json:"name,omitempty"` + Defaults_from string `json:"defaultsFrom,omitempty"` + Interval int `json:"interval,omitempty"` + Probe_timeout int `json:"probeTimeout,omitempty"` + Recv string `json:"recv,omitempty"` + Send string `json:"send,omitempty"` +} + +type Servers struct { + Servers []Server `json:"items"` +} + +type Server struct { + Name string + Datacenter string + Monitor string + Virtual_server_discovery bool + Product string + Addresses []ServerAddresses + GTMVirtual_Server []VSrecord +} + +type serverDTO struct { + Name string `json:"name"` + Datacenter string `json:"datacenter,omitempty"` + Monitor string `json:"monitor,omitempty"` + Virtual_server_discovery bool `json:"virtual_server_discovery"` + Product string `json:"product,omitempty"` + Addresses struct { + Items []ServerAddresses`json:"items,omitempty"` + } `json:"addressesReference,omitempty"` + GTMVirtual_Server struct { + Items []VSrecord `json:"items,omitempty"` } `json:"virtualServersReference,omitempty"` + } + + func (p *Server) MarshalJSON() ([]byte, error) { + return json.Marshal(serverDTO{ + Name: p.Name, + Datacenter: p.Datacenter, + Monitor: p.Monitor, + Virtual_server_discovery: p.Virtual_server_discovery, + Product: p.Product, + Addresses: struct { + Items []ServerAddresses `json:"items,omitempty"` + }{Items: p.Addresses}, + GTMVirtual_Server: struct { + Items []VSrecord `json:"items,omitempty"` + }{Items: p.GTMVirtual_Server}, + }) + } + + func (p *Server) UnmarshalJSON(b []byte) error { + var dto serverDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + + p.Name = dto.Name + p.Datacenter = dto.Datacenter + p.Monitor = dto.Monitor + p.Virtual_server_discovery = dto.Virtual_server_discovery + p.Product = dto.Product + p.Addresses = dto.Addresses.Items + p.GTMVirtual_Server = dto.GTMVirtual_Server.Items + return nil + } + + + type ServerAddressess struct { + Items []ServerAddresses `json:"items,omitempty"` + } + + + + type ServerAddresses struct { + Name string `json:"name"` + Device_name string `json:"deviceName,omitempty"` + Translation string `json:"translation,omitempty"` + } + + + + type VSrecords struct { + Items []VSrecord `json:"items,omitempty"` + } + + + + type VSrecord struct { + Name string `json:"name"` + Destination string `json:"destination,omitempty"` + } + + + + + +const ( + uriGtm = "gtm" + uriServer = "server" + uriDatacenter = "datacenter" + uriGtmmonitor = "monitor" + uriHttp = "http" +) + +func (b *BigIP) Datacenters() (*Datacenter, error) { + var datacenter Datacenter + err, _ := b.getForEntity(&datacenter, uriGtm, uriDatacenter) + + if err != nil { + return nil, err + } + + return &datacenter, nil +} + +func (b *BigIP) CreateDatacenter(name, description,contact, app_service string, enabled, disabled bool, prober_pool string) error { + config := &Datacenter{ + Name: name, + Description: description, + Contact: contact, + App_service: app_service, + Enabled: enabled, + Disabled: disabled, + Prober_pool: prober_pool, + } + log.Printf("I am %#v\n here %s ", config) + return b.post(config, uriGtm, uriDatacenter) +} + +func (b *BigIP) ModifyDatacenter(*Datacenter) error { + return b.patch(uriGtm, uriDatacenter) +} + + +func (b *BigIP) DeleteDatacenter(name string) error { + return b.delete(uriGtm, uriDatacenter, name) +} + + + +func (b *BigIP) Gtmmonitors() (*Gtmmonitor, error) { + var gtmmonitor Gtmmonitor + err, _ := b.getForEntity(>mmonitor, uriGtm, uriGtmmonitor, uriHttp) + + if err != nil { + return nil, err + } + + return >mmonitor, nil +} +func (b *BigIP) CreateGtmmonitor(name, defaults_from string, interval, probeTimeout int, recv, send string) error { + config := &Gtmmonitor{ + Name: name, + Defaults_from: defaults_from, + Interval: interval, + Probe_timeout: probeTimeout, + Recv: recv, + Send: send, + } + log.Printf("I am %#v\n here %s ", config) + return b.post(config, uriGtm, uriGtmmonitor, uriHttp) +} + +func (b *BigIP) ModifyGtmmonitor(*Gtmmonitor) error { + return b.patch(uriGtm, uriGtmmonitor, uriHttp) +} + + +func (b *BigIP) DeleteGtmmonitor(name string) error { + return b.delete(uriGtm, uriGtmmonitor, uriHttp, name) +} + + +func (b *BigIP) CreateGtmserver(p *Server) error { + log.Println(" what is the complete payload ", p) + return b.post(p, uriGtm, uriServer) +} + +//Update an existing policy. +func (b *BigIP) UpdateGtmserver(name string, p *Server) error { + return b.put(p, uriGtm, uriServer, name) +} + +//Delete a policy by name. +func (b *BigIP) DeleteGtmserver(name string) error { + return b.delete(uriGtm, uriServer, name) +} + + +func (b *BigIP) GetGtmserver(name string) (*Server, error) { + var p Server + err, ok := b.getForEntity(&p, uriGtm, uriServer, name) + if err != nil { + return nil, err + } + if !ok { + return nil, nil + } + + return &p, nil + } diff --git a/ltm.go b/ltm.go index 56827f0..dd0eccb 100644 --- a/ltm.go +++ b/ltm.go @@ -286,8 +286,8 @@ type poolDTO struct { Partition string `json:"partition,omitempty"` FullPath string `json:"fullPath,omitempty"` Generation int `json:"generation,omitempty"` - AllowNAT string `json:"allowNat,omitempty" bool:"yes"` - AllowSNAT string `json:"allowSnat,omitempty" bool:"yes"` + AllowNAT string `json:"allowNat,omitempty"` + AllowSNAT string `json:"allowSnat,omitempty"` IgnorePersistedWeight string `json:"ignorePersistedWeight,omitempty" bool:"enabled"` IPTOSToClient string `json:"ipTosToClient,omitempty"` IPTOSToServer string `json:"ipTosToServer,omitempty"` diff --git a/net.go b/net.go index 6c21624..954560c 100644 --- a/net.go +++ b/net.go @@ -2,6 +2,7 @@ package bigip import ( "strings" + "log" ) // Interfaces contains a list of every interface on the BIG-IP system. @@ -190,7 +191,7 @@ func (b *BigIP) AddInterfaceToVlan(vlan, iface string, tagged bool) error { config.Untagged = true } - return b.put(config, uriNet, uriVlan, vlan, "interfaces") + return b.post(config, uriNet, uriVlan, vlan, "interfaces") } // SelfIPs returns a list of self IP's. @@ -289,7 +290,7 @@ func (b *BigIP) CreateVlan(name string, tag int) error { Name: name, Tag: tag, } - +log.Println("I am here in vlan post", config) return b.post(config, uriNet, uriVlan) } diff --git a/sys.go b/sys.go index d4dcfbf..ee2cbf2 100644 --- a/sys.go +++ b/sys.go @@ -1,6 +1,7 @@ package bigip import "encoding/json" +import "log" type NTPs struct { NTPs []NTP `json:"items"` @@ -143,7 +144,6 @@ const ( uriAfm = "afm" uriAsm = "asm" uriApm = "apm" - uriGtm = "gtm" uriAvr = "avr" uriIlx = "ilx" uriSyslog = "syslog" @@ -183,7 +183,7 @@ func (b *BigIP) CreateDNS(description string, nameservers []string, numberofdots NumberOfDots: numberofdots, Search: search, } - +log.Printf("I am %#v\n DNS %s ", config) return b.patch(config, uriSys, uriDNS) } From 0612c2b05369ef855ca16176c5cc963a92b86900 Mon Sep 17 00:00:00 2001 From: Sanjay Date: Thu, 16 Nov 2017 19:56:20 -0800 Subject: [PATCH 03/80] change gtm.go --- gtm.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/gtm.go b/gtm.go index 41c199d..eee0a63 100644 --- a/gtm.go +++ b/gtm.go @@ -120,7 +120,20 @@ type serverDTO struct { Destination string `json:"destination,omitempty"` } + type Pool_as struct { + Pool_as []Pool_a `json:"items"` + } + type Pool_a struct { + Name string `json:"name,omitempty"` + Monitor string `json:"monitor,omitempty"` + Load_balancing_mode string `json:"load_balancing_mode,omitempty"` + Max_answers_returned int `json:"max_answers_returned,omitempty"` + Alternate_mode string `json:"alternate_mode,omitempty"` + Fallback_ip string `json:"fallback_ip,omitempty"` + Fallback_mode string `json:"fallback_mode,omitempty"` + Members []string `json:"members,omitempty"` + } @@ -130,6 +143,7 @@ const ( uriDatacenter = "datacenter" uriGtmmonitor = "monitor" uriHttp = "http" + uriPool_a = "pool/a" ) func (b *BigIP) Datacenters() (*Datacenter, error) { @@ -229,3 +243,34 @@ func (b *BigIP) GetGtmserver(name string) (*Server, error) { return &p, nil } + + + func (b *BigIP) CreatePool_a(name, monitor, load_balancing_mode string, max_answers_returned int, alternate_mode, fallback_ip, fallback_mode string, members []string) error { + config := &Pool_a{ + Name: name, + Monitor: monitor, + Load_balancing_mode: load_balancing_mode, + Max_answers_returned: max_answers_returned, + Alternate_mode: alternate_mode, + Fallback_ip: fallback_ip, + Fallback_mode: fallback_mode, + Members: members, + } + log.Println("in poola now", config) + return b.patch(config, uriGtm, uriPool_a) + } + + func (b *BigIP) ModifyPool_a(config *Pool_a) error { + return b.put(config, uriGtm, uriPool_a) + } + + func (b *BigIP) Pool_as() (*Pool_a, error) { + var pool_a Pool_a + err, _ := b.getForEntity(&pool_a, uriGtm, uriPool_a) + + if err != nil { + return nil, err + } + + return &pool_a, nil + } From bad084c380277e7b7e877940365aec96e232e31e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sun, 19 Nov 2017 13:17:55 -0500 Subject: [PATCH 04/80] Correct Travis build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- .travis.yml | 12 +++++++----- README.md | 9 +++++---- bigip.go | 4 ++-- gtm.go | 2 -- ltm.go | 2 +- ltm_test.go | 1 - net.go | 2 -- net_test.go | 2 +- sys.go | 2 -- 9 files changed, 16 insertions(+), 20 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8fe0835..22d2878 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,9 @@ language: go -go: - - 1.7 - - 1.8 - - 1.9 - - tip +matrix: + include: + - go: 1.8 + - go: 1.9 + - go: tip + allow_failures: + - go: tip diff --git a/README.md b/README.md index 9e1361e..8d727b9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ ## go-bigip -[![GoDoc](https://godoc.org/github.com/scottdware/go-bigip?status.svg)](https://godoc.org/github.com/scottdware/go-bigip) [![Travis-CI](https://travis-ci.org/scottdware/go-bigip.svg?branch=master)](https://travis-ci.org/scottdware/go-bigip) -[![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/scottdware/go-bigip/master/LICENSE) +[![GoDoc](https://godoc.org/github.com/f5devcentral/go-bigip?status.svg)](https://godoc.org/github.com/f5devcentral/go-bigip) [![Travis-CI](https://travis-ci.org/f5devcentral/go-bigip.svg?branch=master)](https://travis-ci.org/f5devcentral/go-bigip) +[![Go Report Card](https://goreportcard.com/badge/github.com/f5devcentral/go-bigip)](https://goreportcard.com/report/github.com/f5devcentral/go-bigip) +[![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/f5devcentral/go-bigip/master/LICENSE) A Go package that interacts with F5 BIG-IP systems using the REST API. @@ -24,6 +25,6 @@ A very special thanks to the following who have helped contribute to this softwa * [Adam Burnett](https://github.com/aburnett) * [Michael D. Ivey](https://github.com/ivey) -[godoc-go-bigip]: http://godoc.org/github.com/scottdware/go-bigip -[license]: https://github.com/scottdware/go-bigip/blob/master/LICENSE +[godoc-go-bigip]: http://godoc.org/github.com/f5devcentral/go-bigip +[license]: https://github.com/f5devcentral/go-bigip/blob/master/LICENSE [blog]: http://sdubs.org/go-big-ip-or-go-home/ diff --git a/bigip.go b/bigip.go index bcc33f5..24b3c26 100644 --- a/bigip.go +++ b/bigip.go @@ -213,7 +213,7 @@ func (b *BigIP) delete(path ...string) error { } func (b *BigIP) post(body interface{}, path ...string) error { - marshalJSON, err := json.Marshal(body) + marshalJSON, err := jsonMarshal(body) if err != nil { return err } @@ -247,7 +247,7 @@ func (b *BigIP) put(body interface{}, path ...string) error { } func (b *BigIP) patch(body interface{}, path ...string) error { - marshalJSON, err := json.Marshal(body) + marshalJSON, err := jsonMarshal(body) if err != nil { return err } diff --git a/gtm.go b/gtm.go index eee0a63..164125e 100644 --- a/gtm.go +++ b/gtm.go @@ -167,7 +167,6 @@ func (b *BigIP) CreateDatacenter(name, description,contact, app_service string, Disabled: disabled, Prober_pool: prober_pool, } - log.Printf("I am %#v\n here %s ", config) return b.post(config, uriGtm, uriDatacenter) } @@ -201,7 +200,6 @@ func (b *BigIP) CreateGtmmonitor(name, defaults_from string, interval, probeTime Recv: recv, Send: send, } - log.Printf("I am %#v\n here %s ", config) return b.post(config, uriGtm, uriGtmmonitor, uriHttp) } diff --git a/ltm.go b/ltm.go index dd0eccb..9ba28d3 100644 --- a/ltm.go +++ b/ltm.go @@ -1054,7 +1054,7 @@ func (p *Monitor) MarshalJSON() ([]byte, error) { if strings.Contains(dto.SendString, "\r\n") { dto.SendString = strings.Replace(dto.SendString, "\r\n", "\\r\\n", -1) } - return json.Marshal(dto) + return jsonMarshal(dto) } func (p *Monitor) UnmarshalJSON(b []byte) error { diff --git a/ltm_test.go b/ltm_test.go index 965cfab..b70ed75 100644 --- a/ltm_test.go +++ b/ltm_test.go @@ -777,7 +777,6 @@ func (s *LTMTestSuite) TestModifyPoolMember() { s.Client.ModifyPoolMember(pool, config) - fmt.Println(s.LastRequest.URL) assert.Equal(s.T(), "PUT", s.LastRequest.Method) assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s/%s/%s", uriLtm, uriPool, "~Common~test-pool", uriPoolMember, "~Common~test-pool-member:80"), s.LastRequest.URL.Path) assert.Equal(s.T(), `{"monitor":"/Common/icmp"}`, s.LastRequestBody) diff --git a/net.go b/net.go index 954560c..40509bf 100644 --- a/net.go +++ b/net.go @@ -2,7 +2,6 @@ package bigip import ( "strings" - "log" ) // Interfaces contains a list of every interface on the BIG-IP system. @@ -290,7 +289,6 @@ func (b *BigIP) CreateVlan(name string, tag int) error { Name: name, Tag: tag, } -log.Println("I am here in vlan post", config) return b.post(config, uriNet, uriVlan) } diff --git a/net_test.go b/net_test.go index 5b00821..3034b22 100644 --- a/net_test.go +++ b/net_test.go @@ -93,7 +93,7 @@ func (s *NetTestSuite) TestAddInterfaceToVLan() { assert.Nil(s.T(), err) assertRestCall(s, - "PUT", + "POST", "/mgmt/tm/net/vlan/vlan-name/interfaces", `{"name":"iface-name", "untagged":true}`) } diff --git a/sys.go b/sys.go index ee2cbf2..c357881 100644 --- a/sys.go +++ b/sys.go @@ -1,7 +1,6 @@ package bigip import "encoding/json" -import "log" type NTPs struct { NTPs []NTP `json:"items"` @@ -183,7 +182,6 @@ func (b *BigIP) CreateDNS(description string, nameservers []string, numberofdots NumberOfDots: numberofdots, Search: search, } -log.Printf("I am %#v\n DNS %s ", config) return b.patch(config, uriSys, uriDNS) } From a65cdad1aa581fb9afcec6546314c30eec56ea88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sun, 19 Nov 2017 15:39:10 -0500 Subject: [PATCH 05/80] Correct GetInternalDataGroupRecords processing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- ltm.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ltm.go b/ltm.go index dd0eccb..90dd25d 100644 --- a/ltm.go +++ b/ltm.go @@ -1554,13 +1554,13 @@ func (b *BigIP) ModifyInternalDataGroupRecords(name string, records *[]DataGroup // Get the internal data group records for a named internal data group func (b *BigIP) GetInternalDataGroupRecords(name string) (*[]DataGroupRecord, error) { - var dataGroupRecords []DataGroupRecord - err, _ := b.getForEntity(&dataGroupRecords, uriLtm, uriDatagroup, uriInternal, name) + var dataGroup DataGroup + err, _ := b.getForEntity(&dataGroup, uriLtm, uriDatagroup, uriInternal, name) if err != nil { return nil, err } - return &dataGroupRecords, nil + return &dataGroup.Records, nil } // Pools returns a list of pools. From f168e62615e7b471246aa3b3432d52321e7b11a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Mon, 27 Nov 2017 08:35:09 -0500 Subject: [PATCH 06/80] Correct spelling --- device.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/device.go b/device.go index d36d2de..409f47f 100644 --- a/device.go +++ b/device.go @@ -102,7 +102,7 @@ func (b *BigIP) getLicensePool() (*LicensePool, error) { // for loop over all returned license pools to check which one has available licenses // getAvailablePool(member[index_of_array].Uuid) // At the end change return statement to return only the UUID string of the one where license - // is availble + // is available return &licensePool, nil } From 65f5ed5e2534dbee7dd426b5fd3cb5e8bfbcec75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Mon, 27 Nov 2017 08:35:44 -0500 Subject: [PATCH 07/80] Correct spelling --- utility.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utility.go b/utility.go index 90354e1..5596ddb 100644 --- a/utility.go +++ b/utility.go @@ -82,7 +82,7 @@ func (b *BigIP) getUtilityPool() (*UtilityPool, error) { // for loop over all returned license pools to check which one has available licenses // getAvailablePool(member[index_of_array].Uuid) // At the end change return statement to return only the UUID string of the one where license - // is availble + // is available return &utilityPool, nil } From 5883d3ae52a9de8472b263faee16050decac10af Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 8 Dec 2017 18:08:01 -0800 Subject: [PATCH 08/80] updated gtm --- gtm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtm.go b/gtm.go index 164125e..6a66b03 100644 --- a/gtm.go +++ b/gtm.go @@ -4,7 +4,7 @@ import "encoding/json" import "log" - +// updated type Datacenters struct { Datacenters []Datacenter `json:"items"` } From 6a067faa1ac43f925d0b5374dae95ccb1a6b4fb0 Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 8 Dec 2017 18:32:05 -0800 Subject: [PATCH 09/80] gtm --- gtm.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gtm.go b/gtm.go index 6a66b03..4e36891 100644 --- a/gtm.go +++ b/gtm.go @@ -3,8 +3,9 @@ package bigip import "encoding/json" import "log" +//ooo + -// updated type Datacenters struct { Datacenters []Datacenter `json:"items"` } From 940ff9a0400f8af9b2cc1c0246d5736b91699205 Mon Sep 17 00:00:00 2001 From: Zach Leslie Date: Tue, 14 Nov 2017 10:35:24 -0800 Subject: [PATCH 10/80] Add new types and associated functions to manage * TcpProfiles * TcpProfile * UdpProfiles * UdpProfile * HttpProfiles * HttpProfile * OneconnectProfiles * OneconnectProfile * HttpProfiles * HttpProfile --- ltm.go | 474 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 474 insertions(+) diff --git a/ltm.go b/ltm.go index d52dace..41e6a0c 100644 --- a/ltm.go +++ b/ltm.go @@ -130,6 +130,205 @@ type ClientSSLProfile struct { UncleanShutdown string `json:"uncleanShutdown,omitempty"` } +// TcpProfiles contains a list of every tcp profile on the BIG-IP system. +type TcpProfiles struct { + TcpProfiles []TcpProfile `json:"items"` +} + +type TcpProfile struct { + Abc string `json:"abc,omitempty"` + AckOnPush string `json:"ackOnPush,omitempty"` + AppService string `json:"appService,omitempty"` + AutoProxyBufferSize string `json:"autoProxyBufferSize,omitempty"` + AutoReceiveWindowSize string `json:"autoReceiveWindowSize,omitempty"` + AutoSendBufferSize string `json:"autoSendBufferSize,omitempty"` + CloseWaitTimeout int `json:"closeWaitTimeout,omitempty"` + CmetricsCache string `json:"cmetricsCache,omitempty"` + CmetricsCacheTimeout int `json:"cmetricsCacheTimeout,omitempty"` + CongestionControl string `json:"congestionControl,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + DeferredAccept string `json:"deferredAccept,omitempty"` + DelayWindowControl string `json:"delayWindowControl,omitempty"` + DelayedAcks string `json:"delayedAcks,omitempty"` + Description string `json:"description,omitempty"` + Dsack string `json:"dsack,omitempty"` + EarlyRetransmit string `json:"earlyRetransmit,omitempty"` + Ecn string `json:"ecn,omitempty"` + EnhancedLossRecovery string `json:"enhancedLossRecovery,omitempty"` + FastOpen string `json:"fastOpen,omitempty"` + FastOpenCookieExpiration int `json:"fastOpenCookieExpiration,omitempty"` + FinWait_2Timeout int `json:"finWait_2Timeout,omitempty"` + FinWaitTimeout int `json:"finWaitTimeout,omitempty"` + HardwareSynCookie string `json:"hardwareSynCookie,omitempty"` + IdleTimeout int `json:"idleTimeout,omitempty"` + InitCwnd int `json:"initCwnd,omitempty"` + InitRwnd int `json:"initRwnd,omitempty"` + IpDfMode string `json:"ipDfMode,omitempty"` + IpTosToClient string `json:"ipTosToClient,omitempty"` + IpTtlMode string `json:"ipTtlMode,omitempty"` + IpTtlV4 int `json:"ipTtlV4,omitempty"` + IpTtlV6 int `json:"ipTtlV6,omitempty"` + KeepAliveInterval int `json:"keepAliveInterval,omitempty"` + LimitedTransmit string `json:"limitedTransmit,omitempty"` + LinkQosToClient string `json:"linkQosToClient,omitempty"` + MaxRetrans int `json:"maxRetrans,omitempty"` + MaxSegmentSize int `json:"maxSegmentSize,omitempty"` + Md5Signature string `json:"md5Signature,omitempty"` + Md5SignaturePassphrase string `json:"md5SignaturePassphrase,omitempty"` + MinimumRto int `json:"minimumRto,omitempty"` + Mptcp string `json:"mptcp,omitempty"` + MptcpCsum string `json:"mptcpCsum,omitempty"` + MptcpCsumVerify string `json:"mptcpCsumVerify,omitempty"` + MptcpDebug string `json:"mptcpDebug,omitempty"` + MptcpFallback string `json:"mptcpFallback,omitempty"` + MptcpFastjoin string `json:"mptcpFastjoin,omitempty"` + MptcpIdleTimeout int `json:"mptcpIdleTimeout,omitempty"` + MptcpJoinMax int `json:"mptcpJoinMax,omitempty"` + MptcpMakeafterbreak string `json:"mptcpMakeafterbreak,omitempty"` + MptcpNojoindssack string `json:"mptcpNojoindssack,omitempty"` + MptcpRtomax int `json:"mptcpRtomax,omitempty"` + MptcpRxmitmin int `json:"mptcpRxmitmin,omitempty"` + MptcpSubflowmax int `json:"mptcpSubflowmax,omitempty"` + MptcpTimeout int `json:"mptcpTimeout,omitempty"` + Nagle string `json:"nagle,omitempty"` + Name string `json:"name,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + PktLossIgnoreBurst int `json:"pktLossIgnoreBurst,omitempty"` + PktLossIgnoreRate int `json:"pktLossIgnoreRate,omitempty"` + ProxyBufferHigh int `json:"proxyBufferHigh,omitempty"` + ProxyBufferLow int `json:"proxyBufferLow,omitempty"` + ProxyMss string `json:"proxyMss,omitempty"` + ProxyOptions string `json:"proxyOptions,omitempty"` + RatePace string `json:"ratePace,omitempty"` + RatePaceMaxRate int `json:"ratePaceMaxRate,omitempty"` + ReceiveWindowSize int `json:"receiveWindowSize,omitempty"` + ResetOnTimeout string `json:"resetOnTimeout,omitempty"` + RexmtThresh int `json:"rexmtThresh,omitempty"` + SelectiveAcks string `json:"selectiveAcks,omitempty"` + SelectiveNack string `json:"selectiveNack,omitempty"` + SendBufferSize int `json:"sendBufferSize,omitempty"` + SlowStart string `json:"slowStart,omitempty"` + SynCookieEnable string `json:"synCookieEnable,omitempty"` + SynCookieWhitelist string `json:"synCookieWhitelist,omitempty"` + SynMaxRetrans int `json:"synMaxRetrans,omitempty"` + SynRtoBase int `json:"synRtoBase,omitempty"` + TailLossProbe string `json:"tailLossProbe,omitempty"` + TcpOptions string `json:"tcpOptions,omitempty"` + TimeWaitRecycle string `json:"timeWaitRecycle,omitempty"` + TimeWaitTimeout string `json:"timeWaitTimeout,omitempty"` + Timestamps string `json:"timestamps,omitempty"` + VerifiedAccept string `json:"verifiedAccept,omitempty"` +} + +// UdpProfiles contains a list of every tcp profile on the BIG-IP system. +type UdpProfiles struct { + UdpProfiles []UdpProfile `json:"items"` +} + +type UdpProfile struct { + AllowNoPayload string `json:"allowNoPayload,omitempty"` + AppService string `json:"appService,omitempty"` + BufferMaxBytes int `json:"bufferMaxBytes,omitempty"` + BufferMaxPackets int `json:"bufferMaxPackets,omitempty"` + DatagramLoadBalancing string `json:"datagramLoadBalancing,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + IdleTimeout string `json:"idleTimeout,omitempty"` + IpDfMode string `json:"ipDfMode,omitempty"` + IpTosToClient string `json:"ipTosToClient,omitempty"` + IpTtlMode string `json:"ipTtlMode,omitempty"` + IpTtlV4 int `json:"ipTtlV4,omitempty"` + IpTtlV6 int `json:"ipTtlV6,omitempty"` + LinkQosToClient string `json:"linkQosToClient,omitempty"` + Name string `json:"name,omitempty"` + NoChecksum string `json:"noChecksum,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + ProxyMss string `json:"proxyMss,omitempty"` +} + +type HttpProfiles struct { + HttpProfiles []HttpProfile `json:"items"` +} + +type HttpProfile struct { + AcceptXff string `json:"acceptXff,omitempty"` + AppService string `json:"appService,omitempty"` + BasicAuthRealm string `json:"basicAuthRealm,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + EncryptCookieSecret string `json:"encryptCookieSecret,omitempty"` + EncryptCookies string `json:"encryptCookies,omitempty"` + FallbackHost string `json:"fallbackHost,omitempty"` + FallbackStatusCodes string `json:"fallbackStatusCodes,omitempty"` + HeaderErase string `json:"headerErase,omitempty"` + HeaderInsert string `json:"headerInsert,omitempty"` + InsertXforwardedFor string `json:"insertXforwardedFor,omitempty"` + LwsSeparator string `json:"lwsSeparator,omitempty"` + LwsWidth int `json:"lwsWidth,omitempty"` + Name string `json:"name,omitempty"` + OneconnectTransformations string `json:"oneconnectTransformations,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + ProxyType string `json:"proxyType,omitempty"` + RedirectRewrite string `json:"redirectRewrite,omitempty"` + RequestChunking string `json:"requestChunking,omitempty"` + ResponseChunking string `json:"responseChunking,omitempty"` + ResponseHeadersPermitted string `json:"responseHeadersPermitted,omitempty"` + ServerAgentName string `json:"serverAgentName,omitempty"` + ViaHostName string `json:"viaHostName,omitempty"` + ViaRequest string `json:"viaRequest,omitempty"` + ViaResponse string `json:"viaResponse,omitempty"` + XffAlternativeNames string `json:"xffAlternativeNames,omitempty"` +} + +type OneconnectProfiles struct { + OneconnectProfiles []OneconnectProfile `json:"items"` +} + +type OneconnectProfile struct { + AppService string `json:"appService,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + IdleTimeoutOverride string `json:"idleTimeoutOverride,omitempty"` + LimitType string `json:"limitType,omitempty"` + MaxAge int `json:"maxAge,omitempty"` + MaxReuse int `json:"maxReuse,omitempty"` + MaxSize int `json:"maxSize,omitempty"` + Name string `json:"name,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + SharePools string `json:"sharePools,omitempty"` + SourceMask string `json:"sourceMask,omitempty"` +} + +type HttpCompressionProfiles struct { + HttpCompressionProfiles []HttpCompressionProfile `json:"items"` +} + +type HttpCompressionProfile struct { + AllowHttp_10 string `json:"allowHttp_10,omitempty"` + AppService string `json:"appService,omitempty"` + BrowserWorkarounds string `json:"browserWorkarounds,omitempty"` + BufferSize int `json:"bufferSize,omitempty"` + ContentTypeExclude []string `json:"contentTypeExclude,omitempty"` + ContentTypeInclude []string `json:"contentTypeInclude,omitempty"` + CpuSaver string `json:"cpuSaver,omitempty"` + CpuSaverHigh int `json:"cpuSaverHigh,omitempty"` + CpuSaverLow int `json:"cpuSaverLow,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + GzipLevel int `json:"gzipLevel,omitempty"` + GzipMemoryLevel int `json:"gzipMemoryLevel,omitempty"` + GzipWindowSize int `json:"gzipWindowSize,omitempty"` + KeepAcceptEncoding string `json:"keepAcceptEncoding,omitempty"` + MethodPrefer string `json:"methodPrefer,omitempty"` + MinSize int `json:"minSize,omitempty"` + Name string `json:"name,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + Selective string `json:"selective,omitempty"` + UriExclude []string `json:"uriExclude,omitempty"` + UriInclude []string `json:"uriInclude,omitempty"` + VaryHeader string `json:"varyHeader,omitempty"` +} + // Nodes contains a list of every node on the BIG-IP system. type Nodes struct { Nodes []Node `json:"items"` @@ -1459,6 +1658,256 @@ func (b *BigIP) ModifyClientSSLProfile(name string, config *ClientSSLProfile) er return b.put(config, uriLtm, uriProfile, uriClientSSL, name) } +// TcpProfiles returns a list of Tcp profiles +func (b *BigIP) TcpProfiles() (*TcpProfiles, error) { + var tcpProfiles TcpProfiles + err, _ := b.getForEntity(&tcpProfiles, uriLtm, uriProfile, uriTcp) + if err != nil { + return nil, err + } + + return &tcpProfiles, nil +} + +func (b *BigIP) GetTcpProfile(name string) (*TcpProfile, error) { + var tcpProfile TcpProfile + err, ok := b.getForEntity(&tcpProfile, uriLtm, uriProfile, uriTcp, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &tcpProfile, nil +} + +// CreateTcpProfile creates a new tcp profile on the BIG-IP system. +func (b *BigIP) CreateTcpProfile(name string, parent string) error { + config := &TcpProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriProfile, uriTcp) +} + +func (b *BigIP) AddTcpProfile(config *TcpProfile) error { + return b.post(config, uriLtm, uriProfile, uriTcp) +} + +// DeleteTcpProfile removes a tcp profile. +func (b *BigIP) DeleteTcpProfile(name string) error { + return b.delete(uriLtm, uriProfile, uriTcp, name) +} + +// ModifyTcpProfile allows you to change any attribute of a tcp profile. +// Fields that can be modified are referenced in the TcpProfile struct. +func (b *BigIP) ModifyTcpProfile(name string, config *TcpProfile) error { + return b.put(config, uriLtm, uriProfile, uriTcp, name) +} + +// UdpProfiles returns a list of Udp profiles +func (b *BigIP) UdpProfiles() (*UdpProfiles, error) { + var udpProfiles UdpProfiles + err, _ := b.getForEntity(&udpProfiles, uriLtm, uriProfile, uriUdp) + if err != nil { + return nil, err + } + + return &udpProfiles, nil +} + +func (b *BigIP) GetUdpProfile(name string) (*UdpProfile, error) { + var udpProfile UdpProfile + err, ok := b.getForEntity(&udpProfile, uriLtm, uriProfile, uriUdp, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &udpProfile, nil +} + +// CreateUdpProfile creates a new udp profile on the BIG-IP system. +func (b *BigIP) CreateUdpProfile(name string, parent string) error { + config := &UdpProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriProfile, uriUdp) +} + +func (b *BigIP) AddUdpProfile(config *UdpProfile) error { + return b.post(config, uriLtm, uriProfile, uriUdp) +} + +// DeleteUdpProfile removes a udp profile. +func (b *BigIP) DeleteUdpProfile(name string) error { + return b.delete(uriLtm, uriProfile, uriUdp, name) +} + +// ModifyUdpProfile allows you to change any attribute of a udp profile. +// Fields that can be modified are referenced in the UdpProfile struct. +func (b *BigIP) ModifyUdpProfile(name string, config *UdpProfile) error { + return b.put(config, uriLtm, uriProfile, uriUdp, name) +} + +// HttpProfiles returns a list of HTTP profiles +func (b *BigIP) HttpProfiles() (*HttpProfiles, error) { + var httpProfiles HttpProfiles + err, _ := b.getForEntity(&httpProfiles, uriLtm, uriProfile, uriHttp) + if err != nil { + return nil, err + } + + return &httpProfiles, nil +} + +func (b *BigIP) GetHttpProfile(name string) (*HttpProfile, error) { + var httpProfile HttpProfile + err, ok := b.getForEntity(&httpProfile, uriLtm, uriProfile, uriHttp, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &httpProfile, nil +} + +// CreateHttpProfile creates a new http profile on the BIG-IP system. +func (b *BigIP) CreateHttpProfile(name string, parent string) error { + config := &HttpProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriProfile, uriHttp) +} + +func (b *BigIP) AddHttpProfile(config *HttpProfile) error { + return b.post(config, uriLtm, uriProfile, uriHttp) +} + +// DeleteHttpProfile removes a http profile. +func (b *BigIP) DeleteHttpProfile(name string) error { + return b.delete(uriLtm, uriProfile, uriHttp, name) +} + +// ModifyHttpProfile allows you to change any attribute of a http profile. +// Fields that can be modified are referenced in the HttpProfile struct. +func (b *BigIP) ModifyHttpProfile(name string, config *HttpProfile) error { + return b.put(config, uriLtm, uriProfile, uriHttp, name) +} + +// OneconnectProfiles returns a list of HTTP profiles +func (b *BigIP) OneconnectProfiles() (*OneconnectProfiles, error) { + var oneconnectProfiles OneconnectProfiles + err, _ := b.getForEntity(&oneconnectProfiles, uriLtm, uriProfile, uriOneConnect) + if err != nil { + return nil, err + } + + return &oneconnectProfiles, nil +} + +func (b *BigIP) GetOneconnectProfile(name string) (*OneconnectProfile, error) { + var oneconnectProfile OneconnectProfile + err, ok := b.getForEntity(&oneconnectProfile, uriLtm, uriProfile, uriOneConnect, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &oneconnectProfile, nil +} + +// CreateOneconnectProfile creates a new http profile on the BIG-IP system. +func (b *BigIP) CreateOneconnectProfile(name string, parent string) error { + config := &OneconnectProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriProfile, uriOneConnect) +} + +func (b *BigIP) AddOneconnectProfile(config *OneconnectProfile) error { + return b.post(config, uriLtm, uriProfile, uriOneConnect) +} + +// DeleteOneconnectProfile removes a http profile. +func (b *BigIP) DeleteOneconnectProfile(name string) error { + return b.delete(uriLtm, uriProfile, uriOneConnect, name) +} + +// ModifyOneconnectProfile allows you to change any attribute of a http profile. +// Fields that can be modified are referenced in the OneconnectProfile struct. +func (b *BigIP) ModifyOneconnectProfile(name string, config *OneconnectProfile) error { + return b.put(config, uriLtm, uriProfile, uriOneConnect, name) +} + +// HttpCompressionProfiles returns a list of HTTP profiles +func (b *BigIP) HttpCompressionProfiles() (*HttpCompressionProfiles, error) { + var httpCompressionProfiles HttpCompressionProfiles + err, _ := b.getForEntity(&httpCompressionProfiles, uriLtm, uriProfile, uriHttpCompression) + if err != nil { + return nil, err + } + + return &httpCompressionProfiles, nil +} + +func (b *BigIP) GetHttpCompressionProfile(name string) (*HttpCompressionProfile, error) { + var httpCompressionProfile HttpCompressionProfile + err, ok := b.getForEntity(&httpCompressionProfile, uriLtm, uriProfile, uriHttpCompression, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &httpCompressionProfile, nil +} + +// CreateHttpCompressionProfile creates a new http profile on the BIG-IP system. +func (b *BigIP) CreateHttpCompressionProfile(name string, parent string) error { + config := &HttpCompressionProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriProfile, uriHttpCompression) +} + +func (b *BigIP) AddHttpCompressionProfile(config *HttpCompressionProfile) error { + return b.post(config, uriLtm, uriProfile, uriHttpCompression) +} + +// DeleteHttpCompressionProfile removes a http profile. +func (b *BigIP) DeleteHttpCompressionProfile(name string) error { + return b.delete(uriLtm, uriProfile, uriHttpCompression, name) +} + +// ModifyHttpCompressionProfile allows you to change any attribute of a http profile. +// Fields that can be modified are referenced in the HttpCompressionProfile struct. +func (b *BigIP) ModifyHttpCompressionProfile(name string, config *HttpCompressionProfile) error { + return b.put(config, uriLtm, uriProfile, uriHttpCompression, name) +} + // Nodes returns a list of nodes. func (b *BigIP) Nodes() (*Nodes, error) { var nodes Nodes @@ -1536,6 +1985,31 @@ func (b *BigIP) InternalDataGroups() (*DataGroups, error) { return &dataGroups, nil } +func (b *BigIP) GetInternalDataGroup(name string) (*DataGroup, error) { + var dataGroup DataGroup + err, ok := b.getForEntity(&dataGroup, uriLtm, uriDatagroup, uriInternal, name) + + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &dataGroup, nil +} + +// Create an internal data group; dataype must bee one of "ip", "string", or "integer" +func (b *BigIP) CreateInternalDataGroup(name string, datatype string) error { + config := &DataGroup{ + Name: name, + Type: datatype, + } + + return b.post(config, uriLtm, uriDatagroup, uriInternal) +} + func (b *BigIP) AddInternalDataGroup(config *DataGroup) error { return b.post(config, uriLtm, uriDatagroup, uriInternal) } From 96d2949a800e386b4782ec5f73a1997083277bc2 Mon Sep 17 00:00:00 2001 From: Zach Leslie Date: Tue, 14 Nov 2017 10:40:46 -0800 Subject: [PATCH 11/80] Improve monitor management using monitorType Fixes #39 The management of monitors used a limited set of parent monitors, which in inaccurately restricts which parents are able to be used. Here we adjust that notion by adding a new monitorType field that is not included in the json, but used during the calls to create a monitor. --- ltm.go | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/ltm.go b/ltm.go index 41e6a0c..48643c8 100644 --- a/ltm.go +++ b/ltm.go @@ -970,6 +970,7 @@ type Monitor struct { Interval int IPDSCP int ManualResume bool + MonitorType string Password string ReceiveString string ReceiveDisable string @@ -993,6 +994,7 @@ type monitorDTO struct { Interval int `json:"interval,omitempty"` IPDSCP int `json:"ipDscp,omitempty"` ManualResume string `json:"manualResume,omitempty" bool:"enabled"` + MonitorType string Password string `json:"password,omitempty"` ReceiveString string `json:"recv,omitempty"` ReceiveDisable string `json:"recvDisable,omitempty"` @@ -2317,10 +2319,20 @@ func (b *BigIP) DeleteVirtualAddress(vaddr string) error { return b.delete(uriLtm, uriVirtualAddress, vaddr) } -// Monitors returns a list of all HTTP, HTTPS, Gateway ICMP, ICMP, and TCP monitors. +// Monitors returns a list of all HTTP, HTTPS, Gateway ICMP, ICMP, and Tcp monitors. func (b *BigIP) Monitors() ([]Monitor, error) { var monitors []Monitor - monitorUris := []string{"http", "https", "icmp", "gateway-icmp", "tcp"} + monitorUris := []string{ + "gateway-icmp", + "http", + "https", + "icmp", + "inband", + "mysql", + "postgresql", + "tcp", + "udp", + } for _, name := range monitorUris { var m Monitors @@ -2329,6 +2341,7 @@ func (b *BigIP) Monitors() ([]Monitor, error) { return nil, err } for _, monitor := range m.Monitors { + monitor.MonitorType = name monitors = append(monitors, monitor) } } @@ -2336,9 +2349,9 @@ func (b *BigIP) Monitors() ([]Monitor, error) { return monitors, nil } -// CreateMonitor adds a new monitor to the BIG-IP system. must be one of "http", "https", -// "icmp", "gateway icmp", or "tcp". -func (b *BigIP) CreateMonitor(name, parent string, interval, timeout int, send, receive string) error { +// CreateMonitor adds a new monitor to the BIG-IP system. must be one of "http", "https", +// "icmp", "gateway icmp", "inband", "postgresql", "mysql", "udp" or "tcp". +func (b *BigIP) CreateMonitor(name, parent string, interval, timeout int, send, receive, monitorType string) error { config := &Monitor{ Name: name, ParentMonitor: parent, @@ -2348,16 +2361,16 @@ func (b *BigIP) CreateMonitor(name, parent string, interval, timeout int, send, ReceiveString: receive, } - return b.AddMonitor(config) + return b.AddMonitor(config, monitorType) } // Create a monitor by supplying a config -func (b *BigIP) AddMonitor(config *Monitor) error { +func (b *BigIP) AddMonitor(config *Monitor, monitorType string) error { if strings.Contains(config.ParentMonitor, "gateway") { config.ParentMonitor = "gateway_icmp" } - return b.post(config, uriLtm, uriMonitor, config.ParentMonitor) + return b.post(config, uriLtm, uriMonitor, monitorType) } // GetVirtualServer retrieves a monitor by name. Returns nil if the monitor does not exist @@ -2380,15 +2393,15 @@ func (b *BigIP) DeleteMonitor(name, parent string) error { return b.delete(uriLtm, uriMonitor, parent, name) } -// ModifyMonitor allows you to change any attribute of a monitor. must be -// one of "http", "https", "icmp", "gateway icmp", or "tcp". Fields that -// can be modified are referenced in the Monitor struct. -func (b *BigIP) ModifyMonitor(name, parent string, config *Monitor) error { +// ModifyMonitor allows you to change any attribute of a monitor. must +// be one of "http", "https", "icmp", "inband", "gateway icmp", "postgresql", "mysql", "udp" or "tcp". +// Fields that can be modified are referenced in the Monitor struct. +func (b *BigIP) ModifyMonitor(name, monitorType string, config *Monitor) error { if strings.Contains(config.ParentMonitor, "gateway") { config.ParentMonitor = "gateway_icmp" } - return b.put(config, uriLtm, uriMonitor, parent, name) + return b.put(config, uriLtm, uriMonitor, monitorType, name) } // AddMonitorToPool assigns the monitor, to the given . From ea7ea2a2cff55584251dd7964dc8c11c54e5be91 Mon Sep 17 00:00:00 2001 From: Zach Leslie Date: Tue, 14 Nov 2017 10:43:36 -0800 Subject: [PATCH 12/80] Add description field for VirtualServer struct --- ltm.go | 1 + 1 file changed, 1 insertion(+) diff --git a/ltm.go b/ltm.go index 48643c8..c96831b 100644 --- a/ltm.go +++ b/ltm.go @@ -537,6 +537,7 @@ type VirtualServer struct { CMPEnabled string `json:"cmpEnabled,omitempty"` ConnectionLimit int `json:"connectionLimit,omitempty"` Destination string `json:"destination,omitempty"` + Description string `json:"description,omitempty"` Enabled bool `json:"enabled,omitempty"` GTMScore int `json:"gtmScore,omitempty"` IPProtocol string `json:"ipProtocol,omitempty"` From 442e23d63f5140f3563ecae6a4ea17772785df57 Mon Sep 17 00:00:00 2001 From: Zach Leslie Date: Tue, 14 Nov 2017 11:35:17 -0800 Subject: [PATCH 13/80] Update test for CreateMonitor call --- examples/go-bigip_example.go | 2 +- ltm_test.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/go-bigip_example.go b/examples/go-bigip_example.go index 0f497cd..9b2411e 100644 --- a/examples/go-bigip_example.go +++ b/examples/go-bigip_example.go @@ -45,7 +45,7 @@ func main() { f5.AddPoolMember("ssl_443_pool", "ssl-web-server-2:443") // Create a monitor, and assign it to a pool. - f5.CreateMonitor("web_http_monitor", "http", 5, 16, "GET /\r\n", "200 OK") + f5.CreateMonitor("web_http_monitor", "http", 5, 16, "GET /\r\n", "200 OK", "http") f5.AddMonitorToPool("web_http_monitor", "web_farm_80_pool") // Create a virtual server, with the above pool. The third field is the subnet diff --git a/ltm_test.go b/ltm_test.go index b70ed75..208ad9f 100644 --- a/ltm_test.go +++ b/ltm_test.go @@ -792,7 +792,7 @@ func (s *LTMTestSuite) TestCreateMonitor() { ReceiveString: "200 OK", } - s.Client.CreateMonitor(config.Name, config.ParentMonitor, config.Interval, config.Timeout, config.SendString, config.ReceiveString) + s.Client.CreateMonitor(config.Name, config.ParentMonitor, config.Interval, config.Timeout, config.SendString, config.ReceiveString, "http") assert.Equal(s.T(), "POST", s.LastRequest.Method) assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriMonitor, config.ParentMonitor), s.LastRequest.URL.Path) @@ -809,7 +809,7 @@ func (s *LTMTestSuite) TestCreateMonitorSpecialCharacters() { ReceiveString: "Response &<>", } - s.Client.CreateMonitor(config.Name, config.ParentMonitor, config.Interval, config.Timeout, config.SendString, config.ReceiveString) + s.Client.CreateMonitor(config.Name, config.ParentMonitor, config.Interval, config.Timeout, config.SendString, config.ReceiveString, "http") assert.Equal(s.T(), "POST", s.LastRequest.Method) assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriMonitor, config.ParentMonitor), s.LastRequest.URL.Path) @@ -828,7 +828,7 @@ func (s *LTMTestSuite) TestAddMonitor() { Password: "monitoring", } - s.Client.AddMonitor(config) + s.Client.AddMonitor(config, "http") assert.Equal(s.T(), "POST", s.LastRequest.Method) assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriMonitor, config.ParentMonitor), s.LastRequest.URL.Path) From e5c0cbe8a901b205d5a6ca985db37a38d7e853f6 Mon Sep 17 00:00:00 2001 From: Zach Leslie Date: Fri, 1 Dec 2017 11:26:34 -0800 Subject: [PATCH 14/80] Add database monitor fields --- ltm.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ltm.go b/ltm.go index c96831b..dd31491 100644 --- a/ltm.go +++ b/ltm.go @@ -966,6 +966,7 @@ type Monitor struct { FullPath string Generation int ParentMonitor string + Database string Description string Destination string Interval int @@ -973,6 +974,8 @@ type Monitor struct { ManualResume bool MonitorType string Password string + ReceiveColumn string + ReceiveRow string ReceiveString string ReceiveDisable string Reverse bool @@ -990,6 +993,7 @@ type monitorDTO struct { FullPath string `json:"fullPath,omitempty"` Generation int `json:"generation,omitempty"` ParentMonitor string `json:"defaultsFrom,omitempty"` + Database string `json:"database,omitempty"` Description string `json:"description,omitempty"` Destination string `json:"destination,omitempty"` Interval int `json:"interval,omitempty"` @@ -997,6 +1001,8 @@ type monitorDTO struct { ManualResume string `json:"manualResume,omitempty" bool:"enabled"` MonitorType string Password string `json:"password,omitempty"` + ReceiveColumn string `json:"recvColumn,omitempty"` + ReceiveRow string `json:"recvRow,omitempty"` ReceiveString string `json:"recv,omitempty"` ReceiveDisable string `json:"recvDisable,omitempty"` Reverse string `json:"reverse,omitempty" bool:"enabled"` From 65c636362afc0c3bc6983cc65fcf82d75193587e Mon Sep 17 00:00:00 2001 From: Zach Leslie Date: Thu, 14 Dec 2017 15:47:51 -0800 Subject: [PATCH 15/80] Passing tests --- ltm.go | 49 +++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/ltm.go b/ltm.go index dd31491..f0ad5c9 100644 --- a/ltm.go +++ b/ltm.go @@ -988,18 +988,18 @@ type Monitor struct { } type monitorDTO struct { - Name string `json:"name,omitempty"` - Partition string `json:"partition,omitempty"` - FullPath string `json:"fullPath,omitempty"` - Generation int `json:"generation,omitempty"` - ParentMonitor string `json:"defaultsFrom,omitempty"` - Database string `json:"database,omitempty"` - Description string `json:"description,omitempty"` - Destination string `json:"destination,omitempty"` - Interval int `json:"interval,omitempty"` - IPDSCP int `json:"ipDscp,omitempty"` - ManualResume string `json:"manualResume,omitempty" bool:"enabled"` - MonitorType string + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` + Generation int `json:"generation,omitempty"` + ParentMonitor string `json:"defaultsFrom,omitempty"` + Database string `json:"database,omitempty"` + Description string `json:"description,omitempty"` + Destination string `json:"destination,omitempty"` + Interval int `json:"interval,omitempty"` + IPDSCP int `json:"ipDscp,omitempty"` + ManualResume string `json:"manualResume,omitempty" bool:"enabled"` + // MonitorType string `json:"monitorType,omitempty"` Password string `json:"password,omitempty"` ReceiveColumn string `json:"recvColumn,omitempty"` ReceiveRow string `json:"recvRow,omitempty"` @@ -1475,6 +1475,7 @@ const ( uriHttp2 = "http2" uriSnat = "snat" uriSnatpool = "snatpool" + uriUdp = "udp" ) var cidr = map[string]string{ @@ -1820,7 +1821,7 @@ func (b *BigIP) ModifyHttpProfile(name string, config *HttpProfile) error { // OneconnectProfiles returns a list of HTTP profiles func (b *BigIP) OneconnectProfiles() (*OneconnectProfiles, error) { var oneconnectProfiles OneconnectProfiles - err, _ := b.getForEntity(&oneconnectProfiles, uriLtm, uriProfile, uriOneConnect) + err, _ := b.getForEntity(&oneconnectProfiles, uriLtm, uriProfile, uriOneconnect) if err != nil { return nil, err } @@ -1830,7 +1831,7 @@ func (b *BigIP) OneconnectProfiles() (*OneconnectProfiles, error) { func (b *BigIP) GetOneconnectProfile(name string) (*OneconnectProfile, error) { var oneconnectProfile OneconnectProfile - err, ok := b.getForEntity(&oneconnectProfile, uriLtm, uriProfile, uriOneConnect, name) + err, ok := b.getForEntity(&oneconnectProfile, uriLtm, uriProfile, uriOneconnect, name) if err != nil { return nil, err } @@ -1849,28 +1850,28 @@ func (b *BigIP) CreateOneconnectProfile(name string, parent string) error { DefaultsFrom: parent, } - return b.post(config, uriLtm, uriProfile, uriOneConnect) + return b.post(config, uriLtm, uriProfile, uriOneconnect) } func (b *BigIP) AddOneconnectProfile(config *OneconnectProfile) error { - return b.post(config, uriLtm, uriProfile, uriOneConnect) + return b.post(config, uriLtm, uriProfile, uriOneconnect) } // DeleteOneconnectProfile removes a http profile. func (b *BigIP) DeleteOneconnectProfile(name string) error { - return b.delete(uriLtm, uriProfile, uriOneConnect, name) + return b.delete(uriLtm, uriProfile, uriOneconnect, name) } // ModifyOneconnectProfile allows you to change any attribute of a http profile. // Fields that can be modified are referenced in the OneconnectProfile struct. func (b *BigIP) ModifyOneconnectProfile(name string, config *OneconnectProfile) error { - return b.put(config, uriLtm, uriProfile, uriOneConnect, name) + return b.put(config, uriLtm, uriProfile, uriOneconnect, name) } // HttpCompressionProfiles returns a list of HTTP profiles func (b *BigIP) HttpCompressionProfiles() (*HttpCompressionProfiles, error) { var httpCompressionProfiles HttpCompressionProfiles - err, _ := b.getForEntity(&httpCompressionProfiles, uriLtm, uriProfile, uriHttpCompression) + err, _ := b.getForEntity(&httpCompressionProfiles, uriLtm, uriProfile, uriHttpcompress) if err != nil { return nil, err } @@ -1880,7 +1881,7 @@ func (b *BigIP) HttpCompressionProfiles() (*HttpCompressionProfiles, error) { func (b *BigIP) GetHttpCompressionProfile(name string) (*HttpCompressionProfile, error) { var httpCompressionProfile HttpCompressionProfile - err, ok := b.getForEntity(&httpCompressionProfile, uriLtm, uriProfile, uriHttpCompression, name) + err, ok := b.getForEntity(&httpCompressionProfile, uriLtm, uriProfile, uriHttpcompress, name) if err != nil { return nil, err } @@ -1899,22 +1900,22 @@ func (b *BigIP) CreateHttpCompressionProfile(name string, parent string) error { DefaultsFrom: parent, } - return b.post(config, uriLtm, uriProfile, uriHttpCompression) + return b.post(config, uriLtm, uriProfile, uriHttpcompress) } func (b *BigIP) AddHttpCompressionProfile(config *HttpCompressionProfile) error { - return b.post(config, uriLtm, uriProfile, uriHttpCompression) + return b.post(config, uriLtm, uriProfile, uriHttpcompress) } // DeleteHttpCompressionProfile removes a http profile. func (b *BigIP) DeleteHttpCompressionProfile(name string) error { - return b.delete(uriLtm, uriProfile, uriHttpCompression, name) + return b.delete(uriLtm, uriProfile, uriHttpcompress, name) } // ModifyHttpCompressionProfile allows you to change any attribute of a http profile. // Fields that can be modified are referenced in the HttpCompressionProfile struct. func (b *BigIP) ModifyHttpCompressionProfile(name string, config *HttpCompressionProfile) error { - return b.put(config, uriLtm, uriProfile, uriHttpCompression, name) + return b.put(config, uriLtm, uriProfile, uriHttpcompress, name) } // Nodes returns a list of nodes. From 034b9e512ff2e3a0f30a9bc11c54d2a9bb137fd4 Mon Sep 17 00:00:00 2001 From: John Anderson Date: Fri, 9 Feb 2018 15:34:46 -0500 Subject: [PATCH 16/80] added support for persistence profiles and their use in virtual servers --- ltm.go | 689 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 654 insertions(+), 35 deletions(-) diff --git a/ltm.go b/ltm.go index f0ad5c9..d252064 100644 --- a/ltm.go +++ b/ltm.go @@ -329,6 +329,145 @@ type HttpCompressionProfile struct { VaryHeader string `json:"varyHeader,omitempty"` } +// PersistenceProfiles contains of list of persistence profiles +type PersistenceProfiles struct { + PersistenceProfiles []PersistenceProfile `json:"items"` +} + +// PersistenceProfile is a base for all persistence profiles +type PersistenceProfile struct { + AppService string `json:"appService,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + FullPath string `json:"fullPath,omitempty"` + MatchAcrossPools string `json:"matchAcrossPools,omitempty"` + MatchAcrossServices string `json:"matchAcrossServices,omitempty"` + MatchAcrossVirtuals string `json:"matchAcrossVirtuals,omitempty"` + Method string `json:"method,omitempty"` + Mirror string `json:"mirror,omitempty"` + Mode string `json:"mode,omitempty"` + Name string `json:"name,omitempty"` + OverrideConnectionLimit string `json:"overrideConnectionLimit,omitempty"` + Partition string `json:"partition,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + Timeout string `json:"timeout,omitempty"` +} + +// CookiePersistenceProfiles contains a list of all cookies profiles +type CookiePersistenceProfiles struct { + CookiePersistenceProfiles []CookiePersistenceProfile `json:"items"` +} + +// CookiePersistenceProfile Defines a single cookie profile +type CookiePersistenceProfile struct { + PersistenceProfile + AlwaysSend string `json:"alwaysSend,omitempty"` + CookieEncryption string `json:"cookieEncryption,omitempty"` + CookieEncryptionPassphrase string `json:"cookieEncryptionPassphrase,omitempty"` + CookieName string `json:"cookieName,omitempty"` + Expiration string `json:"expiration,omitempty"` + HashLength int `json:"hashLength,omitempty"` + HashOffset int `json:"hashOffset,omitempty"` + HTTPOnly string `json:"httponly,omitempty"` + Secure string `json:"secure,omitempty"` +} + +// DestAddrPersistenceProfiles contains a list of all dest-addr profiles +type DestAddrPersistenceProfiles struct { + DestAddrPersistenceProfiles []DestAddrPersistenceProfile `json:"items"` +} + +// DestAddrPersistenceProfile Defines a single dest-addr profile +type DestAddrPersistenceProfile struct { + PersistenceProfile + HashAlgorithm string `json:"hashAlgorithm,omitempty"` + Mask string `json:"mask,omitempty"` +} + +// HashPersistenceProfiles contains a list of all hash profiles +type HashPersistenceProfiles struct { + HashPersistenceProfiles []HashPersistenceProfile `json:"items"` +} + +// HashPersistenceProfile Defines a single hash profile +type HashPersistenceProfile struct { + PersistenceProfile + HashAlgorithm string `json:"hashAlgorithm,omitempty"` + HashBufferLimit int `json:"hashBufferLimit,omitempty"` + HashEndPattern int `json:"hashEndPattern,omitempty"` + HashLength int `json:"hashLength,omitempty"` + HashOffset int `json:"hashOffset,omitempty"` + HashStartPattern int `json:"hashStartPattern,omitempty"` +} + +// HostPersistenceProfiles contains a list of all host profiles +type HostPersistenceProfiles struct { + HostPersistenceProfiles []HostPersistenceProfile `json:"items"` +} + +// HostPersistenceProfile Defines a single host profile +type HostPersistenceProfile struct { + PersistenceProfile +} + +// MSRDPPersistenceProfiles contains a list of all msrdp profiles +type MSRDPPersistenceProfiles struct { + MSRDPPersistenceProfiles []MSRDPPersistenceProfile `json:"items"` +} + +// MSRDPPersistenceProfile Defines a single msrdp profile +type MSRDPPersistenceProfile struct { + PersistenceProfile + HasSessionDir string `json:"hasSessionDir,omitempty"` +} + +// SIPPersistenceProfiles contains a list of all sip profiles +type SIPPersistenceProfiles struct { + SIPPersistenceProfiles []SIPPersistenceProfile `json:"items"` +} + +// SIPPersistenceProfile Defines a single sip profile +type SIPPersistenceProfile struct { + PersistenceProfile + SIPInfo string `json:"sipInfo,omitempty"` +} + +// SourceAddrPersistenceProfiles contains a list of all source-addr profiles +type SourceAddrPersistenceProfiles struct { + SourceAddrPersistenceProfiles []SourceAddrPersistenceProfile `json:"items"` +} + +// SourceAddrPersistenceProfile Defines a single source-addr profile +type SourceAddrPersistenceProfile struct { + PersistenceProfile + HashAlgorithm string `json:"hashAlgorithm,omitempty"` + MapProxies string `json:"mapProxies,omitempty"` + MapProxyAddress string `json:"mapProxyAddress,omitempty"` + MapProxyClass string `json:"mapProxyClass,omitempty"` + Mask string `json:"mask,omitempty"` +} + +// SSLPersistenceProfiles contains a list of all ssl profiles +type SSLPersistenceProfiles struct { + SSLPersistenceProfiles []SSLPersistenceProfile `json:"items"` +} + +// SSLPersistenceProfile Defines a single ssl profile +type SSLPersistenceProfile struct { + PersistenceProfile +} + +// UniversalPersistenceProfiles contains a list of all universal profiles +type UniversalPersistenceProfiles struct { + SSLPersistenceProfiles []UniversalPersistenceProfile `json:"items"` +} + +// UniversalPersistenceProfile Defines a single universal profile +type UniversalPersistenceProfile struct { + PersistenceProfile + Rule string `json:"rule,omitempty"` +} + // Nodes contains a list of every node on the BIG-IP system. type Nodes struct { Nodes []Node `json:"items"` @@ -528,44 +667,46 @@ type VirtualServers struct { // VirtualServer contains information about each individual virtual server. type VirtualServer struct { - Name string `json:"name,omitempty"` - Partition string `json:"partition,omitempty"` - FullPath string `json:"fullPath,omitempty"` - Generation int `json:"generation,omitempty"` - AddressStatus string `json:"addressStatus,omitempty"` - AutoLastHop string `json:"autoLastHop,omitempty"` - CMPEnabled string `json:"cmpEnabled,omitempty"` - ConnectionLimit int `json:"connectionLimit,omitempty"` - Destination string `json:"destination,omitempty"` - Description string `json:"description,omitempty"` - Enabled bool `json:"enabled,omitempty"` - GTMScore int `json:"gtmScore,omitempty"` - IPProtocol string `json:"ipProtocol,omitempty"` - Mask string `json:"mask,omitempty"` - Mirror string `json:"mirror,omitempty"` - MobileAppTunnel string `json:"mobileAppTunnel,omitempty"` - NAT64 string `json:"nat64,omitempty"` - Pool string `json:"pool,omitempty"` - RateLimit string `json:"rateLimit,omitempty"` - RateLimitDestinationMask int `json:"rateLimitDstMask,omitempty"` - RateLimitMode string `json:"rateLimitMode,omitempty"` - RateLimitSourceMask int `json:"rateLimitSrcMask,omitempty"` - Source string `json:"source,omitempty"` - SourceAddressTranslation struct { + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` + Generation int `json:"generation,omitempty"` + AddressStatus string `json:"addressStatus,omitempty"` + AutoLastHop string `json:"autoLastHop,omitempty"` + CMPEnabled string `json:"cmpEnabled,omitempty"` + ConnectionLimit int `json:"connectionLimit,omitempty"` + Destination string `json:"destination,omitempty"` + Description string `json:"description,omitempty"` + Enabled bool `json:"enabled,omitempty"` + FallbackPersistenceProfile string `json:"fallbackPersistence,omitempty"` + GTMScore int `json:"gtmScore,omitempty"` + IPProtocol string `json:"ipProtocol,omitempty"` + Mask string `json:"mask,omitempty"` + Mirror string `json:"mirror,omitempty"` + MobileAppTunnel string `json:"mobileAppTunnel,omitempty"` + NAT64 string `json:"nat64,omitempty"` + Pool string `json:"pool,omitempty"` + RateLimit string `json:"rateLimit,omitempty"` + RateLimitDestinationMask int `json:"rateLimitDstMask,omitempty"` + RateLimitMode string `json:"rateLimitMode,omitempty"` + RateLimitSourceMask int `json:"rateLimitSrcMask,omitempty"` + Source string `json:"source,omitempty"` + SourceAddressTranslation struct { Type string `json:"type,omitempty"` Pool string `json:"pool,omitempty"` } `json:"sourceAddressTranslation,omitempty"` - SourcePort string `json:"sourcePort,omitempty"` - SYNCookieStatus string `json:"synCookieStatus,omitempty"` - TranslateAddress string `json:"translateAddress,omitempty"` - TranslatePort string `json:"translatePort,omitempty"` - VlansEnabled bool `json:"vlansEnabled,omitempty"` - VlansDisabled bool `json:"vlansDisabled,omitempty"` - VSIndex int `json:"vsIndex,omitempty"` - Vlans []string `json:"vlans,omitempty"` - Rules []string `json:"rules,omitempty"` - Profiles []Profile `json:"profiles,omitempty"` - Policies []string `json:"policies,omitempty"` + SourcePort string `json:"sourcePort,omitempty"` + SYNCookieStatus string `json:"synCookieStatus,omitempty"` + TranslateAddress string `json:"translateAddress,omitempty"` + TranslatePort string `json:"translatePort,omitempty"` + VlansEnabled bool `json:"vlansEnabled,omitempty"` + VlansDisabled bool `json:"vlansDisabled,omitempty"` + VSIndex int `json:"vsIndex,omitempty"` + Vlans []string `json:"vlans,omitempty"` + Rules []string `json:"rules,omitempty"` + PersistenceProfiles []Profile `json:"persist,omitempty"` + Profiles []Profile `json:"profiles,omitempty"` + Policies []string `json:"policies,omitempty"` } // VirtualAddresses contains a list of all virtual addresses on the BIG-IP system. @@ -1463,6 +1604,7 @@ const ( uriInternal = "internal" uriPolicy = "policy" uriOneconnect = "one-connect" + uriPersistence = "persistence" ENABLED = "enable" DISABLED = "disable" CONTEXT_SERVER = "serverside" @@ -1476,6 +1618,15 @@ const ( uriSnat = "snat" uriSnatpool = "snatpool" uriUdp = "udp" + uriCookie = "cookie" + uriDestAddr = "dest-addr" + uriHash = "hash" + uriHost = "host" + uriMSRDP = "msrdp" + uriSIP = "sip" + uriSourceAddr = "source-addr" + uriSSL = "ssl" + uriUniversal = "universal" ) var cidr = map[string]string{ @@ -1918,6 +2069,474 @@ func (b *BigIP) ModifyHttpCompressionProfile(name string, config *HttpCompressio return b.put(config, uriLtm, uriProfile, uriHttpcompress, name) } +// CookiePersistenceProfiles returns a list of cookie persist profiles +func (b *BigIP) CookiePersistenceProfiles() (*CookiePersistenceProfiles, error) { + var cookiePersistenceProfiles CookiePersistenceProfiles + err, _ := b.getForEntity(&cookiePersistenceProfiles, uriLtm, uriPersistence, uriCookie) + if err != nil { + return nil, err + } + + return &cookiePersistenceProfiles, nil +} + +// GetCookiePersistenceProfile gets a single cookie persist profile by name +func (b *BigIP) GetCookiePersistenceProfile(name string) (*CookiePersistenceProfile, error) { + var cookiePersistenceProfile CookiePersistenceProfile + err, ok := b.getForEntity(&cookiePersistenceProfile, uriLtm, uriPersistence, uriCookie, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &cookiePersistenceProfile, nil +} + +// CreateCookiePersistenceProfile creates a new cookie persist profile on the BIG-IP system. +func (b *BigIP) CreateCookiePersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriCookie) +} + +// AddCookiePersistenceProfile adds a cookie persist profile to the BIG-IP system +func (b *BigIP) AddCookiePersistenceProfile(config *CookiePersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriCookie) +} + +// DeleteCookiePersistenceProfile removes a cookie persist profile. +func (b *BigIP) DeleteCookiePersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriCookie, name) +} + +// ModifyCookiePersistenceProfile allows you to change any attribute of a cookie persist profile. +// Fields that can be modified are referenced in the CookiePersistenceProfile struct. +func (b *BigIP) ModifyCookiePersistenceProfile(name string, config *CookiePersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriCookie, name) +} + +// DestAddrPersistenceProfiles returns a list of dest-addr persist profiles +func (b *BigIP) DestAddrPersistenceProfiles() (*DestAddrPersistenceProfiles, error) { + var destAddrPersistenceProfiles DestAddrPersistenceProfiles + err, _ := b.getForEntity(&destAddrPersistenceProfiles, uriLtm, uriPersistence, uriDestAddr) + if err != nil { + return nil, err + } + + return &destAddrPersistenceProfiles, nil +} + +// GetDestAddrPersistenceProfile gets a single dest-addr persist profile by name +func (b *BigIP) GetDestAddrPersistenceProfile(name string) (*DestAddrPersistenceProfile, error) { + var destAddrPersistenceProfile DestAddrPersistenceProfile + err, ok := b.getForEntity(&destAddrPersistenceProfile, uriLtm, uriPersistence, uriDestAddr, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &destAddrPersistenceProfile, nil +} + +// CreateDestAddrPersistenceProfile creates a new dest-addr persist profile on the BIG-IP system. +func (b *BigIP) CreateDestAddrPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriDestAddr) +} + +// AddDestAddrPersistenceProfile adds a dest-addr persist profile to the BIG-IP system +func (b *BigIP) AddDestAddrPersistenceProfile(config *DestAddrPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriDestAddr) +} + +// DeleteDestAddrPersistenceProfile removes a dest-addr persist profile. +func (b *BigIP) DeleteDestAddrPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriDestAddr, name) +} + +// ModifyDestAddrPersistenceProfile allows you to change any attribute of a dest-addr persist profile. +// Fields that can be modified are referenced in the DestAddrPersistenceProfile struct. +func (b *BigIP) ModifyDestAddrPersistenceProfile(name string, config *DestAddrPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriDestAddr, name) +} + +// HashPersistenceProfiles returns a list of hash persist profiles +func (b *BigIP) HashPersistenceProfiles() (*HashPersistenceProfiles, error) { + var hashPersistenceProfiles HashPersistenceProfiles + err, _ := b.getForEntity(&hashPersistenceProfiles, uriLtm, uriPersistence, uriHash) + if err != nil { + return nil, err + } + + return &hashPersistenceProfiles, nil +} + +// GetHashPersistenceProfile gets a single hash persist profile by name +func (b *BigIP) GetHashPersistenceProfile(name string) (*HashPersistenceProfile, error) { + var hashPersistenceProfile HashPersistenceProfile + err, ok := b.getForEntity(&hashPersistenceProfile, uriLtm, uriPersistence, uriHash, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &hashPersistenceProfile, nil +} + +// CreateHashPersistenceProfile creates a new hash persist profile on the BIG-IP system. +func (b *BigIP) CreateHashPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriHash) +} + +// AddHashPersistenceProfile adds a hash persist profile to the BIG-IP system +func (b *BigIP) AddHashPersistenceProfile(config *HashPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriHash) +} + +// DeleteHashPersistenceProfile removes a dest-addr persist profile. +func (b *BigIP) DeleteHashPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriHash, name) +} + +// ModifyHashPersistenceProfile allows you to change any attribute of a hash persist profile. +// Fields that can be modified are referenced in the HashPersistenceProfile struct. +func (b *BigIP) ModifyHashPersistenceProfile(name string, config *HashPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriHash, name) +} + +// HostPersistenceProfiles returns a list of host persist profiles +func (b *BigIP) HostPersistenceProfiles() (*HostPersistenceProfiles, error) { + var hostPersistenceProfiles HostPersistenceProfiles + err, _ := b.getForEntity(&hostPersistenceProfiles, uriLtm, uriPersistence, uriHost) + if err != nil { + return nil, err + } + + return &hostPersistenceProfiles, nil +} + +// GetHostPersistenceProfile gets a single host persist profile by name +func (b *BigIP) GetHostPersistenceProfile(name string) (*HostPersistenceProfile, error) { + var hostPersistenceProfile HostPersistenceProfile + err, ok := b.getForEntity(&hostPersistenceProfile, uriLtm, uriPersistence, uriHost, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &hostPersistenceProfile, nil +} + +// CreateHostPersistenceProfile creates a new host persist profile on the BIG-IP system. +func (b *BigIP) CreateHostPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriHost) +} + +// AddHostPersistenceProfile adds a host persist profile to the BIG-IP system +func (b *BigIP) AddHostPersistenceProfile(config *HostPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriHost) +} + +// DeleteHashHostPersistenceProfile removes a host persist profile. +func (b *BigIP) DeleteHashHostPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriHost, name) +} + +// ModifyHostPersistenceProfile allows you to change any attribute of a host persist profile. +// Fields that can be modified are referenced in the HostPersistenceProfile struct. +func (b *BigIP) ModifyHostPersistenceProfile(name string, config *HostPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriHost, name) +} + +// MSRDPPersistenceProfiles returns a list of msrdp persist profiles +func (b *BigIP) MSRDPPersistenceProfiles() (*MSRDPPersistenceProfiles, error) { + var msrdpPersistenceProfiles MSRDPPersistenceProfiles + err, _ := b.getForEntity(&msrdpPersistenceProfiles, uriLtm, uriPersistence, uriMSRDP) + if err != nil { + return nil, err + } + + return &msrdpPersistenceProfiles, nil +} + +// GetMSRDPPersistenceProfile gets a single msrdp persist profile by name +func (b *BigIP) GetMSRDPPersistenceProfile(name string) (*MSRDPPersistenceProfile, error) { + var msrdpPersistenceProfile MSRDPPersistenceProfile + err, ok := b.getForEntity(&msrdpPersistenceProfile, uriLtm, uriPersistence, uriMSRDP, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &msrdpPersistenceProfile, nil +} + +// CreateMSRDPPersistenceProfile creates a new msrdp persist profile on the BIG-IP system. +func (b *BigIP) CreateMSRDPPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriMSRDP) +} + +// AddMSRDPPersistenceProfile adds a msrdp persist profile to the BIG-IP system +func (b *BigIP) AddMSRDPPersistenceProfile(config *MSRDPPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriMSRDP) +} + +// DeleteMSRDPPersistenceProfile removes a msrdp persist profile. +func (b *BigIP) DeleteMSRDPPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriMSRDP, name) +} + +// ModifyMSRDPPersistenceProfile allows you to change any attribute of a msrdp persist profile. +// Fields that can be modified are referenced in the MSRDPPersistenceProfile struct. +func (b *BigIP) ModifyMSRDPPersistenceProfile(name string, config *MSRDPPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriMSRDP, name) +} + +// SIPPersistenceProfiles returns a list of sip persist profiles +func (b *BigIP) SIPPersistenceProfiles() (*SIPPersistenceProfiles, error) { + var sipPersistenceProfiles SIPPersistenceProfiles + err, _ := b.getForEntity(&sipPersistenceProfiles, uriLtm, uriPersistence, uriSIP) + if err != nil { + return nil, err + } + + return &sipPersistenceProfiles, nil +} + +// GetSIPPersistenceProfile gets a single sip persist profile by name +func (b *BigIP) GetSIPPersistenceProfile(name string) (*SIPPersistenceProfile, error) { + var sipPersistenceProfile SIPPersistenceProfile + err, ok := b.getForEntity(&sipPersistenceProfile, uriLtm, uriPersistence, uriSIP, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &sipPersistenceProfile, nil +} + +// CreateSIPPersistenceProfile creates a new sip persist profile on the BIG-IP system. +func (b *BigIP) CreateSIPPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriSIP) +} + +// AddSIPPersistenceProfile adds a sip persist profile to the BIG-IP system +func (b *BigIP) AddSIPPersistenceProfile(config *SIPPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriSIP) +} + +// DeleteSIPPersistenceProfile removes a sip persist profile. +func (b *BigIP) DeleteSIPPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriSIP, name) +} + +// ModifySIPPersistenceProfile allows you to change any attribute of a sip persist profile. +// Fields that can be modified are referenced in the SIPPersistenceProfile struct. +func (b *BigIP) ModifySIPPersistenceProfile(name string, config *SIPPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriSIP, name) +} + +// SourceAddrPersistenceProfiles returns a list of source-addr persist profiles +func (b *BigIP) SourceAddrPersistenceProfiles() (*SourceAddrPersistenceProfiles, error) { + var sourceAddrPersistenceProfiles SourceAddrPersistenceProfiles + err, _ := b.getForEntity(&sourceAddrPersistenceProfiles, uriLtm, uriPersistence, uriSourceAddr) + if err != nil { + return nil, err + } + + return &sourceAddrPersistenceProfiles, nil +} + +// GetSourceAddrPersistenceProfile gets a single source-addr persist profile by name +func (b *BigIP) GetSourceAddrPersistenceProfile(name string) (*SourceAddrPersistenceProfile, error) { + var sourceAddrPersistenceProfile SourceAddrPersistenceProfile + err, ok := b.getForEntity(&sourceAddrPersistenceProfile, uriLtm, uriPersistence, uriSourceAddr, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &sourceAddrPersistenceProfile, nil +} + +// CreateSourceAddrPersistenceProfile creates a new source-addr persist profile on the BIG-IP system. +func (b *BigIP) CreateSourceAddrPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriSourceAddr) +} + +// AddSourceAddrPersistenceProfile adds a source-addr persist profile to the BIG-IP system +func (b *BigIP) AddSourceAddrPersistenceProfile(config *SourceAddrPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriSourceAddr) +} + +// DeleteSourceAddrPersistenceProfile removes a source-addr persist profile. +func (b *BigIP) DeleteSourceAddrPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriSourceAddr, name) +} + +// ModifySourceAddrPersistenceProfile allows you to change any attribute of a source-addr persist profile. +// Fields that can be modified are referenced in the SourceAddrPersistenceProfile struct. +func (b *BigIP) ModifySourceAddrPersistenceProfile(name string, config *SourceAddrPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriSourceAddr, name) +} + +// SSLPersistenceProfiles returns a list of ssl persist profiles +func (b *BigIP) SSLPersistenceProfiles() (*SSLPersistenceProfiles, error) { + var sslPersistenceProfiles SSLPersistenceProfiles + err, _ := b.getForEntity(&sslPersistenceProfiles, uriLtm, uriPersistence, uriSSL) + if err != nil { + return nil, err + } + + return &sslPersistenceProfiles, nil +} + +// GetSSLPersistenceProfile gets a single ssl persist profile by name +func (b *BigIP) GetSSLPersistenceProfile(name string) (*SSLPersistenceProfile, error) { + var sslPersistenceProfile SSLPersistenceProfile + err, ok := b.getForEntity(&sslPersistenceProfile, uriLtm, uriPersistence, uriSSL, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &sslPersistenceProfile, nil +} + +// CreateSSLPersistenceProfile creates a new ssl persist profile on the BIG-IP system. +func (b *BigIP) CreateSSLPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriSSL) +} + +// AddSSLPersistenceProfile adds a ssl persist profile to the BIG-IP system +func (b *BigIP) AddSSLPersistenceProfile(config *SSLPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriSSL) +} + +// DeleteSSLPersistenceProfile removes a ssl persist profile. +func (b *BigIP) DeleteSSLPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriSSL, name) +} + +// ModifySSLPersistenceProfile allows you to change any attribute of a ssl persist profile. +// Fields that can be modified are referenced in the SSLPersistenceProfile struct. +func (b *BigIP) ModifySSLPersistenceProfile(name string, config *SSLPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriSSL, name) +} + +// UniversalPersistenceProfiles returns a list of universal persist profiles +func (b *BigIP) UniversalPersistenceProfiles() (*UniversalPersistenceProfiles, error) { + var universalPersistenceProfiles UniversalPersistenceProfiles + err, _ := b.getForEntity(&universalPersistenceProfiles, uriLtm, uriPersistence, uriUniversal) + if err != nil { + return nil, err + } + + return &universalPersistenceProfiles, nil +} + +// GetUniversalPersistenceProfile gets a single universal persist profile by name +func (b *BigIP) GetUniversalPersistenceProfile(name string) (*UniversalPersistenceProfile, error) { + var universalPersistenceProfile UniversalPersistenceProfile + err, ok := b.getForEntity(&universalPersistenceProfile, uriLtm, uriPersistence, uriUniversal, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &universalPersistenceProfile, nil +} + +// CreateUniversalPersistenceProfile creates a new universal persist profile on the BIG-IP system. +func (b *BigIP) CreateUniversalPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriUniversal) +} + +// AddUniversalPersistenceProfile adds a universal persist profile to the BIG-IP system +func (b *BigIP) AddUniversalPersistenceProfile(config *UniversalPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriUniversal) +} + +// DeleteUniversalPersistenceProfile removes a universal persist profile. +func (b *BigIP) DeleteUniversalPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriUniversal, name) +} + +// ModifyUniversalPersistenceProfile allows you to change any attribute of a universal persist profile. +// Fields that can be modified are referenced in the UniversalPersistenceProfile struct. +func (b *BigIP) ModifyUniversalPersistenceProfile(name string, config *UniversalPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriUniversal, name) +} + // Nodes returns a list of nodes. func (b *BigIP) Nodes() (*Nodes, error) { var nodes Nodes From 2fe7b24b10b42c25fbcbc512ace4b8a08d58a8ff Mon Sep 17 00:00:00 2001 From: Sanjay Date: Thu, 5 Apr 2018 19:57:05 -0700 Subject: [PATCH 17/80] updated the files with vendor changes --- bigip.go | 3 +- device.go | 152 ++++-- gtm.go | 296 ++++++----- ltm.go | 1417 ++++++++++++++++++++++++++++++++++------------------- net.go | 31 +- sys.go | 70 ++- 6 files changed, 1243 insertions(+), 726 deletions(-) diff --git a/bigip.go b/bigip.go index 24b3c26..cf87208 100644 --- a/bigip.go +++ b/bigip.go @@ -12,6 +12,7 @@ import ( "reflect" "strings" "time" + "log" ) var defaultConfigOptions = &ConfigOptions{ @@ -258,7 +259,7 @@ func (b *BigIP) patch(body interface{}, path ...string) error { Body: string(marshalJSON), ContentType: "application/json", } - + log.Println(" patch ----------------- ", req) _, callErr := b.APICall(req) return callErr } diff --git a/device.go b/device.go index 409f47f..7675a7e 100644 --- a/device.go +++ b/device.go @@ -1,6 +1,8 @@ package bigip -import "encoding/json" +import ( + "encoding/json" +) // LIC contains device license for BIG-IP system. type LICs struct { @@ -56,10 +58,77 @@ type Devicegroups struct { } type Devicegroup struct { - AutoSync string `json:"autoSync,omitempty"` - Name string `json:"name,omitempty"` - Type string `json:"type,omitempty"` - FullLoadOnSync string `json:"fullLoadOnSync,omitempty"` + AutoSync string + Name string + Partition string + Description string + Type string + FullLoadOnSync string + SaveOnAutoSync string + NetworkFailover string + IncrementalConfigSyncSizeMax int + Deviceb []Devicerecord +} +type devicegroupDTO struct { + AutoSync string `json:"autoSync,omitempty"` + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + Description string `json:"description,omitempty"` + Type string `json:"type,omitempty"` + FullLoadOnSync string `json:"fullLoadOnSync,omitempty"` + SaveOnAutoSync string `json:"saveOnAutoSync,omitempty"` + NetworkFailover string `json:"networkFailover,omitempty"` + IncrementalConfigSyncSizeMax int `json:"incrementalConfigSyncSizeMax,omitempty"` + Deviceb struct { + Items []Devicerecord `json:"items,omitempty"` + } `json:"devicesReference,omitempty"` +} + +type Devicerecords struct { + Items []Devicerecord `json:"items,omitempty"` +} + +type Devicerecord struct { + SetSyncLeader bool `json:"setSyncLeader"` + Name string `json:"name"` +} + +func (p *Devicegroup) MarshalJSON() ([]byte, error) { + return json.Marshal(devicegroupDTO{ + Name: p.Name, + Partition: p.Partition, + AutoSync: p.AutoSync, + Description: p.Description, + Type: p.Type, + FullLoadOnSync: p.FullLoadOnSync, + SaveOnAutoSync: p.SaveOnAutoSync, + NetworkFailover: p.NetworkFailover, + IncrementalConfigSyncSizeMax: p.IncrementalConfigSyncSizeMax, + Deviceb: struct { + Items []Devicerecord `json:"items,omitempty"` + }{Items: p.Deviceb}, + }) +} + +func (p *Devicegroup) UnmarshalJSON(b []byte) error { + var dto devicegroupDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + + p.Name = dto.Name + p.Partition = dto.Partition + p.AutoSync = dto.AutoSync + p.Description = dto.Description + p.Type = dto.Type + p.FullLoadOnSync = dto.FullLoadOnSync + p.SaveOnAutoSync = dto.SaveOnAutoSync + p.NetworkFailover = dto.NetworkFailover + p.IncrementalConfigSyncSizeMax = dto.IncrementalConfigSyncSizeMax + p.Deviceb = dto.Deviceb.Items + + return nil } // https://10.192.74.80/mgmt/cm/device/licensing/pool/purchased-pool/licenses @@ -68,6 +137,8 @@ const ( uriMgmt = "mgmt" uriCm = "cm" uriDiv = "device" + uriDevices = "devices" + uriDG = "device-group" uriLins = "licensing" uriPoo = "pool" uriPur = "purchased-pool" @@ -158,31 +229,6 @@ func (b *BigIP) LICs() (*LIC, error) { return &members, nil } -func (b *BigIP) CreateDevicename(command, name, target string) error { - config := &Devicename{ - Command: command, - Name: name, - Target: target, - } - - return b.post(config, uriCm, uriDiv) -} - -func (b *BigIP) ModifyDevicename(config *Devicename) error { - return b.put(config, uriCm, uriDiv) -} - -func (b *BigIP) Devicenames() (*Devicename, error) { - var devicename Devicename - err, _ := b.getForEntity(&devicename, uriCm, uriDiv) - - if err != nil { - return nil, err - } - - return &devicename, nil -} - func (b *BigIP) CreateDevice(name, configsyncIp, mirrorIp, mirrorSecondaryIp string) error { config := &Device{ Name: name, @@ -194,13 +240,18 @@ func (b *BigIP) CreateDevice(name, configsyncIp, mirrorIp, mirrorSecondaryIp str return b.post(config, uriCm, uriDiv) } +// API does not work, you cannot modify API issue func (b *BigIP) ModifyDevice(config *Device) error { return b.put(config, uriCm, uriDiv) } -func (b *BigIP) Devices() (*Device, error) { +func (b *BigIP) DeleteDevice(name string) error { + return b.delete(uriCm, uriDiv, name) +} + +func (b *BigIP) Devices(name string) (*Device, error) { var device Device - err, _ := b.getForEntity(&device, uriCm, uriDiv) + err, _ := b.getForEntity(&device, uriCm, uriDiv, name) if err != nil { return nil, err @@ -209,25 +260,38 @@ func (b *BigIP) Devices() (*Device, error) { return &device, nil } -func (b *BigIP) CreateDevicegroup(name, autoSync, typo, fullLoadOnSync string) error { - config := &Devicegroup{ - Name: name, - AutoSync: autoSync, - Type: typo, - FullLoadOnSync: fullLoadOnSync, - } - - return b.post(config, uriCm, uriDiv) +func (b *BigIP) CreateDevicegroup(p *Devicegroup) error { + return b.post(p, uriCm, uriDG) } +func (b *BigIP) UpdateDevicegroup(name string, p *Devicegroup) error { + return b.put(p, uriCm, uriDG, name) +} func (b *BigIP) ModifyDevicegroup(config *Devicegroup) error { - return b.put(config, uriCm, uriDiv) + return b.put(config, uriCm, uriDG) } -func (b *BigIP) Devicegroups() (*Devicegroup, error) { +func (b *BigIP) Devicegroups(name string) (*Devicegroup, error) { var devicegroup Devicegroup - err, _ := b.getForEntity(&devicegroup, uriCm, uriDiv) + err, _ := b.getForEntity(&devicegroup, uriCm, uriDG, name) + if err != nil { + return nil, err + } + + return &devicegroup, nil +} + +func (b *BigIP) DeleteDevicegroup(name string) error { + return b.delete(uriCm, uriDG, name) +} +func (b *BigIP) DeleteDevicegroupDevices(name, rname string) error { + return b.delete(uriCm, uriDG, name, uriDevices, rname) +} + +func (b *BigIP) DevicegroupsDevices(name, rname string) (*Devicegroup, error) { + var devicegroup Devicegroup + err, _ := b.getForEntity(&devicegroup, uriCm, uriDG, name, uriDevices, rname) if err != nil { return nil, err } diff --git a/gtm.go b/gtm.go index 4e36891..55143c6 100644 --- a/gtm.go +++ b/gtm.go @@ -5,34 +5,31 @@ import "log" //ooo - type Datacenters struct { Datacenters []Datacenter `json:"items"` } type Datacenter struct { - Name string `json:"name,omitempty"` + Name string `json:"name,omitempty"` Description string `json:"description,omitempty"` - Contact string `json:"contact,omitempty"` - App_service string `json:"appService,omitempty"` - Disabled bool `json:"disabled,omitempty"` - Enabled bool `json:"enabled,omitempty"` - Prober_pool string `json:"proberPool,omitempty"` + Contact string `json:"contact,omitempty"` + App_service string `json:"appService,omitempty"` + Disabled bool `json:"disabled,omitempty"` + Enabled bool `json:"enabled,omitempty"` + Prober_pool string `json:"proberPool,omitempty"` } - type Gtmmonitors struct { Gtmmonitors []Gtmmonitor `json:"items"` } - type Gtmmonitor struct { - Name string `json:"name,omitempty"` + Name string `json:"name,omitempty"` Defaults_from string `json:"defaultsFrom,omitempty"` - Interval int `json:"interval,omitempty"` - Probe_timeout int `json:"probeTimeout,omitempty"` - Recv string `json:"recv,omitempty"` - Send string `json:"send,omitempty"` + Interval int `json:"interval,omitempty"` + Probe_timeout int `json:"probeTimeout,omitempty"` + Recv string `json:"recv,omitempty"` + Send string `json:"send,omitempty"` } type Servers struct { @@ -40,109 +37,101 @@ type Servers struct { } type Server struct { - Name string - Datacenter string - Monitor string + Name string + Datacenter string + Monitor string Virtual_server_discovery bool - Product string - Addresses []ServerAddresses - GTMVirtual_Server []VSrecord + Product string + Addresses []ServerAddresses + GTMVirtual_Server []VSrecord } type serverDTO struct { - Name string `json:"name"` - Datacenter string `json:"datacenter,omitempty"` - Monitor string `json:"monitor,omitempty"` - Virtual_server_discovery bool `json:"virtual_server_discovery"` - Product string `json:"product,omitempty"` - Addresses struct { - Items []ServerAddresses`json:"items,omitempty"` + Name string `json:"name"` + Datacenter string `json:"datacenter,omitempty"` + Monitor string `json:"monitor,omitempty"` + Virtual_server_discovery bool `json:"virtual_server_discovery"` + Product string `json:"product,omitempty"` + Addresses struct { + Items []ServerAddresses `json:"items,omitempty"` } `json:"addressesReference,omitempty"` GTMVirtual_Server struct { - Items []VSrecord `json:"items,omitempty"` } `json:"virtualServersReference,omitempty"` - } - - func (p *Server) MarshalJSON() ([]byte, error) { - return json.Marshal(serverDTO{ - Name: p.Name, - Datacenter: p.Datacenter, - Monitor: p.Monitor, - Virtual_server_discovery: p.Virtual_server_discovery, - Product: p.Product, - Addresses: struct { - Items []ServerAddresses `json:"items,omitempty"` - }{Items: p.Addresses}, - GTMVirtual_Server: struct { - Items []VSrecord `json:"items,omitempty"` - }{Items: p.GTMVirtual_Server}, - }) - } - - func (p *Server) UnmarshalJSON(b []byte) error { - var dto serverDTO - err := json.Unmarshal(b, &dto) - if err != nil { - return err - } - - p.Name = dto.Name - p.Datacenter = dto.Datacenter - p.Monitor = dto.Monitor - p.Virtual_server_discovery = dto.Virtual_server_discovery - p.Product = dto.Product - p.Addresses = dto.Addresses.Items - p.GTMVirtual_Server = dto.GTMVirtual_Server.Items - return nil - } - - - type ServerAddressess struct { - Items []ServerAddresses `json:"items,omitempty"` - } - - - - type ServerAddresses struct { - Name string `json:"name"` - Device_name string `json:"deviceName,omitempty"` - Translation string `json:"translation,omitempty"` - } - + Items []VSrecord `json:"items,omitempty"` + } `json:"virtualServersReference,omitempty"` +} +func (p *Server) MarshalJSON() ([]byte, error) { + return json.Marshal(serverDTO{ + Name: p.Name, + Datacenter: p.Datacenter, + Monitor: p.Monitor, + Virtual_server_discovery: p.Virtual_server_discovery, + Product: p.Product, + Addresses: struct { + Items []ServerAddresses `json:"items,omitempty"` + }{Items: p.Addresses}, + GTMVirtual_Server: struct { + Items []VSrecord `json:"items,omitempty"` + }{Items: p.GTMVirtual_Server}, + }) +} - type VSrecords struct { - Items []VSrecord `json:"items,omitempty"` +func (p *Server) UnmarshalJSON(b []byte) error { + var dto serverDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err } + p.Name = dto.Name + p.Datacenter = dto.Datacenter + p.Monitor = dto.Monitor + p.Virtual_server_discovery = dto.Virtual_server_discovery + p.Product = dto.Product + p.Addresses = dto.Addresses.Items + p.GTMVirtual_Server = dto.GTMVirtual_Server.Items + return nil +} +type ServerAddressess struct { + Items []ServerAddresses `json:"items,omitempty"` +} - type VSrecord struct { - Name string `json:"name"` - Destination string `json:"destination,omitempty"` - } +type ServerAddresses struct { + Name string `json:"name"` + Device_name string `json:"deviceName,omitempty"` + Translation string `json:"translation,omitempty"` +} - type Pool_as struct { - Pool_as []Pool_a `json:"items"` - } +type VSrecords struct { + Items []VSrecord `json:"items,omitempty"` +} - type Pool_a struct { - Name string `json:"name,omitempty"` - Monitor string `json:"monitor,omitempty"` - Load_balancing_mode string `json:"load_balancing_mode,omitempty"` - Max_answers_returned int `json:"max_answers_returned,omitempty"` - Alternate_mode string `json:"alternate_mode,omitempty"` - Fallback_ip string `json:"fallback_ip,omitempty"` - Fallback_mode string `json:"fallback_mode,omitempty"` - Members []string `json:"members,omitempty"` - } +type VSrecord struct { + Name string `json:"name"` + Destination string `json:"destination,omitempty"` +} +type Pool_as struct { + Pool_as []Pool_a `json:"items"` +} +type Pool_a struct { + Name string `json:"name,omitempty"` + Monitor string `json:"monitor,omitempty"` + Load_balancing_mode string `json:"load_balancing_mode,omitempty"` + Max_answers_returned int `json:"max_answers_returned,omitempty"` + Alternate_mode string `json:"alternate_mode,omitempty"` + Fallback_ip string `json:"fallback_ip,omitempty"` + Fallback_mode string `json:"fallback_mode,omitempty"` + Members []string `json:"members,omitempty"` +} const ( - uriGtm = "gtm" - uriServer = "server" + uriGtm = "gtm" + uriServer = "server" uriDatacenter = "datacenter" - uriGtmmonitor = "monitor" + uriGtmmonitor = "monitor" uriHttp = "http" uriPool_a = "pool/a" ) @@ -158,14 +147,14 @@ func (b *BigIP) Datacenters() (*Datacenter, error) { return &datacenter, nil } -func (b *BigIP) CreateDatacenter(name, description,contact, app_service string, enabled, disabled bool, prober_pool string) error { +func (b *BigIP) CreateDatacenter(name, description, contact, app_service string, enabled, disabled bool, prober_pool string) error { config := &Datacenter{ - Name: name, - Description: description, - Contact: contact, + Name: name, + Description: description, + Contact: contact, App_service: app_service, - Enabled: enabled, - Disabled: disabled, + Enabled: enabled, + Disabled: disabled, Prober_pool: prober_pool, } return b.post(config, uriGtm, uriDatacenter) @@ -175,13 +164,10 @@ func (b *BigIP) ModifyDatacenter(*Datacenter) error { return b.patch(uriGtm, uriDatacenter) } - func (b *BigIP) DeleteDatacenter(name string) error { return b.delete(uriGtm, uriDatacenter, name) } - - func (b *BigIP) Gtmmonitors() (*Gtmmonitor, error) { var gtmmonitor Gtmmonitor err, _ := b.getForEntity(>mmonitor, uriGtm, uriGtmmonitor, uriHttp) @@ -194,12 +180,12 @@ func (b *BigIP) Gtmmonitors() (*Gtmmonitor, error) { } func (b *BigIP) CreateGtmmonitor(name, defaults_from string, interval, probeTimeout int, recv, send string) error { config := &Gtmmonitor{ - Name: name, - Defaults_from: defaults_from, - Interval: interval, + Name: name, + Defaults_from: defaults_from, + Interval: interval, Probe_timeout: probeTimeout, - Recv: recv, - Send: send, + Recv: recv, + Send: send, } return b.post(config, uriGtm, uriGtmmonitor, uriHttp) } @@ -208,12 +194,10 @@ func (b *BigIP) ModifyGtmmonitor(*Gtmmonitor) error { return b.patch(uriGtm, uriGtmmonitor, uriHttp) } - func (b *BigIP) DeleteGtmmonitor(name string) error { return b.delete(uriGtm, uriGtmmonitor, uriHttp, name) } - func (b *BigIP) CreateGtmserver(p *Server) error { log.Println(" what is the complete payload ", p) return b.post(p, uriGtm, uriServer) @@ -229,47 +213,45 @@ func (b *BigIP) DeleteGtmserver(name string) error { return b.delete(uriGtm, uriServer, name) } - func (b *BigIP) GetGtmserver(name string) (*Server, error) { - var p Server - err, ok := b.getForEntity(&p, uriGtm, uriServer, name) - if err != nil { - return nil, err - } - if !ok { - return nil, nil - } - - return &p, nil - } - - - func (b *BigIP) CreatePool_a(name, monitor, load_balancing_mode string, max_answers_returned int, alternate_mode, fallback_ip, fallback_mode string, members []string) error { - config := &Pool_a{ - Name: name, - Monitor: monitor, - Load_balancing_mode: load_balancing_mode, - Max_answers_returned: max_answers_returned, - Alternate_mode: alternate_mode, - Fallback_ip: fallback_ip, - Fallback_mode: fallback_mode, - Members: members, - } - log.Println("in poola now", config) - return b.patch(config, uriGtm, uriPool_a) - } - - func (b *BigIP) ModifyPool_a(config *Pool_a) error { - return b.put(config, uriGtm, uriPool_a) - } - - func (b *BigIP) Pool_as() (*Pool_a, error) { - var pool_a Pool_a - err, _ := b.getForEntity(&pool_a, uriGtm, uriPool_a) - - if err != nil { - return nil, err - } - - return &pool_a, nil - } + var p Server + err, ok := b.getForEntity(&p, uriGtm, uriServer, name) + if err != nil { + return nil, err + } + if !ok { + return nil, nil + } + + return &p, nil +} + +func (b *BigIP) CreatePool_a(name, monitor, load_balancing_mode string, max_answers_returned int, alternate_mode, fallback_ip, fallback_mode string, members []string) error { + config := &Pool_a{ + Name: name, + Monitor: monitor, + Load_balancing_mode: load_balancing_mode, + Max_answers_returned: max_answers_returned, + Alternate_mode: alternate_mode, + Fallback_ip: fallback_ip, + Fallback_mode: fallback_mode, + Members: members, + } + log.Println("in poola now", config) + return b.patch(config, uriGtm, uriPool_a) +} + +func (b *BigIP) ModifyPool_a(config *Pool_a) error { + return b.put(config, uriGtm, uriPool_a) +} + +func (b *BigIP) Pool_as() (*Pool_a, error) { + var pool_a Pool_a + err, _ := b.getForEntity(&pool_a, uriGtm, uriPool_a) + + if err != nil { + return nil, err + } + + return &pool_a, nil +} diff --git a/ltm.go b/ltm.go index d252064..7f6306e 100644 --- a/ltm.go +++ b/ltm.go @@ -130,344 +130,6 @@ type ClientSSLProfile struct { UncleanShutdown string `json:"uncleanShutdown,omitempty"` } -// TcpProfiles contains a list of every tcp profile on the BIG-IP system. -type TcpProfiles struct { - TcpProfiles []TcpProfile `json:"items"` -} - -type TcpProfile struct { - Abc string `json:"abc,omitempty"` - AckOnPush string `json:"ackOnPush,omitempty"` - AppService string `json:"appService,omitempty"` - AutoProxyBufferSize string `json:"autoProxyBufferSize,omitempty"` - AutoReceiveWindowSize string `json:"autoReceiveWindowSize,omitempty"` - AutoSendBufferSize string `json:"autoSendBufferSize,omitempty"` - CloseWaitTimeout int `json:"closeWaitTimeout,omitempty"` - CmetricsCache string `json:"cmetricsCache,omitempty"` - CmetricsCacheTimeout int `json:"cmetricsCacheTimeout,omitempty"` - CongestionControl string `json:"congestionControl,omitempty"` - DefaultsFrom string `json:"defaultsFrom,omitempty"` - DeferredAccept string `json:"deferredAccept,omitempty"` - DelayWindowControl string `json:"delayWindowControl,omitempty"` - DelayedAcks string `json:"delayedAcks,omitempty"` - Description string `json:"description,omitempty"` - Dsack string `json:"dsack,omitempty"` - EarlyRetransmit string `json:"earlyRetransmit,omitempty"` - Ecn string `json:"ecn,omitempty"` - EnhancedLossRecovery string `json:"enhancedLossRecovery,omitempty"` - FastOpen string `json:"fastOpen,omitempty"` - FastOpenCookieExpiration int `json:"fastOpenCookieExpiration,omitempty"` - FinWait_2Timeout int `json:"finWait_2Timeout,omitempty"` - FinWaitTimeout int `json:"finWaitTimeout,omitempty"` - HardwareSynCookie string `json:"hardwareSynCookie,omitempty"` - IdleTimeout int `json:"idleTimeout,omitempty"` - InitCwnd int `json:"initCwnd,omitempty"` - InitRwnd int `json:"initRwnd,omitempty"` - IpDfMode string `json:"ipDfMode,omitempty"` - IpTosToClient string `json:"ipTosToClient,omitempty"` - IpTtlMode string `json:"ipTtlMode,omitempty"` - IpTtlV4 int `json:"ipTtlV4,omitempty"` - IpTtlV6 int `json:"ipTtlV6,omitempty"` - KeepAliveInterval int `json:"keepAliveInterval,omitempty"` - LimitedTransmit string `json:"limitedTransmit,omitempty"` - LinkQosToClient string `json:"linkQosToClient,omitempty"` - MaxRetrans int `json:"maxRetrans,omitempty"` - MaxSegmentSize int `json:"maxSegmentSize,omitempty"` - Md5Signature string `json:"md5Signature,omitempty"` - Md5SignaturePassphrase string `json:"md5SignaturePassphrase,omitempty"` - MinimumRto int `json:"minimumRto,omitempty"` - Mptcp string `json:"mptcp,omitempty"` - MptcpCsum string `json:"mptcpCsum,omitempty"` - MptcpCsumVerify string `json:"mptcpCsumVerify,omitempty"` - MptcpDebug string `json:"mptcpDebug,omitempty"` - MptcpFallback string `json:"mptcpFallback,omitempty"` - MptcpFastjoin string `json:"mptcpFastjoin,omitempty"` - MptcpIdleTimeout int `json:"mptcpIdleTimeout,omitempty"` - MptcpJoinMax int `json:"mptcpJoinMax,omitempty"` - MptcpMakeafterbreak string `json:"mptcpMakeafterbreak,omitempty"` - MptcpNojoindssack string `json:"mptcpNojoindssack,omitempty"` - MptcpRtomax int `json:"mptcpRtomax,omitempty"` - MptcpRxmitmin int `json:"mptcpRxmitmin,omitempty"` - MptcpSubflowmax int `json:"mptcpSubflowmax,omitempty"` - MptcpTimeout int `json:"mptcpTimeout,omitempty"` - Nagle string `json:"nagle,omitempty"` - Name string `json:"name,omitempty"` - TmPartition string `json:"tmPartition,omitempty"` - PktLossIgnoreBurst int `json:"pktLossIgnoreBurst,omitempty"` - PktLossIgnoreRate int `json:"pktLossIgnoreRate,omitempty"` - ProxyBufferHigh int `json:"proxyBufferHigh,omitempty"` - ProxyBufferLow int `json:"proxyBufferLow,omitempty"` - ProxyMss string `json:"proxyMss,omitempty"` - ProxyOptions string `json:"proxyOptions,omitempty"` - RatePace string `json:"ratePace,omitempty"` - RatePaceMaxRate int `json:"ratePaceMaxRate,omitempty"` - ReceiveWindowSize int `json:"receiveWindowSize,omitempty"` - ResetOnTimeout string `json:"resetOnTimeout,omitempty"` - RexmtThresh int `json:"rexmtThresh,omitempty"` - SelectiveAcks string `json:"selectiveAcks,omitempty"` - SelectiveNack string `json:"selectiveNack,omitempty"` - SendBufferSize int `json:"sendBufferSize,omitempty"` - SlowStart string `json:"slowStart,omitempty"` - SynCookieEnable string `json:"synCookieEnable,omitempty"` - SynCookieWhitelist string `json:"synCookieWhitelist,omitempty"` - SynMaxRetrans int `json:"synMaxRetrans,omitempty"` - SynRtoBase int `json:"synRtoBase,omitempty"` - TailLossProbe string `json:"tailLossProbe,omitempty"` - TcpOptions string `json:"tcpOptions,omitempty"` - TimeWaitRecycle string `json:"timeWaitRecycle,omitempty"` - TimeWaitTimeout string `json:"timeWaitTimeout,omitempty"` - Timestamps string `json:"timestamps,omitempty"` - VerifiedAccept string `json:"verifiedAccept,omitempty"` -} - -// UdpProfiles contains a list of every tcp profile on the BIG-IP system. -type UdpProfiles struct { - UdpProfiles []UdpProfile `json:"items"` -} - -type UdpProfile struct { - AllowNoPayload string `json:"allowNoPayload,omitempty"` - AppService string `json:"appService,omitempty"` - BufferMaxBytes int `json:"bufferMaxBytes,omitempty"` - BufferMaxPackets int `json:"bufferMaxPackets,omitempty"` - DatagramLoadBalancing string `json:"datagramLoadBalancing,omitempty"` - DefaultsFrom string `json:"defaultsFrom,omitempty"` - Description string `json:"description,omitempty"` - IdleTimeout string `json:"idleTimeout,omitempty"` - IpDfMode string `json:"ipDfMode,omitempty"` - IpTosToClient string `json:"ipTosToClient,omitempty"` - IpTtlMode string `json:"ipTtlMode,omitempty"` - IpTtlV4 int `json:"ipTtlV4,omitempty"` - IpTtlV6 int `json:"ipTtlV6,omitempty"` - LinkQosToClient string `json:"linkQosToClient,omitempty"` - Name string `json:"name,omitempty"` - NoChecksum string `json:"noChecksum,omitempty"` - TmPartition string `json:"tmPartition,omitempty"` - ProxyMss string `json:"proxyMss,omitempty"` -} - -type HttpProfiles struct { - HttpProfiles []HttpProfile `json:"items"` -} - -type HttpProfile struct { - AcceptXff string `json:"acceptXff,omitempty"` - AppService string `json:"appService,omitempty"` - BasicAuthRealm string `json:"basicAuthRealm,omitempty"` - DefaultsFrom string `json:"defaultsFrom,omitempty"` - Description string `json:"description,omitempty"` - EncryptCookieSecret string `json:"encryptCookieSecret,omitempty"` - EncryptCookies string `json:"encryptCookies,omitempty"` - FallbackHost string `json:"fallbackHost,omitempty"` - FallbackStatusCodes string `json:"fallbackStatusCodes,omitempty"` - HeaderErase string `json:"headerErase,omitempty"` - HeaderInsert string `json:"headerInsert,omitempty"` - InsertXforwardedFor string `json:"insertXforwardedFor,omitempty"` - LwsSeparator string `json:"lwsSeparator,omitempty"` - LwsWidth int `json:"lwsWidth,omitempty"` - Name string `json:"name,omitempty"` - OneconnectTransformations string `json:"oneconnectTransformations,omitempty"` - TmPartition string `json:"tmPartition,omitempty"` - ProxyType string `json:"proxyType,omitempty"` - RedirectRewrite string `json:"redirectRewrite,omitempty"` - RequestChunking string `json:"requestChunking,omitempty"` - ResponseChunking string `json:"responseChunking,omitempty"` - ResponseHeadersPermitted string `json:"responseHeadersPermitted,omitempty"` - ServerAgentName string `json:"serverAgentName,omitempty"` - ViaHostName string `json:"viaHostName,omitempty"` - ViaRequest string `json:"viaRequest,omitempty"` - ViaResponse string `json:"viaResponse,omitempty"` - XffAlternativeNames string `json:"xffAlternativeNames,omitempty"` -} - -type OneconnectProfiles struct { - OneconnectProfiles []OneconnectProfile `json:"items"` -} - -type OneconnectProfile struct { - AppService string `json:"appService,omitempty"` - DefaultsFrom string `json:"defaultsFrom,omitempty"` - Description string `json:"description,omitempty"` - IdleTimeoutOverride string `json:"idleTimeoutOverride,omitempty"` - LimitType string `json:"limitType,omitempty"` - MaxAge int `json:"maxAge,omitempty"` - MaxReuse int `json:"maxReuse,omitempty"` - MaxSize int `json:"maxSize,omitempty"` - Name string `json:"name,omitempty"` - TmPartition string `json:"tmPartition,omitempty"` - SharePools string `json:"sharePools,omitempty"` - SourceMask string `json:"sourceMask,omitempty"` -} - -type HttpCompressionProfiles struct { - HttpCompressionProfiles []HttpCompressionProfile `json:"items"` -} - -type HttpCompressionProfile struct { - AllowHttp_10 string `json:"allowHttp_10,omitempty"` - AppService string `json:"appService,omitempty"` - BrowserWorkarounds string `json:"browserWorkarounds,omitempty"` - BufferSize int `json:"bufferSize,omitempty"` - ContentTypeExclude []string `json:"contentTypeExclude,omitempty"` - ContentTypeInclude []string `json:"contentTypeInclude,omitempty"` - CpuSaver string `json:"cpuSaver,omitempty"` - CpuSaverHigh int `json:"cpuSaverHigh,omitempty"` - CpuSaverLow int `json:"cpuSaverLow,omitempty"` - DefaultsFrom string `json:"defaultsFrom,omitempty"` - Description string `json:"description,omitempty"` - GzipLevel int `json:"gzipLevel,omitempty"` - GzipMemoryLevel int `json:"gzipMemoryLevel,omitempty"` - GzipWindowSize int `json:"gzipWindowSize,omitempty"` - KeepAcceptEncoding string `json:"keepAcceptEncoding,omitempty"` - MethodPrefer string `json:"methodPrefer,omitempty"` - MinSize int `json:"minSize,omitempty"` - Name string `json:"name,omitempty"` - TmPartition string `json:"tmPartition,omitempty"` - Selective string `json:"selective,omitempty"` - UriExclude []string `json:"uriExclude,omitempty"` - UriInclude []string `json:"uriInclude,omitempty"` - VaryHeader string `json:"varyHeader,omitempty"` -} - -// PersistenceProfiles contains of list of persistence profiles -type PersistenceProfiles struct { - PersistenceProfiles []PersistenceProfile `json:"items"` -} - -// PersistenceProfile is a base for all persistence profiles -type PersistenceProfile struct { - AppService string `json:"appService,omitempty"` - DefaultsFrom string `json:"defaultsFrom,omitempty"` - Description string `json:"description,omitempty"` - FullPath string `json:"fullPath,omitempty"` - MatchAcrossPools string `json:"matchAcrossPools,omitempty"` - MatchAcrossServices string `json:"matchAcrossServices,omitempty"` - MatchAcrossVirtuals string `json:"matchAcrossVirtuals,omitempty"` - Method string `json:"method,omitempty"` - Mirror string `json:"mirror,omitempty"` - Mode string `json:"mode,omitempty"` - Name string `json:"name,omitempty"` - OverrideConnectionLimit string `json:"overrideConnectionLimit,omitempty"` - Partition string `json:"partition,omitempty"` - TmPartition string `json:"tmPartition,omitempty"` - Timeout string `json:"timeout,omitempty"` -} - -// CookiePersistenceProfiles contains a list of all cookies profiles -type CookiePersistenceProfiles struct { - CookiePersistenceProfiles []CookiePersistenceProfile `json:"items"` -} - -// CookiePersistenceProfile Defines a single cookie profile -type CookiePersistenceProfile struct { - PersistenceProfile - AlwaysSend string `json:"alwaysSend,omitempty"` - CookieEncryption string `json:"cookieEncryption,omitempty"` - CookieEncryptionPassphrase string `json:"cookieEncryptionPassphrase,omitempty"` - CookieName string `json:"cookieName,omitempty"` - Expiration string `json:"expiration,omitempty"` - HashLength int `json:"hashLength,omitempty"` - HashOffset int `json:"hashOffset,omitempty"` - HTTPOnly string `json:"httponly,omitempty"` - Secure string `json:"secure,omitempty"` -} - -// DestAddrPersistenceProfiles contains a list of all dest-addr profiles -type DestAddrPersistenceProfiles struct { - DestAddrPersistenceProfiles []DestAddrPersistenceProfile `json:"items"` -} - -// DestAddrPersistenceProfile Defines a single dest-addr profile -type DestAddrPersistenceProfile struct { - PersistenceProfile - HashAlgorithm string `json:"hashAlgorithm,omitempty"` - Mask string `json:"mask,omitempty"` -} - -// HashPersistenceProfiles contains a list of all hash profiles -type HashPersistenceProfiles struct { - HashPersistenceProfiles []HashPersistenceProfile `json:"items"` -} - -// HashPersistenceProfile Defines a single hash profile -type HashPersistenceProfile struct { - PersistenceProfile - HashAlgorithm string `json:"hashAlgorithm,omitempty"` - HashBufferLimit int `json:"hashBufferLimit,omitempty"` - HashEndPattern int `json:"hashEndPattern,omitempty"` - HashLength int `json:"hashLength,omitempty"` - HashOffset int `json:"hashOffset,omitempty"` - HashStartPattern int `json:"hashStartPattern,omitempty"` -} - -// HostPersistenceProfiles contains a list of all host profiles -type HostPersistenceProfiles struct { - HostPersistenceProfiles []HostPersistenceProfile `json:"items"` -} - -// HostPersistenceProfile Defines a single host profile -type HostPersistenceProfile struct { - PersistenceProfile -} - -// MSRDPPersistenceProfiles contains a list of all msrdp profiles -type MSRDPPersistenceProfiles struct { - MSRDPPersistenceProfiles []MSRDPPersistenceProfile `json:"items"` -} - -// MSRDPPersistenceProfile Defines a single msrdp profile -type MSRDPPersistenceProfile struct { - PersistenceProfile - HasSessionDir string `json:"hasSessionDir,omitempty"` -} - -// SIPPersistenceProfiles contains a list of all sip profiles -type SIPPersistenceProfiles struct { - SIPPersistenceProfiles []SIPPersistenceProfile `json:"items"` -} - -// SIPPersistenceProfile Defines a single sip profile -type SIPPersistenceProfile struct { - PersistenceProfile - SIPInfo string `json:"sipInfo,omitempty"` -} - -// SourceAddrPersistenceProfiles contains a list of all source-addr profiles -type SourceAddrPersistenceProfiles struct { - SourceAddrPersistenceProfiles []SourceAddrPersistenceProfile `json:"items"` -} - -// SourceAddrPersistenceProfile Defines a single source-addr profile -type SourceAddrPersistenceProfile struct { - PersistenceProfile - HashAlgorithm string `json:"hashAlgorithm,omitempty"` - MapProxies string `json:"mapProxies,omitempty"` - MapProxyAddress string `json:"mapProxyAddress,omitempty"` - MapProxyClass string `json:"mapProxyClass,omitempty"` - Mask string `json:"mask,omitempty"` -} - -// SSLPersistenceProfiles contains a list of all ssl profiles -type SSLPersistenceProfiles struct { - SSLPersistenceProfiles []SSLPersistenceProfile `json:"items"` -} - -// SSLPersistenceProfile Defines a single ssl profile -type SSLPersistenceProfile struct { - PersistenceProfile -} - -// UniversalPersistenceProfiles contains a list of all universal profiles -type UniversalPersistenceProfiles struct { - SSLPersistenceProfiles []UniversalPersistenceProfile `json:"items"` -} - -// UniversalPersistenceProfile Defines a single universal profile -type UniversalPersistenceProfile struct { - PersistenceProfile - Rule string `json:"rule,omitempty"` -} - // Nodes contains a list of every node on the BIG-IP system. type Nodes struct { Nodes []Node `json:"items"` @@ -489,6 +151,13 @@ type Node struct { Ratio int `json:"ratio,omitempty"` Session string `json:"session,omitempty"` State string `json:"state,omitempty"` + FQDN struct { + AddressFamily string `json:"addressFamily,omitempty"` + AutoPopulate string `json:"autopopulate,omitempty"` + DownInterval int `json:"downInterval,omitempty"` + Interval string `json:"interval,omitempty"` + Name string `json:"tmName,omitempty"` + } `json:"fqdn,omitempty"` } // DataGroups contains a list of data groups on the BIG-IP system. @@ -506,24 +175,37 @@ type DataGroup struct { Records []DataGroupRecord } +type DataGroupRecords struct { + Items []DataGroupRecord `json:"items,omitempty"` +} + type DataGroupRecord struct { Name string `json:"name,omitempty"` Data string `json:"data,omitempty"` } type dataGroupDTO struct { - Name string `json:"name,omitempty"` - Partition string `json:"partition,omitempty"` - FullPath string `json:"fullPath,omitempty"` - Generation int `json:"generation,omitempty"` - Type string `json:"type,omitempty"` - Records []DataGroupRecord `json:"records,omitempty"` + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` + Generation int `json:"generation,omitempty"` + Type string `json:"type,omitempty"` + Records struct { + Items []DataGroupRecord `json:"items,omitempty"` + } `json:"recordsReference,omitempty"` } func (p *DataGroup) MarshalJSON() ([]byte, error) { - var dto dataGroupDTO - marshal(&dto, p) - return json.Marshal(dto) + return json.Marshal(dataGroupDTO{ + Name: p.Name, + Partition: p.Partition, + FullPath: p.FullPath, + Generation: p.Generation, + Type: p.Type, + Records: struct { + Items []DataGroupRecord `json:"items,omitempty"` + }{Items: p.Records}, + }) } func (p *DataGroup) UnmarshalJSON(b []byte) error { @@ -532,7 +214,14 @@ func (p *DataGroup) UnmarshalJSON(b []byte) error { if err != nil { return err } - return marshal(p, &dto) + + p.Name = dto.Name + p.Partition = dto.Partition + p.Type = dto.Type + p.FullPath = dto.FullPath + p.Generation = dto.Generation + p.Records = dto.Records.Items + return nil } // SnatPools contains a list of every snatpool on the BIG-IP system. @@ -578,9 +267,9 @@ type Pool struct { QueueDepthLimit int `json:"queueDepthLimit,omitempty"` QueueOnConnectionLimit string `json:"queueOnConnectionLimit,omitempty"` QueueTimeLimit int `json:"queueTimeLimit,omitempty"` - ReselectTries int `json:"reselectTries,omitempty"` + ReselectTries int `json:"reselectTries"` ServiceDownAction string `json:"serviceDownAction,omitempty"` - SlowRampTime int `json:"slowRampTime,omitempty"` + SlowRampTime int `json:"slowRampTime"` } // Pool Members contains a list of pool members within a pool on the BIG-IP system. @@ -640,9 +329,9 @@ type poolDTO struct { QueueDepthLimit int `json:"queueDepthLimit,omitempty"` QueueOnConnectionLimit string `json:"queueOnConnectionLimit,omitempty"` QueueTimeLimit int `json:"queueTimeLimit,omitempty"` - ReselectTries int `json:"reselectTries,omitempty"` + ReselectTries int `json:"reselectTries"` ServiceDownAction string `json:"serviceDownAction,omitempty"` - SlowRampTime int `json:"slowRampTime,omitempty"` + SlowRampTime int `json:"slowRampTime"` } func (p *Pool) MarshalJSON() ([]byte, error) { @@ -660,78 +349,216 @@ func (p *Pool) UnmarshalJSON(b []byte) error { return marshal(p, &dto) } -// VirtualServers contains a list of all virtual servers on the BIG-IP system. -type VirtualServers struct { - VirtualServers []VirtualServer `json:"items"` +// PersistenceProfiles contains of list of persistence profiles +type PersistenceProfiles struct { + PersistenceProfiles []PersistenceProfile `json:"items"` } -// VirtualServer contains information about each individual virtual server. -type VirtualServer struct { - Name string `json:"name,omitempty"` - Partition string `json:"partition,omitempty"` - FullPath string `json:"fullPath,omitempty"` - Generation int `json:"generation,omitempty"` - AddressStatus string `json:"addressStatus,omitempty"` - AutoLastHop string `json:"autoLastHop,omitempty"` - CMPEnabled string `json:"cmpEnabled,omitempty"` - ConnectionLimit int `json:"connectionLimit,omitempty"` - Destination string `json:"destination,omitempty"` - Description string `json:"description,omitempty"` - Enabled bool `json:"enabled,omitempty"` - FallbackPersistenceProfile string `json:"fallbackPersistence,omitempty"` - GTMScore int `json:"gtmScore,omitempty"` - IPProtocol string `json:"ipProtocol,omitempty"` - Mask string `json:"mask,omitempty"` - Mirror string `json:"mirror,omitempty"` - MobileAppTunnel string `json:"mobileAppTunnel,omitempty"` - NAT64 string `json:"nat64,omitempty"` - Pool string `json:"pool,omitempty"` - RateLimit string `json:"rateLimit,omitempty"` - RateLimitDestinationMask int `json:"rateLimitDstMask,omitempty"` - RateLimitMode string `json:"rateLimitMode,omitempty"` - RateLimitSourceMask int `json:"rateLimitSrcMask,omitempty"` - Source string `json:"source,omitempty"` - SourceAddressTranslation struct { - Type string `json:"type,omitempty"` - Pool string `json:"pool,omitempty"` - } `json:"sourceAddressTranslation,omitempty"` - SourcePort string `json:"sourcePort,omitempty"` - SYNCookieStatus string `json:"synCookieStatus,omitempty"` - TranslateAddress string `json:"translateAddress,omitempty"` - TranslatePort string `json:"translatePort,omitempty"` - VlansEnabled bool `json:"vlansEnabled,omitempty"` - VlansDisabled bool `json:"vlansDisabled,omitempty"` - VSIndex int `json:"vsIndex,omitempty"` - Vlans []string `json:"vlans,omitempty"` - Rules []string `json:"rules,omitempty"` - PersistenceProfiles []Profile `json:"persist,omitempty"` - Profiles []Profile `json:"profiles,omitempty"` - Policies []string `json:"policies,omitempty"` +// PersistenceProfile is a base for all persistence profiles +type PersistenceProfile struct { + AppService string `json:"appService,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + FullPath string `json:"fullPath,omitempty"` + MatchAcrossPools string `json:"matchAcrossPools,omitempty"` + MatchAcrossServices string `json:"matchAcrossServices,omitempty"` + MatchAcrossVirtuals string `json:"matchAcrossVirtuals,omitempty"` + Method string `json:"method,omitempty"` + Mirror string `json:"mirror,omitempty"` + Mode string `json:"mode,omitempty"` + Name string `json:"name,omitempty"` + OverrideConnectionLimit string `json:"overrideConnectionLimit,omitempty"` + Partition string `json:"partition,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + Timeout string `json:"timeout,omitempty"` } -// VirtualAddresses contains a list of all virtual addresses on the BIG-IP system. -type VirtualAddresses struct { - VirtualAddresses []VirtualAddress `json:"items"` +// CookiePersistenceProfiles contains a list of all cookies profiles +type CookiePersistenceProfiles struct { + CookiePersistenceProfiles []CookiePersistenceProfile `json:"items"` } -// VirtualAddress contains information about each individual virtual address. -type VirtualAddress struct { - Name string - Partition string - FullPath string - Generation int - Address string - ARP bool - AutoDelete bool - ConnectionLimit int - Enabled bool - Floating bool - ICMPEcho bool - InheritedTrafficGroup bool - Mask string - RouteAdvertisement bool - ServerScope string - TrafficGroup string +// CookiePersistenceProfile Defines a single cookie profile +type CookiePersistenceProfile struct { + PersistenceProfile + AlwaysSend string `json:"alwaysSend,omitempty"` + CookieEncryption string `json:"cookieEncryption,omitempty"` + CookieEncryptionPassphrase string `json:"cookieEncryptionPassphrase,omitempty"` + CookieName string `json:"cookieName,omitempty"` + Expiration string `json:"expiration,omitempty"` + HashLength int `json:"hashLength,omitempty"` + HashOffset int `json:"hashOffset,omitempty"` + HTTPOnly string `json:"httponly,omitempty"` + Secure string `json:"secure,omitempty"` +} + +// DestAddrPersistenceProfiles contains a list of all dest-addr profiles +type DestAddrPersistenceProfiles struct { + DestAddrPersistenceProfiles []DestAddrPersistenceProfile `json:"items"` +} + +// DestAddrPersistenceProfile Defines a single dest-addr profile +type DestAddrPersistenceProfile struct { + PersistenceProfile + HashAlgorithm string `json:"hashAlgorithm,omitempty"` + Mask string `json:"mask,omitempty"` +} + +// HashPersistenceProfiles contains a list of all hash profiles +type HashPersistenceProfiles struct { + HashPersistenceProfiles []HashPersistenceProfile `json:"items"` +} + +// HashPersistenceProfile Defines a single hash profile +type HashPersistenceProfile struct { + PersistenceProfile + HashAlgorithm string `json:"hashAlgorithm,omitempty"` + HashBufferLimit int `json:"hashBufferLimit,omitempty"` + HashEndPattern int `json:"hashEndPattern,omitempty"` + HashLength int `json:"hashLength,omitempty"` + HashOffset int `json:"hashOffset,omitempty"` + HashStartPattern int `json:"hashStartPattern,omitempty"` +} + +// HostPersistenceProfiles contains a list of all host profiles +type HostPersistenceProfiles struct { + HostPersistenceProfiles []HostPersistenceProfile `json:"items"` +} + +// HostPersistenceProfile Defines a single host profile +type HostPersistenceProfile struct { + PersistenceProfile +} + +// MSRDPPersistenceProfiles contains a list of all msrdp profiles +type MSRDPPersistenceProfiles struct { + MSRDPPersistenceProfiles []MSRDPPersistenceProfile `json:"items"` +} + +// MSRDPPersistenceProfile Defines a single msrdp profile +type MSRDPPersistenceProfile struct { + PersistenceProfile + HasSessionDir string `json:"hasSessionDir,omitempty"` +} + +// SIPPersistenceProfiles contains a list of all sip profiles +type SIPPersistenceProfiles struct { + SIPPersistenceProfiles []SIPPersistenceProfile `json:"items"` +} + +// SIPPersistenceProfile Defines a single sip profile +type SIPPersistenceProfile struct { + PersistenceProfile + SIPInfo string `json:"sipInfo,omitempty"` +} + +// SourceAddrPersistenceProfiles contains a list of all source-addr profiles +type SourceAddrPersistenceProfiles struct { + SourceAddrPersistenceProfiles []SourceAddrPersistenceProfile `json:"items"` +} + +// SourceAddrPersistenceProfile Defines a single source-addr profile +type SourceAddrPersistenceProfile struct { + PersistenceProfile + HashAlgorithm string `json:"hashAlgorithm,omitempty"` + MapProxies string `json:"mapProxies,omitempty"` + MapProxyAddress string `json:"mapProxyAddress,omitempty"` + MapProxyClass string `json:"mapProxyClass,omitempty"` + Mask string `json:"mask,omitempty"` +} + +// SSLPersistenceProfiles contains a list of all ssl profiles +type SSLPersistenceProfiles struct { + SSLPersistenceProfiles []SSLPersistenceProfile `json:"items"` +} + +// SSLPersistenceProfile Defines a single ssl profile +type SSLPersistenceProfile struct { + PersistenceProfile +} + +// UniversalPersistenceProfiles contains a list of all universal profiles +type UniversalPersistenceProfiles struct { + SSLPersistenceProfiles []UniversalPersistenceProfile `json:"items"` +} + +// UniversalPersistenceProfile Defines a single universal profile +type UniversalPersistenceProfile struct { + PersistenceProfile + Rule string `json:"rule,omitempty"` +} + +// VirtualServers contains a list of all virtual servers on the BIG-IP system. +type VirtualServers struct { + VirtualServers []VirtualServer `json:"items"` +} + +// VirtualServer contains information about each individual virtual server. +type VirtualServer struct { + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` + Generation int `json:"generation,omitempty"` + AddressStatus string `json:"addressStatus,omitempty"` + AutoLastHop string `json:"autoLastHop,omitempty"` + CMPEnabled string `json:"cmpEnabled,omitempty"` + ConnectionLimit int `json:"connectionLimit,omitempty"` + Destination string `json:"destination,omitempty"` + Enabled bool `json:"enabled,omitempty"` + GTMScore int `json:"gtmScore,omitempty"` + FallbackPersistenceProfile string `json:"fallbackPersistence,omitempty"` + IPProtocol string `json:"ipProtocol,omitempty"` + Mask string `json:"mask,omitempty"` + Mirror string `json:"mirror,omitempty"` + MobileAppTunnel string `json:"mobileAppTunnel,omitempty"` + NAT64 string `json:"nat64,omitempty"` + Pool string `json:"pool,omitempty"` + RateLimit string `json:"rateLimit,omitempty"` + RateLimitDestinationMask int `json:"rateLimitDstMask,omitempty"` + RateLimitMode string `json:"rateLimitMode,omitempty"` + RateLimitSourceMask int `json:"rateLimitSrcMask,omitempty"` + Source string `json:"source,omitempty"` + SourceAddressTranslation struct { + Type string `json:"type,omitempty"` + Pool string `json:"pool,omitempty"` + } `json:"sourceAddressTranslation,omitempty"` + SourcePort string `json:"sourcePort,omitempty"` + SYNCookieStatus string `json:"synCookieStatus,omitempty"` + TranslateAddress string `json:"translateAddress,omitempty"` + TranslatePort string `json:"translatePort,omitempty"` + VlansEnabled bool `json:"vlansEnabled,omitempty"` + VlansDisabled bool `json:"vlansDisabled,omitempty"` + VSIndex int `json:"vsIndex,omitempty"` + Vlans []string `json:"vlans,omitempty"` + Rules []string `json:"rules,omitempty"` + PersistenceProfiles []Profile `json:"persist,omitempty"` + Profiles []Profile `json:"profiles,omitempty"` + Policies []string `json:"policies,omitempty"` +} + +// VirtualAddresses contains a list of all virtual addresses on the BIG-IP system. +type VirtualAddresses struct { + VirtualAddresses []VirtualAddress `json:"items"` +} + +// VirtualAddress contains information about each individual virtual address. +type VirtualAddress struct { + Name string + Partition string + FullPath string + Generation int + Address string + ARP bool + AutoDelete bool + ConnectionLimit int + Enabled bool + Floating bool + ICMPEcho bool + InheritedTrafficGroup bool + Mask string + RouteAdvertisement bool + ServerScope string + TrafficGroup string Unit int } @@ -763,8 +590,13 @@ type VirtualServerPolicies struct { PolicyRef Policies `json:"policiesReference"` } +type PolicyPublish struct { + Name string `json:"name"` + PublishCopy string `json:"publishedCopy"` +} type Policy struct { Name string + PublishCopy string Partition string FullPath string Controls []string @@ -775,6 +607,7 @@ type Policy struct { type policyDTO struct { Name string `json:"name"` + PublishCopy string `json:"publishedCopy"` Partition string `json:"partition,omitempty"` Controls []string `json:"controls,omitempty"` Requires []string `json:"requires,omitempty"` @@ -788,6 +621,7 @@ type policyDTO struct { func (p *Policy) MarshalJSON() ([]byte, error) { return json.Marshal(policyDTO{ Name: p.Name, + PublishCopy: p.PublishCopy, Partition: p.Partition, Controls: p.Controls, Requires: p.Requires, @@ -807,6 +641,7 @@ func (p *Policy) UnmarshalJSON(b []byte) error { } p.Name = dto.Name + p.PublishCopy = dto.PublishCopy p.Partition = dto.Partition p.Controls = dto.Controls p.Requires = dto.Requires @@ -1080,6 +915,8 @@ type PolicyRuleCondition struct { VlanId bool `json:"vlanId,omitempty"` } + + func (p *VirtualAddress) MarshalJSON() ([]byte, error) { var dto virtualAddressDTO marshal(&dto, p) @@ -1104,53 +941,48 @@ type Monitors struct { type Monitor struct { Name string Partition string + DefaultsFrom string FullPath string Generation int ParentMonitor string - Database string Description string Destination string Interval int IPDSCP int - ManualResume bool - MonitorType string + ManualResume string Password string - ReceiveColumn string - ReceiveRow string ReceiveString string ReceiveDisable string - Reverse bool + Reverse string SendString string TimeUntilUp int Timeout int - Transparent bool + Transparent string UpInterval int Username string + } type monitorDTO struct { - Name string `json:"name,omitempty"` - Partition string `json:"partition,omitempty"` - FullPath string `json:"fullPath,omitempty"` - Generation int `json:"generation,omitempty"` - ParentMonitor string `json:"defaultsFrom,omitempty"` - Database string `json:"database,omitempty"` - Description string `json:"description,omitempty"` - Destination string `json:"destination,omitempty"` - Interval int `json:"interval,omitempty"` - IPDSCP int `json:"ipDscp,omitempty"` - ManualResume string `json:"manualResume,omitempty" bool:"enabled"` - // MonitorType string `json:"monitorType,omitempty"` + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + FullPath string `json:"fullPath,omitempty"` + Generation int `json:"generation,omitempty"` + ParentMonitor string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + Destination string `json:"destination,omitempty"` + Interval int `json:"interval,omitempty"` + IPDSCP int `json:"ipDscp,omitempty"` + ManualResume string `json:"manualResume,omitempty"` Password string `json:"password,omitempty"` - ReceiveColumn string `json:"recvColumn,omitempty"` - ReceiveRow string `json:"recvRow,omitempty"` ReceiveString string `json:"recv,omitempty"` ReceiveDisable string `json:"recvDisable,omitempty"` - Reverse string `json:"reverse,omitempty" bool:"enabled"` + Reverse string `json:"reverse,omitempty"` SendString string `json:"send,omitempty"` TimeUntilUp int `json:"timeUntilUp,omitempty"` Timeout int `json:"timeout,omitempty"` - Transparent string `json:"transparent,omitempty" bool:"enabled"` + Transparent string `json:"transparent,omitempty"` UpInterval int `json:"upInterval,omitempty"` Username string `json:"username,omitempty"` } @@ -1515,31 +1347,52 @@ type Snat struct { Partition string FullPath string AutoLasthop string - Mirror bool + Mirror string SourcePort string Translation string Snatpool string VlansDisabled bool - Origins []string + Origins []Originsrecord } type snatDTO struct { - Name string `json:"name"` - Partition string `json:"partition,omitempty"` - FullPath string `json:"fullPath,omitempty"` - AutoLasthop string `json:"autoLastHop,omitempty"` - Mirror bool `json:"mirror,omitempty" bool:"disabled"` - SourcePort string `json:"sourePort,omitempty"` - Translation string `json:"translation,omitempty"` - Snatpool string `json:"snatpool,omitempty"` - VlansDisabled bool `json:"vlansDisabled,omitempty" bool:"disabled"` - Origins []string `json:"origins,omitempty"` + Name string `json:"name"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` + AutoLasthop string `json:"autoLastHop,omitempty"` + Mirror string `json:"mirror,omitempty"` + SourcePort string `json:"sourePort,omitempty"` + Translation string `json:"translation,omitempty"` + Snatpool string `json:"snatpool,omitempty"` + VlansDisabled bool `json:"vlansDisabled,omitempty" bool:"disabled"` + Origins struct { + Items []Originsrecord `json:"items,omitempty"` + } `json:"originsReference,omitempty"` +} + +type Originsrecords struct { + Items []Originsrecord `json:"items,omitempty"` +} + +type Originsrecord struct { + Name string `json:"name"` + app_service string `json:"appService,omitempty"` } func (p *Snat) MarshalJSON() ([]byte, error) { - var dto snatDTO - marshal(&dto, p) - return json.Marshal(dto) + return json.Marshal(snatDTO{ + Name: p.Name, + Partition: p.Partition, + FullPath: p.FullPath, + Mirror: p.Mirror, + SourcePort: p.SourcePort, + Translation: p.Translation, + Snatpool: p.Snatpool, + VlansDisabled: p.VlansDisabled, + Origins: struct { + Items []Originsrecord `json:"items,omitempty"` + }{Items: p.Origins}, + }) } func (p *Snat) UnmarshalJSON(b []byte) error { @@ -1548,8 +1401,18 @@ func (p *Snat) UnmarshalJSON(b []byte) error { if err != nil { return err } - p.Origins = dto.Origins - //return marshal(p, &dto) + + p.Name = dto.Name + p.Partition = dto.Partition + p.FullPath = dto.FullPath + p.AutoLasthop = dto.AutoLasthop + p.Mirror = dto.Mirror + p.SourcePort = dto.SourcePort + p.Translation = dto.Translation + p.Snatpool = dto.Snatpool + p.VlansDisabled = dto.VlansDisabled + p.Origins = dto.Origins.Items + return nil } @@ -1617,7 +1480,6 @@ const ( uriHttp2 = "http2" uriSnat = "snat" uriSnatpool = "snatpool" - uriUdp = "udp" uriCookie = "cookie" uriDestAddr = "dest-addr" uriHash = "hash" @@ -1695,13 +1557,13 @@ func (b *BigIP) AddSnatPool(config *SnatPool) error { // GetSnatPool retrieves a SnatPool by name. Returns nil if the snatpool does not exist func (b *BigIP) GetSnatPool(name string) (*SnatPool, error) { var snatPool SnatPool - err, ok := b.getForEntity(&snatPool, uriLtm, uriSnatPool, name) + err, _ := b.getForEntity(&snatPool, uriLtm, uriSnatPool, name) if err != nil { return nil, err } - if !ok { - return nil, nil - } + //if !ok { + // return nil, nil + //} return &snatPool, nil } @@ -2548,16 +2410,36 @@ func (b *BigIP) Nodes() (*Nodes, error) { return &nodes, nil } -// CreateNode adds a new node to the BIG-IP system. -func (b *BigIP) CreateNode(name, address string) error { +// CreateNode adds a new IP based node to the BIG-IP system. +func (b *BigIP) CreateNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state string) error { config := &Node{ Name: name, Address: address, + RateLimit: rate_limit, + ConnectionLimit: connection_limit, + DynamicRatio: dynamic_ratio, + Monitor: monitor, + State: state, } return b.post(config, uriLtm, uriNode) } +// CreateFQDNNode adds a new FQDN based node to the BIG-IP system. +func (b *BigIP) CreateFQDNNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state string) error { + config := &Node{ + Name: name, + RateLimit: rate_limit, + ConnectionLimit: connection_limit, + DynamicRatio: dynamic_ratio, + Monitor: monitor, + State: state, + } + config.FQDN.Name = address + + return b.post(config, uriLtm, uriNode) +} + // Get a Node by name. Returns nil if the node does not exist func (b *BigIP) GetNode(name string) (*Node, error) { var node Node @@ -2826,7 +2708,7 @@ func (b *BigIP) VirtualServers() (*VirtualServers, error) { // CreateVirtualServer adds a new virtual server to the BIG-IP system. can either be // in CIDR notation or decimal, i.e.: "24" or "255.255.255.0". A CIDR mask of "0" is the same // as "0.0.0.0". -func (b *BigIP) CreateVirtualServer(name, destination, mask, pool string, port int) error { +func (b *BigIP) CreateVirtualServer(name, destination, mask, pool string, vlans_enabled, vlans_disabled bool, port int, translate_address, translate_port string) error { subnetMask := cidr[mask] if strings.Contains(mask, ".") { @@ -2834,10 +2716,12 @@ func (b *BigIP) CreateVirtualServer(name, destination, mask, pool string, port i } config := &VirtualServer{ - Name: name, - Destination: fmt.Sprintf("%s:%d", destination, port), - Mask: subnetMask, - Pool: pool, + Name: name, + Destination: fmt.Sprintf("%s:%d", destination, port), + Mask: subnetMask, + Pool: pool, + TranslateAddress: translate_address, + TranslatePort: translate_port, } return b.post(config, uriLtm, uriVirtual) @@ -3097,7 +2981,12 @@ func (b *BigIP) Policies() (*Policies, error) { //Load a fully policy definition. Policies seem to be best dealt with as one big entity. func (b *BigIP) GetPolicy(name string) (*Policy, error) { var p Policy - err, ok := b.getForEntity(&p, uriLtm, uriPolicy, name) + values := []string{} + values = append(values, "Drafts/") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") + err, ok := b.getForEntity(&p, uriLtm, uriPolicy, result) if err != nil { return nil, err } @@ -3150,18 +3039,42 @@ func (b *BigIP) CreatePolicy(p *Policy) error { return b.post(p, uriLtm, uriPolicy) } +func (b *BigIP) PublishPolicy(name, publish string) error { + config := &Policy{ + PublishCopy: publish, + } + values := []string{} + values = append(values, "~Common~Drafts~") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") + + log.Println( " ================== here in publish ", result, publish) + + return b.patch(config, uriLtm, uriPolicy, result) +} + //Update an existing policy. -func (b *BigIP) UpdatePolicy(name string, p *Policy) error { + func (b *BigIP) UpdatePolicy(name string, p *Policy) error { normalizePolicy(p) - return b.put(p, uriLtm, uriPolicy, name) + values := []string{} + values = append(values, "Drafts/") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") + return b.put(p, uriLtm, uriPolicy, result) } //Delete a policy by name. func (b *BigIP) DeletePolicy(name string) error { - return b.delete(uriLtm, uriPolicy, name) -} - -// Oneconnect profile creation + values := []string{} + values = append(values, "Drafts/") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") +return b.delete(uriLtm, uriPolicy, result) +} + // Oneconnect profile creation func (b *BigIP) CreateOneconnect(name, idleTimeoutOverride, partition, defaultsFrom, sharePools, sourceMask string, maxAge, maxReuse, maxSize int) error { oneconnect := &Oneconnect{ Name: name, @@ -3177,15 +3090,17 @@ func (b *BigIP) CreateOneconnect(name, idleTimeoutOverride, partition, defaultsF return b.post(oneconnect, uriLtm, uriProfile, uriOneconnect) } -func (b *BigIP) Oneconnect(name string) (*Oneconnects, error) { - var oneconnects Oneconnects - err, _ := b.getForEntity(&oneconnects, uriLtm, uriProfile, uriOneconnect) - +func (b *BigIP) GetOneconnect(name string) (*Oneconnect, error) { + var oneconnect Oneconnect + err, ok := b.getForEntity(&oneconnect, uriLtm, uriProfile, uriOneconnect, name) if err != nil { return nil, err } + if !ok { + return nil, nil + } - return &oneconnects, nil + return &oneconnect, nil } // DeleteOneconnect removes an OneConnect profile from the system. @@ -3228,15 +3143,17 @@ func (b *BigIP) ModifyTcp(name string, tcp *Tcp) error { return b.put(tcp, uriLtm, uriProfile, uriTcp, name) } -func (b *BigIP) Tcp(name string) (*Tcps, error) { - var tcps Tcps - err, _ := b.getForEntity(&tcps, uriLtm, uriProfile, uriTcp) - +func (b *BigIP) GetTcp(name string) (*Tcp, error) { + var tcp Tcp + err, ok := b.getForEntity(&tcp, uriLtm, uriProfile, uriTcp, name) if err != nil { return nil, err } + if !ok { + return nil, nil + } - return &tcps, nil + return &tcp, nil } func (b *BigIP) CreateFasthttp(name, defaultsFrom string, idleTimeout, connpoolIdleTimeoutOverride, connpoolMaxReuse, connpoolMaxSize, connpoolMinSize int, connpoolReplenish string, connpoolStep int, forceHttp_10Response string, maxHeaderSize int) error { @@ -3267,15 +3184,15 @@ func (b *BigIP) ModifyFasthttp(name string, fasthttp *Fasthttp) error { return b.put(fasthttp, uriLtm, uriProfile, uriFasthttp, name) } -func (b *BigIP) Fasthttp() (*Fasthttps, error) { - var fasthttps Fasthttps - err, _ := b.getForEntity(&fasthttps, uriLtm, uriProfile, uriFasthttp) +func (b *BigIP) GetFasthttp(name string) (*Fasthttp, error) { + var fasthttp Fasthttp + err, _ := b.getForEntity(&fasthttp, uriLtm, uriProfile, uriFasthttp) if err != nil { return nil, err } - return &fasthttps, nil + return &fasthttp, nil } func (b *BigIP) CreateFastl4(name, partition, defaultsFrom string, clientTimeout int, explicitFlowMigration, hardwareSynCookie string, idleTimeout string, ipTosToClient, ipTosToServer, keepAliveInterval string) error { @@ -3305,15 +3222,17 @@ func (b *BigIP) ModifyFastl4(name string, fastl4 *Fastl4) error { return b.put(fastl4, uriLtm, uriProfile, uriFastl4, name) } -func (b *BigIP) Fastl4(name string) (*Fastl4s, error) { - var fastl4s Fastl4s - err, _ := b.getForEntity(&fastl4s, uriLtm, uriProfile, uriFastl4) - +func (b *BigIP) GetFastl4(name string) (*Fastl4, error) { + var fastl4 Fastl4 + err, ok := b.getForEntity(&fastl4, uriLtm, uriProfile, uriFastl4, name) if err != nil { return nil, err } + if !ok { + return nil, nil + } - return &fastl4s, nil + return &fastl4, nil } // =============== @@ -3339,15 +3258,17 @@ func (b *BigIP) ModifyHttpcompress(name string, httpcompress *Httpcompress) erro return b.put(httpcompress, uriLtm, uriProfile, uriHttpcompress, name) } -func (b *BigIP) Httpcompress() (*Httpcompresss, error) { - var httpcompresss Httpcompresss - err, _ := b.getForEntity(&httpcompresss, uriLtm, uriProfile, uriHttpcompress) - +func (b *BigIP) GetHttpcompress(name string) (*Httpcompress, error) { + var httpcompress Httpcompress + err, ok := b.getForEntity(&httpcompress, uriLtm, uriProfile, uriHttpcompress, name) if err != nil { return nil, err } + if !ok { + return nil, nil + } - return &httpcompresss, nil + return &httpcompress, nil } func (b *BigIP) CreateHttp2(name, defaultsFrom string, concurrentStreamsPerConnection, connectionIdleTimeout, headerTableSize int, activationModes []string) error { @@ -3373,15 +3294,17 @@ func (b *BigIP) ModifyHttp2(name string, http2 *Http2) error { return b.put(http2, uriLtm, uriProfile, uriHttp2, name) } -func (b *BigIP) Http2() (*Http2s, error) { - var http2s Http2s - err, _ := b.getForEntity(&http2s, uriLtm, uriProfile, uriHttp2) - +func (b *BigIP) GetHttp2(name string) (*Http2, error) { + var http2 Http2 + err, ok := b.getForEntity(&http2, uriLtm, uriProfile, uriHttp2, name) if err != nil { return nil, err } + if !ok { + return nil, nil + } - return &http2s, nil + return &http2, nil } // Datagroups returns a list of datagroups. @@ -3432,7 +3355,7 @@ func (b *BigIP) AddRecords(name, rname, data string) error { } // Snats returns a list of snat -func (b *BigIP) Snats(name string) (*Snats, error) { +/*func (b *BigIP) Snats(name string) (*Snats, error) { var snats Snats err, _ := b.getForEntity(&snats, uriLtm, uriSnat, name) @@ -3441,9 +3364,9 @@ func (b *BigIP) Snats(name string) (*Snats, error) { } return &snats, nil -} +}*/ -func (b *BigIP) CreateSnat(name, partition, autoLastHop, sourcePort, translation, snatpool string, vlansDisabled, mirror bool, origins []string) error { +/*func (b *BigIP) CreateSnat(name, partition, autoLastHop, sourcePort, translation, snatpool, mirror string, vlansDisabled bool, origins []string) error { snat := &Snat{ Name: name, Partition: partition, @@ -3457,6 +3380,10 @@ func (b *BigIP) CreateSnat(name, partition, autoLastHop, sourcePort, translation } log.Println("[INFO] Creating snat ", snat) return b.post(snat, uriLtm, uriSnat) +} */ +func (b *BigIP) CreateSnat(p *Snat) error { + log.Println(" what is the complete payload ", p) + return b.post(p, uriLtm, uriSnat) } func (b *BigIP) ModifySnat(config *Snat) error { @@ -3481,6 +3408,10 @@ func (b *BigIP) DeleteSnat(name string) error { return b.delete(uriLtm, uriSnat, name) } +func (b *BigIP) UpdateSnat(name string, p *Snat) error { + return b.put(p, uriLtm, uriSnat, name) +} + // Snats returns a list of snat func (b *BigIP) Snatpools(name string) (*Snatpools, error) { var snatpools Snatpools @@ -3524,3 +3455,471 @@ func (b *BigIP) GetSnatpool(name string) (*Snatpool, error) { func (b *BigIP) DeleteSnatpool(name string) error { return b.delete(uriLtm, uriSnatpool, name) } + +// CookiePersistenceProfiles returns a list of cookie persist profiles +func (b *BigIP) CookiePersistenceProfiles() (*CookiePersistenceProfiles, error) { + var cookiePersistenceProfiles CookiePersistenceProfiles + err, _ := b.getForEntity(&cookiePersistenceProfiles, uriLtm, uriPersistence, uriCookie) + if err != nil { + return nil, err + } + + return &cookiePersistenceProfiles, nil +} + +// GetCookiePersistenceProfile gets a single cookie persist profile by name +func (b *BigIP) GetCookiePersistenceProfile(name string) (*CookiePersistenceProfile, error) { + var cookiePersistenceProfile CookiePersistenceProfile + err, ok := b.getForEntity(&cookiePersistenceProfile, uriLtm, uriPersistence, uriCookie, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &cookiePersistenceProfile, nil +} + +// CreateCookiePersistenceProfile creates a new cookie persist profile on the BIG-IP system. +func (b *BigIP) CreateCookiePersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriCookie) +} + +// AddCookiePersistenceProfile adds a cookie persist profile to the BIG-IP system +func (b *BigIP) AddCookiePersistenceProfile(config *CookiePersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriCookie) +} + +// DeleteCookiePersistenceProfile removes a cookie persist profile. +func (b *BigIP) DeleteCookiePersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriCookie, name) +} + +// ModifyCookiePersistenceProfile allows you to change any attribute of a cookie persist profile. +// Fields that can be modified are referenced in the CookiePersistenceProfile struct. +func (b *BigIP) ModifyCookiePersistenceProfile(name string, config *CookiePersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriCookie, name) +} + +// DestAddrPersistenceProfiles returns a list of dest-addr persist profiles +func (b *BigIP) DestAddrPersistenceProfiles() (*DestAddrPersistenceProfiles, error) { + var destAddrPersistenceProfiles DestAddrPersistenceProfiles + err, _ := b.getForEntity(&destAddrPersistenceProfiles, uriLtm, uriPersistence, uriDestAddr) + if err != nil { + return nil, err + } + + return &destAddrPersistenceProfiles, nil +} + +// GetDestAddrPersistenceProfile gets a single dest-addr persist profile by name +func (b *BigIP) GetDestAddrPersistenceProfile(name string) (*DestAddrPersistenceProfile, error) { + var destAddrPersistenceProfile DestAddrPersistenceProfile + err, ok := b.getForEntity(&destAddrPersistenceProfile, uriLtm, uriPersistence, uriDestAddr, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &destAddrPersistenceProfile, nil +} + +// CreateDestAddrPersistenceProfile creates a new dest-addr persist profile on the BIG-IP system. +func (b *BigIP) CreateDestAddrPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriDestAddr) +} + +// AddDestAddrPersistenceProfile adds a dest-addr persist profile to the BIG-IP system +func (b *BigIP) AddDestAddrPersistenceProfile(config *DestAddrPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriDestAddr) +} + +// DeleteDestAddrPersistenceProfile removes a dest-addr persist profile. +func (b *BigIP) DeleteDestAddrPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriDestAddr, name) +} + +// ModifyDestAddrPersistenceProfile allows you to change any attribute of a dest-addr persist profile. +// Fields that can be modified are referenced in the DestAddrPersistenceProfile struct. +func (b *BigIP) ModifyDestAddrPersistenceProfile(name string, config *DestAddrPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriDestAddr, name) +} + +// HashPersistenceProfiles returns a list of hash persist profiles +func (b *BigIP) HashPersistenceProfiles() (*HashPersistenceProfiles, error) { + var hashPersistenceProfiles HashPersistenceProfiles + err, _ := b.getForEntity(&hashPersistenceProfiles, uriLtm, uriPersistence, uriHash) + if err != nil { + return nil, err + } + + return &hashPersistenceProfiles, nil +} + +// GetHashPersistenceProfile gets a single hash persist profile by name +func (b *BigIP) GetHashPersistenceProfile(name string) (*HashPersistenceProfile, error) { + var hashPersistenceProfile HashPersistenceProfile + err, ok := b.getForEntity(&hashPersistenceProfile, uriLtm, uriPersistence, uriHash, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &hashPersistenceProfile, nil +} + +// CreateHashPersistenceProfile creates a new hash persist profile on the BIG-IP system. +func (b *BigIP) CreateHashPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriHash) +} + +// AddHashPersistenceProfile adds a hash persist profile to the BIG-IP system +func (b *BigIP) AddHashPersistenceProfile(config *HashPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriHash) +} + +// DeleteHashPersistenceProfile removes a dest-addr persist profile. +func (b *BigIP) DeleteHashPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriHash, name) +} + +// ModifyHashPersistenceProfile allows you to change any attribute of a hash persist profile. +// Fields that can be modified are referenced in the HashPersistenceProfile struct. +func (b *BigIP) ModifyHashPersistenceProfile(name string, config *HashPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriHash, name) +} + +// HostPersistenceProfiles returns a list of host persist profiles +func (b *BigIP) HostPersistenceProfiles() (*HostPersistenceProfiles, error) { + var hostPersistenceProfiles HostPersistenceProfiles + err, _ := b.getForEntity(&hostPersistenceProfiles, uriLtm, uriPersistence, uriHost) + if err != nil { + return nil, err + } + + return &hostPersistenceProfiles, nil +} + +// GetHostPersistenceProfile gets a single host persist profile by name +func (b *BigIP) GetHostPersistenceProfile(name string) (*HostPersistenceProfile, error) { + var hostPersistenceProfile HostPersistenceProfile + err, ok := b.getForEntity(&hostPersistenceProfile, uriLtm, uriPersistence, uriHost, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &hostPersistenceProfile, nil +} + +// CreateHostPersistenceProfile creates a new host persist profile on the BIG-IP system. +func (b *BigIP) CreateHostPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriHost) +} + +// AddHostPersistenceProfile adds a host persist profile to the BIG-IP system +func (b *BigIP) AddHostPersistenceProfile(config *HostPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriHost) +} + +// DeleteHashHostPersistenceProfile removes a host persist profile. +func (b *BigIP) DeleteHashHostPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriHost, name) +} + +// ModifyHostPersistenceProfile allows you to change any attribute of a host persist profile. +// Fields that can be modified are referenced in the HostPersistenceProfile struct. +func (b *BigIP) ModifyHostPersistenceProfile(name string, config *HostPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriHost, name) +} + +// MSRDPPersistenceProfiles returns a list of msrdp persist profiles +func (b *BigIP) MSRDPPersistenceProfiles() (*MSRDPPersistenceProfiles, error) { + var msrdpPersistenceProfiles MSRDPPersistenceProfiles + err, _ := b.getForEntity(&msrdpPersistenceProfiles, uriLtm, uriPersistence, uriMSRDP) + if err != nil { + return nil, err + } + + return &msrdpPersistenceProfiles, nil +} + +// GetMSRDPPersistenceProfile gets a single msrdp persist profile by name +func (b *BigIP) GetMSRDPPersistenceProfile(name string) (*MSRDPPersistenceProfile, error) { + var msrdpPersistenceProfile MSRDPPersistenceProfile + err, ok := b.getForEntity(&msrdpPersistenceProfile, uriLtm, uriPersistence, uriMSRDP, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &msrdpPersistenceProfile, nil +} + +// CreateMSRDPPersistenceProfile creates a new msrdp persist profile on the BIG-IP system. +func (b *BigIP) CreateMSRDPPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriMSRDP) +} + +// AddMSRDPPersistenceProfile adds a msrdp persist profile to the BIG-IP system +func (b *BigIP) AddMSRDPPersistenceProfile(config *MSRDPPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriMSRDP) +} + +// DeleteMSRDPPersistenceProfile removes a msrdp persist profile. +func (b *BigIP) DeleteMSRDPPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriMSRDP, name) +} + +// ModifyMSRDPPersistenceProfile allows you to change any attribute of a msrdp persist profile. +// Fields that can be modified are referenced in the MSRDPPersistenceProfile struct. +func (b *BigIP) ModifyMSRDPPersistenceProfile(name string, config *MSRDPPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriMSRDP, name) +} + +// SIPPersistenceProfiles returns a list of sip persist profiles +func (b *BigIP) SIPPersistenceProfiles() (*SIPPersistenceProfiles, error) { + var sipPersistenceProfiles SIPPersistenceProfiles + err, _ := b.getForEntity(&sipPersistenceProfiles, uriLtm, uriPersistence, uriSIP) + if err != nil { + return nil, err + } + + return &sipPersistenceProfiles, nil +} + +// GetSIPPersistenceProfile gets a single sip persist profile by name +func (b *BigIP) GetSIPPersistenceProfile(name string) (*SIPPersistenceProfile, error) { + var sipPersistenceProfile SIPPersistenceProfile + err, ok := b.getForEntity(&sipPersistenceProfile, uriLtm, uriPersistence, uriSIP, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &sipPersistenceProfile, nil +} + +// CreateSIPPersistenceProfile creates a new sip persist profile on the BIG-IP system. +func (b *BigIP) CreateSIPPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriSIP) +} + +// AddSIPPersistenceProfile adds a sip persist profile to the BIG-IP system +func (b *BigIP) AddSIPPersistenceProfile(config *SIPPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriSIP) +} + +// DeleteSIPPersistenceProfile removes a sip persist profile. +func (b *BigIP) DeleteSIPPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriSIP, name) +} + +// ModifySIPPersistenceProfile allows you to change any attribute of a sip persist profile. +// Fields that can be modified are referenced in the SIPPersistenceProfile struct. +func (b *BigIP) ModifySIPPersistenceProfile(name string, config *SIPPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriSIP, name) +} + +// SourceAddrPersistenceProfiles returns a list of source-addr persist profiles +func (b *BigIP) SourceAddrPersistenceProfiles() (*SourceAddrPersistenceProfiles, error) { + var sourceAddrPersistenceProfiles SourceAddrPersistenceProfiles + err, _ := b.getForEntity(&sourceAddrPersistenceProfiles, uriLtm, uriPersistence, uriSourceAddr) + if err != nil { + return nil, err + } + + return &sourceAddrPersistenceProfiles, nil +} + +// GetSourceAddrPersistenceProfile gets a single source-addr persist profile by name +func (b *BigIP) GetSourceAddrPersistenceProfile(name string) (*SourceAddrPersistenceProfile, error) { + var sourceAddrPersistenceProfile SourceAddrPersistenceProfile + err, ok := b.getForEntity(&sourceAddrPersistenceProfile, uriLtm, uriPersistence, uriSourceAddr, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &sourceAddrPersistenceProfile, nil +} + +// CreateSourceAddrPersistenceProfile creates a new source-addr persist profile on the BIG-IP system. +func (b *BigIP) CreateSourceAddrPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriSourceAddr) +} + +// AddSourceAddrPersistenceProfile adds a source-addr persist profile to the BIG-IP system +func (b *BigIP) AddSourceAddrPersistenceProfile(config *SourceAddrPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriSourceAddr) +} + +// DeleteSourceAddrPersistenceProfile removes a source-addr persist profile. +func (b *BigIP) DeleteSourceAddrPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriSourceAddr, name) +} + +// ModifySourceAddrPersistenceProfile allows you to change any attribute of a source-addr persist profile. +// Fields that can be modified are referenced in the SourceAddrPersistenceProfile struct. +func (b *BigIP) ModifySourceAddrPersistenceProfile(name string, config *SourceAddrPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriSourceAddr, name) +} + +// SSLPersistenceProfiles returns a list of ssl persist profiles +func (b *BigIP) SSLPersistenceProfiles() (*SSLPersistenceProfiles, error) { + var sslPersistenceProfiles SSLPersistenceProfiles + err, _ := b.getForEntity(&sslPersistenceProfiles, uriLtm, uriPersistence, uriSSL) + if err != nil { + return nil, err + } + + return &sslPersistenceProfiles, nil +} + +// GetSSLPersistenceProfile gets a single ssl persist profile by name +func (b *BigIP) GetSSLPersistenceProfile(name string) (*SSLPersistenceProfile, error) { + var sslPersistenceProfile SSLPersistenceProfile + err, ok := b.getForEntity(&sslPersistenceProfile, uriLtm, uriPersistence, uriSSL, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &sslPersistenceProfile, nil +} + +// CreateSSLPersistenceProfile creates a new ssl persist profile on the BIG-IP system. +func (b *BigIP) CreateSSLPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriSSL) +} + +// AddSSLPersistenceProfile adds a ssl persist profile to the BIG-IP system +func (b *BigIP) AddSSLPersistenceProfile(config *SSLPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriSSL) +} + +// DeleteSSLPersistenceProfile removes a ssl persist profile. +func (b *BigIP) DeleteSSLPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriSSL, name) +} + +// ModifySSLPersistenceProfile allows you to change any attribute of a ssl persist profile. +// Fields that can be modified are referenced in the SSLPersistenceProfile struct. +func (b *BigIP) ModifySSLPersistenceProfile(name string, config *SSLPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriSSL, name) +} + +// UniversalPersistenceProfiles returns a list of universal persist profiles +func (b *BigIP) UniversalPersistenceProfiles() (*UniversalPersistenceProfiles, error) { + var universalPersistenceProfiles UniversalPersistenceProfiles + err, _ := b.getForEntity(&universalPersistenceProfiles, uriLtm, uriPersistence, uriUniversal) + if err != nil { + return nil, err + } + + return &universalPersistenceProfiles, nil +} + +// GetUniversalPersistenceProfile gets a single universal persist profile by name +func (b *BigIP) GetUniversalPersistenceProfile(name string) (*UniversalPersistenceProfile, error) { + var universalPersistenceProfile UniversalPersistenceProfile + err, ok := b.getForEntity(&universalPersistenceProfile, uriLtm, uriPersistence, uriUniversal, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &universalPersistenceProfile, nil +} + +// CreateUniversalPersistenceProfile creates a new universal persist profile on the BIG-IP system. +func (b *BigIP) CreateUniversalPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriUniversal) +} + +// AddUniversalPersistenceProfile adds a universal persist profile to the BIG-IP system +func (b *BigIP) AddUniversalPersistenceProfile(config *UniversalPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriUniversal) +} + +// DeleteUniversalPersistenceProfile removes a universal persist profile. +func (b *BigIP) DeleteUniversalPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriUniversal, name) +} + +// ModifyUniversalPersistenceProfile allows you to change any attribute of a universal persist profile. +// Fields that can be modified are referenced in the UniversalPersistenceProfile struct. +func (b *BigIP) ModifyUniversalPersistenceProfile(name string, config *UniversalPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriUniversal, name) +} diff --git a/net.go b/net.go index 40509bf..4314c16 100644 --- a/net.go +++ b/net.go @@ -2,6 +2,8 @@ package bigip import ( "strings" + "log" + "fmt" ) // Interfaces contains a list of every interface on the BIG-IP system. @@ -196,8 +198,9 @@ func (b *BigIP) AddInterfaceToVlan(vlan, iface string, tagged bool) error { // SelfIPs returns a list of self IP's. func (b *BigIP) SelfIPs() (*SelfIPs, error) { var self SelfIPs - err, _ := b.getForEntity(&self, uriNet, uriSelf) + err, _:= b.getForEntity(&self, uriNet, uriSelf) if err != nil { + fmt.Println(" Please check reachability ", err) return nil, err } @@ -315,6 +318,24 @@ func (b *BigIP) Routes() (*Routes, error) { return &routes, nil } +func (b *BigIP) GetRoute(name string) (*Route, error) { + var route Route + values := []string{} + values = append(values, "~Common~") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") + err, ok := b.getForEntity(&route, uriNet, uriRoute, result) + if err != nil { + return nil, err + } + if !ok { + return nil, nil + } + + return &route, nil +} + // CreateRoute adds a new static route to the BIG-IP system. must include the // subnet mask in CIDR notation, i.e.: "10.1.1.0/24". func (b *BigIP) CreateRoute(name, dest, gateway string) error { @@ -335,7 +356,13 @@ func (b *BigIP) DeleteRoute(name string) error { // ModifyRoute allows you to change any attribute of a static route. Fields that // can be modified are referenced in the Route struct. func (b *BigIP) ModifyRoute(name string, config *Route) error { - return b.put(config, uriNet, uriRoute, name) + values := []string{} + values = append(values, "~Common~") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") + log.Println("value of result +======================", result) + return b.put(config, uriNet, uriRoute, result) } // RouteDomains returns a list of route domains. diff --git a/sys.go b/sys.go index c357881..362dad8 100644 --- a/sys.go +++ b/sys.go @@ -1,6 +1,9 @@ package bigip -import "encoding/json" +import ( + "encoding/json" + "log" +) type NTPs struct { NTPs []NTP `json:"items"` @@ -171,7 +174,6 @@ func (b *BigIP) NTPs() (*NTP, error) { if err != nil { return nil, err } - return &ntp, nil } @@ -189,6 +191,7 @@ func (b *BigIP) ModifyDNS(config *DNS) error { return b.put(config, uriSys, uriDNS) } +// DNS & NTP resource does not support Delete API func (b *BigIP) DNSs() (*DNS, error) { var dns DNS err, _ := b.getForEntity(&dns, uriSys, uriDNS) @@ -209,46 +212,87 @@ func (b *BigIP) CreateProvision(name string, fullPath string, cpuRatio int, disk Level: level, MemoryRatio: memoryRatio, } - if name == "/Common/asm" { + if fullPath == "/Common/asm" { return b.put(config, uriSys, uriProvision, uriAsm) } - if name == "/Common/afm" { + if fullPath == "/Common/afm" { return b.put(config, uriSys, uriProvision, uriAfm) + } - if name == "/Common/gtm" { + if fullPath == "/Common/gtm" { return b.put(config, uriSys, uriProvision, uriGtm) } - if name == "/Common/apm" { + if fullPath == "/Common/apm" { return b.put(config, uriSys, uriProvision, uriApm) } - if name == "/Common/avr" { + if fullPath == "/Common/avr" { return b.put(config, uriSys, uriProvision, uriAvr) } - if name == "/Common/ilx" { + if fullPath == "/Common/ilx" { return b.put(config, uriSys, uriProvision, uriIlx) } return nil } func (b *BigIP) ModifyProvision(config *Provision) error { - return b.put(config, uriSys, uriProvision, uriAfm) } func (b *BigIP) DeleteProvision(name string) error { + // Delete API does not exists for resource Provision return b.delete(uriSys, uriProvision, uriIlx, name) } -func (b *BigIP) Provisions() (*Provision, error) { +func (b *BigIP) Provisions(name string) (*Provision, error) { var provision Provision - err, _ := b.getForEntity(&provision, uriProvision, uriAfm) + if name == "afm" { + err, _ := b.getForEntity(&provision, uriSys, uriProvision, uriAfm) + + if err != nil { + return nil, err + } + } + if name == "asm" { + err, _ := b.getForEntity(&provision, uriSys, uriProvision, uriAsm) + + if err != nil { + return nil, err + } + } + if name == "gtm" { + err, _ := b.getForEntity(&provision, uriSys, uriProvision, uriGtm) + + if err != nil { + return nil, err + } + } + if name == "apm" { + err, _ := b.getForEntity(&provision, uriSys, uriProvision, uriApm) + + if err != nil { + return nil, err + } + } + if name == "avr" { + err, _ := b.getForEntity(&provision, uriSys, uriProvision, uriAvr) + + if err != nil { + return nil, err + } + + } + if name == "ilx" { + err, _ := b.getForEntity(&provision, uriSys, uriProvision, uriIlx) + + if err != nil { + return nil, err + } - if err != nil { - return nil, err } + log.Println("Display ****************** provision ", provision) return &provision, nil } From 5b70844ac1630267d2ed58a445d8003accb9dd0a Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 6 Apr 2018 08:15:52 -0700 Subject: [PATCH 18/80] removed duplicate funcs --- ltm.go | 75 ---------------------------------------------------------- 1 file changed, 75 deletions(-) diff --git a/ltm.go b/ltm.go index 7f6306e..aa0d70b 100644 --- a/ltm.go +++ b/ltm.go @@ -3456,98 +3456,23 @@ func (b *BigIP) DeleteSnatpool(name string) error { return b.delete(uriLtm, uriSnatpool, name) } -// CookiePersistenceProfiles returns a list of cookie persist profiles -func (b *BigIP) CookiePersistenceProfiles() (*CookiePersistenceProfiles, error) { - var cookiePersistenceProfiles CookiePersistenceProfiles - err, _ := b.getForEntity(&cookiePersistenceProfiles, uriLtm, uriPersistence, uriCookie) - if err != nil { - return nil, err - } - return &cookiePersistenceProfiles, nil -} -// GetCookiePersistenceProfile gets a single cookie persist profile by name -func (b *BigIP) GetCookiePersistenceProfile(name string) (*CookiePersistenceProfile, error) { - var cookiePersistenceProfile CookiePersistenceProfile - err, ok := b.getForEntity(&cookiePersistenceProfile, uriLtm, uriPersistence, uriCookie, name) - if err != nil { - return nil, err - } - if !ok { - return nil, nil - } - return &cookiePersistenceProfile, nil -} -// CreateCookiePersistenceProfile creates a new cookie persist profile on the BIG-IP system. -func (b *BigIP) CreateCookiePersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - return b.post(config, uriLtm, uriPersistence, uriCookie) -} -// AddCookiePersistenceProfile adds a cookie persist profile to the BIG-IP system -func (b *BigIP) AddCookiePersistenceProfile(config *CookiePersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriCookie) -} -// DeleteCookiePersistenceProfile removes a cookie persist profile. -func (b *BigIP) DeleteCookiePersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriCookie, name) -} -// ModifyCookiePersistenceProfile allows you to change any attribute of a cookie persist profile. -// Fields that can be modified are referenced in the CookiePersistenceProfile struct. -func (b *BigIP) ModifyCookiePersistenceProfile(name string, config *CookiePersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriCookie, name) -} -// DestAddrPersistenceProfiles returns a list of dest-addr persist profiles -func (b *BigIP) DestAddrPersistenceProfiles() (*DestAddrPersistenceProfiles, error) { - var destAddrPersistenceProfiles DestAddrPersistenceProfiles - err, _ := b.getForEntity(&destAddrPersistenceProfiles, uriLtm, uriPersistence, uriDestAddr) - if err != nil { - return nil, err - } - return &destAddrPersistenceProfiles, nil -} -// GetDestAddrPersistenceProfile gets a single dest-addr persist profile by name -func (b *BigIP) GetDestAddrPersistenceProfile(name string) (*DestAddrPersistenceProfile, error) { - var destAddrPersistenceProfile DestAddrPersistenceProfile - err, ok := b.getForEntity(&destAddrPersistenceProfile, uriLtm, uriPersistence, uriDestAddr, name) - if err != nil { - return nil, err - } - if !ok { - return nil, nil - } - return &destAddrPersistenceProfile, nil -} -// CreateDestAddrPersistenceProfile creates a new dest-addr persist profile on the BIG-IP system. -func (b *BigIP) CreateDestAddrPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - return b.post(config, uriLtm, uriPersistence, uriDestAddr) -} -// AddDestAddrPersistenceProfile adds a dest-addr persist profile to the BIG-IP system -func (b *BigIP) AddDestAddrPersistenceProfile(config *DestAddrPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriDestAddr) -} // DeleteDestAddrPersistenceProfile removes a dest-addr persist profile. func (b *BigIP) DeleteDestAddrPersistenceProfile(name string) error { From 9d7f5e5106457441045ada6577c312253097632b Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 6 Apr 2018 08:29:59 -0700 Subject: [PATCH 19/80] removed duplicate funcs --- ltm.go | 60 ---------------------------------------------------------- 1 file changed, 60 deletions(-) diff --git a/ltm.go b/ltm.go index aa0d70b..0f52a93 100644 --- a/ltm.go +++ b/ltm.go @@ -3474,42 +3474,6 @@ func (b *BigIP) DeleteSnatpool(name string) error { -// DeleteDestAddrPersistenceProfile removes a dest-addr persist profile. -func (b *BigIP) DeleteDestAddrPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriDestAddr, name) -} - -// ModifyDestAddrPersistenceProfile allows you to change any attribute of a dest-addr persist profile. -// Fields that can be modified are referenced in the DestAddrPersistenceProfile struct. -func (b *BigIP) ModifyDestAddrPersistenceProfile(name string, config *DestAddrPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriDestAddr, name) -} - -// HashPersistenceProfiles returns a list of hash persist profiles -func (b *BigIP) HashPersistenceProfiles() (*HashPersistenceProfiles, error) { - var hashPersistenceProfiles HashPersistenceProfiles - err, _ := b.getForEntity(&hashPersistenceProfiles, uriLtm, uriPersistence, uriHash) - if err != nil { - return nil, err - } - - return &hashPersistenceProfiles, nil -} - -// GetHashPersistenceProfile gets a single hash persist profile by name -func (b *BigIP) GetHashPersistenceProfile(name string) (*HashPersistenceProfile, error) { - var hashPersistenceProfile HashPersistenceProfile - err, ok := b.getForEntity(&hashPersistenceProfile, uriLtm, uriPersistence, uriHash, name) - if err != nil { - return nil, err - } - - if !ok { - return nil, nil - } - - return &hashPersistenceProfile, nil -} // CreateHashPersistenceProfile creates a new hash persist profile on the BIG-IP system. func (b *BigIP) CreateHashPersistenceProfile(name string, parent string) error { @@ -3537,31 +3501,7 @@ func (b *BigIP) ModifyHashPersistenceProfile(name string, config *HashPersistenc return b.put(config, uriLtm, uriPersistence, uriHash, name) } -// HostPersistenceProfiles returns a list of host persist profiles -func (b *BigIP) HostPersistenceProfiles() (*HostPersistenceProfiles, error) { - var hostPersistenceProfiles HostPersistenceProfiles - err, _ := b.getForEntity(&hostPersistenceProfiles, uriLtm, uriPersistence, uriHost) - if err != nil { - return nil, err - } - - return &hostPersistenceProfiles, nil -} - -// GetHostPersistenceProfile gets a single host persist profile by name -func (b *BigIP) GetHostPersistenceProfile(name string) (*HostPersistenceProfile, error) { - var hostPersistenceProfile HostPersistenceProfile - err, ok := b.getForEntity(&hostPersistenceProfile, uriLtm, uriPersistence, uriHost, name) - if err != nil { - return nil, err - } - if !ok { - return nil, nil - } - - return &hostPersistenceProfile, nil -} // CreateHostPersistenceProfile creates a new host persist profile on the BIG-IP system. func (b *BigIP) CreateHostPersistenceProfile(name string, parent string) error { From f74fc32a7fc68f7fa6a4e8acbb0349fd6311dc5d Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 6 Apr 2018 08:46:09 -0700 Subject: [PATCH 20/80] removed duplicate funcs --- ltm.go | 333 --------------------------------------------------------- 1 file changed, 333 deletions(-) diff --git a/ltm.go b/ltm.go index 0f52a93..7617f4a 100644 --- a/ltm.go +++ b/ltm.go @@ -3455,336 +3455,3 @@ func (b *BigIP) GetSnatpool(name string) (*Snatpool, error) { func (b *BigIP) DeleteSnatpool(name string) error { return b.delete(uriLtm, uriSnatpool, name) } - - - - - - - - - - - - - - - - - - - - -// CreateHashPersistenceProfile creates a new hash persist profile on the BIG-IP system. -func (b *BigIP) CreateHashPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriPersistence, uriHash) -} - -// AddHashPersistenceProfile adds a hash persist profile to the BIG-IP system -func (b *BigIP) AddHashPersistenceProfile(config *HashPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriHash) -} - -// DeleteHashPersistenceProfile removes a dest-addr persist profile. -func (b *BigIP) DeleteHashPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriHash, name) -} - -// ModifyHashPersistenceProfile allows you to change any attribute of a hash persist profile. -// Fields that can be modified are referenced in the HashPersistenceProfile struct. -func (b *BigIP) ModifyHashPersistenceProfile(name string, config *HashPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriHash, name) -} - - - -// CreateHostPersistenceProfile creates a new host persist profile on the BIG-IP system. -func (b *BigIP) CreateHostPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriPersistence, uriHost) -} - -// AddHostPersistenceProfile adds a host persist profile to the BIG-IP system -func (b *BigIP) AddHostPersistenceProfile(config *HostPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriHost) -} - -// DeleteHashHostPersistenceProfile removes a host persist profile. -func (b *BigIP) DeleteHashHostPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriHost, name) -} - -// ModifyHostPersistenceProfile allows you to change any attribute of a host persist profile. -// Fields that can be modified are referenced in the HostPersistenceProfile struct. -func (b *BigIP) ModifyHostPersistenceProfile(name string, config *HostPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriHost, name) -} - -// MSRDPPersistenceProfiles returns a list of msrdp persist profiles -func (b *BigIP) MSRDPPersistenceProfiles() (*MSRDPPersistenceProfiles, error) { - var msrdpPersistenceProfiles MSRDPPersistenceProfiles - err, _ := b.getForEntity(&msrdpPersistenceProfiles, uriLtm, uriPersistence, uriMSRDP) - if err != nil { - return nil, err - } - - return &msrdpPersistenceProfiles, nil -} - -// GetMSRDPPersistenceProfile gets a single msrdp persist profile by name -func (b *BigIP) GetMSRDPPersistenceProfile(name string) (*MSRDPPersistenceProfile, error) { - var msrdpPersistenceProfile MSRDPPersistenceProfile - err, ok := b.getForEntity(&msrdpPersistenceProfile, uriLtm, uriPersistence, uriMSRDP, name) - if err != nil { - return nil, err - } - - if !ok { - return nil, nil - } - - return &msrdpPersistenceProfile, nil -} - -// CreateMSRDPPersistenceProfile creates a new msrdp persist profile on the BIG-IP system. -func (b *BigIP) CreateMSRDPPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriPersistence, uriMSRDP) -} - -// AddMSRDPPersistenceProfile adds a msrdp persist profile to the BIG-IP system -func (b *BigIP) AddMSRDPPersistenceProfile(config *MSRDPPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriMSRDP) -} - -// DeleteMSRDPPersistenceProfile removes a msrdp persist profile. -func (b *BigIP) DeleteMSRDPPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriMSRDP, name) -} - -// ModifyMSRDPPersistenceProfile allows you to change any attribute of a msrdp persist profile. -// Fields that can be modified are referenced in the MSRDPPersistenceProfile struct. -func (b *BigIP) ModifyMSRDPPersistenceProfile(name string, config *MSRDPPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriMSRDP, name) -} - -// SIPPersistenceProfiles returns a list of sip persist profiles -func (b *BigIP) SIPPersistenceProfiles() (*SIPPersistenceProfiles, error) { - var sipPersistenceProfiles SIPPersistenceProfiles - err, _ := b.getForEntity(&sipPersistenceProfiles, uriLtm, uriPersistence, uriSIP) - if err != nil { - return nil, err - } - - return &sipPersistenceProfiles, nil -} - -// GetSIPPersistenceProfile gets a single sip persist profile by name -func (b *BigIP) GetSIPPersistenceProfile(name string) (*SIPPersistenceProfile, error) { - var sipPersistenceProfile SIPPersistenceProfile - err, ok := b.getForEntity(&sipPersistenceProfile, uriLtm, uriPersistence, uriSIP, name) - if err != nil { - return nil, err - } - - if !ok { - return nil, nil - } - - return &sipPersistenceProfile, nil -} - -// CreateSIPPersistenceProfile creates a new sip persist profile on the BIG-IP system. -func (b *BigIP) CreateSIPPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriPersistence, uriSIP) -} - -// AddSIPPersistenceProfile adds a sip persist profile to the BIG-IP system -func (b *BigIP) AddSIPPersistenceProfile(config *SIPPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriSIP) -} - -// DeleteSIPPersistenceProfile removes a sip persist profile. -func (b *BigIP) DeleteSIPPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriSIP, name) -} - -// ModifySIPPersistenceProfile allows you to change any attribute of a sip persist profile. -// Fields that can be modified are referenced in the SIPPersistenceProfile struct. -func (b *BigIP) ModifySIPPersistenceProfile(name string, config *SIPPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriSIP, name) -} - -// SourceAddrPersistenceProfiles returns a list of source-addr persist profiles -func (b *BigIP) SourceAddrPersistenceProfiles() (*SourceAddrPersistenceProfiles, error) { - var sourceAddrPersistenceProfiles SourceAddrPersistenceProfiles - err, _ := b.getForEntity(&sourceAddrPersistenceProfiles, uriLtm, uriPersistence, uriSourceAddr) - if err != nil { - return nil, err - } - - return &sourceAddrPersistenceProfiles, nil -} - -// GetSourceAddrPersistenceProfile gets a single source-addr persist profile by name -func (b *BigIP) GetSourceAddrPersistenceProfile(name string) (*SourceAddrPersistenceProfile, error) { - var sourceAddrPersistenceProfile SourceAddrPersistenceProfile - err, ok := b.getForEntity(&sourceAddrPersistenceProfile, uriLtm, uriPersistence, uriSourceAddr, name) - if err != nil { - return nil, err - } - - if !ok { - return nil, nil - } - - return &sourceAddrPersistenceProfile, nil -} - -// CreateSourceAddrPersistenceProfile creates a new source-addr persist profile on the BIG-IP system. -func (b *BigIP) CreateSourceAddrPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriPersistence, uriSourceAddr) -} - -// AddSourceAddrPersistenceProfile adds a source-addr persist profile to the BIG-IP system -func (b *BigIP) AddSourceAddrPersistenceProfile(config *SourceAddrPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriSourceAddr) -} - -// DeleteSourceAddrPersistenceProfile removes a source-addr persist profile. -func (b *BigIP) DeleteSourceAddrPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriSourceAddr, name) -} - -// ModifySourceAddrPersistenceProfile allows you to change any attribute of a source-addr persist profile. -// Fields that can be modified are referenced in the SourceAddrPersistenceProfile struct. -func (b *BigIP) ModifySourceAddrPersistenceProfile(name string, config *SourceAddrPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriSourceAddr, name) -} - -// SSLPersistenceProfiles returns a list of ssl persist profiles -func (b *BigIP) SSLPersistenceProfiles() (*SSLPersistenceProfiles, error) { - var sslPersistenceProfiles SSLPersistenceProfiles - err, _ := b.getForEntity(&sslPersistenceProfiles, uriLtm, uriPersistence, uriSSL) - if err != nil { - return nil, err - } - - return &sslPersistenceProfiles, nil -} - -// GetSSLPersistenceProfile gets a single ssl persist profile by name -func (b *BigIP) GetSSLPersistenceProfile(name string) (*SSLPersistenceProfile, error) { - var sslPersistenceProfile SSLPersistenceProfile - err, ok := b.getForEntity(&sslPersistenceProfile, uriLtm, uriPersistence, uriSSL, name) - if err != nil { - return nil, err - } - - if !ok { - return nil, nil - } - - return &sslPersistenceProfile, nil -} - -// CreateSSLPersistenceProfile creates a new ssl persist profile on the BIG-IP system. -func (b *BigIP) CreateSSLPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriPersistence, uriSSL) -} - -// AddSSLPersistenceProfile adds a ssl persist profile to the BIG-IP system -func (b *BigIP) AddSSLPersistenceProfile(config *SSLPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriSSL) -} - -// DeleteSSLPersistenceProfile removes a ssl persist profile. -func (b *BigIP) DeleteSSLPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriSSL, name) -} - -// ModifySSLPersistenceProfile allows you to change any attribute of a ssl persist profile. -// Fields that can be modified are referenced in the SSLPersistenceProfile struct. -func (b *BigIP) ModifySSLPersistenceProfile(name string, config *SSLPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriSSL, name) -} - -// UniversalPersistenceProfiles returns a list of universal persist profiles -func (b *BigIP) UniversalPersistenceProfiles() (*UniversalPersistenceProfiles, error) { - var universalPersistenceProfiles UniversalPersistenceProfiles - err, _ := b.getForEntity(&universalPersistenceProfiles, uriLtm, uriPersistence, uriUniversal) - if err != nil { - return nil, err - } - - return &universalPersistenceProfiles, nil -} - -// GetUniversalPersistenceProfile gets a single universal persist profile by name -func (b *BigIP) GetUniversalPersistenceProfile(name string) (*UniversalPersistenceProfile, error) { - var universalPersistenceProfile UniversalPersistenceProfile - err, ok := b.getForEntity(&universalPersistenceProfile, uriLtm, uriPersistence, uriUniversal, name) - if err != nil { - return nil, err - } - - if !ok { - return nil, nil - } - - return &universalPersistenceProfile, nil -} - -// CreateUniversalPersistenceProfile creates a new universal persist profile on the BIG-IP system. -func (b *BigIP) CreateUniversalPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriPersistence, uriUniversal) -} - -// AddUniversalPersistenceProfile adds a universal persist profile to the BIG-IP system -func (b *BigIP) AddUniversalPersistenceProfile(config *UniversalPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriUniversal) -} - -// DeleteUniversalPersistenceProfile removes a universal persist profile. -func (b *BigIP) DeleteUniversalPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriUniversal, name) -} - -// ModifyUniversalPersistenceProfile allows you to change any attribute of a universal persist profile. -// Fields that can be modified are referenced in the UniversalPersistenceProfile struct. -func (b *BigIP) ModifyUniversalPersistenceProfile(name string, config *UniversalPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriUniversal, name) -} From 9523546e3fef3ab7d4ab3cc85b63a7ff49beee87 Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 6 Apr 2018 09:10:44 -0700 Subject: [PATCH 21/80] removed duplicate funcs --- ltm.go | 468 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 468 insertions(+) diff --git a/ltm.go b/ltm.go index 7617f4a..7f6306e 100644 --- a/ltm.go +++ b/ltm.go @@ -3455,3 +3455,471 @@ func (b *BigIP) GetSnatpool(name string) (*Snatpool, error) { func (b *BigIP) DeleteSnatpool(name string) error { return b.delete(uriLtm, uriSnatpool, name) } + +// CookiePersistenceProfiles returns a list of cookie persist profiles +func (b *BigIP) CookiePersistenceProfiles() (*CookiePersistenceProfiles, error) { + var cookiePersistenceProfiles CookiePersistenceProfiles + err, _ := b.getForEntity(&cookiePersistenceProfiles, uriLtm, uriPersistence, uriCookie) + if err != nil { + return nil, err + } + + return &cookiePersistenceProfiles, nil +} + +// GetCookiePersistenceProfile gets a single cookie persist profile by name +func (b *BigIP) GetCookiePersistenceProfile(name string) (*CookiePersistenceProfile, error) { + var cookiePersistenceProfile CookiePersistenceProfile + err, ok := b.getForEntity(&cookiePersistenceProfile, uriLtm, uriPersistence, uriCookie, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &cookiePersistenceProfile, nil +} + +// CreateCookiePersistenceProfile creates a new cookie persist profile on the BIG-IP system. +func (b *BigIP) CreateCookiePersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriCookie) +} + +// AddCookiePersistenceProfile adds a cookie persist profile to the BIG-IP system +func (b *BigIP) AddCookiePersistenceProfile(config *CookiePersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriCookie) +} + +// DeleteCookiePersistenceProfile removes a cookie persist profile. +func (b *BigIP) DeleteCookiePersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriCookie, name) +} + +// ModifyCookiePersistenceProfile allows you to change any attribute of a cookie persist profile. +// Fields that can be modified are referenced in the CookiePersistenceProfile struct. +func (b *BigIP) ModifyCookiePersistenceProfile(name string, config *CookiePersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriCookie, name) +} + +// DestAddrPersistenceProfiles returns a list of dest-addr persist profiles +func (b *BigIP) DestAddrPersistenceProfiles() (*DestAddrPersistenceProfiles, error) { + var destAddrPersistenceProfiles DestAddrPersistenceProfiles + err, _ := b.getForEntity(&destAddrPersistenceProfiles, uriLtm, uriPersistence, uriDestAddr) + if err != nil { + return nil, err + } + + return &destAddrPersistenceProfiles, nil +} + +// GetDestAddrPersistenceProfile gets a single dest-addr persist profile by name +func (b *BigIP) GetDestAddrPersistenceProfile(name string) (*DestAddrPersistenceProfile, error) { + var destAddrPersistenceProfile DestAddrPersistenceProfile + err, ok := b.getForEntity(&destAddrPersistenceProfile, uriLtm, uriPersistence, uriDestAddr, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &destAddrPersistenceProfile, nil +} + +// CreateDestAddrPersistenceProfile creates a new dest-addr persist profile on the BIG-IP system. +func (b *BigIP) CreateDestAddrPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriDestAddr) +} + +// AddDestAddrPersistenceProfile adds a dest-addr persist profile to the BIG-IP system +func (b *BigIP) AddDestAddrPersistenceProfile(config *DestAddrPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriDestAddr) +} + +// DeleteDestAddrPersistenceProfile removes a dest-addr persist profile. +func (b *BigIP) DeleteDestAddrPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriDestAddr, name) +} + +// ModifyDestAddrPersistenceProfile allows you to change any attribute of a dest-addr persist profile. +// Fields that can be modified are referenced in the DestAddrPersistenceProfile struct. +func (b *BigIP) ModifyDestAddrPersistenceProfile(name string, config *DestAddrPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriDestAddr, name) +} + +// HashPersistenceProfiles returns a list of hash persist profiles +func (b *BigIP) HashPersistenceProfiles() (*HashPersistenceProfiles, error) { + var hashPersistenceProfiles HashPersistenceProfiles + err, _ := b.getForEntity(&hashPersistenceProfiles, uriLtm, uriPersistence, uriHash) + if err != nil { + return nil, err + } + + return &hashPersistenceProfiles, nil +} + +// GetHashPersistenceProfile gets a single hash persist profile by name +func (b *BigIP) GetHashPersistenceProfile(name string) (*HashPersistenceProfile, error) { + var hashPersistenceProfile HashPersistenceProfile + err, ok := b.getForEntity(&hashPersistenceProfile, uriLtm, uriPersistence, uriHash, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &hashPersistenceProfile, nil +} + +// CreateHashPersistenceProfile creates a new hash persist profile on the BIG-IP system. +func (b *BigIP) CreateHashPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriHash) +} + +// AddHashPersistenceProfile adds a hash persist profile to the BIG-IP system +func (b *BigIP) AddHashPersistenceProfile(config *HashPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriHash) +} + +// DeleteHashPersistenceProfile removes a dest-addr persist profile. +func (b *BigIP) DeleteHashPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriHash, name) +} + +// ModifyHashPersistenceProfile allows you to change any attribute of a hash persist profile. +// Fields that can be modified are referenced in the HashPersistenceProfile struct. +func (b *BigIP) ModifyHashPersistenceProfile(name string, config *HashPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriHash, name) +} + +// HostPersistenceProfiles returns a list of host persist profiles +func (b *BigIP) HostPersistenceProfiles() (*HostPersistenceProfiles, error) { + var hostPersistenceProfiles HostPersistenceProfiles + err, _ := b.getForEntity(&hostPersistenceProfiles, uriLtm, uriPersistence, uriHost) + if err != nil { + return nil, err + } + + return &hostPersistenceProfiles, nil +} + +// GetHostPersistenceProfile gets a single host persist profile by name +func (b *BigIP) GetHostPersistenceProfile(name string) (*HostPersistenceProfile, error) { + var hostPersistenceProfile HostPersistenceProfile + err, ok := b.getForEntity(&hostPersistenceProfile, uriLtm, uriPersistence, uriHost, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &hostPersistenceProfile, nil +} + +// CreateHostPersistenceProfile creates a new host persist profile on the BIG-IP system. +func (b *BigIP) CreateHostPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriHost) +} + +// AddHostPersistenceProfile adds a host persist profile to the BIG-IP system +func (b *BigIP) AddHostPersistenceProfile(config *HostPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriHost) +} + +// DeleteHashHostPersistenceProfile removes a host persist profile. +func (b *BigIP) DeleteHashHostPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriHost, name) +} + +// ModifyHostPersistenceProfile allows you to change any attribute of a host persist profile. +// Fields that can be modified are referenced in the HostPersistenceProfile struct. +func (b *BigIP) ModifyHostPersistenceProfile(name string, config *HostPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriHost, name) +} + +// MSRDPPersistenceProfiles returns a list of msrdp persist profiles +func (b *BigIP) MSRDPPersistenceProfiles() (*MSRDPPersistenceProfiles, error) { + var msrdpPersistenceProfiles MSRDPPersistenceProfiles + err, _ := b.getForEntity(&msrdpPersistenceProfiles, uriLtm, uriPersistence, uriMSRDP) + if err != nil { + return nil, err + } + + return &msrdpPersistenceProfiles, nil +} + +// GetMSRDPPersistenceProfile gets a single msrdp persist profile by name +func (b *BigIP) GetMSRDPPersistenceProfile(name string) (*MSRDPPersistenceProfile, error) { + var msrdpPersistenceProfile MSRDPPersistenceProfile + err, ok := b.getForEntity(&msrdpPersistenceProfile, uriLtm, uriPersistence, uriMSRDP, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &msrdpPersistenceProfile, nil +} + +// CreateMSRDPPersistenceProfile creates a new msrdp persist profile on the BIG-IP system. +func (b *BigIP) CreateMSRDPPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriMSRDP) +} + +// AddMSRDPPersistenceProfile adds a msrdp persist profile to the BIG-IP system +func (b *BigIP) AddMSRDPPersistenceProfile(config *MSRDPPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriMSRDP) +} + +// DeleteMSRDPPersistenceProfile removes a msrdp persist profile. +func (b *BigIP) DeleteMSRDPPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriMSRDP, name) +} + +// ModifyMSRDPPersistenceProfile allows you to change any attribute of a msrdp persist profile. +// Fields that can be modified are referenced in the MSRDPPersistenceProfile struct. +func (b *BigIP) ModifyMSRDPPersistenceProfile(name string, config *MSRDPPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriMSRDP, name) +} + +// SIPPersistenceProfiles returns a list of sip persist profiles +func (b *BigIP) SIPPersistenceProfiles() (*SIPPersistenceProfiles, error) { + var sipPersistenceProfiles SIPPersistenceProfiles + err, _ := b.getForEntity(&sipPersistenceProfiles, uriLtm, uriPersistence, uriSIP) + if err != nil { + return nil, err + } + + return &sipPersistenceProfiles, nil +} + +// GetSIPPersistenceProfile gets a single sip persist profile by name +func (b *BigIP) GetSIPPersistenceProfile(name string) (*SIPPersistenceProfile, error) { + var sipPersistenceProfile SIPPersistenceProfile + err, ok := b.getForEntity(&sipPersistenceProfile, uriLtm, uriPersistence, uriSIP, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &sipPersistenceProfile, nil +} + +// CreateSIPPersistenceProfile creates a new sip persist profile on the BIG-IP system. +func (b *BigIP) CreateSIPPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriSIP) +} + +// AddSIPPersistenceProfile adds a sip persist profile to the BIG-IP system +func (b *BigIP) AddSIPPersistenceProfile(config *SIPPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriSIP) +} + +// DeleteSIPPersistenceProfile removes a sip persist profile. +func (b *BigIP) DeleteSIPPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriSIP, name) +} + +// ModifySIPPersistenceProfile allows you to change any attribute of a sip persist profile. +// Fields that can be modified are referenced in the SIPPersistenceProfile struct. +func (b *BigIP) ModifySIPPersistenceProfile(name string, config *SIPPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriSIP, name) +} + +// SourceAddrPersistenceProfiles returns a list of source-addr persist profiles +func (b *BigIP) SourceAddrPersistenceProfiles() (*SourceAddrPersistenceProfiles, error) { + var sourceAddrPersistenceProfiles SourceAddrPersistenceProfiles + err, _ := b.getForEntity(&sourceAddrPersistenceProfiles, uriLtm, uriPersistence, uriSourceAddr) + if err != nil { + return nil, err + } + + return &sourceAddrPersistenceProfiles, nil +} + +// GetSourceAddrPersistenceProfile gets a single source-addr persist profile by name +func (b *BigIP) GetSourceAddrPersistenceProfile(name string) (*SourceAddrPersistenceProfile, error) { + var sourceAddrPersistenceProfile SourceAddrPersistenceProfile + err, ok := b.getForEntity(&sourceAddrPersistenceProfile, uriLtm, uriPersistence, uriSourceAddr, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &sourceAddrPersistenceProfile, nil +} + +// CreateSourceAddrPersistenceProfile creates a new source-addr persist profile on the BIG-IP system. +func (b *BigIP) CreateSourceAddrPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriSourceAddr) +} + +// AddSourceAddrPersistenceProfile adds a source-addr persist profile to the BIG-IP system +func (b *BigIP) AddSourceAddrPersistenceProfile(config *SourceAddrPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriSourceAddr) +} + +// DeleteSourceAddrPersistenceProfile removes a source-addr persist profile. +func (b *BigIP) DeleteSourceAddrPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriSourceAddr, name) +} + +// ModifySourceAddrPersistenceProfile allows you to change any attribute of a source-addr persist profile. +// Fields that can be modified are referenced in the SourceAddrPersistenceProfile struct. +func (b *BigIP) ModifySourceAddrPersistenceProfile(name string, config *SourceAddrPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriSourceAddr, name) +} + +// SSLPersistenceProfiles returns a list of ssl persist profiles +func (b *BigIP) SSLPersistenceProfiles() (*SSLPersistenceProfiles, error) { + var sslPersistenceProfiles SSLPersistenceProfiles + err, _ := b.getForEntity(&sslPersistenceProfiles, uriLtm, uriPersistence, uriSSL) + if err != nil { + return nil, err + } + + return &sslPersistenceProfiles, nil +} + +// GetSSLPersistenceProfile gets a single ssl persist profile by name +func (b *BigIP) GetSSLPersistenceProfile(name string) (*SSLPersistenceProfile, error) { + var sslPersistenceProfile SSLPersistenceProfile + err, ok := b.getForEntity(&sslPersistenceProfile, uriLtm, uriPersistence, uriSSL, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &sslPersistenceProfile, nil +} + +// CreateSSLPersistenceProfile creates a new ssl persist profile on the BIG-IP system. +func (b *BigIP) CreateSSLPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriSSL) +} + +// AddSSLPersistenceProfile adds a ssl persist profile to the BIG-IP system +func (b *BigIP) AddSSLPersistenceProfile(config *SSLPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriSSL) +} + +// DeleteSSLPersistenceProfile removes a ssl persist profile. +func (b *BigIP) DeleteSSLPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriSSL, name) +} + +// ModifySSLPersistenceProfile allows you to change any attribute of a ssl persist profile. +// Fields that can be modified are referenced in the SSLPersistenceProfile struct. +func (b *BigIP) ModifySSLPersistenceProfile(name string, config *SSLPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriSSL, name) +} + +// UniversalPersistenceProfiles returns a list of universal persist profiles +func (b *BigIP) UniversalPersistenceProfiles() (*UniversalPersistenceProfiles, error) { + var universalPersistenceProfiles UniversalPersistenceProfiles + err, _ := b.getForEntity(&universalPersistenceProfiles, uriLtm, uriPersistence, uriUniversal) + if err != nil { + return nil, err + } + + return &universalPersistenceProfiles, nil +} + +// GetUniversalPersistenceProfile gets a single universal persist profile by name +func (b *BigIP) GetUniversalPersistenceProfile(name string) (*UniversalPersistenceProfile, error) { + var universalPersistenceProfile UniversalPersistenceProfile + err, ok := b.getForEntity(&universalPersistenceProfile, uriLtm, uriPersistence, uriUniversal, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &universalPersistenceProfile, nil +} + +// CreateUniversalPersistenceProfile creates a new universal persist profile on the BIG-IP system. +func (b *BigIP) CreateUniversalPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriUniversal) +} + +// AddUniversalPersistenceProfile adds a universal persist profile to the BIG-IP system +func (b *BigIP) AddUniversalPersistenceProfile(config *UniversalPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriUniversal) +} + +// DeleteUniversalPersistenceProfile removes a universal persist profile. +func (b *BigIP) DeleteUniversalPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriUniversal, name) +} + +// ModifyUniversalPersistenceProfile allows you to change any attribute of a universal persist profile. +// Fields that can be modified are referenced in the UniversalPersistenceProfile struct. +func (b *BigIP) ModifyUniversalPersistenceProfile(name string, config *UniversalPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriUniversal, name) +} From 519fd8fdf78162647354b477e64415a05a1c7bfb Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 6 Apr 2018 10:04:31 -0700 Subject: [PATCH 22/80] Revert "updated the files with vendor changes" This reverts commit 2fe7b24b10b42c25fbcbc512ace4b8a08d58a8ff. --- bigip.go | 3 +- device.go | 152 ++---- gtm.go | 296 ++++++------ ltm.go | 1381 +++++++++++++++++++---------------------------------- net.go | 31 +- sys.go | 70 +-- 6 files changed, 708 insertions(+), 1225 deletions(-) diff --git a/bigip.go b/bigip.go index cf87208..24b3c26 100644 --- a/bigip.go +++ b/bigip.go @@ -12,7 +12,6 @@ import ( "reflect" "strings" "time" - "log" ) var defaultConfigOptions = &ConfigOptions{ @@ -259,7 +258,7 @@ func (b *BigIP) patch(body interface{}, path ...string) error { Body: string(marshalJSON), ContentType: "application/json", } - log.Println(" patch ----------------- ", req) + _, callErr := b.APICall(req) return callErr } diff --git a/device.go b/device.go index 7675a7e..409f47f 100644 --- a/device.go +++ b/device.go @@ -1,8 +1,6 @@ package bigip -import ( - "encoding/json" -) +import "encoding/json" // LIC contains device license for BIG-IP system. type LICs struct { @@ -58,77 +56,10 @@ type Devicegroups struct { } type Devicegroup struct { - AutoSync string - Name string - Partition string - Description string - Type string - FullLoadOnSync string - SaveOnAutoSync string - NetworkFailover string - IncrementalConfigSyncSizeMax int - Deviceb []Devicerecord -} -type devicegroupDTO struct { - AutoSync string `json:"autoSync,omitempty"` - Name string `json:"name,omitempty"` - Partition string `json:"partition,omitempty"` - Description string `json:"description,omitempty"` - Type string `json:"type,omitempty"` - FullLoadOnSync string `json:"fullLoadOnSync,omitempty"` - SaveOnAutoSync string `json:"saveOnAutoSync,omitempty"` - NetworkFailover string `json:"networkFailover,omitempty"` - IncrementalConfigSyncSizeMax int `json:"incrementalConfigSyncSizeMax,omitempty"` - Deviceb struct { - Items []Devicerecord `json:"items,omitempty"` - } `json:"devicesReference,omitempty"` -} - -type Devicerecords struct { - Items []Devicerecord `json:"items,omitempty"` -} - -type Devicerecord struct { - SetSyncLeader bool `json:"setSyncLeader"` - Name string `json:"name"` -} - -func (p *Devicegroup) MarshalJSON() ([]byte, error) { - return json.Marshal(devicegroupDTO{ - Name: p.Name, - Partition: p.Partition, - AutoSync: p.AutoSync, - Description: p.Description, - Type: p.Type, - FullLoadOnSync: p.FullLoadOnSync, - SaveOnAutoSync: p.SaveOnAutoSync, - NetworkFailover: p.NetworkFailover, - IncrementalConfigSyncSizeMax: p.IncrementalConfigSyncSizeMax, - Deviceb: struct { - Items []Devicerecord `json:"items,omitempty"` - }{Items: p.Deviceb}, - }) -} - -func (p *Devicegroup) UnmarshalJSON(b []byte) error { - var dto devicegroupDTO - err := json.Unmarshal(b, &dto) - if err != nil { - return err - } - - p.Name = dto.Name - p.Partition = dto.Partition - p.AutoSync = dto.AutoSync - p.Description = dto.Description - p.Type = dto.Type - p.FullLoadOnSync = dto.FullLoadOnSync - p.SaveOnAutoSync = dto.SaveOnAutoSync - p.NetworkFailover = dto.NetworkFailover - p.IncrementalConfigSyncSizeMax = dto.IncrementalConfigSyncSizeMax - p.Deviceb = dto.Deviceb.Items - - return nil + AutoSync string `json:"autoSync,omitempty"` + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` + FullLoadOnSync string `json:"fullLoadOnSync,omitempty"` } // https://10.192.74.80/mgmt/cm/device/licensing/pool/purchased-pool/licenses @@ -137,8 +68,6 @@ const ( uriMgmt = "mgmt" uriCm = "cm" uriDiv = "device" - uriDevices = "devices" - uriDG = "device-group" uriLins = "licensing" uriPoo = "pool" uriPur = "purchased-pool" @@ -229,6 +158,31 @@ func (b *BigIP) LICs() (*LIC, error) { return &members, nil } +func (b *BigIP) CreateDevicename(command, name, target string) error { + config := &Devicename{ + Command: command, + Name: name, + Target: target, + } + + return b.post(config, uriCm, uriDiv) +} + +func (b *BigIP) ModifyDevicename(config *Devicename) error { + return b.put(config, uriCm, uriDiv) +} + +func (b *BigIP) Devicenames() (*Devicename, error) { + var devicename Devicename + err, _ := b.getForEntity(&devicename, uriCm, uriDiv) + + if err != nil { + return nil, err + } + + return &devicename, nil +} + func (b *BigIP) CreateDevice(name, configsyncIp, mirrorIp, mirrorSecondaryIp string) error { config := &Device{ Name: name, @@ -240,18 +194,13 @@ func (b *BigIP) CreateDevice(name, configsyncIp, mirrorIp, mirrorSecondaryIp str return b.post(config, uriCm, uriDiv) } -// API does not work, you cannot modify API issue func (b *BigIP) ModifyDevice(config *Device) error { return b.put(config, uriCm, uriDiv) } -func (b *BigIP) DeleteDevice(name string) error { - return b.delete(uriCm, uriDiv, name) -} - -func (b *BigIP) Devices(name string) (*Device, error) { +func (b *BigIP) Devices() (*Device, error) { var device Device - err, _ := b.getForEntity(&device, uriCm, uriDiv, name) + err, _ := b.getForEntity(&device, uriCm, uriDiv) if err != nil { return nil, err @@ -260,38 +209,25 @@ func (b *BigIP) Devices(name string) (*Device, error) { return &device, nil } -func (b *BigIP) CreateDevicegroup(p *Devicegroup) error { - return b.post(p, uriCm, uriDG) -} - -func (b *BigIP) UpdateDevicegroup(name string, p *Devicegroup) error { - return b.put(p, uriCm, uriDG, name) -} -func (b *BigIP) ModifyDevicegroup(config *Devicegroup) error { - return b.put(config, uriCm, uriDG) -} - -func (b *BigIP) Devicegroups(name string) (*Devicegroup, error) { - var devicegroup Devicegroup - err, _ := b.getForEntity(&devicegroup, uriCm, uriDG, name) - if err != nil { - return nil, err +func (b *BigIP) CreateDevicegroup(name, autoSync, typo, fullLoadOnSync string) error { + config := &Devicegroup{ + Name: name, + AutoSync: autoSync, + Type: typo, + FullLoadOnSync: fullLoadOnSync, } - return &devicegroup, nil -} - -func (b *BigIP) DeleteDevicegroup(name string) error { - return b.delete(uriCm, uriDG, name) + return b.post(config, uriCm, uriDiv) } -func (b *BigIP) DeleteDevicegroupDevices(name, rname string) error { - return b.delete(uriCm, uriDG, name, uriDevices, rname) +func (b *BigIP) ModifyDevicegroup(config *Devicegroup) error { + return b.put(config, uriCm, uriDiv) } -func (b *BigIP) DevicegroupsDevices(name, rname string) (*Devicegroup, error) { +func (b *BigIP) Devicegroups() (*Devicegroup, error) { var devicegroup Devicegroup - err, _ := b.getForEntity(&devicegroup, uriCm, uriDG, name, uriDevices, rname) + err, _ := b.getForEntity(&devicegroup, uriCm, uriDiv) + if err != nil { return nil, err } diff --git a/gtm.go b/gtm.go index 55143c6..4e36891 100644 --- a/gtm.go +++ b/gtm.go @@ -5,31 +5,34 @@ import "log" //ooo + type Datacenters struct { Datacenters []Datacenter `json:"items"` } type Datacenter struct { - Name string `json:"name,omitempty"` + Name string `json:"name,omitempty"` Description string `json:"description,omitempty"` - Contact string `json:"contact,omitempty"` - App_service string `json:"appService,omitempty"` - Disabled bool `json:"disabled,omitempty"` - Enabled bool `json:"enabled,omitempty"` - Prober_pool string `json:"proberPool,omitempty"` + Contact string `json:"contact,omitempty"` + App_service string `json:"appService,omitempty"` + Disabled bool `json:"disabled,omitempty"` + Enabled bool `json:"enabled,omitempty"` + Prober_pool string `json:"proberPool,omitempty"` } + type Gtmmonitors struct { Gtmmonitors []Gtmmonitor `json:"items"` } + type Gtmmonitor struct { - Name string `json:"name,omitempty"` + Name string `json:"name,omitempty"` Defaults_from string `json:"defaultsFrom,omitempty"` - Interval int `json:"interval,omitempty"` - Probe_timeout int `json:"probeTimeout,omitempty"` - Recv string `json:"recv,omitempty"` - Send string `json:"send,omitempty"` + Interval int `json:"interval,omitempty"` + Probe_timeout int `json:"probeTimeout,omitempty"` + Recv string `json:"recv,omitempty"` + Send string `json:"send,omitempty"` } type Servers struct { @@ -37,101 +40,109 @@ type Servers struct { } type Server struct { - Name string - Datacenter string - Monitor string + Name string + Datacenter string + Monitor string Virtual_server_discovery bool - Product string - Addresses []ServerAddresses - GTMVirtual_Server []VSrecord + Product string + Addresses []ServerAddresses + GTMVirtual_Server []VSrecord } type serverDTO struct { - Name string `json:"name"` - Datacenter string `json:"datacenter,omitempty"` - Monitor string `json:"monitor,omitempty"` - Virtual_server_discovery bool `json:"virtual_server_discovery"` - Product string `json:"product,omitempty"` - Addresses struct { - Items []ServerAddresses `json:"items,omitempty"` + Name string `json:"name"` + Datacenter string `json:"datacenter,omitempty"` + Monitor string `json:"monitor,omitempty"` + Virtual_server_discovery bool `json:"virtual_server_discovery"` + Product string `json:"product,omitempty"` + Addresses struct { + Items []ServerAddresses`json:"items,omitempty"` } `json:"addressesReference,omitempty"` GTMVirtual_Server struct { - Items []VSrecord `json:"items,omitempty"` - } `json:"virtualServersReference,omitempty"` -} + Items []VSrecord `json:"items,omitempty"` } `json:"virtualServersReference,omitempty"` + } -func (p *Server) MarshalJSON() ([]byte, error) { - return json.Marshal(serverDTO{ - Name: p.Name, - Datacenter: p.Datacenter, - Monitor: p.Monitor, - Virtual_server_discovery: p.Virtual_server_discovery, - Product: p.Product, - Addresses: struct { - Items []ServerAddresses `json:"items,omitempty"` - }{Items: p.Addresses}, - GTMVirtual_Server: struct { - Items []VSrecord `json:"items,omitempty"` - }{Items: p.GTMVirtual_Server}, - }) -} + func (p *Server) MarshalJSON() ([]byte, error) { + return json.Marshal(serverDTO{ + Name: p.Name, + Datacenter: p.Datacenter, + Monitor: p.Monitor, + Virtual_server_discovery: p.Virtual_server_discovery, + Product: p.Product, + Addresses: struct { + Items []ServerAddresses `json:"items,omitempty"` + }{Items: p.Addresses}, + GTMVirtual_Server: struct { + Items []VSrecord `json:"items,omitempty"` + }{Items: p.GTMVirtual_Server}, + }) + } -func (p *Server) UnmarshalJSON(b []byte) error { - var dto serverDTO - err := json.Unmarshal(b, &dto) - if err != nil { - return err + func (p *Server) UnmarshalJSON(b []byte) error { + var dto serverDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + + p.Name = dto.Name + p.Datacenter = dto.Datacenter + p.Monitor = dto.Monitor + p.Virtual_server_discovery = dto.Virtual_server_discovery + p.Product = dto.Product + p.Addresses = dto.Addresses.Items + p.GTMVirtual_Server = dto.GTMVirtual_Server.Items + return nil } - p.Name = dto.Name - p.Datacenter = dto.Datacenter - p.Monitor = dto.Monitor - p.Virtual_server_discovery = dto.Virtual_server_discovery - p.Product = dto.Product - p.Addresses = dto.Addresses.Items - p.GTMVirtual_Server = dto.GTMVirtual_Server.Items - return nil -} -type ServerAddressess struct { - Items []ServerAddresses `json:"items,omitempty"` -} + type ServerAddressess struct { + Items []ServerAddresses `json:"items,omitempty"` + } -type ServerAddresses struct { - Name string `json:"name"` - Device_name string `json:"deviceName,omitempty"` - Translation string `json:"translation,omitempty"` -} -type VSrecords struct { - Items []VSrecord `json:"items,omitempty"` -} -type VSrecord struct { - Name string `json:"name"` - Destination string `json:"destination,omitempty"` -} + type ServerAddresses struct { + Name string `json:"name"` + Device_name string `json:"deviceName,omitempty"` + Translation string `json:"translation,omitempty"` + } + + + + type VSrecords struct { + Items []VSrecord `json:"items,omitempty"` + } + + + + type VSrecord struct { + Name string `json:"name"` + Destination string `json:"destination,omitempty"` + } + + type Pool_as struct { + Pool_as []Pool_a `json:"items"` + } + + type Pool_a struct { + Name string `json:"name,omitempty"` + Monitor string `json:"monitor,omitempty"` + Load_balancing_mode string `json:"load_balancing_mode,omitempty"` + Max_answers_returned int `json:"max_answers_returned,omitempty"` + Alternate_mode string `json:"alternate_mode,omitempty"` + Fallback_ip string `json:"fallback_ip,omitempty"` + Fallback_mode string `json:"fallback_mode,omitempty"` + Members []string `json:"members,omitempty"` + } -type Pool_as struct { - Pool_as []Pool_a `json:"items"` -} -type Pool_a struct { - Name string `json:"name,omitempty"` - Monitor string `json:"monitor,omitempty"` - Load_balancing_mode string `json:"load_balancing_mode,omitempty"` - Max_answers_returned int `json:"max_answers_returned,omitempty"` - Alternate_mode string `json:"alternate_mode,omitempty"` - Fallback_ip string `json:"fallback_ip,omitempty"` - Fallback_mode string `json:"fallback_mode,omitempty"` - Members []string `json:"members,omitempty"` -} const ( - uriGtm = "gtm" - uriServer = "server" + uriGtm = "gtm" + uriServer = "server" uriDatacenter = "datacenter" - uriGtmmonitor = "monitor" + uriGtmmonitor = "monitor" uriHttp = "http" uriPool_a = "pool/a" ) @@ -147,14 +158,14 @@ func (b *BigIP) Datacenters() (*Datacenter, error) { return &datacenter, nil } -func (b *BigIP) CreateDatacenter(name, description, contact, app_service string, enabled, disabled bool, prober_pool string) error { +func (b *BigIP) CreateDatacenter(name, description,contact, app_service string, enabled, disabled bool, prober_pool string) error { config := &Datacenter{ - Name: name, - Description: description, - Contact: contact, + Name: name, + Description: description, + Contact: contact, App_service: app_service, - Enabled: enabled, - Disabled: disabled, + Enabled: enabled, + Disabled: disabled, Prober_pool: prober_pool, } return b.post(config, uriGtm, uriDatacenter) @@ -164,10 +175,13 @@ func (b *BigIP) ModifyDatacenter(*Datacenter) error { return b.patch(uriGtm, uriDatacenter) } + func (b *BigIP) DeleteDatacenter(name string) error { return b.delete(uriGtm, uriDatacenter, name) } + + func (b *BigIP) Gtmmonitors() (*Gtmmonitor, error) { var gtmmonitor Gtmmonitor err, _ := b.getForEntity(>mmonitor, uriGtm, uriGtmmonitor, uriHttp) @@ -180,12 +194,12 @@ func (b *BigIP) Gtmmonitors() (*Gtmmonitor, error) { } func (b *BigIP) CreateGtmmonitor(name, defaults_from string, interval, probeTimeout int, recv, send string) error { config := &Gtmmonitor{ - Name: name, - Defaults_from: defaults_from, - Interval: interval, + Name: name, + Defaults_from: defaults_from, + Interval: interval, Probe_timeout: probeTimeout, - Recv: recv, - Send: send, + Recv: recv, + Send: send, } return b.post(config, uriGtm, uriGtmmonitor, uriHttp) } @@ -194,10 +208,12 @@ func (b *BigIP) ModifyGtmmonitor(*Gtmmonitor) error { return b.patch(uriGtm, uriGtmmonitor, uriHttp) } + func (b *BigIP) DeleteGtmmonitor(name string) error { return b.delete(uriGtm, uriGtmmonitor, uriHttp, name) } + func (b *BigIP) CreateGtmserver(p *Server) error { log.Println(" what is the complete payload ", p) return b.post(p, uriGtm, uriServer) @@ -213,45 +229,47 @@ func (b *BigIP) DeleteGtmserver(name string) error { return b.delete(uriGtm, uriServer, name) } -func (b *BigIP) GetGtmserver(name string) (*Server, error) { - var p Server - err, ok := b.getForEntity(&p, uriGtm, uriServer, name) - if err != nil { - return nil, err - } - if !ok { - return nil, nil - } - - return &p, nil -} - -func (b *BigIP) CreatePool_a(name, monitor, load_balancing_mode string, max_answers_returned int, alternate_mode, fallback_ip, fallback_mode string, members []string) error { - config := &Pool_a{ - Name: name, - Monitor: monitor, - Load_balancing_mode: load_balancing_mode, - Max_answers_returned: max_answers_returned, - Alternate_mode: alternate_mode, - Fallback_ip: fallback_ip, - Fallback_mode: fallback_mode, - Members: members, - } - log.Println("in poola now", config) - return b.patch(config, uriGtm, uriPool_a) -} - -func (b *BigIP) ModifyPool_a(config *Pool_a) error { - return b.put(config, uriGtm, uriPool_a) -} - -func (b *BigIP) Pool_as() (*Pool_a, error) { - var pool_a Pool_a - err, _ := b.getForEntity(&pool_a, uriGtm, uriPool_a) - if err != nil { - return nil, err - } - - return &pool_a, nil -} +func (b *BigIP) GetGtmserver(name string) (*Server, error) { + var p Server + err, ok := b.getForEntity(&p, uriGtm, uriServer, name) + if err != nil { + return nil, err + } + if !ok { + return nil, nil + } + + return &p, nil + } + + + func (b *BigIP) CreatePool_a(name, monitor, load_balancing_mode string, max_answers_returned int, alternate_mode, fallback_ip, fallback_mode string, members []string) error { + config := &Pool_a{ + Name: name, + Monitor: monitor, + Load_balancing_mode: load_balancing_mode, + Max_answers_returned: max_answers_returned, + Alternate_mode: alternate_mode, + Fallback_ip: fallback_ip, + Fallback_mode: fallback_mode, + Members: members, + } + log.Println("in poola now", config) + return b.patch(config, uriGtm, uriPool_a) + } + + func (b *BigIP) ModifyPool_a(config *Pool_a) error { + return b.put(config, uriGtm, uriPool_a) + } + + func (b *BigIP) Pool_as() (*Pool_a, error) { + var pool_a Pool_a + err, _ := b.getForEntity(&pool_a, uriGtm, uriPool_a) + + if err != nil { + return nil, err + } + + return &pool_a, nil + } diff --git a/ltm.go b/ltm.go index 7f6306e..d252064 100644 --- a/ltm.go +++ b/ltm.go @@ -130,6 +130,344 @@ type ClientSSLProfile struct { UncleanShutdown string `json:"uncleanShutdown,omitempty"` } +// TcpProfiles contains a list of every tcp profile on the BIG-IP system. +type TcpProfiles struct { + TcpProfiles []TcpProfile `json:"items"` +} + +type TcpProfile struct { + Abc string `json:"abc,omitempty"` + AckOnPush string `json:"ackOnPush,omitempty"` + AppService string `json:"appService,omitempty"` + AutoProxyBufferSize string `json:"autoProxyBufferSize,omitempty"` + AutoReceiveWindowSize string `json:"autoReceiveWindowSize,omitempty"` + AutoSendBufferSize string `json:"autoSendBufferSize,omitempty"` + CloseWaitTimeout int `json:"closeWaitTimeout,omitempty"` + CmetricsCache string `json:"cmetricsCache,omitempty"` + CmetricsCacheTimeout int `json:"cmetricsCacheTimeout,omitempty"` + CongestionControl string `json:"congestionControl,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + DeferredAccept string `json:"deferredAccept,omitempty"` + DelayWindowControl string `json:"delayWindowControl,omitempty"` + DelayedAcks string `json:"delayedAcks,omitempty"` + Description string `json:"description,omitempty"` + Dsack string `json:"dsack,omitempty"` + EarlyRetransmit string `json:"earlyRetransmit,omitempty"` + Ecn string `json:"ecn,omitempty"` + EnhancedLossRecovery string `json:"enhancedLossRecovery,omitempty"` + FastOpen string `json:"fastOpen,omitempty"` + FastOpenCookieExpiration int `json:"fastOpenCookieExpiration,omitempty"` + FinWait_2Timeout int `json:"finWait_2Timeout,omitempty"` + FinWaitTimeout int `json:"finWaitTimeout,omitempty"` + HardwareSynCookie string `json:"hardwareSynCookie,omitempty"` + IdleTimeout int `json:"idleTimeout,omitempty"` + InitCwnd int `json:"initCwnd,omitempty"` + InitRwnd int `json:"initRwnd,omitempty"` + IpDfMode string `json:"ipDfMode,omitempty"` + IpTosToClient string `json:"ipTosToClient,omitempty"` + IpTtlMode string `json:"ipTtlMode,omitempty"` + IpTtlV4 int `json:"ipTtlV4,omitempty"` + IpTtlV6 int `json:"ipTtlV6,omitempty"` + KeepAliveInterval int `json:"keepAliveInterval,omitempty"` + LimitedTransmit string `json:"limitedTransmit,omitempty"` + LinkQosToClient string `json:"linkQosToClient,omitempty"` + MaxRetrans int `json:"maxRetrans,omitempty"` + MaxSegmentSize int `json:"maxSegmentSize,omitempty"` + Md5Signature string `json:"md5Signature,omitempty"` + Md5SignaturePassphrase string `json:"md5SignaturePassphrase,omitempty"` + MinimumRto int `json:"minimumRto,omitempty"` + Mptcp string `json:"mptcp,omitempty"` + MptcpCsum string `json:"mptcpCsum,omitempty"` + MptcpCsumVerify string `json:"mptcpCsumVerify,omitempty"` + MptcpDebug string `json:"mptcpDebug,omitempty"` + MptcpFallback string `json:"mptcpFallback,omitempty"` + MptcpFastjoin string `json:"mptcpFastjoin,omitempty"` + MptcpIdleTimeout int `json:"mptcpIdleTimeout,omitempty"` + MptcpJoinMax int `json:"mptcpJoinMax,omitempty"` + MptcpMakeafterbreak string `json:"mptcpMakeafterbreak,omitempty"` + MptcpNojoindssack string `json:"mptcpNojoindssack,omitempty"` + MptcpRtomax int `json:"mptcpRtomax,omitempty"` + MptcpRxmitmin int `json:"mptcpRxmitmin,omitempty"` + MptcpSubflowmax int `json:"mptcpSubflowmax,omitempty"` + MptcpTimeout int `json:"mptcpTimeout,omitempty"` + Nagle string `json:"nagle,omitempty"` + Name string `json:"name,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + PktLossIgnoreBurst int `json:"pktLossIgnoreBurst,omitempty"` + PktLossIgnoreRate int `json:"pktLossIgnoreRate,omitempty"` + ProxyBufferHigh int `json:"proxyBufferHigh,omitempty"` + ProxyBufferLow int `json:"proxyBufferLow,omitempty"` + ProxyMss string `json:"proxyMss,omitempty"` + ProxyOptions string `json:"proxyOptions,omitempty"` + RatePace string `json:"ratePace,omitempty"` + RatePaceMaxRate int `json:"ratePaceMaxRate,omitempty"` + ReceiveWindowSize int `json:"receiveWindowSize,omitempty"` + ResetOnTimeout string `json:"resetOnTimeout,omitempty"` + RexmtThresh int `json:"rexmtThresh,omitempty"` + SelectiveAcks string `json:"selectiveAcks,omitempty"` + SelectiveNack string `json:"selectiveNack,omitempty"` + SendBufferSize int `json:"sendBufferSize,omitempty"` + SlowStart string `json:"slowStart,omitempty"` + SynCookieEnable string `json:"synCookieEnable,omitempty"` + SynCookieWhitelist string `json:"synCookieWhitelist,omitempty"` + SynMaxRetrans int `json:"synMaxRetrans,omitempty"` + SynRtoBase int `json:"synRtoBase,omitempty"` + TailLossProbe string `json:"tailLossProbe,omitempty"` + TcpOptions string `json:"tcpOptions,omitempty"` + TimeWaitRecycle string `json:"timeWaitRecycle,omitempty"` + TimeWaitTimeout string `json:"timeWaitTimeout,omitempty"` + Timestamps string `json:"timestamps,omitempty"` + VerifiedAccept string `json:"verifiedAccept,omitempty"` +} + +// UdpProfiles contains a list of every tcp profile on the BIG-IP system. +type UdpProfiles struct { + UdpProfiles []UdpProfile `json:"items"` +} + +type UdpProfile struct { + AllowNoPayload string `json:"allowNoPayload,omitempty"` + AppService string `json:"appService,omitempty"` + BufferMaxBytes int `json:"bufferMaxBytes,omitempty"` + BufferMaxPackets int `json:"bufferMaxPackets,omitempty"` + DatagramLoadBalancing string `json:"datagramLoadBalancing,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + IdleTimeout string `json:"idleTimeout,omitempty"` + IpDfMode string `json:"ipDfMode,omitempty"` + IpTosToClient string `json:"ipTosToClient,omitempty"` + IpTtlMode string `json:"ipTtlMode,omitempty"` + IpTtlV4 int `json:"ipTtlV4,omitempty"` + IpTtlV6 int `json:"ipTtlV6,omitempty"` + LinkQosToClient string `json:"linkQosToClient,omitempty"` + Name string `json:"name,omitempty"` + NoChecksum string `json:"noChecksum,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + ProxyMss string `json:"proxyMss,omitempty"` +} + +type HttpProfiles struct { + HttpProfiles []HttpProfile `json:"items"` +} + +type HttpProfile struct { + AcceptXff string `json:"acceptXff,omitempty"` + AppService string `json:"appService,omitempty"` + BasicAuthRealm string `json:"basicAuthRealm,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + EncryptCookieSecret string `json:"encryptCookieSecret,omitempty"` + EncryptCookies string `json:"encryptCookies,omitempty"` + FallbackHost string `json:"fallbackHost,omitempty"` + FallbackStatusCodes string `json:"fallbackStatusCodes,omitempty"` + HeaderErase string `json:"headerErase,omitempty"` + HeaderInsert string `json:"headerInsert,omitempty"` + InsertXforwardedFor string `json:"insertXforwardedFor,omitempty"` + LwsSeparator string `json:"lwsSeparator,omitempty"` + LwsWidth int `json:"lwsWidth,omitempty"` + Name string `json:"name,omitempty"` + OneconnectTransformations string `json:"oneconnectTransformations,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + ProxyType string `json:"proxyType,omitempty"` + RedirectRewrite string `json:"redirectRewrite,omitempty"` + RequestChunking string `json:"requestChunking,omitempty"` + ResponseChunking string `json:"responseChunking,omitempty"` + ResponseHeadersPermitted string `json:"responseHeadersPermitted,omitempty"` + ServerAgentName string `json:"serverAgentName,omitempty"` + ViaHostName string `json:"viaHostName,omitempty"` + ViaRequest string `json:"viaRequest,omitempty"` + ViaResponse string `json:"viaResponse,omitempty"` + XffAlternativeNames string `json:"xffAlternativeNames,omitempty"` +} + +type OneconnectProfiles struct { + OneconnectProfiles []OneconnectProfile `json:"items"` +} + +type OneconnectProfile struct { + AppService string `json:"appService,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + IdleTimeoutOverride string `json:"idleTimeoutOverride,omitempty"` + LimitType string `json:"limitType,omitempty"` + MaxAge int `json:"maxAge,omitempty"` + MaxReuse int `json:"maxReuse,omitempty"` + MaxSize int `json:"maxSize,omitempty"` + Name string `json:"name,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + SharePools string `json:"sharePools,omitempty"` + SourceMask string `json:"sourceMask,omitempty"` +} + +type HttpCompressionProfiles struct { + HttpCompressionProfiles []HttpCompressionProfile `json:"items"` +} + +type HttpCompressionProfile struct { + AllowHttp_10 string `json:"allowHttp_10,omitempty"` + AppService string `json:"appService,omitempty"` + BrowserWorkarounds string `json:"browserWorkarounds,omitempty"` + BufferSize int `json:"bufferSize,omitempty"` + ContentTypeExclude []string `json:"contentTypeExclude,omitempty"` + ContentTypeInclude []string `json:"contentTypeInclude,omitempty"` + CpuSaver string `json:"cpuSaver,omitempty"` + CpuSaverHigh int `json:"cpuSaverHigh,omitempty"` + CpuSaverLow int `json:"cpuSaverLow,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + GzipLevel int `json:"gzipLevel,omitempty"` + GzipMemoryLevel int `json:"gzipMemoryLevel,omitempty"` + GzipWindowSize int `json:"gzipWindowSize,omitempty"` + KeepAcceptEncoding string `json:"keepAcceptEncoding,omitempty"` + MethodPrefer string `json:"methodPrefer,omitempty"` + MinSize int `json:"minSize,omitempty"` + Name string `json:"name,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + Selective string `json:"selective,omitempty"` + UriExclude []string `json:"uriExclude,omitempty"` + UriInclude []string `json:"uriInclude,omitempty"` + VaryHeader string `json:"varyHeader,omitempty"` +} + +// PersistenceProfiles contains of list of persistence profiles +type PersistenceProfiles struct { + PersistenceProfiles []PersistenceProfile `json:"items"` +} + +// PersistenceProfile is a base for all persistence profiles +type PersistenceProfile struct { + AppService string `json:"appService,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + FullPath string `json:"fullPath,omitempty"` + MatchAcrossPools string `json:"matchAcrossPools,omitempty"` + MatchAcrossServices string `json:"matchAcrossServices,omitempty"` + MatchAcrossVirtuals string `json:"matchAcrossVirtuals,omitempty"` + Method string `json:"method,omitempty"` + Mirror string `json:"mirror,omitempty"` + Mode string `json:"mode,omitempty"` + Name string `json:"name,omitempty"` + OverrideConnectionLimit string `json:"overrideConnectionLimit,omitempty"` + Partition string `json:"partition,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + Timeout string `json:"timeout,omitempty"` +} + +// CookiePersistenceProfiles contains a list of all cookies profiles +type CookiePersistenceProfiles struct { + CookiePersistenceProfiles []CookiePersistenceProfile `json:"items"` +} + +// CookiePersistenceProfile Defines a single cookie profile +type CookiePersistenceProfile struct { + PersistenceProfile + AlwaysSend string `json:"alwaysSend,omitempty"` + CookieEncryption string `json:"cookieEncryption,omitempty"` + CookieEncryptionPassphrase string `json:"cookieEncryptionPassphrase,omitempty"` + CookieName string `json:"cookieName,omitempty"` + Expiration string `json:"expiration,omitempty"` + HashLength int `json:"hashLength,omitempty"` + HashOffset int `json:"hashOffset,omitempty"` + HTTPOnly string `json:"httponly,omitempty"` + Secure string `json:"secure,omitempty"` +} + +// DestAddrPersistenceProfiles contains a list of all dest-addr profiles +type DestAddrPersistenceProfiles struct { + DestAddrPersistenceProfiles []DestAddrPersistenceProfile `json:"items"` +} + +// DestAddrPersistenceProfile Defines a single dest-addr profile +type DestAddrPersistenceProfile struct { + PersistenceProfile + HashAlgorithm string `json:"hashAlgorithm,omitempty"` + Mask string `json:"mask,omitempty"` +} + +// HashPersistenceProfiles contains a list of all hash profiles +type HashPersistenceProfiles struct { + HashPersistenceProfiles []HashPersistenceProfile `json:"items"` +} + +// HashPersistenceProfile Defines a single hash profile +type HashPersistenceProfile struct { + PersistenceProfile + HashAlgorithm string `json:"hashAlgorithm,omitempty"` + HashBufferLimit int `json:"hashBufferLimit,omitempty"` + HashEndPattern int `json:"hashEndPattern,omitempty"` + HashLength int `json:"hashLength,omitempty"` + HashOffset int `json:"hashOffset,omitempty"` + HashStartPattern int `json:"hashStartPattern,omitempty"` +} + +// HostPersistenceProfiles contains a list of all host profiles +type HostPersistenceProfiles struct { + HostPersistenceProfiles []HostPersistenceProfile `json:"items"` +} + +// HostPersistenceProfile Defines a single host profile +type HostPersistenceProfile struct { + PersistenceProfile +} + +// MSRDPPersistenceProfiles contains a list of all msrdp profiles +type MSRDPPersistenceProfiles struct { + MSRDPPersistenceProfiles []MSRDPPersistenceProfile `json:"items"` +} + +// MSRDPPersistenceProfile Defines a single msrdp profile +type MSRDPPersistenceProfile struct { + PersistenceProfile + HasSessionDir string `json:"hasSessionDir,omitempty"` +} + +// SIPPersistenceProfiles contains a list of all sip profiles +type SIPPersistenceProfiles struct { + SIPPersistenceProfiles []SIPPersistenceProfile `json:"items"` +} + +// SIPPersistenceProfile Defines a single sip profile +type SIPPersistenceProfile struct { + PersistenceProfile + SIPInfo string `json:"sipInfo,omitempty"` +} + +// SourceAddrPersistenceProfiles contains a list of all source-addr profiles +type SourceAddrPersistenceProfiles struct { + SourceAddrPersistenceProfiles []SourceAddrPersistenceProfile `json:"items"` +} + +// SourceAddrPersistenceProfile Defines a single source-addr profile +type SourceAddrPersistenceProfile struct { + PersistenceProfile + HashAlgorithm string `json:"hashAlgorithm,omitempty"` + MapProxies string `json:"mapProxies,omitempty"` + MapProxyAddress string `json:"mapProxyAddress,omitempty"` + MapProxyClass string `json:"mapProxyClass,omitempty"` + Mask string `json:"mask,omitempty"` +} + +// SSLPersistenceProfiles contains a list of all ssl profiles +type SSLPersistenceProfiles struct { + SSLPersistenceProfiles []SSLPersistenceProfile `json:"items"` +} + +// SSLPersistenceProfile Defines a single ssl profile +type SSLPersistenceProfile struct { + PersistenceProfile +} + +// UniversalPersistenceProfiles contains a list of all universal profiles +type UniversalPersistenceProfiles struct { + SSLPersistenceProfiles []UniversalPersistenceProfile `json:"items"` +} + +// UniversalPersistenceProfile Defines a single universal profile +type UniversalPersistenceProfile struct { + PersistenceProfile + Rule string `json:"rule,omitempty"` +} + // Nodes contains a list of every node on the BIG-IP system. type Nodes struct { Nodes []Node `json:"items"` @@ -151,13 +489,6 @@ type Node struct { Ratio int `json:"ratio,omitempty"` Session string `json:"session,omitempty"` State string `json:"state,omitempty"` - FQDN struct { - AddressFamily string `json:"addressFamily,omitempty"` - AutoPopulate string `json:"autopopulate,omitempty"` - DownInterval int `json:"downInterval,omitempty"` - Interval string `json:"interval,omitempty"` - Name string `json:"tmName,omitempty"` - } `json:"fqdn,omitempty"` } // DataGroups contains a list of data groups on the BIG-IP system. @@ -175,37 +506,24 @@ type DataGroup struct { Records []DataGroupRecord } -type DataGroupRecords struct { - Items []DataGroupRecord `json:"items,omitempty"` -} - type DataGroupRecord struct { Name string `json:"name,omitempty"` Data string `json:"data,omitempty"` } type dataGroupDTO struct { - Name string `json:"name,omitempty"` - Partition string `json:"partition,omitempty"` - FullPath string `json:"fullPath,omitempty"` - Generation int `json:"generation,omitempty"` - Type string `json:"type,omitempty"` - Records struct { - Items []DataGroupRecord `json:"items,omitempty"` - } `json:"recordsReference,omitempty"` + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` + Generation int `json:"generation,omitempty"` + Type string `json:"type,omitempty"` + Records []DataGroupRecord `json:"records,omitempty"` } func (p *DataGroup) MarshalJSON() ([]byte, error) { - return json.Marshal(dataGroupDTO{ - Name: p.Name, - Partition: p.Partition, - FullPath: p.FullPath, - Generation: p.Generation, - Type: p.Type, - Records: struct { - Items []DataGroupRecord `json:"items,omitempty"` - }{Items: p.Records}, - }) + var dto dataGroupDTO + marshal(&dto, p) + return json.Marshal(dto) } func (p *DataGroup) UnmarshalJSON(b []byte) error { @@ -214,14 +532,7 @@ func (p *DataGroup) UnmarshalJSON(b []byte) error { if err != nil { return err } - - p.Name = dto.Name - p.Partition = dto.Partition - p.Type = dto.Type - p.FullPath = dto.FullPath - p.Generation = dto.Generation - p.Records = dto.Records.Items - return nil + return marshal(p, &dto) } // SnatPools contains a list of every snatpool on the BIG-IP system. @@ -267,9 +578,9 @@ type Pool struct { QueueDepthLimit int `json:"queueDepthLimit,omitempty"` QueueOnConnectionLimit string `json:"queueOnConnectionLimit,omitempty"` QueueTimeLimit int `json:"queueTimeLimit,omitempty"` - ReselectTries int `json:"reselectTries"` + ReselectTries int `json:"reselectTries,omitempty"` ServiceDownAction string `json:"serviceDownAction,omitempty"` - SlowRampTime int `json:"slowRampTime"` + SlowRampTime int `json:"slowRampTime,omitempty"` } // Pool Members contains a list of pool members within a pool on the BIG-IP system. @@ -329,9 +640,9 @@ type poolDTO struct { QueueDepthLimit int `json:"queueDepthLimit,omitempty"` QueueOnConnectionLimit string `json:"queueOnConnectionLimit,omitempty"` QueueTimeLimit int `json:"queueTimeLimit,omitempty"` - ReselectTries int `json:"reselectTries"` + ReselectTries int `json:"reselectTries,omitempty"` ServiceDownAction string `json:"serviceDownAction,omitempty"` - SlowRampTime int `json:"slowRampTime"` + SlowRampTime int `json:"slowRampTime,omitempty"` } func (p *Pool) MarshalJSON() ([]byte, error) { @@ -349,196 +660,58 @@ func (p *Pool) UnmarshalJSON(b []byte) error { return marshal(p, &dto) } -// PersistenceProfiles contains of list of persistence profiles -type PersistenceProfiles struct { - PersistenceProfiles []PersistenceProfile `json:"items"` -} - -// PersistenceProfile is a base for all persistence profiles -type PersistenceProfile struct { - AppService string `json:"appService,omitempty"` - DefaultsFrom string `json:"defaultsFrom,omitempty"` - Description string `json:"description,omitempty"` - FullPath string `json:"fullPath,omitempty"` - MatchAcrossPools string `json:"matchAcrossPools,omitempty"` - MatchAcrossServices string `json:"matchAcrossServices,omitempty"` - MatchAcrossVirtuals string `json:"matchAcrossVirtuals,omitempty"` - Method string `json:"method,omitempty"` - Mirror string `json:"mirror,omitempty"` - Mode string `json:"mode,omitempty"` - Name string `json:"name,omitempty"` - OverrideConnectionLimit string `json:"overrideConnectionLimit,omitempty"` - Partition string `json:"partition,omitempty"` - TmPartition string `json:"tmPartition,omitempty"` - Timeout string `json:"timeout,omitempty"` +// VirtualServers contains a list of all virtual servers on the BIG-IP system. +type VirtualServers struct { + VirtualServers []VirtualServer `json:"items"` } -// CookiePersistenceProfiles contains a list of all cookies profiles -type CookiePersistenceProfiles struct { - CookiePersistenceProfiles []CookiePersistenceProfile `json:"items"` +// VirtualServer contains information about each individual virtual server. +type VirtualServer struct { + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` + Generation int `json:"generation,omitempty"` + AddressStatus string `json:"addressStatus,omitempty"` + AutoLastHop string `json:"autoLastHop,omitempty"` + CMPEnabled string `json:"cmpEnabled,omitempty"` + ConnectionLimit int `json:"connectionLimit,omitempty"` + Destination string `json:"destination,omitempty"` + Description string `json:"description,omitempty"` + Enabled bool `json:"enabled,omitempty"` + FallbackPersistenceProfile string `json:"fallbackPersistence,omitempty"` + GTMScore int `json:"gtmScore,omitempty"` + IPProtocol string `json:"ipProtocol,omitempty"` + Mask string `json:"mask,omitempty"` + Mirror string `json:"mirror,omitempty"` + MobileAppTunnel string `json:"mobileAppTunnel,omitempty"` + NAT64 string `json:"nat64,omitempty"` + Pool string `json:"pool,omitempty"` + RateLimit string `json:"rateLimit,omitempty"` + RateLimitDestinationMask int `json:"rateLimitDstMask,omitempty"` + RateLimitMode string `json:"rateLimitMode,omitempty"` + RateLimitSourceMask int `json:"rateLimitSrcMask,omitempty"` + Source string `json:"source,omitempty"` + SourceAddressTranslation struct { + Type string `json:"type,omitempty"` + Pool string `json:"pool,omitempty"` + } `json:"sourceAddressTranslation,omitempty"` + SourcePort string `json:"sourcePort,omitempty"` + SYNCookieStatus string `json:"synCookieStatus,omitempty"` + TranslateAddress string `json:"translateAddress,omitempty"` + TranslatePort string `json:"translatePort,omitempty"` + VlansEnabled bool `json:"vlansEnabled,omitempty"` + VlansDisabled bool `json:"vlansDisabled,omitempty"` + VSIndex int `json:"vsIndex,omitempty"` + Vlans []string `json:"vlans,omitempty"` + Rules []string `json:"rules,omitempty"` + PersistenceProfiles []Profile `json:"persist,omitempty"` + Profiles []Profile `json:"profiles,omitempty"` + Policies []string `json:"policies,omitempty"` } -// CookiePersistenceProfile Defines a single cookie profile -type CookiePersistenceProfile struct { - PersistenceProfile - AlwaysSend string `json:"alwaysSend,omitempty"` - CookieEncryption string `json:"cookieEncryption,omitempty"` - CookieEncryptionPassphrase string `json:"cookieEncryptionPassphrase,omitempty"` - CookieName string `json:"cookieName,omitempty"` - Expiration string `json:"expiration,omitempty"` - HashLength int `json:"hashLength,omitempty"` - HashOffset int `json:"hashOffset,omitempty"` - HTTPOnly string `json:"httponly,omitempty"` - Secure string `json:"secure,omitempty"` -} - -// DestAddrPersistenceProfiles contains a list of all dest-addr profiles -type DestAddrPersistenceProfiles struct { - DestAddrPersistenceProfiles []DestAddrPersistenceProfile `json:"items"` -} - -// DestAddrPersistenceProfile Defines a single dest-addr profile -type DestAddrPersistenceProfile struct { - PersistenceProfile - HashAlgorithm string `json:"hashAlgorithm,omitempty"` - Mask string `json:"mask,omitempty"` -} - -// HashPersistenceProfiles contains a list of all hash profiles -type HashPersistenceProfiles struct { - HashPersistenceProfiles []HashPersistenceProfile `json:"items"` -} - -// HashPersistenceProfile Defines a single hash profile -type HashPersistenceProfile struct { - PersistenceProfile - HashAlgorithm string `json:"hashAlgorithm,omitempty"` - HashBufferLimit int `json:"hashBufferLimit,omitempty"` - HashEndPattern int `json:"hashEndPattern,omitempty"` - HashLength int `json:"hashLength,omitempty"` - HashOffset int `json:"hashOffset,omitempty"` - HashStartPattern int `json:"hashStartPattern,omitempty"` -} - -// HostPersistenceProfiles contains a list of all host profiles -type HostPersistenceProfiles struct { - HostPersistenceProfiles []HostPersistenceProfile `json:"items"` -} - -// HostPersistenceProfile Defines a single host profile -type HostPersistenceProfile struct { - PersistenceProfile -} - -// MSRDPPersistenceProfiles contains a list of all msrdp profiles -type MSRDPPersistenceProfiles struct { - MSRDPPersistenceProfiles []MSRDPPersistenceProfile `json:"items"` -} - -// MSRDPPersistenceProfile Defines a single msrdp profile -type MSRDPPersistenceProfile struct { - PersistenceProfile - HasSessionDir string `json:"hasSessionDir,omitempty"` -} - -// SIPPersistenceProfiles contains a list of all sip profiles -type SIPPersistenceProfiles struct { - SIPPersistenceProfiles []SIPPersistenceProfile `json:"items"` -} - -// SIPPersistenceProfile Defines a single sip profile -type SIPPersistenceProfile struct { - PersistenceProfile - SIPInfo string `json:"sipInfo,omitempty"` -} - -// SourceAddrPersistenceProfiles contains a list of all source-addr profiles -type SourceAddrPersistenceProfiles struct { - SourceAddrPersistenceProfiles []SourceAddrPersistenceProfile `json:"items"` -} - -// SourceAddrPersistenceProfile Defines a single source-addr profile -type SourceAddrPersistenceProfile struct { - PersistenceProfile - HashAlgorithm string `json:"hashAlgorithm,omitempty"` - MapProxies string `json:"mapProxies,omitempty"` - MapProxyAddress string `json:"mapProxyAddress,omitempty"` - MapProxyClass string `json:"mapProxyClass,omitempty"` - Mask string `json:"mask,omitempty"` -} - -// SSLPersistenceProfiles contains a list of all ssl profiles -type SSLPersistenceProfiles struct { - SSLPersistenceProfiles []SSLPersistenceProfile `json:"items"` -} - -// SSLPersistenceProfile Defines a single ssl profile -type SSLPersistenceProfile struct { - PersistenceProfile -} - -// UniversalPersistenceProfiles contains a list of all universal profiles -type UniversalPersistenceProfiles struct { - SSLPersistenceProfiles []UniversalPersistenceProfile `json:"items"` -} - -// UniversalPersistenceProfile Defines a single universal profile -type UniversalPersistenceProfile struct { - PersistenceProfile - Rule string `json:"rule,omitempty"` -} - -// VirtualServers contains a list of all virtual servers on the BIG-IP system. -type VirtualServers struct { - VirtualServers []VirtualServer `json:"items"` -} - -// VirtualServer contains information about each individual virtual server. -type VirtualServer struct { - Name string `json:"name,omitempty"` - Partition string `json:"partition,omitempty"` - FullPath string `json:"fullPath,omitempty"` - Generation int `json:"generation,omitempty"` - AddressStatus string `json:"addressStatus,omitempty"` - AutoLastHop string `json:"autoLastHop,omitempty"` - CMPEnabled string `json:"cmpEnabled,omitempty"` - ConnectionLimit int `json:"connectionLimit,omitempty"` - Destination string `json:"destination,omitempty"` - Enabled bool `json:"enabled,omitempty"` - GTMScore int `json:"gtmScore,omitempty"` - FallbackPersistenceProfile string `json:"fallbackPersistence,omitempty"` - IPProtocol string `json:"ipProtocol,omitempty"` - Mask string `json:"mask,omitempty"` - Mirror string `json:"mirror,omitempty"` - MobileAppTunnel string `json:"mobileAppTunnel,omitempty"` - NAT64 string `json:"nat64,omitempty"` - Pool string `json:"pool,omitempty"` - RateLimit string `json:"rateLimit,omitempty"` - RateLimitDestinationMask int `json:"rateLimitDstMask,omitempty"` - RateLimitMode string `json:"rateLimitMode,omitempty"` - RateLimitSourceMask int `json:"rateLimitSrcMask,omitempty"` - Source string `json:"source,omitempty"` - SourceAddressTranslation struct { - Type string `json:"type,omitempty"` - Pool string `json:"pool,omitempty"` - } `json:"sourceAddressTranslation,omitempty"` - SourcePort string `json:"sourcePort,omitempty"` - SYNCookieStatus string `json:"synCookieStatus,omitempty"` - TranslateAddress string `json:"translateAddress,omitempty"` - TranslatePort string `json:"translatePort,omitempty"` - VlansEnabled bool `json:"vlansEnabled,omitempty"` - VlansDisabled bool `json:"vlansDisabled,omitempty"` - VSIndex int `json:"vsIndex,omitempty"` - Vlans []string `json:"vlans,omitempty"` - Rules []string `json:"rules,omitempty"` - PersistenceProfiles []Profile `json:"persist,omitempty"` - Profiles []Profile `json:"profiles,omitempty"` - Policies []string `json:"policies,omitempty"` -} - -// VirtualAddresses contains a list of all virtual addresses on the BIG-IP system. -type VirtualAddresses struct { - VirtualAddresses []VirtualAddress `json:"items"` +// VirtualAddresses contains a list of all virtual addresses on the BIG-IP system. +type VirtualAddresses struct { + VirtualAddresses []VirtualAddress `json:"items"` } // VirtualAddress contains information about each individual virtual address. @@ -590,13 +763,8 @@ type VirtualServerPolicies struct { PolicyRef Policies `json:"policiesReference"` } -type PolicyPublish struct { - Name string `json:"name"` - PublishCopy string `json:"publishedCopy"` -} type Policy struct { Name string - PublishCopy string Partition string FullPath string Controls []string @@ -607,7 +775,6 @@ type Policy struct { type policyDTO struct { Name string `json:"name"` - PublishCopy string `json:"publishedCopy"` Partition string `json:"partition,omitempty"` Controls []string `json:"controls,omitempty"` Requires []string `json:"requires,omitempty"` @@ -621,7 +788,6 @@ type policyDTO struct { func (p *Policy) MarshalJSON() ([]byte, error) { return json.Marshal(policyDTO{ Name: p.Name, - PublishCopy: p.PublishCopy, Partition: p.Partition, Controls: p.Controls, Requires: p.Requires, @@ -641,7 +807,6 @@ func (p *Policy) UnmarshalJSON(b []byte) error { } p.Name = dto.Name - p.PublishCopy = dto.PublishCopy p.Partition = dto.Partition p.Controls = dto.Controls p.Requires = dto.Requires @@ -915,8 +1080,6 @@ type PolicyRuleCondition struct { VlanId bool `json:"vlanId,omitempty"` } - - func (p *VirtualAddress) MarshalJSON() ([]byte, error) { var dto virtualAddressDTO marshal(&dto, p) @@ -941,48 +1104,53 @@ type Monitors struct { type Monitor struct { Name string Partition string - DefaultsFrom string FullPath string Generation int ParentMonitor string + Database string Description string Destination string Interval int IPDSCP int - ManualResume string + ManualResume bool + MonitorType string Password string + ReceiveColumn string + ReceiveRow string ReceiveString string ReceiveDisable string - Reverse string + Reverse bool SendString string TimeUntilUp int Timeout int - Transparent string + Transparent bool UpInterval int Username string - } type monitorDTO struct { - Name string `json:"name,omitempty"` - Partition string `json:"partition,omitempty"` - DefaultsFrom string `json:"defaultsFrom,omitempty"` - FullPath string `json:"fullPath,omitempty"` - Generation int `json:"generation,omitempty"` - ParentMonitor string `json:"defaultsFrom,omitempty"` - Description string `json:"description,omitempty"` - Destination string `json:"destination,omitempty"` - Interval int `json:"interval,omitempty"` - IPDSCP int `json:"ipDscp,omitempty"` - ManualResume string `json:"manualResume,omitempty"` + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` + Generation int `json:"generation,omitempty"` + ParentMonitor string `json:"defaultsFrom,omitempty"` + Database string `json:"database,omitempty"` + Description string `json:"description,omitempty"` + Destination string `json:"destination,omitempty"` + Interval int `json:"interval,omitempty"` + IPDSCP int `json:"ipDscp,omitempty"` + ManualResume string `json:"manualResume,omitempty" bool:"enabled"` + // MonitorType string `json:"monitorType,omitempty"` Password string `json:"password,omitempty"` + ReceiveColumn string `json:"recvColumn,omitempty"` + ReceiveRow string `json:"recvRow,omitempty"` ReceiveString string `json:"recv,omitempty"` ReceiveDisable string `json:"recvDisable,omitempty"` - Reverse string `json:"reverse,omitempty"` + Reverse string `json:"reverse,omitempty" bool:"enabled"` SendString string `json:"send,omitempty"` TimeUntilUp int `json:"timeUntilUp,omitempty"` Timeout int `json:"timeout,omitempty"` - Transparent string `json:"transparent,omitempty"` + Transparent string `json:"transparent,omitempty" bool:"enabled"` UpInterval int `json:"upInterval,omitempty"` Username string `json:"username,omitempty"` } @@ -1347,52 +1515,31 @@ type Snat struct { Partition string FullPath string AutoLasthop string - Mirror string + Mirror bool SourcePort string Translation string Snatpool string VlansDisabled bool - Origins []Originsrecord + Origins []string } type snatDTO struct { - Name string `json:"name"` - Partition string `json:"partition,omitempty"` - FullPath string `json:"fullPath,omitempty"` - AutoLasthop string `json:"autoLastHop,omitempty"` - Mirror string `json:"mirror,omitempty"` - SourcePort string `json:"sourePort,omitempty"` - Translation string `json:"translation,omitempty"` - Snatpool string `json:"snatpool,omitempty"` - VlansDisabled bool `json:"vlansDisabled,omitempty" bool:"disabled"` - Origins struct { - Items []Originsrecord `json:"items,omitempty"` - } `json:"originsReference,omitempty"` -} - -type Originsrecords struct { - Items []Originsrecord `json:"items,omitempty"` -} - -type Originsrecord struct { - Name string `json:"name"` - app_service string `json:"appService,omitempty"` + Name string `json:"name"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` + AutoLasthop string `json:"autoLastHop,omitempty"` + Mirror bool `json:"mirror,omitempty" bool:"disabled"` + SourcePort string `json:"sourePort,omitempty"` + Translation string `json:"translation,omitempty"` + Snatpool string `json:"snatpool,omitempty"` + VlansDisabled bool `json:"vlansDisabled,omitempty" bool:"disabled"` + Origins []string `json:"origins,omitempty"` } func (p *Snat) MarshalJSON() ([]byte, error) { - return json.Marshal(snatDTO{ - Name: p.Name, - Partition: p.Partition, - FullPath: p.FullPath, - Mirror: p.Mirror, - SourcePort: p.SourcePort, - Translation: p.Translation, - Snatpool: p.Snatpool, - VlansDisabled: p.VlansDisabled, - Origins: struct { - Items []Originsrecord `json:"items,omitempty"` - }{Items: p.Origins}, - }) + var dto snatDTO + marshal(&dto, p) + return json.Marshal(dto) } func (p *Snat) UnmarshalJSON(b []byte) error { @@ -1401,18 +1548,8 @@ func (p *Snat) UnmarshalJSON(b []byte) error { if err != nil { return err } - - p.Name = dto.Name - p.Partition = dto.Partition - p.FullPath = dto.FullPath - p.AutoLasthop = dto.AutoLasthop - p.Mirror = dto.Mirror - p.SourcePort = dto.SourcePort - p.Translation = dto.Translation - p.Snatpool = dto.Snatpool - p.VlansDisabled = dto.VlansDisabled - p.Origins = dto.Origins.Items - + p.Origins = dto.Origins + //return marshal(p, &dto) return nil } @@ -1480,6 +1617,7 @@ const ( uriHttp2 = "http2" uriSnat = "snat" uriSnatpool = "snatpool" + uriUdp = "udp" uriCookie = "cookie" uriDestAddr = "dest-addr" uriHash = "hash" @@ -1557,13 +1695,13 @@ func (b *BigIP) AddSnatPool(config *SnatPool) error { // GetSnatPool retrieves a SnatPool by name. Returns nil if the snatpool does not exist func (b *BigIP) GetSnatPool(name string) (*SnatPool, error) { var snatPool SnatPool - err, _ := b.getForEntity(&snatPool, uriLtm, uriSnatPool, name) + err, ok := b.getForEntity(&snatPool, uriLtm, uriSnatPool, name) if err != nil { return nil, err } - //if !ok { - // return nil, nil - //} + if !ok { + return nil, nil + } return &snatPool, nil } @@ -2410,32 +2548,12 @@ func (b *BigIP) Nodes() (*Nodes, error) { return &nodes, nil } -// CreateNode adds a new IP based node to the BIG-IP system. -func (b *BigIP) CreateNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state string) error { +// CreateNode adds a new node to the BIG-IP system. +func (b *BigIP) CreateNode(name, address string) error { config := &Node{ Name: name, Address: address, - RateLimit: rate_limit, - ConnectionLimit: connection_limit, - DynamicRatio: dynamic_ratio, - Monitor: monitor, - State: state, - } - - return b.post(config, uriLtm, uriNode) -} - -// CreateFQDNNode adds a new FQDN based node to the BIG-IP system. -func (b *BigIP) CreateFQDNNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state string) error { - config := &Node{ - Name: name, - RateLimit: rate_limit, - ConnectionLimit: connection_limit, - DynamicRatio: dynamic_ratio, - Monitor: monitor, - State: state, } - config.FQDN.Name = address return b.post(config, uriLtm, uriNode) } @@ -2708,7 +2826,7 @@ func (b *BigIP) VirtualServers() (*VirtualServers, error) { // CreateVirtualServer adds a new virtual server to the BIG-IP system. can either be // in CIDR notation or decimal, i.e.: "24" or "255.255.255.0". A CIDR mask of "0" is the same // as "0.0.0.0". -func (b *BigIP) CreateVirtualServer(name, destination, mask, pool string, vlans_enabled, vlans_disabled bool, port int, translate_address, translate_port string) error { +func (b *BigIP) CreateVirtualServer(name, destination, mask, pool string, port int) error { subnetMask := cidr[mask] if strings.Contains(mask, ".") { @@ -2716,12 +2834,10 @@ func (b *BigIP) CreateVirtualServer(name, destination, mask, pool string, vlans_ } config := &VirtualServer{ - Name: name, - Destination: fmt.Sprintf("%s:%d", destination, port), - Mask: subnetMask, - Pool: pool, - TranslateAddress: translate_address, - TranslatePort: translate_port, + Name: name, + Destination: fmt.Sprintf("%s:%d", destination, port), + Mask: subnetMask, + Pool: pool, } return b.post(config, uriLtm, uriVirtual) @@ -2981,12 +3097,7 @@ func (b *BigIP) Policies() (*Policies, error) { //Load a fully policy definition. Policies seem to be best dealt with as one big entity. func (b *BigIP) GetPolicy(name string) (*Policy, error) { var p Policy - values := []string{} - values = append(values, "Drafts/") - values = append(values, name) - // Join three strings into one. - result := strings.Join(values, "") - err, ok := b.getForEntity(&p, uriLtm, uriPolicy, result) + err, ok := b.getForEntity(&p, uriLtm, uriPolicy, name) if err != nil { return nil, err } @@ -3039,42 +3150,18 @@ func (b *BigIP) CreatePolicy(p *Policy) error { return b.post(p, uriLtm, uriPolicy) } -func (b *BigIP) PublishPolicy(name, publish string) error { - config := &Policy{ - PublishCopy: publish, - } - values := []string{} - values = append(values, "~Common~Drafts~") - values = append(values, name) - // Join three strings into one. - result := strings.Join(values, "") - - log.Println( " ================== here in publish ", result, publish) - - return b.patch(config, uriLtm, uriPolicy, result) -} - //Update an existing policy. - func (b *BigIP) UpdatePolicy(name string, p *Policy) error { +func (b *BigIP) UpdatePolicy(name string, p *Policy) error { normalizePolicy(p) - values := []string{} - values = append(values, "Drafts/") - values = append(values, name) - // Join three strings into one. - result := strings.Join(values, "") - return b.put(p, uriLtm, uriPolicy, result) + return b.put(p, uriLtm, uriPolicy, name) } //Delete a policy by name. func (b *BigIP) DeletePolicy(name string) error { - values := []string{} - values = append(values, "Drafts/") - values = append(values, name) - // Join three strings into one. - result := strings.Join(values, "") -return b.delete(uriLtm, uriPolicy, result) -} - // Oneconnect profile creation + return b.delete(uriLtm, uriPolicy, name) +} + +// Oneconnect profile creation func (b *BigIP) CreateOneconnect(name, idleTimeoutOverride, partition, defaultsFrom, sharePools, sourceMask string, maxAge, maxReuse, maxSize int) error { oneconnect := &Oneconnect{ Name: name, @@ -3090,17 +3177,15 @@ func (b *BigIP) CreateOneconnect(name, idleTimeoutOverride, partition, defaultsF return b.post(oneconnect, uriLtm, uriProfile, uriOneconnect) } -func (b *BigIP) GetOneconnect(name string) (*Oneconnect, error) { - var oneconnect Oneconnect - err, ok := b.getForEntity(&oneconnect, uriLtm, uriProfile, uriOneconnect, name) +func (b *BigIP) Oneconnect(name string) (*Oneconnects, error) { + var oneconnects Oneconnects + err, _ := b.getForEntity(&oneconnects, uriLtm, uriProfile, uriOneconnect) + if err != nil { return nil, err } - if !ok { - return nil, nil - } - return &oneconnect, nil + return &oneconnects, nil } // DeleteOneconnect removes an OneConnect profile from the system. @@ -3143,17 +3228,15 @@ func (b *BigIP) ModifyTcp(name string, tcp *Tcp) error { return b.put(tcp, uriLtm, uriProfile, uriTcp, name) } -func (b *BigIP) GetTcp(name string) (*Tcp, error) { - var tcp Tcp - err, ok := b.getForEntity(&tcp, uriLtm, uriProfile, uriTcp, name) +func (b *BigIP) Tcp(name string) (*Tcps, error) { + var tcps Tcps + err, _ := b.getForEntity(&tcps, uriLtm, uriProfile, uriTcp) + if err != nil { return nil, err } - if !ok { - return nil, nil - } - return &tcp, nil + return &tcps, nil } func (b *BigIP) CreateFasthttp(name, defaultsFrom string, idleTimeout, connpoolIdleTimeoutOverride, connpoolMaxReuse, connpoolMaxSize, connpoolMinSize int, connpoolReplenish string, connpoolStep int, forceHttp_10Response string, maxHeaderSize int) error { @@ -3184,15 +3267,15 @@ func (b *BigIP) ModifyFasthttp(name string, fasthttp *Fasthttp) error { return b.put(fasthttp, uriLtm, uriProfile, uriFasthttp, name) } -func (b *BigIP) GetFasthttp(name string) (*Fasthttp, error) { - var fasthttp Fasthttp - err, _ := b.getForEntity(&fasthttp, uriLtm, uriProfile, uriFasthttp) +func (b *BigIP) Fasthttp() (*Fasthttps, error) { + var fasthttps Fasthttps + err, _ := b.getForEntity(&fasthttps, uriLtm, uriProfile, uriFasthttp) if err != nil { return nil, err } - return &fasthttp, nil + return &fasthttps, nil } func (b *BigIP) CreateFastl4(name, partition, defaultsFrom string, clientTimeout int, explicitFlowMigration, hardwareSynCookie string, idleTimeout string, ipTosToClient, ipTosToServer, keepAliveInterval string) error { @@ -3222,17 +3305,15 @@ func (b *BigIP) ModifyFastl4(name string, fastl4 *Fastl4) error { return b.put(fastl4, uriLtm, uriProfile, uriFastl4, name) } -func (b *BigIP) GetFastl4(name string) (*Fastl4, error) { - var fastl4 Fastl4 - err, ok := b.getForEntity(&fastl4, uriLtm, uriProfile, uriFastl4, name) +func (b *BigIP) Fastl4(name string) (*Fastl4s, error) { + var fastl4s Fastl4s + err, _ := b.getForEntity(&fastl4s, uriLtm, uriProfile, uriFastl4) + if err != nil { return nil, err } - if !ok { - return nil, nil - } - return &fastl4, nil + return &fastl4s, nil } // =============== @@ -3258,17 +3339,15 @@ func (b *BigIP) ModifyHttpcompress(name string, httpcompress *Httpcompress) erro return b.put(httpcompress, uriLtm, uriProfile, uriHttpcompress, name) } -func (b *BigIP) GetHttpcompress(name string) (*Httpcompress, error) { - var httpcompress Httpcompress - err, ok := b.getForEntity(&httpcompress, uriLtm, uriProfile, uriHttpcompress, name) +func (b *BigIP) Httpcompress() (*Httpcompresss, error) { + var httpcompresss Httpcompresss + err, _ := b.getForEntity(&httpcompresss, uriLtm, uriProfile, uriHttpcompress) + if err != nil { return nil, err } - if !ok { - return nil, nil - } - return &httpcompress, nil + return &httpcompresss, nil } func (b *BigIP) CreateHttp2(name, defaultsFrom string, concurrentStreamsPerConnection, connectionIdleTimeout, headerTableSize int, activationModes []string) error { @@ -3294,17 +3373,15 @@ func (b *BigIP) ModifyHttp2(name string, http2 *Http2) error { return b.put(http2, uriLtm, uriProfile, uriHttp2, name) } -func (b *BigIP) GetHttp2(name string) (*Http2, error) { - var http2 Http2 - err, ok := b.getForEntity(&http2, uriLtm, uriProfile, uriHttp2, name) +func (b *BigIP) Http2() (*Http2s, error) { + var http2s Http2s + err, _ := b.getForEntity(&http2s, uriLtm, uriProfile, uriHttp2) + if err != nil { return nil, err } - if !ok { - return nil, nil - } - return &http2, nil + return &http2s, nil } // Datagroups returns a list of datagroups. @@ -3355,7 +3432,7 @@ func (b *BigIP) AddRecords(name, rname, data string) error { } // Snats returns a list of snat -/*func (b *BigIP) Snats(name string) (*Snats, error) { +func (b *BigIP) Snats(name string) (*Snats, error) { var snats Snats err, _ := b.getForEntity(&snats, uriLtm, uriSnat, name) @@ -3364,9 +3441,9 @@ func (b *BigIP) AddRecords(name, rname, data string) error { } return &snats, nil -}*/ +} -/*func (b *BigIP) CreateSnat(name, partition, autoLastHop, sourcePort, translation, snatpool, mirror string, vlansDisabled bool, origins []string) error { +func (b *BigIP) CreateSnat(name, partition, autoLastHop, sourcePort, translation, snatpool string, vlansDisabled, mirror bool, origins []string) error { snat := &Snat{ Name: name, Partition: partition, @@ -3380,10 +3457,6 @@ func (b *BigIP) AddRecords(name, rname, data string) error { } log.Println("[INFO] Creating snat ", snat) return b.post(snat, uriLtm, uriSnat) -} */ -func (b *BigIP) CreateSnat(p *Snat) error { - log.Println(" what is the complete payload ", p) - return b.post(p, uriLtm, uriSnat) } func (b *BigIP) ModifySnat(config *Snat) error { @@ -3408,10 +3481,6 @@ func (b *BigIP) DeleteSnat(name string) error { return b.delete(uriLtm, uriSnat, name) } -func (b *BigIP) UpdateSnat(name string, p *Snat) error { - return b.put(p, uriLtm, uriSnat, name) -} - // Snats returns a list of snat func (b *BigIP) Snatpools(name string) (*Snatpools, error) { var snatpools Snatpools @@ -3455,471 +3524,3 @@ func (b *BigIP) GetSnatpool(name string) (*Snatpool, error) { func (b *BigIP) DeleteSnatpool(name string) error { return b.delete(uriLtm, uriSnatpool, name) } - -// CookiePersistenceProfiles returns a list of cookie persist profiles -func (b *BigIP) CookiePersistenceProfiles() (*CookiePersistenceProfiles, error) { - var cookiePersistenceProfiles CookiePersistenceProfiles - err, _ := b.getForEntity(&cookiePersistenceProfiles, uriLtm, uriPersistence, uriCookie) - if err != nil { - return nil, err - } - - return &cookiePersistenceProfiles, nil -} - -// GetCookiePersistenceProfile gets a single cookie persist profile by name -func (b *BigIP) GetCookiePersistenceProfile(name string) (*CookiePersistenceProfile, error) { - var cookiePersistenceProfile CookiePersistenceProfile - err, ok := b.getForEntity(&cookiePersistenceProfile, uriLtm, uriPersistence, uriCookie, name) - if err != nil { - return nil, err - } - - if !ok { - return nil, nil - } - - return &cookiePersistenceProfile, nil -} - -// CreateCookiePersistenceProfile creates a new cookie persist profile on the BIG-IP system. -func (b *BigIP) CreateCookiePersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriPersistence, uriCookie) -} - -// AddCookiePersistenceProfile adds a cookie persist profile to the BIG-IP system -func (b *BigIP) AddCookiePersistenceProfile(config *CookiePersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriCookie) -} - -// DeleteCookiePersistenceProfile removes a cookie persist profile. -func (b *BigIP) DeleteCookiePersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriCookie, name) -} - -// ModifyCookiePersistenceProfile allows you to change any attribute of a cookie persist profile. -// Fields that can be modified are referenced in the CookiePersistenceProfile struct. -func (b *BigIP) ModifyCookiePersistenceProfile(name string, config *CookiePersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriCookie, name) -} - -// DestAddrPersistenceProfiles returns a list of dest-addr persist profiles -func (b *BigIP) DestAddrPersistenceProfiles() (*DestAddrPersistenceProfiles, error) { - var destAddrPersistenceProfiles DestAddrPersistenceProfiles - err, _ := b.getForEntity(&destAddrPersistenceProfiles, uriLtm, uriPersistence, uriDestAddr) - if err != nil { - return nil, err - } - - return &destAddrPersistenceProfiles, nil -} - -// GetDestAddrPersistenceProfile gets a single dest-addr persist profile by name -func (b *BigIP) GetDestAddrPersistenceProfile(name string) (*DestAddrPersistenceProfile, error) { - var destAddrPersistenceProfile DestAddrPersistenceProfile - err, ok := b.getForEntity(&destAddrPersistenceProfile, uriLtm, uriPersistence, uriDestAddr, name) - if err != nil { - return nil, err - } - - if !ok { - return nil, nil - } - - return &destAddrPersistenceProfile, nil -} - -// CreateDestAddrPersistenceProfile creates a new dest-addr persist profile on the BIG-IP system. -func (b *BigIP) CreateDestAddrPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriPersistence, uriDestAddr) -} - -// AddDestAddrPersistenceProfile adds a dest-addr persist profile to the BIG-IP system -func (b *BigIP) AddDestAddrPersistenceProfile(config *DestAddrPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriDestAddr) -} - -// DeleteDestAddrPersistenceProfile removes a dest-addr persist profile. -func (b *BigIP) DeleteDestAddrPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriDestAddr, name) -} - -// ModifyDestAddrPersistenceProfile allows you to change any attribute of a dest-addr persist profile. -// Fields that can be modified are referenced in the DestAddrPersistenceProfile struct. -func (b *BigIP) ModifyDestAddrPersistenceProfile(name string, config *DestAddrPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriDestAddr, name) -} - -// HashPersistenceProfiles returns a list of hash persist profiles -func (b *BigIP) HashPersistenceProfiles() (*HashPersistenceProfiles, error) { - var hashPersistenceProfiles HashPersistenceProfiles - err, _ := b.getForEntity(&hashPersistenceProfiles, uriLtm, uriPersistence, uriHash) - if err != nil { - return nil, err - } - - return &hashPersistenceProfiles, nil -} - -// GetHashPersistenceProfile gets a single hash persist profile by name -func (b *BigIP) GetHashPersistenceProfile(name string) (*HashPersistenceProfile, error) { - var hashPersistenceProfile HashPersistenceProfile - err, ok := b.getForEntity(&hashPersistenceProfile, uriLtm, uriPersistence, uriHash, name) - if err != nil { - return nil, err - } - - if !ok { - return nil, nil - } - - return &hashPersistenceProfile, nil -} - -// CreateHashPersistenceProfile creates a new hash persist profile on the BIG-IP system. -func (b *BigIP) CreateHashPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriPersistence, uriHash) -} - -// AddHashPersistenceProfile adds a hash persist profile to the BIG-IP system -func (b *BigIP) AddHashPersistenceProfile(config *HashPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriHash) -} - -// DeleteHashPersistenceProfile removes a dest-addr persist profile. -func (b *BigIP) DeleteHashPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriHash, name) -} - -// ModifyHashPersistenceProfile allows you to change any attribute of a hash persist profile. -// Fields that can be modified are referenced in the HashPersistenceProfile struct. -func (b *BigIP) ModifyHashPersistenceProfile(name string, config *HashPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriHash, name) -} - -// HostPersistenceProfiles returns a list of host persist profiles -func (b *BigIP) HostPersistenceProfiles() (*HostPersistenceProfiles, error) { - var hostPersistenceProfiles HostPersistenceProfiles - err, _ := b.getForEntity(&hostPersistenceProfiles, uriLtm, uriPersistence, uriHost) - if err != nil { - return nil, err - } - - return &hostPersistenceProfiles, nil -} - -// GetHostPersistenceProfile gets a single host persist profile by name -func (b *BigIP) GetHostPersistenceProfile(name string) (*HostPersistenceProfile, error) { - var hostPersistenceProfile HostPersistenceProfile - err, ok := b.getForEntity(&hostPersistenceProfile, uriLtm, uriPersistence, uriHost, name) - if err != nil { - return nil, err - } - - if !ok { - return nil, nil - } - - return &hostPersistenceProfile, nil -} - -// CreateHostPersistenceProfile creates a new host persist profile on the BIG-IP system. -func (b *BigIP) CreateHostPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriPersistence, uriHost) -} - -// AddHostPersistenceProfile adds a host persist profile to the BIG-IP system -func (b *BigIP) AddHostPersistenceProfile(config *HostPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriHost) -} - -// DeleteHashHostPersistenceProfile removes a host persist profile. -func (b *BigIP) DeleteHashHostPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriHost, name) -} - -// ModifyHostPersistenceProfile allows you to change any attribute of a host persist profile. -// Fields that can be modified are referenced in the HostPersistenceProfile struct. -func (b *BigIP) ModifyHostPersistenceProfile(name string, config *HostPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriHost, name) -} - -// MSRDPPersistenceProfiles returns a list of msrdp persist profiles -func (b *BigIP) MSRDPPersistenceProfiles() (*MSRDPPersistenceProfiles, error) { - var msrdpPersistenceProfiles MSRDPPersistenceProfiles - err, _ := b.getForEntity(&msrdpPersistenceProfiles, uriLtm, uriPersistence, uriMSRDP) - if err != nil { - return nil, err - } - - return &msrdpPersistenceProfiles, nil -} - -// GetMSRDPPersistenceProfile gets a single msrdp persist profile by name -func (b *BigIP) GetMSRDPPersistenceProfile(name string) (*MSRDPPersistenceProfile, error) { - var msrdpPersistenceProfile MSRDPPersistenceProfile - err, ok := b.getForEntity(&msrdpPersistenceProfile, uriLtm, uriPersistence, uriMSRDP, name) - if err != nil { - return nil, err - } - - if !ok { - return nil, nil - } - - return &msrdpPersistenceProfile, nil -} - -// CreateMSRDPPersistenceProfile creates a new msrdp persist profile on the BIG-IP system. -func (b *BigIP) CreateMSRDPPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriPersistence, uriMSRDP) -} - -// AddMSRDPPersistenceProfile adds a msrdp persist profile to the BIG-IP system -func (b *BigIP) AddMSRDPPersistenceProfile(config *MSRDPPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriMSRDP) -} - -// DeleteMSRDPPersistenceProfile removes a msrdp persist profile. -func (b *BigIP) DeleteMSRDPPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriMSRDP, name) -} - -// ModifyMSRDPPersistenceProfile allows you to change any attribute of a msrdp persist profile. -// Fields that can be modified are referenced in the MSRDPPersistenceProfile struct. -func (b *BigIP) ModifyMSRDPPersistenceProfile(name string, config *MSRDPPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriMSRDP, name) -} - -// SIPPersistenceProfiles returns a list of sip persist profiles -func (b *BigIP) SIPPersistenceProfiles() (*SIPPersistenceProfiles, error) { - var sipPersistenceProfiles SIPPersistenceProfiles - err, _ := b.getForEntity(&sipPersistenceProfiles, uriLtm, uriPersistence, uriSIP) - if err != nil { - return nil, err - } - - return &sipPersistenceProfiles, nil -} - -// GetSIPPersistenceProfile gets a single sip persist profile by name -func (b *BigIP) GetSIPPersistenceProfile(name string) (*SIPPersistenceProfile, error) { - var sipPersistenceProfile SIPPersistenceProfile - err, ok := b.getForEntity(&sipPersistenceProfile, uriLtm, uriPersistence, uriSIP, name) - if err != nil { - return nil, err - } - - if !ok { - return nil, nil - } - - return &sipPersistenceProfile, nil -} - -// CreateSIPPersistenceProfile creates a new sip persist profile on the BIG-IP system. -func (b *BigIP) CreateSIPPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriPersistence, uriSIP) -} - -// AddSIPPersistenceProfile adds a sip persist profile to the BIG-IP system -func (b *BigIP) AddSIPPersistenceProfile(config *SIPPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriSIP) -} - -// DeleteSIPPersistenceProfile removes a sip persist profile. -func (b *BigIP) DeleteSIPPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriSIP, name) -} - -// ModifySIPPersistenceProfile allows you to change any attribute of a sip persist profile. -// Fields that can be modified are referenced in the SIPPersistenceProfile struct. -func (b *BigIP) ModifySIPPersistenceProfile(name string, config *SIPPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriSIP, name) -} - -// SourceAddrPersistenceProfiles returns a list of source-addr persist profiles -func (b *BigIP) SourceAddrPersistenceProfiles() (*SourceAddrPersistenceProfiles, error) { - var sourceAddrPersistenceProfiles SourceAddrPersistenceProfiles - err, _ := b.getForEntity(&sourceAddrPersistenceProfiles, uriLtm, uriPersistence, uriSourceAddr) - if err != nil { - return nil, err - } - - return &sourceAddrPersistenceProfiles, nil -} - -// GetSourceAddrPersistenceProfile gets a single source-addr persist profile by name -func (b *BigIP) GetSourceAddrPersistenceProfile(name string) (*SourceAddrPersistenceProfile, error) { - var sourceAddrPersistenceProfile SourceAddrPersistenceProfile - err, ok := b.getForEntity(&sourceAddrPersistenceProfile, uriLtm, uriPersistence, uriSourceAddr, name) - if err != nil { - return nil, err - } - - if !ok { - return nil, nil - } - - return &sourceAddrPersistenceProfile, nil -} - -// CreateSourceAddrPersistenceProfile creates a new source-addr persist profile on the BIG-IP system. -func (b *BigIP) CreateSourceAddrPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriPersistence, uriSourceAddr) -} - -// AddSourceAddrPersistenceProfile adds a source-addr persist profile to the BIG-IP system -func (b *BigIP) AddSourceAddrPersistenceProfile(config *SourceAddrPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriSourceAddr) -} - -// DeleteSourceAddrPersistenceProfile removes a source-addr persist profile. -func (b *BigIP) DeleteSourceAddrPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriSourceAddr, name) -} - -// ModifySourceAddrPersistenceProfile allows you to change any attribute of a source-addr persist profile. -// Fields that can be modified are referenced in the SourceAddrPersistenceProfile struct. -func (b *BigIP) ModifySourceAddrPersistenceProfile(name string, config *SourceAddrPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriSourceAddr, name) -} - -// SSLPersistenceProfiles returns a list of ssl persist profiles -func (b *BigIP) SSLPersistenceProfiles() (*SSLPersistenceProfiles, error) { - var sslPersistenceProfiles SSLPersistenceProfiles - err, _ := b.getForEntity(&sslPersistenceProfiles, uriLtm, uriPersistence, uriSSL) - if err != nil { - return nil, err - } - - return &sslPersistenceProfiles, nil -} - -// GetSSLPersistenceProfile gets a single ssl persist profile by name -func (b *BigIP) GetSSLPersistenceProfile(name string) (*SSLPersistenceProfile, error) { - var sslPersistenceProfile SSLPersistenceProfile - err, ok := b.getForEntity(&sslPersistenceProfile, uriLtm, uriPersistence, uriSSL, name) - if err != nil { - return nil, err - } - - if !ok { - return nil, nil - } - - return &sslPersistenceProfile, nil -} - -// CreateSSLPersistenceProfile creates a new ssl persist profile on the BIG-IP system. -func (b *BigIP) CreateSSLPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriPersistence, uriSSL) -} - -// AddSSLPersistenceProfile adds a ssl persist profile to the BIG-IP system -func (b *BigIP) AddSSLPersistenceProfile(config *SSLPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriSSL) -} - -// DeleteSSLPersistenceProfile removes a ssl persist profile. -func (b *BigIP) DeleteSSLPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriSSL, name) -} - -// ModifySSLPersistenceProfile allows you to change any attribute of a ssl persist profile. -// Fields that can be modified are referenced in the SSLPersistenceProfile struct. -func (b *BigIP) ModifySSLPersistenceProfile(name string, config *SSLPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriSSL, name) -} - -// UniversalPersistenceProfiles returns a list of universal persist profiles -func (b *BigIP) UniversalPersistenceProfiles() (*UniversalPersistenceProfiles, error) { - var universalPersistenceProfiles UniversalPersistenceProfiles - err, _ := b.getForEntity(&universalPersistenceProfiles, uriLtm, uriPersistence, uriUniversal) - if err != nil { - return nil, err - } - - return &universalPersistenceProfiles, nil -} - -// GetUniversalPersistenceProfile gets a single universal persist profile by name -func (b *BigIP) GetUniversalPersistenceProfile(name string) (*UniversalPersistenceProfile, error) { - var universalPersistenceProfile UniversalPersistenceProfile - err, ok := b.getForEntity(&universalPersistenceProfile, uriLtm, uriPersistence, uriUniversal, name) - if err != nil { - return nil, err - } - - if !ok { - return nil, nil - } - - return &universalPersistenceProfile, nil -} - -// CreateUniversalPersistenceProfile creates a new universal persist profile on the BIG-IP system. -func (b *BigIP) CreateUniversalPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriPersistence, uriUniversal) -} - -// AddUniversalPersistenceProfile adds a universal persist profile to the BIG-IP system -func (b *BigIP) AddUniversalPersistenceProfile(config *UniversalPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriUniversal) -} - -// DeleteUniversalPersistenceProfile removes a universal persist profile. -func (b *BigIP) DeleteUniversalPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriUniversal, name) -} - -// ModifyUniversalPersistenceProfile allows you to change any attribute of a universal persist profile. -// Fields that can be modified are referenced in the UniversalPersistenceProfile struct. -func (b *BigIP) ModifyUniversalPersistenceProfile(name string, config *UniversalPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriUniversal, name) -} diff --git a/net.go b/net.go index 4314c16..40509bf 100644 --- a/net.go +++ b/net.go @@ -2,8 +2,6 @@ package bigip import ( "strings" - "log" - "fmt" ) // Interfaces contains a list of every interface on the BIG-IP system. @@ -198,9 +196,8 @@ func (b *BigIP) AddInterfaceToVlan(vlan, iface string, tagged bool) error { // SelfIPs returns a list of self IP's. func (b *BigIP) SelfIPs() (*SelfIPs, error) { var self SelfIPs - err, _:= b.getForEntity(&self, uriNet, uriSelf) + err, _ := b.getForEntity(&self, uriNet, uriSelf) if err != nil { - fmt.Println(" Please check reachability ", err) return nil, err } @@ -318,24 +315,6 @@ func (b *BigIP) Routes() (*Routes, error) { return &routes, nil } -func (b *BigIP) GetRoute(name string) (*Route, error) { - var route Route - values := []string{} - values = append(values, "~Common~") - values = append(values, name) - // Join three strings into one. - result := strings.Join(values, "") - err, ok := b.getForEntity(&route, uriNet, uriRoute, result) - if err != nil { - return nil, err - } - if !ok { - return nil, nil - } - - return &route, nil -} - // CreateRoute adds a new static route to the BIG-IP system. must include the // subnet mask in CIDR notation, i.e.: "10.1.1.0/24". func (b *BigIP) CreateRoute(name, dest, gateway string) error { @@ -356,13 +335,7 @@ func (b *BigIP) DeleteRoute(name string) error { // ModifyRoute allows you to change any attribute of a static route. Fields that // can be modified are referenced in the Route struct. func (b *BigIP) ModifyRoute(name string, config *Route) error { - values := []string{} - values = append(values, "~Common~") - values = append(values, name) - // Join three strings into one. - result := strings.Join(values, "") - log.Println("value of result +======================", result) - return b.put(config, uriNet, uriRoute, result) + return b.put(config, uriNet, uriRoute, name) } // RouteDomains returns a list of route domains. diff --git a/sys.go b/sys.go index 362dad8..c357881 100644 --- a/sys.go +++ b/sys.go @@ -1,9 +1,6 @@ package bigip -import ( - "encoding/json" - "log" -) +import "encoding/json" type NTPs struct { NTPs []NTP `json:"items"` @@ -174,6 +171,7 @@ func (b *BigIP) NTPs() (*NTP, error) { if err != nil { return nil, err } + return &ntp, nil } @@ -191,7 +189,6 @@ func (b *BigIP) ModifyDNS(config *DNS) error { return b.put(config, uriSys, uriDNS) } -// DNS & NTP resource does not support Delete API func (b *BigIP) DNSs() (*DNS, error) { var dns DNS err, _ := b.getForEntity(&dns, uriSys, uriDNS) @@ -212,87 +209,46 @@ func (b *BigIP) CreateProvision(name string, fullPath string, cpuRatio int, disk Level: level, MemoryRatio: memoryRatio, } - if fullPath == "/Common/asm" { + if name == "/Common/asm" { return b.put(config, uriSys, uriProvision, uriAsm) } - if fullPath == "/Common/afm" { + if name == "/Common/afm" { return b.put(config, uriSys, uriProvision, uriAfm) - } - if fullPath == "/Common/gtm" { + if name == "/Common/gtm" { return b.put(config, uriSys, uriProvision, uriGtm) } - if fullPath == "/Common/apm" { + if name == "/Common/apm" { return b.put(config, uriSys, uriProvision, uriApm) } - if fullPath == "/Common/avr" { + if name == "/Common/avr" { return b.put(config, uriSys, uriProvision, uriAvr) } - if fullPath == "/Common/ilx" { + if name == "/Common/ilx" { return b.put(config, uriSys, uriProvision, uriIlx) } return nil } func (b *BigIP) ModifyProvision(config *Provision) error { + return b.put(config, uriSys, uriProvision, uriAfm) } func (b *BigIP) DeleteProvision(name string) error { - // Delete API does not exists for resource Provision return b.delete(uriSys, uriProvision, uriIlx, name) } -func (b *BigIP) Provisions(name string) (*Provision, error) { +func (b *BigIP) Provisions() (*Provision, error) { var provision Provision - if name == "afm" { - err, _ := b.getForEntity(&provision, uriSys, uriProvision, uriAfm) - - if err != nil { - return nil, err - } - } - if name == "asm" { - err, _ := b.getForEntity(&provision, uriSys, uriProvision, uriAsm) - - if err != nil { - return nil, err - } - } - if name == "gtm" { - err, _ := b.getForEntity(&provision, uriSys, uriProvision, uriGtm) - - if err != nil { - return nil, err - } - } - if name == "apm" { - err, _ := b.getForEntity(&provision, uriSys, uriProvision, uriApm) - - if err != nil { - return nil, err - } - } - if name == "avr" { - err, _ := b.getForEntity(&provision, uriSys, uriProvision, uriAvr) - - if err != nil { - return nil, err - } - - } - if name == "ilx" { - err, _ := b.getForEntity(&provision, uriSys, uriProvision, uriIlx) - - if err != nil { - return nil, err - } + err, _ := b.getForEntity(&provision, uriProvision, uriAfm) + if err != nil { + return nil, err } - log.Println("Display ****************** provision ", provision) return &provision, nil } From 8792a6c2d35114dc1e260d09a744cbce0d217f6b Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 6 Apr 2018 15:22:21 -0700 Subject: [PATCH 23/80] device.go same as vendor --- device.go | 152 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 108 insertions(+), 44 deletions(-) diff --git a/device.go b/device.go index 409f47f..7675a7e 100644 --- a/device.go +++ b/device.go @@ -1,6 +1,8 @@ package bigip -import "encoding/json" +import ( + "encoding/json" +) // LIC contains device license for BIG-IP system. type LICs struct { @@ -56,10 +58,77 @@ type Devicegroups struct { } type Devicegroup struct { - AutoSync string `json:"autoSync,omitempty"` - Name string `json:"name,omitempty"` - Type string `json:"type,omitempty"` - FullLoadOnSync string `json:"fullLoadOnSync,omitempty"` + AutoSync string + Name string + Partition string + Description string + Type string + FullLoadOnSync string + SaveOnAutoSync string + NetworkFailover string + IncrementalConfigSyncSizeMax int + Deviceb []Devicerecord +} +type devicegroupDTO struct { + AutoSync string `json:"autoSync,omitempty"` + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + Description string `json:"description,omitempty"` + Type string `json:"type,omitempty"` + FullLoadOnSync string `json:"fullLoadOnSync,omitempty"` + SaveOnAutoSync string `json:"saveOnAutoSync,omitempty"` + NetworkFailover string `json:"networkFailover,omitempty"` + IncrementalConfigSyncSizeMax int `json:"incrementalConfigSyncSizeMax,omitempty"` + Deviceb struct { + Items []Devicerecord `json:"items,omitempty"` + } `json:"devicesReference,omitempty"` +} + +type Devicerecords struct { + Items []Devicerecord `json:"items,omitempty"` +} + +type Devicerecord struct { + SetSyncLeader bool `json:"setSyncLeader"` + Name string `json:"name"` +} + +func (p *Devicegroup) MarshalJSON() ([]byte, error) { + return json.Marshal(devicegroupDTO{ + Name: p.Name, + Partition: p.Partition, + AutoSync: p.AutoSync, + Description: p.Description, + Type: p.Type, + FullLoadOnSync: p.FullLoadOnSync, + SaveOnAutoSync: p.SaveOnAutoSync, + NetworkFailover: p.NetworkFailover, + IncrementalConfigSyncSizeMax: p.IncrementalConfigSyncSizeMax, + Deviceb: struct { + Items []Devicerecord `json:"items,omitempty"` + }{Items: p.Deviceb}, + }) +} + +func (p *Devicegroup) UnmarshalJSON(b []byte) error { + var dto devicegroupDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + + p.Name = dto.Name + p.Partition = dto.Partition + p.AutoSync = dto.AutoSync + p.Description = dto.Description + p.Type = dto.Type + p.FullLoadOnSync = dto.FullLoadOnSync + p.SaveOnAutoSync = dto.SaveOnAutoSync + p.NetworkFailover = dto.NetworkFailover + p.IncrementalConfigSyncSizeMax = dto.IncrementalConfigSyncSizeMax + p.Deviceb = dto.Deviceb.Items + + return nil } // https://10.192.74.80/mgmt/cm/device/licensing/pool/purchased-pool/licenses @@ -68,6 +137,8 @@ const ( uriMgmt = "mgmt" uriCm = "cm" uriDiv = "device" + uriDevices = "devices" + uriDG = "device-group" uriLins = "licensing" uriPoo = "pool" uriPur = "purchased-pool" @@ -158,31 +229,6 @@ func (b *BigIP) LICs() (*LIC, error) { return &members, nil } -func (b *BigIP) CreateDevicename(command, name, target string) error { - config := &Devicename{ - Command: command, - Name: name, - Target: target, - } - - return b.post(config, uriCm, uriDiv) -} - -func (b *BigIP) ModifyDevicename(config *Devicename) error { - return b.put(config, uriCm, uriDiv) -} - -func (b *BigIP) Devicenames() (*Devicename, error) { - var devicename Devicename - err, _ := b.getForEntity(&devicename, uriCm, uriDiv) - - if err != nil { - return nil, err - } - - return &devicename, nil -} - func (b *BigIP) CreateDevice(name, configsyncIp, mirrorIp, mirrorSecondaryIp string) error { config := &Device{ Name: name, @@ -194,13 +240,18 @@ func (b *BigIP) CreateDevice(name, configsyncIp, mirrorIp, mirrorSecondaryIp str return b.post(config, uriCm, uriDiv) } +// API does not work, you cannot modify API issue func (b *BigIP) ModifyDevice(config *Device) error { return b.put(config, uriCm, uriDiv) } -func (b *BigIP) Devices() (*Device, error) { +func (b *BigIP) DeleteDevice(name string) error { + return b.delete(uriCm, uriDiv, name) +} + +func (b *BigIP) Devices(name string) (*Device, error) { var device Device - err, _ := b.getForEntity(&device, uriCm, uriDiv) + err, _ := b.getForEntity(&device, uriCm, uriDiv, name) if err != nil { return nil, err @@ -209,25 +260,38 @@ func (b *BigIP) Devices() (*Device, error) { return &device, nil } -func (b *BigIP) CreateDevicegroup(name, autoSync, typo, fullLoadOnSync string) error { - config := &Devicegroup{ - Name: name, - AutoSync: autoSync, - Type: typo, - FullLoadOnSync: fullLoadOnSync, - } - - return b.post(config, uriCm, uriDiv) +func (b *BigIP) CreateDevicegroup(p *Devicegroup) error { + return b.post(p, uriCm, uriDG) } +func (b *BigIP) UpdateDevicegroup(name string, p *Devicegroup) error { + return b.put(p, uriCm, uriDG, name) +} func (b *BigIP) ModifyDevicegroup(config *Devicegroup) error { - return b.put(config, uriCm, uriDiv) + return b.put(config, uriCm, uriDG) } -func (b *BigIP) Devicegroups() (*Devicegroup, error) { +func (b *BigIP) Devicegroups(name string) (*Devicegroup, error) { var devicegroup Devicegroup - err, _ := b.getForEntity(&devicegroup, uriCm, uriDiv) + err, _ := b.getForEntity(&devicegroup, uriCm, uriDG, name) + if err != nil { + return nil, err + } + + return &devicegroup, nil +} + +func (b *BigIP) DeleteDevicegroup(name string) error { + return b.delete(uriCm, uriDG, name) +} +func (b *BigIP) DeleteDevicegroupDevices(name, rname string) error { + return b.delete(uriCm, uriDG, name, uriDevices, rname) +} + +func (b *BigIP) DevicegroupsDevices(name, rname string) (*Devicegroup, error) { + var devicegroup Devicegroup + err, _ := b.getForEntity(&devicegroup, uriCm, uriDG, name, uriDevices, rname) if err != nil { return nil, err } From 87383e7422730b06972597584045799f487ca006 Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 6 Apr 2018 15:27:40 -0700 Subject: [PATCH 24/80] gtm.go same as vendor --- gtm.go | 296 +++++++++++++++++++++++++++------------------------------ 1 file changed, 139 insertions(+), 157 deletions(-) diff --git a/gtm.go b/gtm.go index 4e36891..55143c6 100644 --- a/gtm.go +++ b/gtm.go @@ -5,34 +5,31 @@ import "log" //ooo - type Datacenters struct { Datacenters []Datacenter `json:"items"` } type Datacenter struct { - Name string `json:"name,omitempty"` + Name string `json:"name,omitempty"` Description string `json:"description,omitempty"` - Contact string `json:"contact,omitempty"` - App_service string `json:"appService,omitempty"` - Disabled bool `json:"disabled,omitempty"` - Enabled bool `json:"enabled,omitempty"` - Prober_pool string `json:"proberPool,omitempty"` + Contact string `json:"contact,omitempty"` + App_service string `json:"appService,omitempty"` + Disabled bool `json:"disabled,omitempty"` + Enabled bool `json:"enabled,omitempty"` + Prober_pool string `json:"proberPool,omitempty"` } - type Gtmmonitors struct { Gtmmonitors []Gtmmonitor `json:"items"` } - type Gtmmonitor struct { - Name string `json:"name,omitempty"` + Name string `json:"name,omitempty"` Defaults_from string `json:"defaultsFrom,omitempty"` - Interval int `json:"interval,omitempty"` - Probe_timeout int `json:"probeTimeout,omitempty"` - Recv string `json:"recv,omitempty"` - Send string `json:"send,omitempty"` + Interval int `json:"interval,omitempty"` + Probe_timeout int `json:"probeTimeout,omitempty"` + Recv string `json:"recv,omitempty"` + Send string `json:"send,omitempty"` } type Servers struct { @@ -40,109 +37,101 @@ type Servers struct { } type Server struct { - Name string - Datacenter string - Monitor string + Name string + Datacenter string + Monitor string Virtual_server_discovery bool - Product string - Addresses []ServerAddresses - GTMVirtual_Server []VSrecord + Product string + Addresses []ServerAddresses + GTMVirtual_Server []VSrecord } type serverDTO struct { - Name string `json:"name"` - Datacenter string `json:"datacenter,omitempty"` - Monitor string `json:"monitor,omitempty"` - Virtual_server_discovery bool `json:"virtual_server_discovery"` - Product string `json:"product,omitempty"` - Addresses struct { - Items []ServerAddresses`json:"items,omitempty"` + Name string `json:"name"` + Datacenter string `json:"datacenter,omitempty"` + Monitor string `json:"monitor,omitempty"` + Virtual_server_discovery bool `json:"virtual_server_discovery"` + Product string `json:"product,omitempty"` + Addresses struct { + Items []ServerAddresses `json:"items,omitempty"` } `json:"addressesReference,omitempty"` GTMVirtual_Server struct { - Items []VSrecord `json:"items,omitempty"` } `json:"virtualServersReference,omitempty"` - } - - func (p *Server) MarshalJSON() ([]byte, error) { - return json.Marshal(serverDTO{ - Name: p.Name, - Datacenter: p.Datacenter, - Monitor: p.Monitor, - Virtual_server_discovery: p.Virtual_server_discovery, - Product: p.Product, - Addresses: struct { - Items []ServerAddresses `json:"items,omitempty"` - }{Items: p.Addresses}, - GTMVirtual_Server: struct { - Items []VSrecord `json:"items,omitempty"` - }{Items: p.GTMVirtual_Server}, - }) - } - - func (p *Server) UnmarshalJSON(b []byte) error { - var dto serverDTO - err := json.Unmarshal(b, &dto) - if err != nil { - return err - } - - p.Name = dto.Name - p.Datacenter = dto.Datacenter - p.Monitor = dto.Monitor - p.Virtual_server_discovery = dto.Virtual_server_discovery - p.Product = dto.Product - p.Addresses = dto.Addresses.Items - p.GTMVirtual_Server = dto.GTMVirtual_Server.Items - return nil - } - - - type ServerAddressess struct { - Items []ServerAddresses `json:"items,omitempty"` - } - - - - type ServerAddresses struct { - Name string `json:"name"` - Device_name string `json:"deviceName,omitempty"` - Translation string `json:"translation,omitempty"` - } - + Items []VSrecord `json:"items,omitempty"` + } `json:"virtualServersReference,omitempty"` +} +func (p *Server) MarshalJSON() ([]byte, error) { + return json.Marshal(serverDTO{ + Name: p.Name, + Datacenter: p.Datacenter, + Monitor: p.Monitor, + Virtual_server_discovery: p.Virtual_server_discovery, + Product: p.Product, + Addresses: struct { + Items []ServerAddresses `json:"items,omitempty"` + }{Items: p.Addresses}, + GTMVirtual_Server: struct { + Items []VSrecord `json:"items,omitempty"` + }{Items: p.GTMVirtual_Server}, + }) +} - type VSrecords struct { - Items []VSrecord `json:"items,omitempty"` +func (p *Server) UnmarshalJSON(b []byte) error { + var dto serverDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err } + p.Name = dto.Name + p.Datacenter = dto.Datacenter + p.Monitor = dto.Monitor + p.Virtual_server_discovery = dto.Virtual_server_discovery + p.Product = dto.Product + p.Addresses = dto.Addresses.Items + p.GTMVirtual_Server = dto.GTMVirtual_Server.Items + return nil +} +type ServerAddressess struct { + Items []ServerAddresses `json:"items,omitempty"` +} - type VSrecord struct { - Name string `json:"name"` - Destination string `json:"destination,omitempty"` - } +type ServerAddresses struct { + Name string `json:"name"` + Device_name string `json:"deviceName,omitempty"` + Translation string `json:"translation,omitempty"` +} - type Pool_as struct { - Pool_as []Pool_a `json:"items"` - } +type VSrecords struct { + Items []VSrecord `json:"items,omitempty"` +} - type Pool_a struct { - Name string `json:"name,omitempty"` - Monitor string `json:"monitor,omitempty"` - Load_balancing_mode string `json:"load_balancing_mode,omitempty"` - Max_answers_returned int `json:"max_answers_returned,omitempty"` - Alternate_mode string `json:"alternate_mode,omitempty"` - Fallback_ip string `json:"fallback_ip,omitempty"` - Fallback_mode string `json:"fallback_mode,omitempty"` - Members []string `json:"members,omitempty"` - } +type VSrecord struct { + Name string `json:"name"` + Destination string `json:"destination,omitempty"` +} +type Pool_as struct { + Pool_as []Pool_a `json:"items"` +} +type Pool_a struct { + Name string `json:"name,omitempty"` + Monitor string `json:"monitor,omitempty"` + Load_balancing_mode string `json:"load_balancing_mode,omitempty"` + Max_answers_returned int `json:"max_answers_returned,omitempty"` + Alternate_mode string `json:"alternate_mode,omitempty"` + Fallback_ip string `json:"fallback_ip,omitempty"` + Fallback_mode string `json:"fallback_mode,omitempty"` + Members []string `json:"members,omitempty"` +} const ( - uriGtm = "gtm" - uriServer = "server" + uriGtm = "gtm" + uriServer = "server" uriDatacenter = "datacenter" - uriGtmmonitor = "monitor" + uriGtmmonitor = "monitor" uriHttp = "http" uriPool_a = "pool/a" ) @@ -158,14 +147,14 @@ func (b *BigIP) Datacenters() (*Datacenter, error) { return &datacenter, nil } -func (b *BigIP) CreateDatacenter(name, description,contact, app_service string, enabled, disabled bool, prober_pool string) error { +func (b *BigIP) CreateDatacenter(name, description, contact, app_service string, enabled, disabled bool, prober_pool string) error { config := &Datacenter{ - Name: name, - Description: description, - Contact: contact, + Name: name, + Description: description, + Contact: contact, App_service: app_service, - Enabled: enabled, - Disabled: disabled, + Enabled: enabled, + Disabled: disabled, Prober_pool: prober_pool, } return b.post(config, uriGtm, uriDatacenter) @@ -175,13 +164,10 @@ func (b *BigIP) ModifyDatacenter(*Datacenter) error { return b.patch(uriGtm, uriDatacenter) } - func (b *BigIP) DeleteDatacenter(name string) error { return b.delete(uriGtm, uriDatacenter, name) } - - func (b *BigIP) Gtmmonitors() (*Gtmmonitor, error) { var gtmmonitor Gtmmonitor err, _ := b.getForEntity(>mmonitor, uriGtm, uriGtmmonitor, uriHttp) @@ -194,12 +180,12 @@ func (b *BigIP) Gtmmonitors() (*Gtmmonitor, error) { } func (b *BigIP) CreateGtmmonitor(name, defaults_from string, interval, probeTimeout int, recv, send string) error { config := &Gtmmonitor{ - Name: name, - Defaults_from: defaults_from, - Interval: interval, + Name: name, + Defaults_from: defaults_from, + Interval: interval, Probe_timeout: probeTimeout, - Recv: recv, - Send: send, + Recv: recv, + Send: send, } return b.post(config, uriGtm, uriGtmmonitor, uriHttp) } @@ -208,12 +194,10 @@ func (b *BigIP) ModifyGtmmonitor(*Gtmmonitor) error { return b.patch(uriGtm, uriGtmmonitor, uriHttp) } - func (b *BigIP) DeleteGtmmonitor(name string) error { return b.delete(uriGtm, uriGtmmonitor, uriHttp, name) } - func (b *BigIP) CreateGtmserver(p *Server) error { log.Println(" what is the complete payload ", p) return b.post(p, uriGtm, uriServer) @@ -229,47 +213,45 @@ func (b *BigIP) DeleteGtmserver(name string) error { return b.delete(uriGtm, uriServer, name) } - func (b *BigIP) GetGtmserver(name string) (*Server, error) { - var p Server - err, ok := b.getForEntity(&p, uriGtm, uriServer, name) - if err != nil { - return nil, err - } - if !ok { - return nil, nil - } - - return &p, nil - } - - - func (b *BigIP) CreatePool_a(name, monitor, load_balancing_mode string, max_answers_returned int, alternate_mode, fallback_ip, fallback_mode string, members []string) error { - config := &Pool_a{ - Name: name, - Monitor: monitor, - Load_balancing_mode: load_balancing_mode, - Max_answers_returned: max_answers_returned, - Alternate_mode: alternate_mode, - Fallback_ip: fallback_ip, - Fallback_mode: fallback_mode, - Members: members, - } - log.Println("in poola now", config) - return b.patch(config, uriGtm, uriPool_a) - } - - func (b *BigIP) ModifyPool_a(config *Pool_a) error { - return b.put(config, uriGtm, uriPool_a) - } - - func (b *BigIP) Pool_as() (*Pool_a, error) { - var pool_a Pool_a - err, _ := b.getForEntity(&pool_a, uriGtm, uriPool_a) - - if err != nil { - return nil, err - } - - return &pool_a, nil - } + var p Server + err, ok := b.getForEntity(&p, uriGtm, uriServer, name) + if err != nil { + return nil, err + } + if !ok { + return nil, nil + } + + return &p, nil +} + +func (b *BigIP) CreatePool_a(name, monitor, load_balancing_mode string, max_answers_returned int, alternate_mode, fallback_ip, fallback_mode string, members []string) error { + config := &Pool_a{ + Name: name, + Monitor: monitor, + Load_balancing_mode: load_balancing_mode, + Max_answers_returned: max_answers_returned, + Alternate_mode: alternate_mode, + Fallback_ip: fallback_ip, + Fallback_mode: fallback_mode, + Members: members, + } + log.Println("in poola now", config) + return b.patch(config, uriGtm, uriPool_a) +} + +func (b *BigIP) ModifyPool_a(config *Pool_a) error { + return b.put(config, uriGtm, uriPool_a) +} + +func (b *BigIP) Pool_as() (*Pool_a, error) { + var pool_a Pool_a + err, _ := b.getForEntity(&pool_a, uriGtm, uriPool_a) + + if err != nil { + return nil, err + } + + return &pool_a, nil +} From 52b94088949b2ca16ae9a61e78d54f99f1fdaf77 Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 6 Apr 2018 15:31:12 -0700 Subject: [PATCH 25/80] net.go same as vendor --- net.go | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/net.go b/net.go index 40509bf..4314c16 100644 --- a/net.go +++ b/net.go @@ -2,6 +2,8 @@ package bigip import ( "strings" + "log" + "fmt" ) // Interfaces contains a list of every interface on the BIG-IP system. @@ -196,8 +198,9 @@ func (b *BigIP) AddInterfaceToVlan(vlan, iface string, tagged bool) error { // SelfIPs returns a list of self IP's. func (b *BigIP) SelfIPs() (*SelfIPs, error) { var self SelfIPs - err, _ := b.getForEntity(&self, uriNet, uriSelf) + err, _:= b.getForEntity(&self, uriNet, uriSelf) if err != nil { + fmt.Println(" Please check reachability ", err) return nil, err } @@ -315,6 +318,24 @@ func (b *BigIP) Routes() (*Routes, error) { return &routes, nil } +func (b *BigIP) GetRoute(name string) (*Route, error) { + var route Route + values := []string{} + values = append(values, "~Common~") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") + err, ok := b.getForEntity(&route, uriNet, uriRoute, result) + if err != nil { + return nil, err + } + if !ok { + return nil, nil + } + + return &route, nil +} + // CreateRoute adds a new static route to the BIG-IP system. must include the // subnet mask in CIDR notation, i.e.: "10.1.1.0/24". func (b *BigIP) CreateRoute(name, dest, gateway string) error { @@ -335,7 +356,13 @@ func (b *BigIP) DeleteRoute(name string) error { // ModifyRoute allows you to change any attribute of a static route. Fields that // can be modified are referenced in the Route struct. func (b *BigIP) ModifyRoute(name string, config *Route) error { - return b.put(config, uriNet, uriRoute, name) + values := []string{} + values = append(values, "~Common~") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") + log.Println("value of result +======================", result) + return b.put(config, uriNet, uriRoute, result) } // RouteDomains returns a list of route domains. From c797aa26e214ded5cac7a57611c646602558af4f Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 6 Apr 2018 15:41:03 -0700 Subject: [PATCH 26/80] net.go same as vendor --- net.go | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/net.go b/net.go index 4314c16..ff8eed5 100644 --- a/net.go +++ b/net.go @@ -318,24 +318,6 @@ func (b *BigIP) Routes() (*Routes, error) { return &routes, nil } -func (b *BigIP) GetRoute(name string) (*Route, error) { - var route Route - values := []string{} - values = append(values, "~Common~") - values = append(values, name) - // Join three strings into one. - result := strings.Join(values, "") - err, ok := b.getForEntity(&route, uriNet, uriRoute, result) - if err != nil { - return nil, err - } - if !ok { - return nil, nil - } - - return &route, nil -} - // CreateRoute adds a new static route to the BIG-IP system. must include the // subnet mask in CIDR notation, i.e.: "10.1.1.0/24". func (b *BigIP) CreateRoute(name, dest, gateway string) error { @@ -356,13 +338,7 @@ func (b *BigIP) DeleteRoute(name string) error { // ModifyRoute allows you to change any attribute of a static route. Fields that // can be modified are referenced in the Route struct. func (b *BigIP) ModifyRoute(name string, config *Route) error { - values := []string{} - values = append(values, "~Common~") - values = append(values, name) - // Join three strings into one. - result := strings.Join(values, "") - log.Println("value of result +======================", result) - return b.put(config, uriNet, uriRoute, result) + return b.put(config, uriNet, uriRoute, name) } // RouteDomains returns a list of route domains. From 907a0eb995f70194bb59cc69a86d62d0c3433c22 Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 6 Apr 2018 15:43:45 -0700 Subject: [PATCH 27/80] net.go same as vendor --- net.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/net.go b/net.go index ff8eed5..40509bf 100644 --- a/net.go +++ b/net.go @@ -2,8 +2,6 @@ package bigip import ( "strings" - "log" - "fmt" ) // Interfaces contains a list of every interface on the BIG-IP system. @@ -198,9 +196,8 @@ func (b *BigIP) AddInterfaceToVlan(vlan, iface string, tagged bool) error { // SelfIPs returns a list of self IP's. func (b *BigIP) SelfIPs() (*SelfIPs, error) { var self SelfIPs - err, _:= b.getForEntity(&self, uriNet, uriSelf) + err, _ := b.getForEntity(&self, uriNet, uriSelf) if err != nil { - fmt.Println(" Please check reachability ", err) return nil, err } From 2f05dc727fbbebfd12e21eaf8e0d73c093384e48 Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 6 Apr 2018 15:46:57 -0700 Subject: [PATCH 28/80] sys.go same as vendor --- sys.go | 70 +++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 13 deletions(-) diff --git a/sys.go b/sys.go index c357881..362dad8 100644 --- a/sys.go +++ b/sys.go @@ -1,6 +1,9 @@ package bigip -import "encoding/json" +import ( + "encoding/json" + "log" +) type NTPs struct { NTPs []NTP `json:"items"` @@ -171,7 +174,6 @@ func (b *BigIP) NTPs() (*NTP, error) { if err != nil { return nil, err } - return &ntp, nil } @@ -189,6 +191,7 @@ func (b *BigIP) ModifyDNS(config *DNS) error { return b.put(config, uriSys, uriDNS) } +// DNS & NTP resource does not support Delete API func (b *BigIP) DNSs() (*DNS, error) { var dns DNS err, _ := b.getForEntity(&dns, uriSys, uriDNS) @@ -209,46 +212,87 @@ func (b *BigIP) CreateProvision(name string, fullPath string, cpuRatio int, disk Level: level, MemoryRatio: memoryRatio, } - if name == "/Common/asm" { + if fullPath == "/Common/asm" { return b.put(config, uriSys, uriProvision, uriAsm) } - if name == "/Common/afm" { + if fullPath == "/Common/afm" { return b.put(config, uriSys, uriProvision, uriAfm) + } - if name == "/Common/gtm" { + if fullPath == "/Common/gtm" { return b.put(config, uriSys, uriProvision, uriGtm) } - if name == "/Common/apm" { + if fullPath == "/Common/apm" { return b.put(config, uriSys, uriProvision, uriApm) } - if name == "/Common/avr" { + if fullPath == "/Common/avr" { return b.put(config, uriSys, uriProvision, uriAvr) } - if name == "/Common/ilx" { + if fullPath == "/Common/ilx" { return b.put(config, uriSys, uriProvision, uriIlx) } return nil } func (b *BigIP) ModifyProvision(config *Provision) error { - return b.put(config, uriSys, uriProvision, uriAfm) } func (b *BigIP) DeleteProvision(name string) error { + // Delete API does not exists for resource Provision return b.delete(uriSys, uriProvision, uriIlx, name) } -func (b *BigIP) Provisions() (*Provision, error) { +func (b *BigIP) Provisions(name string) (*Provision, error) { var provision Provision - err, _ := b.getForEntity(&provision, uriProvision, uriAfm) + if name == "afm" { + err, _ := b.getForEntity(&provision, uriSys, uriProvision, uriAfm) + + if err != nil { + return nil, err + } + } + if name == "asm" { + err, _ := b.getForEntity(&provision, uriSys, uriProvision, uriAsm) + + if err != nil { + return nil, err + } + } + if name == "gtm" { + err, _ := b.getForEntity(&provision, uriSys, uriProvision, uriGtm) + + if err != nil { + return nil, err + } + } + if name == "apm" { + err, _ := b.getForEntity(&provision, uriSys, uriProvision, uriApm) + + if err != nil { + return nil, err + } + } + if name == "avr" { + err, _ := b.getForEntity(&provision, uriSys, uriProvision, uriAvr) + + if err != nil { + return nil, err + } + + } + if name == "ilx" { + err, _ := b.getForEntity(&provision, uriSys, uriProvision, uriIlx) + + if err != nil { + return nil, err + } - if err != nil { - return nil, err } + log.Println("Display ****************** provision ", provision) return &provision, nil } From c4a6191fafd57425433cf2aabdb605539b96c6ed Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 6 Apr 2018 16:22:39 -0700 Subject: [PATCH 29/80] ltm.go changes --- ltm.go | 216 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 168 insertions(+), 48 deletions(-) diff --git a/ltm.go b/ltm.go index d252064..3c4f42e 100644 --- a/ltm.go +++ b/ltm.go @@ -489,6 +489,13 @@ type Node struct { Ratio int `json:"ratio,omitempty"` Session string `json:"session,omitempty"` State string `json:"state,omitempty"` + FQDN struct { + AddressFamily string `json:"addressFamily,omitempty"` + AutoPopulate string `json:"autopopulate,omitempty"` + DownInterval int `json:"downInterval,omitempty"` + Interval string `json:"interval,omitempty"` + Name string `json:"tmName,omitempty"` + } `json:"fqdn,omitempty"` } // DataGroups contains a list of data groups on the BIG-IP system. @@ -506,24 +513,37 @@ type DataGroup struct { Records []DataGroupRecord } +type DataGroupRecords struct { + Items []DataGroupRecord `json:"items,omitempty"` +} + type DataGroupRecord struct { Name string `json:"name,omitempty"` Data string `json:"data,omitempty"` } type dataGroupDTO struct { - Name string `json:"name,omitempty"` - Partition string `json:"partition,omitempty"` - FullPath string `json:"fullPath,omitempty"` - Generation int `json:"generation,omitempty"` - Type string `json:"type,omitempty"` - Records []DataGroupRecord `json:"records,omitempty"` + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` + Generation int `json:"generation,omitempty"` + Type string `json:"type,omitempty"` + Records struct { + Items []DataGroupRecord `json:"items,omitempty"` + } `json:"recordsReference,omitempty"` } func (p *DataGroup) MarshalJSON() ([]byte, error) { - var dto dataGroupDTO - marshal(&dto, p) - return json.Marshal(dto) + return json.Marshal(dataGroupDTO{ + Name: p.Name, + Partition: p.Partition, + FullPath: p.FullPath, + Generation: p.Generation, + Type: p.Type, + Records: struct { + Items []DataGroupRecord `json:"items,omitempty"` + }{Items: p.Records}, + }) } func (p *DataGroup) UnmarshalJSON(b []byte) error { @@ -532,7 +552,14 @@ func (p *DataGroup) UnmarshalJSON(b []byte) error { if err != nil { return err } - return marshal(p, &dto) + + p.Name = dto.Name + p.Partition = dto.Partition + p.Type = dto.Type + p.FullPath = dto.FullPath + p.Generation = dto.Generation + p.Records = dto.Records.Items + return nil } // SnatPools contains a list of every snatpool on the BIG-IP system. @@ -578,9 +605,9 @@ type Pool struct { QueueDepthLimit int `json:"queueDepthLimit,omitempty"` QueueOnConnectionLimit string `json:"queueOnConnectionLimit,omitempty"` QueueTimeLimit int `json:"queueTimeLimit,omitempty"` - ReselectTries int `json:"reselectTries,omitempty"` + ReselectTries int `json:"reselectTries"` ServiceDownAction string `json:"serviceDownAction,omitempty"` - SlowRampTime int `json:"slowRampTime,omitempty"` + SlowRampTime int `json:"slowRampTime"` } // Pool Members contains a list of pool members within a pool on the BIG-IP system. @@ -640,9 +667,9 @@ type poolDTO struct { QueueDepthLimit int `json:"queueDepthLimit,omitempty"` QueueOnConnectionLimit string `json:"queueOnConnectionLimit,omitempty"` QueueTimeLimit int `json:"queueTimeLimit,omitempty"` - ReselectTries int `json:"reselectTries,omitempty"` + ReselectTries int `json:"reselectTries"` ServiceDownAction string `json:"serviceDownAction,omitempty"` - SlowRampTime int `json:"slowRampTime,omitempty"` + SlowRampTime int `json:"slowRampTime"` } func (p *Pool) MarshalJSON() ([]byte, error) { @@ -763,8 +790,13 @@ type VirtualServerPolicies struct { PolicyRef Policies `json:"policiesReference"` } +type PolicyPublish struct { + Name string `json:"name"` + PublishCopy string `json:"publishedCopy"` +} type Policy struct { Name string + PublishCopy string Partition string FullPath string Controls []string @@ -775,6 +807,7 @@ type Policy struct { type policyDTO struct { Name string `json:"name"` + PublishCopy string `json:"publishedCopy"` Partition string `json:"partition,omitempty"` Controls []string `json:"controls,omitempty"` Requires []string `json:"requires,omitempty"` @@ -788,6 +821,7 @@ type policyDTO struct { func (p *Policy) MarshalJSON() ([]byte, error) { return json.Marshal(policyDTO{ Name: p.Name, + PublishCopy: p.PublishCopy, Partition: p.Partition, Controls: p.Controls, Requires: p.Requires, @@ -807,6 +841,7 @@ func (p *Policy) UnmarshalJSON(b []byte) error { } p.Name = dto.Name + p.PublishCopy = dto.PublishCopy p.Partition = dto.Partition p.Controls = dto.Controls p.Requires = dto.Requires @@ -1515,31 +1550,52 @@ type Snat struct { Partition string FullPath string AutoLasthop string - Mirror bool + Mirror string SourcePort string Translation string Snatpool string VlansDisabled bool - Origins []string + Origins []Originsrecord } type snatDTO struct { - Name string `json:"name"` - Partition string `json:"partition,omitempty"` - FullPath string `json:"fullPath,omitempty"` - AutoLasthop string `json:"autoLastHop,omitempty"` - Mirror bool `json:"mirror,omitempty" bool:"disabled"` - SourcePort string `json:"sourePort,omitempty"` - Translation string `json:"translation,omitempty"` - Snatpool string `json:"snatpool,omitempty"` - VlansDisabled bool `json:"vlansDisabled,omitempty" bool:"disabled"` - Origins []string `json:"origins,omitempty"` + Name string `json:"name"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` + AutoLasthop string `json:"autoLastHop,omitempty"` + Mirror string `json:"mirror,omitempty"` + SourcePort string `json:"sourePort,omitempty"` + Translation string `json:"translation,omitempty"` + Snatpool string `json:"snatpool,omitempty"` + VlansDisabled bool `json:"vlansDisabled,omitempty" bool:"disabled"` + Origins struct { + Items []Originsrecord `json:"items,omitempty"` + } `json:"originsReference,omitempty"` +} + +type Originsrecords struct { + Items []Originsrecord `json:"items,omitempty"` +} + +type Originsrecord struct { + Name string `json:"name"` + app_service string `json:"appService,omitempty"` } func (p *Snat) MarshalJSON() ([]byte, error) { - var dto snatDTO - marshal(&dto, p) - return json.Marshal(dto) + return json.Marshal(snatDTO{ + Name: p.Name, + Partition: p.Partition, + FullPath: p.FullPath, + Mirror: p.Mirror, + SourcePort: p.SourcePort, + Translation: p.Translation, + Snatpool: p.Snatpool, + VlansDisabled: p.VlansDisabled, + Origins: struct { + Items []Originsrecord `json:"items,omitempty"` + }{Items: p.Origins}, + }) } func (p *Snat) UnmarshalJSON(b []byte) error { @@ -1548,8 +1604,18 @@ func (p *Snat) UnmarshalJSON(b []byte) error { if err != nil { return err } - p.Origins = dto.Origins - //return marshal(p, &dto) + + p.Name = dto.Name + p.Partition = dto.Partition + p.FullPath = dto.FullPath + p.AutoLasthop = dto.AutoLasthop + p.Mirror = dto.Mirror + p.SourcePort = dto.SourcePort + p.Translation = dto.Translation + p.Snatpool = dto.Snatpool + p.VlansDisabled = dto.VlansDisabled + p.Origins = dto.Origins.Items + return nil } @@ -1617,7 +1683,6 @@ const ( uriHttp2 = "http2" uriSnat = "snat" uriSnatpool = "snatpool" - uriUdp = "udp" uriCookie = "cookie" uriDestAddr = "dest-addr" uriHash = "hash" @@ -1695,13 +1760,13 @@ func (b *BigIP) AddSnatPool(config *SnatPool) error { // GetSnatPool retrieves a SnatPool by name. Returns nil if the snatpool does not exist func (b *BigIP) GetSnatPool(name string) (*SnatPool, error) { var snatPool SnatPool - err, ok := b.getForEntity(&snatPool, uriLtm, uriSnatPool, name) + err, _ := b.getForEntity(&snatPool, uriLtm, uriSnatPool, name) if err != nil { return nil, err } - if !ok { - return nil, nil - } + //if !ok { + // return nil, nil + //} return &snatPool, nil } @@ -2548,16 +2613,36 @@ func (b *BigIP) Nodes() (*Nodes, error) { return &nodes, nil } -// CreateNode adds a new node to the BIG-IP system. -func (b *BigIP) CreateNode(name, address string) error { +// CreateNode adds a new IP based node to the BIG-IP system. +func (b *BigIP) CreateNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state string) error { config := &Node{ Name: name, Address: address, + RateLimit: rate_limit, + ConnectionLimit: connection_limit, + DynamicRatio: dynamic_ratio, + Monitor: monitor, + State: state, } return b.post(config, uriLtm, uriNode) } +// CreateFQDNNode adds a new FQDN based node to the BIG-IP system. +func (b *BigIP) CreateFQDNNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state string) error { + config := &Node{ + Name: name, + RateLimit: rate_limit, + ConnectionLimit: connection_limit, + DynamicRatio: dynamic_ratio, + Monitor: monitor, + State: state, + } + config.FQDN.Name = address + + return b.post(config, uriLtm, uriNode) +} + // Get a Node by name. Returns nil if the node does not exist func (b *BigIP) GetNode(name string) (*Node, error) { var node Node @@ -2826,7 +2911,7 @@ func (b *BigIP) VirtualServers() (*VirtualServers, error) { // CreateVirtualServer adds a new virtual server to the BIG-IP system. can either be // in CIDR notation or decimal, i.e.: "24" or "255.255.255.0". A CIDR mask of "0" is the same // as "0.0.0.0". -func (b *BigIP) CreateVirtualServer(name, destination, mask, pool string, port int) error { +func (b *BigIP) CreateVirtualServer(name, destination, mask, pool string, vlans_enabled, vlans_disabled bool, port int, translate_address, translate_port string) error { subnetMask := cidr[mask] if strings.Contains(mask, ".") { @@ -2834,10 +2919,12 @@ func (b *BigIP) CreateVirtualServer(name, destination, mask, pool string, port i } config := &VirtualServer{ - Name: name, - Destination: fmt.Sprintf("%s:%d", destination, port), - Mask: subnetMask, - Pool: pool, + Name: name, + Destination: fmt.Sprintf("%s:%d", destination, port), + Mask: subnetMask, + Pool: pool, + TranslateAddress: translate_address, + TranslatePort: translate_port, } return b.post(config, uriLtm, uriVirtual) @@ -3150,15 +3237,40 @@ func (b *BigIP) CreatePolicy(p *Policy) error { return b.post(p, uriLtm, uriPolicy) } +func (b *BigIP) PublishPolicy(name, publish string) error { + config := &Policy{ + PublishCopy: publish, + } + values := []string{} + values = append(values, "~Common~Drafts~") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") + + log.Println( " ================== here in publish ", result, publish) + + return b.patch(config, uriLtm, uriPolicy, result) +} + //Update an existing policy. -func (b *BigIP) UpdatePolicy(name string, p *Policy) error { + func (b *BigIP) UpdatePolicy(name string, p *Policy) error { normalizePolicy(p) - return b.put(p, uriLtm, uriPolicy, name) + values := []string{} + values = append(values, "Drafts/") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") + return b.put(p, uriLtm, uriPolicy, result) } //Delete a policy by name. func (b *BigIP) DeletePolicy(name string) error { - return b.delete(uriLtm, uriPolicy, name) + values := []string{} + values = append(values, "Drafts/") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") +return b.delete(uriLtm, uriPolicy, result) } // Oneconnect profile creation @@ -3441,9 +3553,9 @@ func (b *BigIP) Snats(name string) (*Snats, error) { } return &snats, nil -} +}*/ -func (b *BigIP) CreateSnat(name, partition, autoLastHop, sourcePort, translation, snatpool string, vlansDisabled, mirror bool, origins []string) error { +/*func (b *BigIP) CreateSnat(name, partition, autoLastHop, sourcePort, translation, snatpool, mirror string, vlansDisabled bool, origins []string) error { snat := &Snat{ Name: name, Partition: partition, @@ -3457,6 +3569,10 @@ func (b *BigIP) CreateSnat(name, partition, autoLastHop, sourcePort, translation } log.Println("[INFO] Creating snat ", snat) return b.post(snat, uriLtm, uriSnat) +} */ +func (b *BigIP) CreateSnat(p *Snat) error { + log.Println(" what is the complete payload ", p) + return b.post(p, uriLtm, uriSnat) } func (b *BigIP) ModifySnat(config *Snat) error { @@ -3481,6 +3597,10 @@ func (b *BigIP) DeleteSnat(name string) error { return b.delete(uriLtm, uriSnat, name) } +func (b *BigIP) UpdateSnat(name string, p *Snat) error { + return b.put(p, uriLtm, uriSnat, name) +} + // Snats returns a list of snat func (b *BigIP) Snatpools(name string) (*Snatpools, error) { var snatpools Snatpools From ed58d3475b9512ff2003e0af64c2f051a2bac72f Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 6 Apr 2018 16:26:33 -0700 Subject: [PATCH 30/80] ltm.go changes --- ltm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ltm.go b/ltm.go index 3c4f42e..b738b11 100644 --- a/ltm.go +++ b/ltm.go @@ -3544,7 +3544,7 @@ func (b *BigIP) AddRecords(name, rname, data string) error { } // Snats returns a list of snat -func (b *BigIP) Snats(name string) (*Snats, error) { +/*func (b *BigIP) Snats(name string) (*Snats, error) { var snats Snats err, _ := b.getForEntity(&snats, uriLtm, uriSnat, name) From 87a70a89a01932a2debf0203778c01996df2e530 Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 6 Apr 2018 16:38:51 -0700 Subject: [PATCH 31/80] ltm.go changes --- ltm.go | 1 + 1 file changed, 1 insertion(+) diff --git a/ltm.go b/ltm.go index b738b11..6740ff4 100644 --- a/ltm.go +++ b/ltm.go @@ -1692,6 +1692,7 @@ const ( uriSourceAddr = "source-addr" uriSSL = "ssl" uriUniversal = "universal" + uriUdp = "udp" ) var cidr = map[string]string{ From 62236ad86b1175045bc22015c5a5ab7048635f43 Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 6 Apr 2018 16:48:53 -0700 Subject: [PATCH 32/80] ltm.go changes --- ltm.go | 2865 ++++++++++++++++++++++++-------------------------------- 1 file changed, 1199 insertions(+), 1666 deletions(-) diff --git a/ltm.go b/ltm.go index 6740ff4..cfb7f93 100644 --- a/ltm.go +++ b/ltm.go @@ -130,344 +130,6 @@ type ClientSSLProfile struct { UncleanShutdown string `json:"uncleanShutdown,omitempty"` } -// TcpProfiles contains a list of every tcp profile on the BIG-IP system. -type TcpProfiles struct { - TcpProfiles []TcpProfile `json:"items"` -} - -type TcpProfile struct { - Abc string `json:"abc,omitempty"` - AckOnPush string `json:"ackOnPush,omitempty"` - AppService string `json:"appService,omitempty"` - AutoProxyBufferSize string `json:"autoProxyBufferSize,omitempty"` - AutoReceiveWindowSize string `json:"autoReceiveWindowSize,omitempty"` - AutoSendBufferSize string `json:"autoSendBufferSize,omitempty"` - CloseWaitTimeout int `json:"closeWaitTimeout,omitempty"` - CmetricsCache string `json:"cmetricsCache,omitempty"` - CmetricsCacheTimeout int `json:"cmetricsCacheTimeout,omitempty"` - CongestionControl string `json:"congestionControl,omitempty"` - DefaultsFrom string `json:"defaultsFrom,omitempty"` - DeferredAccept string `json:"deferredAccept,omitempty"` - DelayWindowControl string `json:"delayWindowControl,omitempty"` - DelayedAcks string `json:"delayedAcks,omitempty"` - Description string `json:"description,omitempty"` - Dsack string `json:"dsack,omitempty"` - EarlyRetransmit string `json:"earlyRetransmit,omitempty"` - Ecn string `json:"ecn,omitempty"` - EnhancedLossRecovery string `json:"enhancedLossRecovery,omitempty"` - FastOpen string `json:"fastOpen,omitempty"` - FastOpenCookieExpiration int `json:"fastOpenCookieExpiration,omitempty"` - FinWait_2Timeout int `json:"finWait_2Timeout,omitempty"` - FinWaitTimeout int `json:"finWaitTimeout,omitempty"` - HardwareSynCookie string `json:"hardwareSynCookie,omitempty"` - IdleTimeout int `json:"idleTimeout,omitempty"` - InitCwnd int `json:"initCwnd,omitempty"` - InitRwnd int `json:"initRwnd,omitempty"` - IpDfMode string `json:"ipDfMode,omitempty"` - IpTosToClient string `json:"ipTosToClient,omitempty"` - IpTtlMode string `json:"ipTtlMode,omitempty"` - IpTtlV4 int `json:"ipTtlV4,omitempty"` - IpTtlV6 int `json:"ipTtlV6,omitempty"` - KeepAliveInterval int `json:"keepAliveInterval,omitempty"` - LimitedTransmit string `json:"limitedTransmit,omitempty"` - LinkQosToClient string `json:"linkQosToClient,omitempty"` - MaxRetrans int `json:"maxRetrans,omitempty"` - MaxSegmentSize int `json:"maxSegmentSize,omitempty"` - Md5Signature string `json:"md5Signature,omitempty"` - Md5SignaturePassphrase string `json:"md5SignaturePassphrase,omitempty"` - MinimumRto int `json:"minimumRto,omitempty"` - Mptcp string `json:"mptcp,omitempty"` - MptcpCsum string `json:"mptcpCsum,omitempty"` - MptcpCsumVerify string `json:"mptcpCsumVerify,omitempty"` - MptcpDebug string `json:"mptcpDebug,omitempty"` - MptcpFallback string `json:"mptcpFallback,omitempty"` - MptcpFastjoin string `json:"mptcpFastjoin,omitempty"` - MptcpIdleTimeout int `json:"mptcpIdleTimeout,omitempty"` - MptcpJoinMax int `json:"mptcpJoinMax,omitempty"` - MptcpMakeafterbreak string `json:"mptcpMakeafterbreak,omitempty"` - MptcpNojoindssack string `json:"mptcpNojoindssack,omitempty"` - MptcpRtomax int `json:"mptcpRtomax,omitempty"` - MptcpRxmitmin int `json:"mptcpRxmitmin,omitempty"` - MptcpSubflowmax int `json:"mptcpSubflowmax,omitempty"` - MptcpTimeout int `json:"mptcpTimeout,omitempty"` - Nagle string `json:"nagle,omitempty"` - Name string `json:"name,omitempty"` - TmPartition string `json:"tmPartition,omitempty"` - PktLossIgnoreBurst int `json:"pktLossIgnoreBurst,omitempty"` - PktLossIgnoreRate int `json:"pktLossIgnoreRate,omitempty"` - ProxyBufferHigh int `json:"proxyBufferHigh,omitempty"` - ProxyBufferLow int `json:"proxyBufferLow,omitempty"` - ProxyMss string `json:"proxyMss,omitempty"` - ProxyOptions string `json:"proxyOptions,omitempty"` - RatePace string `json:"ratePace,omitempty"` - RatePaceMaxRate int `json:"ratePaceMaxRate,omitempty"` - ReceiveWindowSize int `json:"receiveWindowSize,omitempty"` - ResetOnTimeout string `json:"resetOnTimeout,omitempty"` - RexmtThresh int `json:"rexmtThresh,omitempty"` - SelectiveAcks string `json:"selectiveAcks,omitempty"` - SelectiveNack string `json:"selectiveNack,omitempty"` - SendBufferSize int `json:"sendBufferSize,omitempty"` - SlowStart string `json:"slowStart,omitempty"` - SynCookieEnable string `json:"synCookieEnable,omitempty"` - SynCookieWhitelist string `json:"synCookieWhitelist,omitempty"` - SynMaxRetrans int `json:"synMaxRetrans,omitempty"` - SynRtoBase int `json:"synRtoBase,omitempty"` - TailLossProbe string `json:"tailLossProbe,omitempty"` - TcpOptions string `json:"tcpOptions,omitempty"` - TimeWaitRecycle string `json:"timeWaitRecycle,omitempty"` - TimeWaitTimeout string `json:"timeWaitTimeout,omitempty"` - Timestamps string `json:"timestamps,omitempty"` - VerifiedAccept string `json:"verifiedAccept,omitempty"` -} - -// UdpProfiles contains a list of every tcp profile on the BIG-IP system. -type UdpProfiles struct { - UdpProfiles []UdpProfile `json:"items"` -} - -type UdpProfile struct { - AllowNoPayload string `json:"allowNoPayload,omitempty"` - AppService string `json:"appService,omitempty"` - BufferMaxBytes int `json:"bufferMaxBytes,omitempty"` - BufferMaxPackets int `json:"bufferMaxPackets,omitempty"` - DatagramLoadBalancing string `json:"datagramLoadBalancing,omitempty"` - DefaultsFrom string `json:"defaultsFrom,omitempty"` - Description string `json:"description,omitempty"` - IdleTimeout string `json:"idleTimeout,omitempty"` - IpDfMode string `json:"ipDfMode,omitempty"` - IpTosToClient string `json:"ipTosToClient,omitempty"` - IpTtlMode string `json:"ipTtlMode,omitempty"` - IpTtlV4 int `json:"ipTtlV4,omitempty"` - IpTtlV6 int `json:"ipTtlV6,omitempty"` - LinkQosToClient string `json:"linkQosToClient,omitempty"` - Name string `json:"name,omitempty"` - NoChecksum string `json:"noChecksum,omitempty"` - TmPartition string `json:"tmPartition,omitempty"` - ProxyMss string `json:"proxyMss,omitempty"` -} - -type HttpProfiles struct { - HttpProfiles []HttpProfile `json:"items"` -} - -type HttpProfile struct { - AcceptXff string `json:"acceptXff,omitempty"` - AppService string `json:"appService,omitempty"` - BasicAuthRealm string `json:"basicAuthRealm,omitempty"` - DefaultsFrom string `json:"defaultsFrom,omitempty"` - Description string `json:"description,omitempty"` - EncryptCookieSecret string `json:"encryptCookieSecret,omitempty"` - EncryptCookies string `json:"encryptCookies,omitempty"` - FallbackHost string `json:"fallbackHost,omitempty"` - FallbackStatusCodes string `json:"fallbackStatusCodes,omitempty"` - HeaderErase string `json:"headerErase,omitempty"` - HeaderInsert string `json:"headerInsert,omitempty"` - InsertXforwardedFor string `json:"insertXforwardedFor,omitempty"` - LwsSeparator string `json:"lwsSeparator,omitempty"` - LwsWidth int `json:"lwsWidth,omitempty"` - Name string `json:"name,omitempty"` - OneconnectTransformations string `json:"oneconnectTransformations,omitempty"` - TmPartition string `json:"tmPartition,omitempty"` - ProxyType string `json:"proxyType,omitempty"` - RedirectRewrite string `json:"redirectRewrite,omitempty"` - RequestChunking string `json:"requestChunking,omitempty"` - ResponseChunking string `json:"responseChunking,omitempty"` - ResponseHeadersPermitted string `json:"responseHeadersPermitted,omitempty"` - ServerAgentName string `json:"serverAgentName,omitempty"` - ViaHostName string `json:"viaHostName,omitempty"` - ViaRequest string `json:"viaRequest,omitempty"` - ViaResponse string `json:"viaResponse,omitempty"` - XffAlternativeNames string `json:"xffAlternativeNames,omitempty"` -} - -type OneconnectProfiles struct { - OneconnectProfiles []OneconnectProfile `json:"items"` -} - -type OneconnectProfile struct { - AppService string `json:"appService,omitempty"` - DefaultsFrom string `json:"defaultsFrom,omitempty"` - Description string `json:"description,omitempty"` - IdleTimeoutOverride string `json:"idleTimeoutOverride,omitempty"` - LimitType string `json:"limitType,omitempty"` - MaxAge int `json:"maxAge,omitempty"` - MaxReuse int `json:"maxReuse,omitempty"` - MaxSize int `json:"maxSize,omitempty"` - Name string `json:"name,omitempty"` - TmPartition string `json:"tmPartition,omitempty"` - SharePools string `json:"sharePools,omitempty"` - SourceMask string `json:"sourceMask,omitempty"` -} - -type HttpCompressionProfiles struct { - HttpCompressionProfiles []HttpCompressionProfile `json:"items"` -} - -type HttpCompressionProfile struct { - AllowHttp_10 string `json:"allowHttp_10,omitempty"` - AppService string `json:"appService,omitempty"` - BrowserWorkarounds string `json:"browserWorkarounds,omitempty"` - BufferSize int `json:"bufferSize,omitempty"` - ContentTypeExclude []string `json:"contentTypeExclude,omitempty"` - ContentTypeInclude []string `json:"contentTypeInclude,omitempty"` - CpuSaver string `json:"cpuSaver,omitempty"` - CpuSaverHigh int `json:"cpuSaverHigh,omitempty"` - CpuSaverLow int `json:"cpuSaverLow,omitempty"` - DefaultsFrom string `json:"defaultsFrom,omitempty"` - Description string `json:"description,omitempty"` - GzipLevel int `json:"gzipLevel,omitempty"` - GzipMemoryLevel int `json:"gzipMemoryLevel,omitempty"` - GzipWindowSize int `json:"gzipWindowSize,omitempty"` - KeepAcceptEncoding string `json:"keepAcceptEncoding,omitempty"` - MethodPrefer string `json:"methodPrefer,omitempty"` - MinSize int `json:"minSize,omitempty"` - Name string `json:"name,omitempty"` - TmPartition string `json:"tmPartition,omitempty"` - Selective string `json:"selective,omitempty"` - UriExclude []string `json:"uriExclude,omitempty"` - UriInclude []string `json:"uriInclude,omitempty"` - VaryHeader string `json:"varyHeader,omitempty"` -} - -// PersistenceProfiles contains of list of persistence profiles -type PersistenceProfiles struct { - PersistenceProfiles []PersistenceProfile `json:"items"` -} - -// PersistenceProfile is a base for all persistence profiles -type PersistenceProfile struct { - AppService string `json:"appService,omitempty"` - DefaultsFrom string `json:"defaultsFrom,omitempty"` - Description string `json:"description,omitempty"` - FullPath string `json:"fullPath,omitempty"` - MatchAcrossPools string `json:"matchAcrossPools,omitempty"` - MatchAcrossServices string `json:"matchAcrossServices,omitempty"` - MatchAcrossVirtuals string `json:"matchAcrossVirtuals,omitempty"` - Method string `json:"method,omitempty"` - Mirror string `json:"mirror,omitempty"` - Mode string `json:"mode,omitempty"` - Name string `json:"name,omitempty"` - OverrideConnectionLimit string `json:"overrideConnectionLimit,omitempty"` - Partition string `json:"partition,omitempty"` - TmPartition string `json:"tmPartition,omitempty"` - Timeout string `json:"timeout,omitempty"` -} - -// CookiePersistenceProfiles contains a list of all cookies profiles -type CookiePersistenceProfiles struct { - CookiePersistenceProfiles []CookiePersistenceProfile `json:"items"` -} - -// CookiePersistenceProfile Defines a single cookie profile -type CookiePersistenceProfile struct { - PersistenceProfile - AlwaysSend string `json:"alwaysSend,omitempty"` - CookieEncryption string `json:"cookieEncryption,omitempty"` - CookieEncryptionPassphrase string `json:"cookieEncryptionPassphrase,omitempty"` - CookieName string `json:"cookieName,omitempty"` - Expiration string `json:"expiration,omitempty"` - HashLength int `json:"hashLength,omitempty"` - HashOffset int `json:"hashOffset,omitempty"` - HTTPOnly string `json:"httponly,omitempty"` - Secure string `json:"secure,omitempty"` -} - -// DestAddrPersistenceProfiles contains a list of all dest-addr profiles -type DestAddrPersistenceProfiles struct { - DestAddrPersistenceProfiles []DestAddrPersistenceProfile `json:"items"` -} - -// DestAddrPersistenceProfile Defines a single dest-addr profile -type DestAddrPersistenceProfile struct { - PersistenceProfile - HashAlgorithm string `json:"hashAlgorithm,omitempty"` - Mask string `json:"mask,omitempty"` -} - -// HashPersistenceProfiles contains a list of all hash profiles -type HashPersistenceProfiles struct { - HashPersistenceProfiles []HashPersistenceProfile `json:"items"` -} - -// HashPersistenceProfile Defines a single hash profile -type HashPersistenceProfile struct { - PersistenceProfile - HashAlgorithm string `json:"hashAlgorithm,omitempty"` - HashBufferLimit int `json:"hashBufferLimit,omitempty"` - HashEndPattern int `json:"hashEndPattern,omitempty"` - HashLength int `json:"hashLength,omitempty"` - HashOffset int `json:"hashOffset,omitempty"` - HashStartPattern int `json:"hashStartPattern,omitempty"` -} - -// HostPersistenceProfiles contains a list of all host profiles -type HostPersistenceProfiles struct { - HostPersistenceProfiles []HostPersistenceProfile `json:"items"` -} - -// HostPersistenceProfile Defines a single host profile -type HostPersistenceProfile struct { - PersistenceProfile -} - -// MSRDPPersistenceProfiles contains a list of all msrdp profiles -type MSRDPPersistenceProfiles struct { - MSRDPPersistenceProfiles []MSRDPPersistenceProfile `json:"items"` -} - -// MSRDPPersistenceProfile Defines a single msrdp profile -type MSRDPPersistenceProfile struct { - PersistenceProfile - HasSessionDir string `json:"hasSessionDir,omitempty"` -} - -// SIPPersistenceProfiles contains a list of all sip profiles -type SIPPersistenceProfiles struct { - SIPPersistenceProfiles []SIPPersistenceProfile `json:"items"` -} - -// SIPPersistenceProfile Defines a single sip profile -type SIPPersistenceProfile struct { - PersistenceProfile - SIPInfo string `json:"sipInfo,omitempty"` -} - -// SourceAddrPersistenceProfiles contains a list of all source-addr profiles -type SourceAddrPersistenceProfiles struct { - SourceAddrPersistenceProfiles []SourceAddrPersistenceProfile `json:"items"` -} - -// SourceAddrPersistenceProfile Defines a single source-addr profile -type SourceAddrPersistenceProfile struct { - PersistenceProfile - HashAlgorithm string `json:"hashAlgorithm,omitempty"` - MapProxies string `json:"mapProxies,omitempty"` - MapProxyAddress string `json:"mapProxyAddress,omitempty"` - MapProxyClass string `json:"mapProxyClass,omitempty"` - Mask string `json:"mask,omitempty"` -} - -// SSLPersistenceProfiles contains a list of all ssl profiles -type SSLPersistenceProfiles struct { - SSLPersistenceProfiles []SSLPersistenceProfile `json:"items"` -} - -// SSLPersistenceProfile Defines a single ssl profile -type SSLPersistenceProfile struct { - PersistenceProfile -} - -// UniversalPersistenceProfiles contains a list of all universal profiles -type UniversalPersistenceProfiles struct { - SSLPersistenceProfiles []UniversalPersistenceProfile `json:"items"` -} - -// UniversalPersistenceProfile Defines a single universal profile -type UniversalPersistenceProfile struct { - PersistenceProfile - Rule string `json:"rule,omitempty"` -} - // Nodes contains a list of every node on the BIG-IP system. type Nodes struct { Nodes []Node `json:"items"` @@ -687,79 +349,217 @@ func (p *Pool) UnmarshalJSON(b []byte) error { return marshal(p, &dto) } -// VirtualServers contains a list of all virtual servers on the BIG-IP system. -type VirtualServers struct { - VirtualServers []VirtualServer `json:"items"` +// PersistenceProfiles contains of list of persistence profiles +type PersistenceProfiles struct { + PersistenceProfiles []PersistenceProfile `json:"items"` } -// VirtualServer contains information about each individual virtual server. -type VirtualServer struct { - Name string `json:"name,omitempty"` - Partition string `json:"partition,omitempty"` - FullPath string `json:"fullPath,omitempty"` - Generation int `json:"generation,omitempty"` - AddressStatus string `json:"addressStatus,omitempty"` - AutoLastHop string `json:"autoLastHop,omitempty"` - CMPEnabled string `json:"cmpEnabled,omitempty"` - ConnectionLimit int `json:"connectionLimit,omitempty"` - Destination string `json:"destination,omitempty"` - Description string `json:"description,omitempty"` - Enabled bool `json:"enabled,omitempty"` - FallbackPersistenceProfile string `json:"fallbackPersistence,omitempty"` - GTMScore int `json:"gtmScore,omitempty"` - IPProtocol string `json:"ipProtocol,omitempty"` - Mask string `json:"mask,omitempty"` - Mirror string `json:"mirror,omitempty"` - MobileAppTunnel string `json:"mobileAppTunnel,omitempty"` - NAT64 string `json:"nat64,omitempty"` - Pool string `json:"pool,omitempty"` - RateLimit string `json:"rateLimit,omitempty"` - RateLimitDestinationMask int `json:"rateLimitDstMask,omitempty"` - RateLimitMode string `json:"rateLimitMode,omitempty"` - RateLimitSourceMask int `json:"rateLimitSrcMask,omitempty"` - Source string `json:"source,omitempty"` - SourceAddressTranslation struct { - Type string `json:"type,omitempty"` - Pool string `json:"pool,omitempty"` - } `json:"sourceAddressTranslation,omitempty"` - SourcePort string `json:"sourcePort,omitempty"` - SYNCookieStatus string `json:"synCookieStatus,omitempty"` - TranslateAddress string `json:"translateAddress,omitempty"` - TranslatePort string `json:"translatePort,omitempty"` - VlansEnabled bool `json:"vlansEnabled,omitempty"` - VlansDisabled bool `json:"vlansDisabled,omitempty"` - VSIndex int `json:"vsIndex,omitempty"` - Vlans []string `json:"vlans,omitempty"` - Rules []string `json:"rules,omitempty"` - PersistenceProfiles []Profile `json:"persist,omitempty"` - Profiles []Profile `json:"profiles,omitempty"` - Policies []string `json:"policies,omitempty"` +// PersistenceProfile is a base for all persistence profiles +type PersistenceProfile struct { + AppService string `json:"appService,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + FullPath string `json:"fullPath,omitempty"` + MatchAcrossPools string `json:"matchAcrossPools,omitempty"` + MatchAcrossServices string `json:"matchAcrossServices,omitempty"` + MatchAcrossVirtuals string `json:"matchAcrossVirtuals,omitempty"` + Method string `json:"method,omitempty"` + Mirror string `json:"mirror,omitempty"` + Mode string `json:"mode,omitempty"` + Name string `json:"name,omitempty"` + OverrideConnectionLimit string `json:"overrideConnectionLimit,omitempty"` + Partition string `json:"partition,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + Timeout string `json:"timeout,omitempty"` } -// VirtualAddresses contains a list of all virtual addresses on the BIG-IP system. -type VirtualAddresses struct { - VirtualAddresses []VirtualAddress `json:"items"` +// CookiePersistenceProfiles contains a list of all cookies profiles +type CookiePersistenceProfiles struct { + CookiePersistenceProfiles []CookiePersistenceProfile `json:"items"` } -// VirtualAddress contains information about each individual virtual address. -type VirtualAddress struct { - Name string - Partition string - FullPath string - Generation int - Address string - ARP bool - AutoDelete bool - ConnectionLimit int - Enabled bool - Floating bool - ICMPEcho bool - InheritedTrafficGroup bool - Mask string - RouteAdvertisement bool - ServerScope string - TrafficGroup string - Unit int +// CookiePersistenceProfile Defines a single cookie profile +type CookiePersistenceProfile struct { + PersistenceProfile + AlwaysSend string `json:"alwaysSend,omitempty"` + CookieEncryption string `json:"cookieEncryption,omitempty"` + CookieEncryptionPassphrase string `json:"cookieEncryptionPassphrase,omitempty"` + CookieName string `json:"cookieName,omitempty"` + Expiration string `json:"expiration,omitempty"` + HashLength int `json:"hashLength,omitempty"` + HashOffset int `json:"hashOffset,omitempty"` + HTTPOnly string `json:"httponly,omitempty"` + Secure string `json:"secure,omitempty"` +} + +// DestAddrPersistenceProfiles contains a list of all dest-addr profiles +type DestAddrPersistenceProfiles struct { + DestAddrPersistenceProfiles []DestAddrPersistenceProfile `json:"items"` +} + +// DestAddrPersistenceProfile Defines a single dest-addr profile +type DestAddrPersistenceProfile struct { + PersistenceProfile + HashAlgorithm string `json:"hashAlgorithm,omitempty"` + Mask string `json:"mask,omitempty"` +} + +// HashPersistenceProfiles contains a list of all hash profiles +type HashPersistenceProfiles struct { + HashPersistenceProfiles []HashPersistenceProfile `json:"items"` +} + +// HashPersistenceProfile Defines a single hash profile +type HashPersistenceProfile struct { + PersistenceProfile + HashAlgorithm string `json:"hashAlgorithm,omitempty"` + HashBufferLimit int `json:"hashBufferLimit,omitempty"` + HashEndPattern int `json:"hashEndPattern,omitempty"` + HashLength int `json:"hashLength,omitempty"` + HashOffset int `json:"hashOffset,omitempty"` + HashStartPattern int `json:"hashStartPattern,omitempty"` +} + +// HostPersistenceProfiles contains a list of all host profiles +type HostPersistenceProfiles struct { + HostPersistenceProfiles []HostPersistenceProfile `json:"items"` +} + +// HostPersistenceProfile Defines a single host profile +type HostPersistenceProfile struct { + PersistenceProfile +} + +// MSRDPPersistenceProfiles contains a list of all msrdp profiles +type MSRDPPersistenceProfiles struct { + MSRDPPersistenceProfiles []MSRDPPersistenceProfile `json:"items"` +} + +// MSRDPPersistenceProfile Defines a single msrdp profile +type MSRDPPersistenceProfile struct { + PersistenceProfile + HasSessionDir string `json:"hasSessionDir,omitempty"` +} + +// SIPPersistenceProfiles contains a list of all sip profiles +type SIPPersistenceProfiles struct { + SIPPersistenceProfiles []SIPPersistenceProfile `json:"items"` +} + +// SIPPersistenceProfile Defines a single sip profile +type SIPPersistenceProfile struct { + PersistenceProfile + SIPInfo string `json:"sipInfo,omitempty"` +} + +// SourceAddrPersistenceProfiles contains a list of all source-addr profiles +type SourceAddrPersistenceProfiles struct { + SourceAddrPersistenceProfiles []SourceAddrPersistenceProfile `json:"items"` +} + +// SourceAddrPersistenceProfile Defines a single source-addr profile +type SourceAddrPersistenceProfile struct { + PersistenceProfile + HashAlgorithm string `json:"hashAlgorithm,omitempty"` + MapProxies string `json:"mapProxies,omitempty"` + MapProxyAddress string `json:"mapProxyAddress,omitempty"` + MapProxyClass string `json:"mapProxyClass,omitempty"` + Mask string `json:"mask,omitempty"` +} + +// SSLPersistenceProfiles contains a list of all ssl profiles +type SSLPersistenceProfiles struct { + SSLPersistenceProfiles []SSLPersistenceProfile `json:"items"` +} + +// SSLPersistenceProfile Defines a single ssl profile +type SSLPersistenceProfile struct { + PersistenceProfile +} + +// UniversalPersistenceProfiles contains a list of all universal profiles +type UniversalPersistenceProfiles struct { + SSLPersistenceProfiles []UniversalPersistenceProfile `json:"items"` +} + +// UniversalPersistenceProfile Defines a single universal profile +type UniversalPersistenceProfile struct { + PersistenceProfile + Rule string `json:"rule,omitempty"` +} + +// VirtualServers contains a list of all virtual servers on the BIG-IP system. +type VirtualServers struct { + VirtualServers []VirtualServer `json:"items"` +} + +// VirtualServer contains information about each individual virtual server. +type VirtualServer struct { + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` + Generation int `json:"generation,omitempty"` + AddressStatus string `json:"addressStatus,omitempty"` + AutoLastHop string `json:"autoLastHop,omitempty"` + CMPEnabled string `json:"cmpEnabled,omitempty"` + ConnectionLimit int `json:"connectionLimit,omitempty"` + Destination string `json:"destination,omitempty"` + Enabled bool `json:"enabled,omitempty"` + GTMScore int `json:"gtmScore,omitempty"` + FallbackPersistenceProfile string `json:"fallbackPersistence,omitempty"` + IPProtocol string `json:"ipProtocol,omitempty"` + Mask string `json:"mask,omitempty"` + Mirror string `json:"mirror,omitempty"` + MobileAppTunnel string `json:"mobileAppTunnel,omitempty"` + NAT64 string `json:"nat64,omitempty"` + Pool string `json:"pool,omitempty"` + RateLimit string `json:"rateLimit,omitempty"` + RateLimitDestinationMask int `json:"rateLimitDstMask,omitempty"` + RateLimitMode string `json:"rateLimitMode,omitempty"` + RateLimitSourceMask int `json:"rateLimitSrcMask,omitempty"` + Source string `json:"source,omitempty"` + SourceAddressTranslation struct { + Type string `json:"type,omitempty"` + Pool string `json:"pool,omitempty"` + } `json:"sourceAddressTranslation,omitempty"` + SourcePort string `json:"sourcePort,omitempty"` + SYNCookieStatus string `json:"synCookieStatus,omitempty"` + TranslateAddress string `json:"translateAddress,omitempty"` + TranslatePort string `json:"translatePort,omitempty"` + VlansEnabled bool `json:"vlansEnabled,omitempty"` + VlansDisabled bool `json:"vlansDisabled,omitempty"` + VSIndex int `json:"vsIndex,omitempty"` + Vlans []string `json:"vlans,omitempty"` + Rules []string `json:"rules,omitempty"` + PersistenceProfiles []Profile `json:"persist,omitempty"` + Profiles []Profile `json:"profiles,omitempty"` + Policies []string `json:"policies,omitempty"` +} + +// VirtualAddresses contains a list of all virtual addresses on the BIG-IP system. +type VirtualAddresses struct { + VirtualAddresses []VirtualAddress `json:"items"` +} + +// VirtualAddress contains information about each individual virtual address. +type VirtualAddress struct { + Name string + Partition string + FullPath string + Generation int + Address string + ARP bool + AutoDelete bool + ConnectionLimit int + Enabled bool + Floating bool + ICMPEcho bool + InheritedTrafficGroup bool + Mask string + RouteAdvertisement bool + ServerScope string + TrafficGroup string + Unit int } type virtualAddressDTO struct { @@ -1115,6 +915,8 @@ type PolicyRuleCondition struct { VlanId bool `json:"vlanId,omitempty"` } + + func (p *VirtualAddress) MarshalJSON() ([]byte, error) { var dto virtualAddressDTO marshal(&dto, p) @@ -1139,53 +941,48 @@ type Monitors struct { type Monitor struct { Name string Partition string + DefaultsFrom string FullPath string Generation int ParentMonitor string - Database string Description string Destination string Interval int IPDSCP int - ManualResume bool - MonitorType string + ManualResume string Password string - ReceiveColumn string - ReceiveRow string ReceiveString string ReceiveDisable string - Reverse bool + Reverse string SendString string TimeUntilUp int Timeout int - Transparent bool + Transparent string UpInterval int Username string + } type monitorDTO struct { - Name string `json:"name,omitempty"` - Partition string `json:"partition,omitempty"` - FullPath string `json:"fullPath,omitempty"` - Generation int `json:"generation,omitempty"` - ParentMonitor string `json:"defaultsFrom,omitempty"` - Database string `json:"database,omitempty"` - Description string `json:"description,omitempty"` - Destination string `json:"destination,omitempty"` - Interval int `json:"interval,omitempty"` - IPDSCP int `json:"ipDscp,omitempty"` - ManualResume string `json:"manualResume,omitempty" bool:"enabled"` - // MonitorType string `json:"monitorType,omitempty"` + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + FullPath string `json:"fullPath,omitempty"` + Generation int `json:"generation,omitempty"` + ParentMonitor string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + Destination string `json:"destination,omitempty"` + Interval int `json:"interval,omitempty"` + IPDSCP int `json:"ipDscp,omitempty"` + ManualResume string `json:"manualResume,omitempty"` Password string `json:"password,omitempty"` - ReceiveColumn string `json:"recvColumn,omitempty"` - ReceiveRow string `json:"recvRow,omitempty"` ReceiveString string `json:"recv,omitempty"` ReceiveDisable string `json:"recvDisable,omitempty"` - Reverse string `json:"reverse,omitempty" bool:"enabled"` + Reverse string `json:"reverse,omitempty"` SendString string `json:"send,omitempty"` TimeUntilUp int `json:"timeUntilUp,omitempty"` Timeout int `json:"timeout,omitempty"` - Transparent string `json:"transparent,omitempty" bool:"enabled"` + Transparent string `json:"transparent,omitempty"` UpInterval int `json:"upInterval,omitempty"` Username string `json:"username,omitempty"` } @@ -1692,7 +1489,6 @@ const ( uriSourceAddr = "source-addr" uriSSL = "ssl" uriUniversal = "universal" - uriUdp = "udp" ) var cidr = map[string]string{ @@ -1885,769 +1681,877 @@ func (b *BigIP) ModifyClientSSLProfile(name string, config *ClientSSLProfile) er return b.put(config, uriLtm, uriProfile, uriClientSSL, name) } -// TcpProfiles returns a list of Tcp profiles -func (b *BigIP) TcpProfiles() (*TcpProfiles, error) { - var tcpProfiles TcpProfiles - err, _ := b.getForEntity(&tcpProfiles, uriLtm, uriProfile, uriTcp) +// Nodes returns a list of nodes. +func (b *BigIP) Nodes() (*Nodes, error) { + var nodes Nodes + err, _ := b.getForEntity(&nodes, uriLtm, uriNode) if err != nil { return nil, err } - return &tcpProfiles, nil + return &nodes, nil } -func (b *BigIP) GetTcpProfile(name string) (*TcpProfile, error) { - var tcpProfile TcpProfile - err, ok := b.getForEntity(&tcpProfile, uriLtm, uriProfile, uriTcp, name) - if err != nil { - return nil, err +// CreateNode adds a new IP based node to the BIG-IP system. +func (b *BigIP) CreateNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state string) error { + config := &Node{ + Name: name, + Address: address, + RateLimit: rate_limit, + ConnectionLimit: connection_limit, + DynamicRatio: dynamic_ratio, + Monitor: monitor, + State: state, } - if !ok { - return nil, nil + return b.post(config, uriLtm, uriNode) +} + +// CreateFQDNNode adds a new FQDN based node to the BIG-IP system. +func (b *BigIP) CreateFQDNNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state string) error { + config := &Node{ + Name: name, + RateLimit: rate_limit, + ConnectionLimit: connection_limit, + DynamicRatio: dynamic_ratio, + Monitor: monitor, + State: state, } + config.FQDN.Name = address - return &tcpProfile, nil + return b.post(config, uriLtm, uriNode) } -// CreateTcpProfile creates a new tcp profile on the BIG-IP system. -func (b *BigIP) CreateTcpProfile(name string, parent string) error { - config := &TcpProfile{ - Name: name, - DefaultsFrom: parent, +// Get a Node by name. Returns nil if the node does not exist +func (b *BigIP) GetNode(name string) (*Node, error) { + var node Node + err, ok := b.getForEntity(&node, uriLtm, uriNode, name) + if err != nil { + return nil, err + } + if !ok { + return nil, nil } - return b.post(config, uriLtm, uriProfile, uriTcp) + return &node, nil } -func (b *BigIP) AddTcpProfile(config *TcpProfile) error { - return b.post(config, uriLtm, uriProfile, uriTcp) +// DeleteNode removes a node. +func (b *BigIP) DeleteNode(name string) error { + return b.delete(uriLtm, uriNode, name) } -// DeleteTcpProfile removes a tcp profile. -func (b *BigIP) DeleteTcpProfile(name string) error { - return b.delete(uriLtm, uriProfile, uriTcp, name) +// ModifyNode allows you to change any attribute of a node. Fields that +// can be modified are referenced in the Node struct. +func (b *BigIP) ModifyNode(name string, config *Node) error { + return b.put(config, uriLtm, uriNode, name) } -// ModifyTcpProfile allows you to change any attribute of a tcp profile. -// Fields that can be modified are referenced in the TcpProfile struct. -func (b *BigIP) ModifyTcpProfile(name string, config *TcpProfile) error { - return b.put(config, uriLtm, uriProfile, uriTcp, name) -} +// NodeStatus changes the status of a node. can be either +// "enable" or "disable". +func (b *BigIP) NodeStatus(name, state string) error { + config := &Node{} -// UdpProfiles returns a list of Udp profiles -func (b *BigIP) UdpProfiles() (*UdpProfiles, error) { - var udpProfiles UdpProfiles - err, _ := b.getForEntity(&udpProfiles, uriLtm, uriProfile, uriUdp) - if err != nil { - return nil, err + switch state { + case "enable": + // config.State = "unchecked" + config.Session = "user-enabled" + case "disable": + // config.State = "unchecked" + config.Session = "user-disabled" + // case "offline": + // config.State = "user-down" + // config.Session = "user-disabled" } - return &udpProfiles, nil + return b.put(config, uriLtm, uriNode, name) } -func (b *BigIP) GetUdpProfile(name string) (*UdpProfile, error) { - var udpProfile UdpProfile - err, ok := b.getForEntity(&udpProfile, uriLtm, uriProfile, uriUdp, name) +// InternalDataGroups returns a list of internal data groups. +func (b *BigIP) InternalDataGroups() (*DataGroups, error) { + var dataGroups DataGroups + err, _ := b.getForEntity(&dataGroups, uriLtm, uriDatagroup, uriInternal) if err != nil { return nil, err } - if !ok { - return nil, nil - } - - return &udpProfile, nil + return &dataGroups, nil } -// CreateUdpProfile creates a new udp profile on the BIG-IP system. -func (b *BigIP) CreateUdpProfile(name string, parent string) error { - config := &UdpProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriProfile, uriUdp) -} - -func (b *BigIP) AddUdpProfile(config *UdpProfile) error { - return b.post(config, uriLtm, uriProfile, uriUdp) +func (b *BigIP) AddInternalDataGroup(config *DataGroup) error { + return b.post(config, uriLtm, uriDatagroup, uriInternal) } -// DeleteUdpProfile removes a udp profile. -func (b *BigIP) DeleteUdpProfile(name string) error { - return b.delete(uriLtm, uriProfile, uriUdp, name) +func (b *BigIP) DeleteInternalDataGroup(name string) error { + return b.delete(uriLtm, uriDatagroup, uriInternal, name) } -// ModifyUdpProfile allows you to change any attribute of a udp profile. -// Fields that can be modified are referenced in the UdpProfile struct. -func (b *BigIP) ModifyUdpProfile(name string, config *UdpProfile) error { - return b.put(config, uriLtm, uriProfile, uriUdp, name) +// Modify a named internal data group, REPLACING all the records +func (b *BigIP) ModifyInternalDataGroupRecords(name string, records *[]DataGroupRecord) error { + config := &DataGroup{ + Records: *records, + } + return b.put(config, uriLtm, uriDatagroup, uriInternal, name) } -// HttpProfiles returns a list of HTTP profiles -func (b *BigIP) HttpProfiles() (*HttpProfiles, error) { - var httpProfiles HttpProfiles - err, _ := b.getForEntity(&httpProfiles, uriLtm, uriProfile, uriHttp) +// Get the internal data group records for a named internal data group +func (b *BigIP) GetInternalDataGroupRecords(name string) (*[]DataGroupRecord, error) { + var dataGroup DataGroup + err, _ := b.getForEntity(&dataGroup, uriLtm, uriDatagroup, uriInternal, name) if err != nil { return nil, err } - return &httpProfiles, nil + return &dataGroup.Records, nil } -func (b *BigIP) GetHttpProfile(name string) (*HttpProfile, error) { - var httpProfile HttpProfile - err, ok := b.getForEntity(&httpProfile, uriLtm, uriProfile, uriHttp, name) +// Pools returns a list of pools. +func (b *BigIP) Pools() (*Pools, error) { + var pools Pools + err, _ := b.getForEntity(&pools, uriLtm, uriPool) if err != nil { return nil, err } - if !ok { - return nil, nil - } - - return &httpProfile, nil + return &pools, nil } -// CreateHttpProfile creates a new http profile on the BIG-IP system. -func (b *BigIP) CreateHttpProfile(name string, parent string) error { - config := &HttpProfile{ - Name: name, - DefaultsFrom: parent, +// PoolMembers returns a list of pool members for the given pool. +func (b *BigIP) PoolMembers(name string) (*PoolMembers, error) { + var poolMembers PoolMembers + err, _ := b.getForEntity(&poolMembers, uriLtm, uriPool, name, uriPoolMember) + if err != nil { + return nil, err } - return b.post(config, uriLtm, uriProfile, uriHttp) + return &poolMembers, nil } -func (b *BigIP) AddHttpProfile(config *HttpProfile) error { - return b.post(config, uriLtm, uriProfile, uriHttp) -} +// AddPoolMember adds a node/member to the given pool. must be in the form +// of :, i.e.: "web-server1:443". +func (b *BigIP) AddPoolMember(pool, member string) error { + config := &poolMember{ + Name: member, + } -// DeleteHttpProfile removes a http profile. -func (b *BigIP) DeleteHttpProfile(name string) error { - return b.delete(uriLtm, uriProfile, uriHttp, name) + return b.post(config, uriLtm, uriPool, pool, uriPoolMember) } -// ModifyHttpProfile allows you to change any attribute of a http profile. -// Fields that can be modified are referenced in the HttpProfile struct. -func (b *BigIP) ModifyHttpProfile(name string, config *HttpProfile) error { - return b.put(config, uriLtm, uriProfile, uriHttp, name) -} +// GetPoolMember returns the details of a member in the specified pool. +func (b *BigIP) GetPoolMember(pool string, member string) (*PoolMember, error) { + var poolMember PoolMember + err, ok := b.getForEntity(&poolMember, uriLtm, uriPool, pool, uriPoolMember, member) -// OneconnectProfiles returns a list of HTTP profiles -func (b *BigIP) OneconnectProfiles() (*OneconnectProfiles, error) { - var oneconnectProfiles OneconnectProfiles - err, _ := b.getForEntity(&oneconnectProfiles, uriLtm, uriProfile, uriOneconnect) if err != nil { return nil, err } + if !ok { + return nil, nil + } - return &oneconnectProfiles, nil + return &poolMember, nil } -func (b *BigIP) GetOneconnectProfile(name string) (*OneconnectProfile, error) { - var oneconnectProfile OneconnectProfile - err, ok := b.getForEntity(&oneconnectProfile, uriLtm, uriProfile, uriOneconnect, name) - if err != nil { - return nil, err - } +// CreatePoolMember creates a pool member for the specified pool. +func (b *BigIP) CreatePoolMember(pool string, config *PoolMember) error { + return b.post(config, uriLtm, uriPool, pool, uriPoolMember) +} - if !ok { - return nil, nil - } +// ModifyPoolMember will update the configuration of a particular pool member. +func (b *BigIP) ModifyPoolMember(pool string, config *PoolMember) error { + member := config.FullPath + // These fields are not used when modifying a pool member; so omit them. + config.Name = "" + config.Partition = "" + config.FullPath = "" - return &oneconnectProfile, nil + // This cannot be modified for an existing pool member. + config.Address = "" + + return b.put(config, uriLtm, uriPool, pool, uriPoolMember, member) } -// CreateOneconnectProfile creates a new http profile on the BIG-IP system. -func (b *BigIP) CreateOneconnectProfile(name string, parent string) error { - config := &OneconnectProfile{ - Name: name, - DefaultsFrom: parent, +// UpdatePoolMembers does a replace-all-with for the members of a pool. +func (b *BigIP) UpdatePoolMembers(pool string, pm *[]PoolMember) error { + config := &poolMembers{ + Members: *pm, } - - return b.post(config, uriLtm, uriProfile, uriOneconnect) + return b.put(config, uriLtm, uriPool, pool) } -func (b *BigIP) AddOneconnectProfile(config *OneconnectProfile) error { - return b.post(config, uriLtm, uriProfile, uriOneconnect) +// RemovePoolMember removes a pool member from the specified pool. +func (b *BigIP) RemovePoolMember(pool string, config *PoolMember) error { + member := config.FullPath + return b.delete(uriLtm, uriPool, pool, uriPoolMember, member) } -// DeleteOneconnectProfile removes a http profile. -func (b *BigIP) DeleteOneconnectProfile(name string) error { - return b.delete(uriLtm, uriProfile, uriOneconnect, name) +// DeletePoolMember removes a member from the given pool. must be in the form +// of :, i.e.: "web-server1:443". +func (b *BigIP) DeletePoolMember(pool string, member string) error { + return b.delete(uriLtm, uriPool, pool, uriPoolMember, member) } -// ModifyOneconnectProfile allows you to change any attribute of a http profile. -// Fields that can be modified are referenced in the OneconnectProfile struct. -func (b *BigIP) ModifyOneconnectProfile(name string, config *OneconnectProfile) error { - return b.put(config, uriLtm, uriProfile, uriOneconnect, name) +// PoolMemberStatus changes the status of a pool member. can be either +// "enable" or "disable". must be in the form of :, +// i.e.: "web-server1:443". +func (b *BigIP) PoolMemberStatus(pool string, member string, state string) error { + config := &Node{} + + switch state { + case "enable": + // config.State = "unchecked" + config.Session = "user-enabled" + case "disable": + // config.State = "unchecked" + config.Session = "user-disabled" + // case "offline": + // config.State = "user-down" + // config.Session = "user-disabled" + } + + return b.put(config, uriLtm, uriPool, pool, uriPoolMember, member) } -// HttpCompressionProfiles returns a list of HTTP profiles -func (b *BigIP) HttpCompressionProfiles() (*HttpCompressionProfiles, error) { - var httpCompressionProfiles HttpCompressionProfiles - err, _ := b.getForEntity(&httpCompressionProfiles, uriLtm, uriProfile, uriHttpcompress) - if err != nil { - return nil, err +// CreatePool adds a new pool to the BIG-IP system by name. +func (b *BigIP) CreatePool(name string) error { + config := &Pool{ + Name: name, } - return &httpCompressionProfiles, nil + return b.post(config, uriLtm, uriPool) +} + +// AddPool creates a new pool on the BIG-IP system. +func (b *BigIP) AddPool(config *Pool) error { + return b.post(config, uriLtm, uriPool) } -func (b *BigIP) GetHttpCompressionProfile(name string) (*HttpCompressionProfile, error) { - var httpCompressionProfile HttpCompressionProfile - err, ok := b.getForEntity(&httpCompressionProfile, uriLtm, uriProfile, uriHttpcompress, name) +// Get a Pool by name. Returns nil if the Pool does not exist +func (b *BigIP) GetPool(name string) (*Pool, error) { + var pool Pool + err, ok := b.getForEntity(&pool, uriLtm, uriPool, name) if err != nil { return nil, err } - if !ok { return nil, nil } - return &httpCompressionProfile, nil + return &pool, nil } -// CreateHttpCompressionProfile creates a new http profile on the BIG-IP system. -func (b *BigIP) CreateHttpCompressionProfile(name string, parent string) error { - config := &HttpCompressionProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriProfile, uriHttpcompress) +// DeletePool removes a pool. +func (b *BigIP) DeletePool(name string) error { + return b.delete(uriLtm, uriPool, name) } -func (b *BigIP) AddHttpCompressionProfile(config *HttpCompressionProfile) error { - return b.post(config, uriLtm, uriProfile, uriHttpcompress) +// ModifyPool allows you to change any attribute of a pool. Fields that +// can be modified are referenced in the Pool struct. +func (b *BigIP) ModifyPool(name string, config *Pool) error { + return b.put(config, uriLtm, uriPool, name) } -// DeleteHttpCompressionProfile removes a http profile. -func (b *BigIP) DeleteHttpCompressionProfile(name string) error { - return b.delete(uriLtm, uriProfile, uriHttpcompress, name) -} +// VirtualServers returns a list of virtual servers. +func (b *BigIP) VirtualServers() (*VirtualServers, error) { + var vs VirtualServers + err, _ := b.getForEntity(&vs, uriLtm, uriVirtual) + if err != nil { + return nil, err + } -// ModifyHttpCompressionProfile allows you to change any attribute of a http profile. -// Fields that can be modified are referenced in the HttpCompressionProfile struct. -func (b *BigIP) ModifyHttpCompressionProfile(name string, config *HttpCompressionProfile) error { - return b.put(config, uriLtm, uriProfile, uriHttpcompress, name) + return &vs, nil } -// CookiePersistenceProfiles returns a list of cookie persist profiles -func (b *BigIP) CookiePersistenceProfiles() (*CookiePersistenceProfiles, error) { - var cookiePersistenceProfiles CookiePersistenceProfiles - err, _ := b.getForEntity(&cookiePersistenceProfiles, uriLtm, uriPersistence, uriCookie) - if err != nil { - return nil, err +// CreateVirtualServer adds a new virtual server to the BIG-IP system. can either be +// in CIDR notation or decimal, i.e.: "24" or "255.255.255.0". A CIDR mask of "0" is the same +// as "0.0.0.0". +func (b *BigIP) CreateVirtualServer(name, destination, mask, pool string, vlans_enabled, vlans_disabled bool, port int, translate_address, translate_port string) error { + subnetMask := cidr[mask] + + if strings.Contains(mask, ".") { + subnetMask = mask } - return &cookiePersistenceProfiles, nil + config := &VirtualServer{ + Name: name, + Destination: fmt.Sprintf("%s:%d", destination, port), + Mask: subnetMask, + Pool: pool, + TranslateAddress: translate_address, + TranslatePort: translate_port, + } + + return b.post(config, uriLtm, uriVirtual) } -// GetCookiePersistenceProfile gets a single cookie persist profile by name -func (b *BigIP) GetCookiePersistenceProfile(name string) (*CookiePersistenceProfile, error) { - var cookiePersistenceProfile CookiePersistenceProfile - err, ok := b.getForEntity(&cookiePersistenceProfile, uriLtm, uriPersistence, uriCookie, name) +// AddVirtualServer adds a new virtual server by config to the BIG-IP system. +func (b *BigIP) AddVirtualServer(config *VirtualServer) error { + return b.post(config, uriLtm, uriVirtual) +} + +// GetVirtualServer retrieves a virtual server by name. Returns nil if the virtual server does not exist +func (b *BigIP) GetVirtualServer(name string) (*VirtualServer, error) { + var vs VirtualServer + err, ok := b.getForEntity(&vs, uriLtm, uriVirtual, name) if err != nil { return nil, err } - if !ok { return nil, nil } - return &cookiePersistenceProfile, nil -} - -// CreateCookiePersistenceProfile creates a new cookie persist profile on the BIG-IP system. -func (b *BigIP) CreateCookiePersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, + profiles, err := b.VirtualServerProfiles(name) + if err != nil { + return nil, err } + vs.Profiles = profiles.Profiles - return b.post(config, uriLtm, uriPersistence, uriCookie) -} + policy_names, err := b.VirtualServerPolicyNames(name) + if err != nil { + return nil, err + } + vs.Policies = policy_names -// AddCookiePersistenceProfile adds a cookie persist profile to the BIG-IP system -func (b *BigIP) AddCookiePersistenceProfile(config *CookiePersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriCookie) + return &vs, nil } -// DeleteCookiePersistenceProfile removes a cookie persist profile. -func (b *BigIP) DeleteCookiePersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriCookie, name) +// DeleteVirtualServer removes a virtual server. +func (b *BigIP) DeleteVirtualServer(name string) error { + return b.delete(uriLtm, uriVirtual, name) } -// ModifyCookiePersistenceProfile allows you to change any attribute of a cookie persist profile. -// Fields that can be modified are referenced in the CookiePersistenceProfile struct. -func (b *BigIP) ModifyCookiePersistenceProfile(name string, config *CookiePersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriCookie, name) +// ModifyVirtualServer allows you to change any attribute of a virtual server. Fields that +// can be modified are referenced in the VirtualServer struct. +func (b *BigIP) ModifyVirtualServer(name string, config *VirtualServer) error { + return b.put(config, uriLtm, uriVirtual, name) } -// DestAddrPersistenceProfiles returns a list of dest-addr persist profiles -func (b *BigIP) DestAddrPersistenceProfiles() (*DestAddrPersistenceProfiles, error) { - var destAddrPersistenceProfiles DestAddrPersistenceProfiles - err, _ := b.getForEntity(&destAddrPersistenceProfiles, uriLtm, uriPersistence, uriDestAddr) +// VirtualServerProfiles gets the profiles currently associated with a virtual server. +func (b *BigIP) VirtualServerProfiles(vs string) (*Profiles, error) { + var p Profiles + err, ok := b.getForEntity(&p, uriLtm, uriVirtual, vs, "profiles") if err != nil { return nil, err } + if !ok { + return nil, nil + } - return &destAddrPersistenceProfiles, nil + return &p, nil } -// GetDestAddrPersistenceProfile gets a single dest-addr persist profile by name -func (b *BigIP) GetDestAddrPersistenceProfile(name string) (*DestAddrPersistenceProfile, error) { - var destAddrPersistenceProfile DestAddrPersistenceProfile - err, ok := b.getForEntity(&destAddrPersistenceProfile, uriLtm, uriPersistence, uriDestAddr, name) +//Get the names of policies associated with a particular virtual server +func (b *BigIP) VirtualServerPolicyNames(vs string) ([]string, error) { + var policies VirtualServerPolicies + err, _ := b.getForEntity(&policies, uriLtm, uriVirtual, vs, "policies") if err != nil { return nil, err } - - if !ok { - return nil, nil + retval := make([]string, 0, len(policies.PolicyRef.Policies)) + for _, p := range policies.PolicyRef.Policies { + retval = append(retval, p.FullPath) } + return retval, nil +} - return &destAddrPersistenceProfile, nil -} - -// CreateDestAddrPersistenceProfile creates a new dest-addr persist profile on the BIG-IP system. -func (b *BigIP) CreateDestAddrPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, +// VirtualAddresses returns a list of virtual addresses. +func (b *BigIP) VirtualAddresses() (*VirtualAddresses, error) { + var va VirtualAddresses + err, _ := b.getForEntity(&va, uriLtm, uriVirtualAddress) + if err != nil { + return nil, err } - - return b.post(config, uriLtm, uriPersistence, uriDestAddr) + return &va, nil } -// AddDestAddrPersistenceProfile adds a dest-addr persist profile to the BIG-IP system -func (b *BigIP) AddDestAddrPersistenceProfile(config *DestAddrPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriDestAddr) +func (b *BigIP) CreateVirtualAddress(vaddr string, config *VirtualAddress) error { + config.Name = vaddr + return b.post(config, uriLtm, uriVirtualAddress) } -// DeleteDestAddrPersistenceProfile removes a dest-addr persist profile. -func (b *BigIP) DeleteDestAddrPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriDestAddr, name) +// VirtualAddressStatus changes the status of a virtual address. can be either +// "enable" or "disable". +func (b *BigIP) VirtualAddressStatus(vaddr, state string) error { + config := &VirtualAddress{} + config.Enabled = (state == ENABLED) + return b.put(config, uriLtm, uriVirtualAddress, vaddr) } -// ModifyDestAddrPersistenceProfile allows you to change any attribute of a dest-addr persist profile. -// Fields that can be modified are referenced in the DestAddrPersistenceProfile struct. -func (b *BigIP) ModifyDestAddrPersistenceProfile(name string, config *DestAddrPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriDestAddr, name) +// ModifyVirtualAddress allows you to change any attribute of a virtual address. Fields that +// can be modified are referenced in the VirtualAddress struct. +func (b *BigIP) ModifyVirtualAddress(vaddr string, config *VirtualAddress) error { + return b.put(config, uriLtm, uriVirtualAddress, vaddr) } -// HashPersistenceProfiles returns a list of hash persist profiles -func (b *BigIP) HashPersistenceProfiles() (*HashPersistenceProfiles, error) { - var hashPersistenceProfiles HashPersistenceProfiles - err, _ := b.getForEntity(&hashPersistenceProfiles, uriLtm, uriPersistence, uriHash) - if err != nil { - return nil, err - } - - return &hashPersistenceProfiles, nil +func (b *BigIP) DeleteVirtualAddress(vaddr string) error { + return b.delete(uriLtm, uriVirtualAddress, vaddr) } -// GetHashPersistenceProfile gets a single hash persist profile by name -func (b *BigIP) GetHashPersistenceProfile(name string) (*HashPersistenceProfile, error) { - var hashPersistenceProfile HashPersistenceProfile - err, ok := b.getForEntity(&hashPersistenceProfile, uriLtm, uriPersistence, uriHash, name) - if err != nil { - return nil, err - } +// Monitors returns a list of all HTTP, HTTPS, Gateway ICMP, ICMP, and TCP monitors. +func (b *BigIP) Monitors() ([]Monitor, error) { + var monitors []Monitor + monitorUris := []string{"http", "https", "icmp", "gateway-icmp", "tcp", "tcp-half-open"} - if !ok { - return nil, nil + for _, name := range monitorUris { + var m Monitors + err, _ := b.getForEntity(&m, uriLtm, uriMonitor, name) + if err != nil { + return nil, err + } + for _, monitor := range m.Monitors { + monitors = append(monitors, monitor) + } } - return &hashPersistenceProfile, nil + return monitors, nil } -// CreateHashPersistenceProfile creates a new hash persist profile on the BIG-IP system. -func (b *BigIP) CreateHashPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, +// CreateMonitor adds a new monitor to the BIG-IP system. must be one of "http", "https", +// "icmp", "gateway icmp", or "tcp". +func (b *BigIP) CreateMonitor(name, parent, defaults_from string, interval, timeout int, send, receive, receive_disable string) error { + config := &Monitor{ + Name: name, + ParentMonitor: parent, + DefaultsFrom: defaults_from, + Interval: interval, + Timeout: timeout, + SendString: send, + ReceiveString: receive, + ReceiveDisable: receive_disable, } - return b.post(config, uriLtm, uriPersistence, uriHash) -} - -// AddHashPersistenceProfile adds a hash persist profile to the BIG-IP system -func (b *BigIP) AddHashPersistenceProfile(config *HashPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriHash) -} - -// DeleteHashPersistenceProfile removes a dest-addr persist profile. -func (b *BigIP) DeleteHashPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriHash, name) -} - -// ModifyHashPersistenceProfile allows you to change any attribute of a hash persist profile. -// Fields that can be modified are referenced in the HashPersistenceProfile struct. -func (b *BigIP) ModifyHashPersistenceProfile(name string, config *HashPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriHash, name) + return b.AddMonitor(config) } -// HostPersistenceProfiles returns a list of host persist profiles -func (b *BigIP) HostPersistenceProfiles() (*HostPersistenceProfiles, error) { - var hostPersistenceProfiles HostPersistenceProfiles - err, _ := b.getForEntity(&hostPersistenceProfiles, uriLtm, uriPersistence, uriHost) - if err != nil { - return nil, err +// Create a monitor by supplying a config +func (b *BigIP) AddMonitor(config *Monitor) error { + if strings.Contains(config.ParentMonitor, "gateway") { + config.ParentMonitor = "gateway_icmp" } - - return &hostPersistenceProfiles, nil + if strings.Contains(config.ParentMonitor, "tcp-half-open") { + config.ParentMonitor = "tcp-half-open" + } + log.Println( " value of config in create monitor ------------- %+v\n", *config, uriLtm, uriMonitor, config.ParentMonitor) + return b.post(config, uriLtm, uriMonitor, config.ParentMonitor) } -// GetHostPersistenceProfile gets a single host persist profile by name -func (b *BigIP) GetHostPersistenceProfile(name string) (*HostPersistenceProfile, error) { - var hostPersistenceProfile HostPersistenceProfile - err, ok := b.getForEntity(&hostPersistenceProfile, uriLtm, uriPersistence, uriHost, name) +// GetVirtualServer retrieves a monitor by name. Returns nil if the monitor does not exist +func (b *BigIP) GetMonitor(name string, parent string) (*Monitor, error) { + // Add a verification that type is an accepted monitor type + var monitor Monitor + err, ok := b.getForEntity(&monitor, uriLtm, uriMonitor, parent, name) if err != nil { return nil, err } - if !ok { return nil, nil } - return &hostPersistenceProfile, nil + return &monitor, nil } -// CreateHostPersistenceProfile creates a new host persist profile on the BIG-IP system. -func (b *BigIP) CreateHostPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriPersistence, uriHost) +// DeleteMonitor removes a monitor. +func (b *BigIP) DeleteMonitor(name, parent string) error { + log.Println( " in delete +++++++++++++++++ ", parent, name) + return b.delete(uriLtm, uriMonitor, parent, name) } -// AddHostPersistenceProfile adds a host persist profile to the BIG-IP system -func (b *BigIP) AddHostPersistenceProfile(config *HostPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriHost) -} +// ModifyMonitor allows you to change any attribute of a monitor. must be +// one of "http", "https", "icmp", "gateway icmp", or "tcp". Fields that +// can be modified are referenced in the Monitor struct. +func (b *BigIP) ModifyMonitor(name, parent string, config *Monitor) error { + if strings.Contains(config.ParentMonitor, "gateway") { + config.ParentMonitor = "gatewayIcmp" + } + if strings.Contains(config.ParentMonitor, "tcp-half-open") { + config.ParentMonitor = "tcp-half-open" + } -// DeleteHashHostPersistenceProfile removes a host persist profile. -func (b *BigIP) DeleteHashHostPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriHost, name) + return b.put(config, uriLtm, uriMonitor, parent, name) } -// ModifyHostPersistenceProfile allows you to change any attribute of a host persist profile. -// Fields that can be modified are referenced in the HostPersistenceProfile struct. -func (b *BigIP) ModifyHostPersistenceProfile(name string, config *HostPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriHost, name) +// AddMonitorToPool assigns the monitor, to the given . +func (b *BigIP) AddMonitorToPool(monitor, pool string) error { + config := &Pool{ + Monitor: monitor, + } + + return b.put(config, uriLtm, uriPool, pool) } -// MSRDPPersistenceProfiles returns a list of msrdp persist profiles -func (b *BigIP) MSRDPPersistenceProfiles() (*MSRDPPersistenceProfiles, error) { - var msrdpPersistenceProfiles MSRDPPersistenceProfiles - err, _ := b.getForEntity(&msrdpPersistenceProfiles, uriLtm, uriPersistence, uriMSRDP) +// IRules returns a list of irules +func (b *BigIP) IRules() (*IRules, error) { + var rules IRules + err, _ := b.getForEntity(&rules, uriLtm, uriIRule) if err != nil { return nil, err } - return &msrdpPersistenceProfiles, nil + return &rules, nil } -// GetMSRDPPersistenceProfile gets a single msrdp persist profile by name -func (b *BigIP) GetMSRDPPersistenceProfile(name string) (*MSRDPPersistenceProfile, error) { - var msrdpPersistenceProfile MSRDPPersistenceProfile - err, ok := b.getForEntity(&msrdpPersistenceProfile, uriLtm, uriPersistence, uriMSRDP, name) +// IRule returns information about the given iRule. +func (b *BigIP) IRule(name string) (*IRule, error) { + var rule IRule + err, ok := b.getForEntity(&rule, uriLtm, uriIRule, name) if err != nil { return nil, err } - if !ok { return nil, nil } - - return &msrdpPersistenceProfile, nil + return &rule, nil } -// CreateMSRDPPersistenceProfile creates a new msrdp persist profile on the BIG-IP system. -func (b *BigIP) CreateMSRDPPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, +// CreateIRule creates a new iRule on the system. +func (b *BigIP) CreateIRule(name, rule string) error { + irule := &IRule{ + Name: name, + Rule: rule, } - - return b.post(config, uriLtm, uriPersistence, uriMSRDP) -} - -// AddMSRDPPersistenceProfile adds a msrdp persist profile to the BIG-IP system -func (b *BigIP) AddMSRDPPersistenceProfile(config *MSRDPPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriMSRDP) + return b.post(irule, uriLtm, uriIRule) } -// DeleteMSRDPPersistenceProfile removes a msrdp persist profile. -func (b *BigIP) DeleteMSRDPPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriMSRDP, name) +// DeleteIRule removes an iRule from the system. +func (b *BigIP) DeleteIRule(name string) error { + return b.delete(uriLtm, uriIRule, name) } -// ModifyMSRDPPersistenceProfile allows you to change any attribute of a msrdp persist profile. -// Fields that can be modified are referenced in the MSRDPPersistenceProfile struct. -func (b *BigIP) ModifyMSRDPPersistenceProfile(name string, config *MSRDPPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriMSRDP, name) +// ModifyIRule updates the given iRule with any changed values. +func (b *BigIP) ModifyIRule(name string, irule *IRule) error { + irule.Name = name + return b.put(irule, uriLtm, uriIRule, name) } -// SIPPersistenceProfiles returns a list of sip persist profiles -func (b *BigIP) SIPPersistenceProfiles() (*SIPPersistenceProfiles, error) { - var sipPersistenceProfiles SIPPersistenceProfiles - err, _ := b.getForEntity(&sipPersistenceProfiles, uriLtm, uriPersistence, uriSIP) +func (b *BigIP) Policies() (*Policies, error) { + var p Policies + err, _ := b.getForEntity(&p, uriLtm, uriPolicy) if err != nil { return nil, err } - return &sipPersistenceProfiles, nil + return &p, nil } -// GetSIPPersistenceProfile gets a single sip persist profile by name -func (b *BigIP) GetSIPPersistenceProfile(name string) (*SIPPersistenceProfile, error) { - var sipPersistenceProfile SIPPersistenceProfile - err, ok := b.getForEntity(&sipPersistenceProfile, uriLtm, uriPersistence, uriSIP, name) +//Load a fully policy definition. Policies seem to be best dealt with as one big entity. +func (b *BigIP) GetPolicy(name string) (*Policy, error) { + var p Policy + values := []string{} + values = append(values, "Drafts/") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") + err, ok := b.getForEntity(&p, uriLtm, uriPolicy, result) if err != nil { return nil, err } - if !ok { return nil, nil } - return &sipPersistenceProfile, nil -} - -// CreateSIPPersistenceProfile creates a new sip persist profile on the BIG-IP system. -func (b *BigIP) CreateSIPPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, + var rules PolicyRules + err, _ = b.getForEntity(&rules, uriLtm, uriPolicy, name, "rules") + if err != nil { + return nil, err } + p.Rules = rules.Items - return b.post(config, uriLtm, uriPersistence, uriSIP) -} + for i, _ := range p.Rules { + var a PolicyRuleActions + var c PolicyRuleConditions -// AddSIPPersistenceProfile adds a sip persist profile to the BIG-IP system -func (b *BigIP) AddSIPPersistenceProfile(config *SIPPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriSIP) -} + err, _ = b.getForEntity(&a, uriLtm, uriPolicy, name, "rules", p.Rules[i].Name, "actions") + if err != nil { + return nil, err + } + err, _ = b.getForEntity(&c, uriLtm, uriPolicy, name, "rules", p.Rules[i].Name, "conditions") + if err != nil { + return nil, err + } + p.Rules[i].Actions = a.Items + p.Rules[i].Conditions = c.Items + } -// DeleteSIPPersistenceProfile removes a sip persist profile. -func (b *BigIP) DeleteSIPPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriSIP, name) + return &p, nil } -// ModifySIPPersistenceProfile allows you to change any attribute of a sip persist profile. -// Fields that can be modified are referenced in the SIPPersistenceProfile struct. -func (b *BigIP) ModifySIPPersistenceProfile(name string, config *SIPPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriSIP, name) +func normalizePolicy(p *Policy) { + //f5 doesn't seem to automatically handle setting the ordinal + for ri, _ := range p.Rules { + p.Rules[ri].Ordinal = ri + for ai, _ := range p.Rules[ri].Actions { + p.Rules[ri].Actions[ai].Name = fmt.Sprintf("%d", ai) + } + for ci, _ := range p.Rules[ri].Conditions { + p.Rules[ri].Conditions[ci].Name = fmt.Sprintf("%d", ci) + } + } } -// SourceAddrPersistenceProfiles returns a list of source-addr persist profiles -func (b *BigIP) SourceAddrPersistenceProfiles() (*SourceAddrPersistenceProfiles, error) { - var sourceAddrPersistenceProfiles SourceAddrPersistenceProfiles - err, _ := b.getForEntity(&sourceAddrPersistenceProfiles, uriLtm, uriPersistence, uriSourceAddr) - if err != nil { - return nil, err +//Create a new policy. It is not necessary to set the Ordinal fields on subcollections. +func (b *BigIP) CreatePolicy(p *Policy) error { + normalizePolicy(p) + return b.post(p, uriLtm, uriPolicy) +} + +func (b *BigIP) PublishPolicy(name, publish string) error { + config := &Policy{ + PublishCopy: publish, } + values := []string{} + values = append(values, "~Common~Drafts~") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") - return &sourceAddrPersistenceProfiles, nil + log.Println( " ================== here in publish ", result, publish) + + return b.patch(config, uriLtm, uriPolicy, result) } -// GetSourceAddrPersistenceProfile gets a single source-addr persist profile by name -func (b *BigIP) GetSourceAddrPersistenceProfile(name string) (*SourceAddrPersistenceProfile, error) { - var sourceAddrPersistenceProfile SourceAddrPersistenceProfile - err, ok := b.getForEntity(&sourceAddrPersistenceProfile, uriLtm, uriPersistence, uriSourceAddr, name) +//Update an existing policy. + func (b *BigIP) UpdatePolicy(name string, p *Policy) error { + normalizePolicy(p) + values := []string{} + values = append(values, "Drafts/") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") + return b.put(p, uriLtm, uriPolicy, result) +} + +//Delete a policy by name. +func (b *BigIP) DeletePolicy(name string) error { + values := []string{} + values = append(values, "Drafts/") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") +return b.delete(uriLtm, uriPolicy, result) +} + // Oneconnect profile creation +func (b *BigIP) CreateOneconnect(name, idleTimeoutOverride, partition, defaultsFrom, sharePools, sourceMask string, maxAge, maxReuse, maxSize int) error { + oneconnect := &Oneconnect{ + Name: name, + IdleTimeoutOverride: idleTimeoutOverride, + Partition: partition, + DefaultsFrom: defaultsFrom, + SharePools: sharePools, + SourceMask: sourceMask, + MaxAge: maxAge, + MaxReuse: maxReuse, + MaxSize: maxSize, + } + return b.post(oneconnect, uriLtm, uriProfile, uriOneconnect) +} + +func (b *BigIP) GetOneconnect(name string) (*Oneconnect, error) { + var oneconnect Oneconnect + err, ok := b.getForEntity(&oneconnect, uriLtm, uriProfile, uriOneconnect, name) if err != nil { return nil, err } - if !ok { return nil, nil } - return &sourceAddrPersistenceProfile, nil + return &oneconnect, nil } -// CreateSourceAddrPersistenceProfile creates a new source-addr persist profile on the BIG-IP system. -func (b *BigIP) CreateSourceAddrPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, - } - - return b.post(config, uriLtm, uriPersistence, uriSourceAddr) +// DeleteOneconnect removes an OneConnect profile from the system. +func (b *BigIP) DeleteOneconnect(name string) error { + return b.delete(uriLtm, uriProfile, uriOneconnect, name) } -// AddSourceAddrPersistenceProfile adds a source-addr persist profile to the BIG-IP system -func (b *BigIP) AddSourceAddrPersistenceProfile(config *SourceAddrPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriSourceAddr) +// ModifyOneconnect updates the given Oneconnect profile with any changed values. +func (b *BigIP) ModifyOneconnect(name string, oneconnect *Oneconnect) error { + oneconnect.Name = name + return b.put(oneconnect, uriLtm, uriProfile, uriOneconnect, name) } -// DeleteSourceAddrPersistenceProfile removes a source-addr persist profile. -func (b *BigIP) DeleteSourceAddrPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriSourceAddr, name) -} +// Create TCP profile for WAN or LAN -// ModifySourceAddrPersistenceProfile allows you to change any attribute of a source-addr persist profile. -// Fields that can be modified are referenced in the SourceAddrPersistenceProfile struct. -func (b *BigIP) ModifySourceAddrPersistenceProfile(name string, config *SourceAddrPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriSourceAddr, name) +func (b *BigIP) CreateTcp(name, partition, defaultsFrom string, idleTimeout, closeWaitTimeout, finWait_2Timeout, finWaitTimeout, keepAliveInterval int, deferredAccept, fastOpen string) error { + tcp := &Tcp{ + Name: name, + Partition: partition, + DefaultsFrom: defaultsFrom, + IdleTimeout: idleTimeout, + CloseWaitTimeout: closeWaitTimeout, + FinWait_2Timeout: finWait_2Timeout, + FinWaitTimeout: finWaitTimeout, + KeepAliveInterval: keepAliveInterval, + DeferredAccept: deferredAccept, + FastOpen: fastOpen, + } + return b.post(tcp, uriLtm, uriProfile, uriTcp) } -// SSLPersistenceProfiles returns a list of ssl persist profiles -func (b *BigIP) SSLPersistenceProfiles() (*SSLPersistenceProfiles, error) { - var sslPersistenceProfiles SSLPersistenceProfiles - err, _ := b.getForEntity(&sslPersistenceProfiles, uriLtm, uriPersistence, uriSSL) - if err != nil { - return nil, err - } +// DeleteOneconnect removes an OneConnect profile from the system. +func (b *BigIP) DeleteTcp(name string) error { + return b.delete(uriLtm, uriProfile, uriTcp, name) +} - return &sslPersistenceProfiles, nil +// ModifyTcp updates the given Oneconnect profile with any changed values. +func (b *BigIP) ModifyTcp(name string, tcp *Tcp) error { + tcp.Name = name + return b.put(tcp, uriLtm, uriProfile, uriTcp, name) } -// GetSSLPersistenceProfile gets a single ssl persist profile by name -func (b *BigIP) GetSSLPersistenceProfile(name string) (*SSLPersistenceProfile, error) { - var sslPersistenceProfile SSLPersistenceProfile - err, ok := b.getForEntity(&sslPersistenceProfile, uriLtm, uriPersistence, uriSSL, name) +func (b *BigIP) GetTcp(name string) (*Tcp, error) { + var tcp Tcp + err, ok := b.getForEntity(&tcp, uriLtm, uriProfile, uriTcp, name) if err != nil { return nil, err } - if !ok { return nil, nil } - return &sslPersistenceProfile, nil + return &tcp, nil } -// CreateSSLPersistenceProfile creates a new ssl persist profile on the BIG-IP system. -func (b *BigIP) CreateSSLPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ - Name: name, - DefaultsFrom: parent, +func (b *BigIP) CreateFasthttp(name, defaultsFrom string, idleTimeout, connpoolIdleTimeoutOverride, connpoolMaxReuse, connpoolMaxSize, connpoolMinSize int, connpoolReplenish string, connpoolStep int, forceHttp_10Response string, maxHeaderSize int) error { + fasthttp := &Fasthttp{ + Name: name, + DefaultsFrom: defaultsFrom, + IdleTimeout: idleTimeout, + ConnpoolIdleTimeoutOverride: connpoolIdleTimeoutOverride, + ConnpoolMaxReuse: connpoolMaxReuse, + ConnpoolMaxSize: connpoolMaxSize, + ConnpoolMinSize: connpoolMinSize, + ConnpoolReplenish: connpoolReplenish, + ConnpoolStep: connpoolStep, + ForceHttp_10Response: forceHttp_10Response, + MaxHeaderSize: maxHeaderSize, } - - return b.post(config, uriLtm, uriPersistence, uriSSL) + return b.post(fasthttp, uriLtm, uriProfile, uriFasthttp) } -// AddSSLPersistenceProfile adds a ssl persist profile to the BIG-IP system -func (b *BigIP) AddSSLPersistenceProfile(config *SSLPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriSSL) +// Delete Fast http removes an Fasthttp profile from the system. +func (b *BigIP) DeleteFasthttp(name string) error { + return b.delete(uriLtm, uriProfile, uriFasthttp, name) } -// DeleteSSLPersistenceProfile removes a ssl persist profile. -func (b *BigIP) DeleteSSLPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriSSL, name) +// ModifyFasthttp updates the given Fasthttp profile with any changed values. +func (b *BigIP) ModifyFasthttp(name string, fasthttp *Fasthttp) error { + fasthttp.Name = name + return b.put(fasthttp, uriLtm, uriProfile, uriFasthttp, name) } -// ModifySSLPersistenceProfile allows you to change any attribute of a ssl persist profile. -// Fields that can be modified are referenced in the SSLPersistenceProfile struct. -func (b *BigIP) ModifySSLPersistenceProfile(name string, config *SSLPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriSSL, name) -} +func (b *BigIP) GetFasthttp(name string) (*Fasthttp, error) { + var fasthttp Fasthttp + err, _ := b.getForEntity(&fasthttp, uriLtm, uriProfile, uriFasthttp) -// UniversalPersistenceProfiles returns a list of universal persist profiles -func (b *BigIP) UniversalPersistenceProfiles() (*UniversalPersistenceProfiles, error) { - var universalPersistenceProfiles UniversalPersistenceProfiles - err, _ := b.getForEntity(&universalPersistenceProfiles, uriLtm, uriPersistence, uriUniversal) if err != nil { return nil, err } - return &universalPersistenceProfiles, nil + return &fasthttp, nil } -// GetUniversalPersistenceProfile gets a single universal persist profile by name -func (b *BigIP) GetUniversalPersistenceProfile(name string) (*UniversalPersistenceProfile, error) { - var universalPersistenceProfile UniversalPersistenceProfile - err, ok := b.getForEntity(&universalPersistenceProfile, uriLtm, uriPersistence, uriUniversal, name) +func (b *BigIP) CreateFastl4(name, partition, defaultsFrom string, clientTimeout int, explicitFlowMigration, hardwareSynCookie string, idleTimeout string, ipTosToClient, ipTosToServer, keepAliveInterval string) error { + fastl4 := &Fastl4{ + Name: name, + Partition: partition, + DefaultsFrom: defaultsFrom, + ClientTimeout: clientTimeout, + ExplicitFlowMigration: explicitFlowMigration, + HardwareSynCookie: hardwareSynCookie, + IdleTimeout: idleTimeout, + IpTosToClient: ipTosToClient, + IpTosToServer: ipTosToServer, + KeepAliveInterval: keepAliveInterval, + } + return b.post(fastl4, uriLtm, uriProfile, uriFastl4) +} + +// Delete Fast http removes an Fasthttp profile from the system. +func (b *BigIP) DeleteFastl4(name string) error { + return b.delete(uriLtm, uriProfile, uriFastl4, name) +} + +// ModifyFastl4 updates the given Fastl4 profile with any changed values. +func (b *BigIP) ModifyFastl4(name string, fastl4 *Fastl4) error { + fastl4.Name = name + return b.put(fastl4, uriLtm, uriProfile, uriFastl4, name) +} + +func (b *BigIP) GetFastl4(name string) (*Fastl4, error) { + var fastl4 Fastl4 + err, ok := b.getForEntity(&fastl4, uriLtm, uriProfile, uriFastl4, name) if err != nil { return nil, err } - if !ok { return nil, nil } - return &universalPersistenceProfile, nil + return &fastl4, nil } -// CreateUniversalPersistenceProfile creates a new universal persist profile on the BIG-IP system. -func (b *BigIP) CreateUniversalPersistenceProfile(name string, parent string) error { - config := &PersistenceProfile{ +// =============== + +func (b *BigIP) CreateHttpcompress(name, defaultsFrom string, uriExclude, uriInclude []string) error { + httpcompress := &Httpcompress{ Name: name, - DefaultsFrom: parent, + DefaultsFrom: defaultsFrom, + UriExclude: uriExclude, + UriInclude: uriInclude, } - - return b.post(config, uriLtm, uriPersistence, uriUniversal) + return b.post(httpcompress, uriLtm, uriProfile, uriHttpcompress) } -// AddUniversalPersistenceProfile adds a universal persist profile to the BIG-IP system -func (b *BigIP) AddUniversalPersistenceProfile(config *UniversalPersistenceProfile) error { - return b.post(config, uriLtm, uriPersistence, uriUniversal) +// Delete Fast http removes an Fasthttp profile from the system. +func (b *BigIP) DeleteHttpcompress(name string) error { + return b.delete(uriLtm, uriProfile, uriHttpcompress, name) } -// DeleteUniversalPersistenceProfile removes a universal persist profile. -func (b *BigIP) DeleteUniversalPersistenceProfile(name string) error { - return b.delete(uriLtm, uriPersistence, uriUniversal, name) -} - -// ModifyUniversalPersistenceProfile allows you to change any attribute of a universal persist profile. -// Fields that can be modified are referenced in the UniversalPersistenceProfile struct. -func (b *BigIP) ModifyUniversalPersistenceProfile(name string, config *UniversalPersistenceProfile) error { - return b.put(config, uriLtm, uriPersistence, uriUniversal, name) +// ModifyFastl4 updates the given Fastl4 profile with any changed values. +func (b *BigIP) ModifyHttpcompress(name string, httpcompress *Httpcompress) error { + httpcompress.Name = name + return b.put(httpcompress, uriLtm, uriProfile, uriHttpcompress, name) } -// Nodes returns a list of nodes. -func (b *BigIP) Nodes() (*Nodes, error) { - var nodes Nodes - err, _ := b.getForEntity(&nodes, uriLtm, uriNode) +func (b *BigIP) GetHttpcompress(name string) (*Httpcompress, error) { + var httpcompress Httpcompress + err, ok := b.getForEntity(&httpcompress, uriLtm, uriProfile, uriHttpcompress, name) if err != nil { return nil, err } + if !ok { + return nil, nil + } - return &nodes, nil + return &httpcompress, nil } -// CreateNode adds a new IP based node to the BIG-IP system. -func (b *BigIP) CreateNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state string) error { - config := &Node{ - Name: name, - Address: address, - RateLimit: rate_limit, - ConnectionLimit: connection_limit, - DynamicRatio: dynamic_ratio, - Monitor: monitor, - State: state, +func (b *BigIP) CreateHttp2(name, defaultsFrom string, concurrentStreamsPerConnection, connectionIdleTimeout, headerTableSize int, activationModes []string) error { + http2 := &Http2{ + Name: name, + DefaultsFrom: defaultsFrom, + ConcurrentStreamsPerConnection: concurrentStreamsPerConnection, + ConnectionIdleTimeout: connectionIdleTimeout, + HeaderTableSize: headerTableSize, + ActivationModes: activationModes, } - - return b.post(config, uriLtm, uriNode) + return b.post(http2, uriLtm, uriProfile, uriHttp2) } -// CreateFQDNNode adds a new FQDN based node to the BIG-IP system. -func (b *BigIP) CreateFQDNNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state string) error { - config := &Node{ - Name: name, - RateLimit: rate_limit, - ConnectionLimit: connection_limit, - DynamicRatio: dynamic_ratio, - Monitor: monitor, - State: state, - } - config.FQDN.Name = address +// Delete http2 removes an http2 profile from the system. +func (b *BigIP) DeleteHttp2(name string) error { + return b.delete(uriLtm, uriProfile, uriHttp2, name) +} - return b.post(config, uriLtm, uriNode) +// Modify http2 updates the given http2 profile with any changed values. +func (b *BigIP) ModifyHttp2(name string, http2 *Http2) error { + http2.Name = name + return b.put(http2, uriLtm, uriProfile, uriHttp2, name) } -// Get a Node by name. Returns nil if the node does not exist -func (b *BigIP) GetNode(name string) (*Node, error) { - var node Node - err, ok := b.getForEntity(&node, uriLtm, uriNode, name) +func (b *BigIP) GetHttp2(name string) (*Http2, error) { + var http2 Http2 + err, ok := b.getForEntity(&http2, uriLtm, uriProfile, uriHttp2, name) if err != nil { return nil, err } @@ -2655,993 +2559,622 @@ func (b *BigIP) GetNode(name string) (*Node, error) { return nil, nil } - return &node, nil + return &http2, nil } -// DeleteNode removes a node. -func (b *BigIP) DeleteNode(name string) error { - return b.delete(uriLtm, uriNode, name) -} +// Datagroups returns a list of datagroups. +func (b *BigIP) Datagroups(name string) (*Datagroups, error) { + var datagroups Datagroups + err, _ := b.getForEntity(&datagroups, uriLtm, uriDatagroup, uriInternal, name) -// ModifyNode allows you to change any attribute of a node. Fields that -// can be modified are referenced in the Node struct. -func (b *BigIP) ModifyNode(name string, config *Node) error { - return b.put(config, uriLtm, uriNode, name) -} + if err != nil { + return nil, err + } -// NodeStatus changes the status of a node. can be either -// "enable" or "disable". -func (b *BigIP) NodeStatus(name, state string) error { - config := &Node{} + return &datagroups, nil +} - switch state { - case "enable": - // config.State = "unchecked" - config.Session = "user-enabled" - case "disable": - // config.State = "unchecked" - config.Session = "user-disabled" - // case "offline": - // config.State = "user-down" - // config.Session = "user-disabled" +// CreateDatagroup adds a new Datagroup to the BIG-IP system. +func (b *BigIP) CreateDatagroup(typo, name string, records []Records) error { + //func (b *BigIP) CreateDatagroup(typo, name string) error { + config := &Datagroup{ + Type: typo, + Name: name, + Records: records, } - return b.put(config, uriLtm, uriNode, name) + return b.post(config, uriLtm, uriDatagroup, uriInternal) } +func (b *BigIP) Records() (*Records, error) { + var records Records + err, _ := b.getForEntity(&records, uriLtm, uriDatagroup, uriInternal) -// InternalDataGroups returns a list of internal data groups. -func (b *BigIP) InternalDataGroups() (*DataGroups, error) { - var dataGroups DataGroups - err, _ := b.getForEntity(&dataGroups, uriLtm, uriDatagroup, uriInternal) if err != nil { return nil, err } - return &dataGroups, nil + return &records, nil } +func (b *BigIP) DeleteDatagroup(name string) error { -func (b *BigIP) GetInternalDataGroup(name string) (*DataGroup, error) { - var dataGroup DataGroup - err, ok := b.getForEntity(&dataGroup, uriLtm, uriDatagroup, uriInternal, name) + return b.delete(uriLtm, uriDatagroup, uriInternal, name) +} + +func (b *BigIP) AddRecords(name, rname, data string) error { + config := &Records{} + + config.Name = rname + config.Data = data + + return b.post(config, uriLtm, uriDatagroup, uriInternal, "records") +} + +// Snats returns a list of snat +/*func (b *BigIP) Snats(name string) (*Snats, error) { + var snats Snats + err, _ := b.getForEntity(&snats, uriLtm, uriSnat, name) if err != nil { return nil, err } - if !ok { - return nil, nil + return &snats, nil +}*/ + +/*func (b *BigIP) CreateSnat(name, partition, autoLastHop, sourcePort, translation, snatpool, mirror string, vlansDisabled bool, origins []string) error { + snat := &Snat{ + Name: name, + Partition: partition, + AutoLasthop: autoLastHop, + SourcePort: sourcePort, + Translation: translation, + Snatpool: snatpool, + Mirror: mirror, + VlansDisabled: vlansDisabled, + Origins: origins, } + log.Println("[INFO] Creating snat ", snat) + return b.post(snat, uriLtm, uriSnat) +} */ +func (b *BigIP) CreateSnat(p *Snat) error { + log.Println(" what is the complete payload ", p) + return b.post(p, uriLtm, uriSnat) +} - return &dataGroup, nil +func (b *BigIP) ModifySnat(config *Snat) error { + return b.patch(config, uriLtm, uriSnat) } -// Create an internal data group; dataype must bee one of "ip", "string", or "integer" -func (b *BigIP) CreateInternalDataGroup(name string, datatype string) error { - config := &DataGroup{ - Name: name, - Type: datatype, +// Get a Snat list by name. Returns nil if the node does not exist +func (b *BigIP) GetSnat(name string) (*Snat, error) { + var snat Snat + err, ok := b.getForEntity(&snat, uriLtm, uriSnat, name) + if err != nil { + return nil, err + } + if !ok { + return nil, nil } - return b.post(config, uriLtm, uriDatagroup, uriInternal) + return &snat, nil } -func (b *BigIP) AddInternalDataGroup(config *DataGroup) error { - return b.post(config, uriLtm, uriDatagroup, uriInternal) +func (b *BigIP) DeleteSnat(name string) error { + return b.delete(uriLtm, uriSnat, name) } -func (b *BigIP) DeleteInternalDataGroup(name string) error { - return b.delete(uriLtm, uriDatagroup, uriInternal, name) +func (b *BigIP) UpdateSnat(name string, p *Snat) error { + return b.put(p, uriLtm, uriSnat, name) } -// Modify a named internal data group, REPLACING all the records -func (b *BigIP) ModifyInternalDataGroupRecords(name string, records *[]DataGroupRecord) error { - config := &DataGroup{ - Records: *records, - } - return b.put(config, uriLtm, uriDatagroup, uriInternal, name) -} +// Snats returns a list of snat +func (b *BigIP) Snatpools(name string) (*Snatpools, error) { + var snatpools Snatpools + err, _ := b.getForEntity(&snatpools, uriLtm, uriSnatpool, name) -// Get the internal data group records for a named internal data group -func (b *BigIP) GetInternalDataGroupRecords(name string) (*[]DataGroupRecord, error) { - var dataGroup DataGroup - err, _ := b.getForEntity(&dataGroup, uriLtm, uriDatagroup, uriInternal, name) if err != nil { return nil, err } - return &dataGroup.Records, nil + return &snatpools, nil } -// Pools returns a list of pools. -func (b *BigIP) Pools() (*Pools, error) { - var pools Pools - err, _ := b.getForEntity(&pools, uriLtm, uriPool) - if err != nil { - return nil, err +func (b *BigIP) CreateSnatpool(name, partition string, members []string) error { + snatpool := &Snatpool{ + Name: name, + Partition: partition, + Members: members, } + log.Println("[INFO] Creating snatpool ", snatpool) + return b.post(snatpool, uriLtm, uriSnatpool) +} - return &pools, nil +func (b *BigIP) ModifySnatpool(config *Snatpool) error { + return b.put(config, uriLtm, uriSnatpool) } -// PoolMembers returns a list of pool members for the given pool. -func (b *BigIP) PoolMembers(name string) (*PoolMembers, error) { - var poolMembers PoolMembers - err, _ := b.getForEntity(&poolMembers, uriLtm, uriPool, name, uriPoolMember) +// Get a Snat list by name. Returns nil if the node does not exist +func (b *BigIP) GetSnatpool(name string) (*Snatpool, error) { + var snatpool Snatpool + err, ok := b.getForEntity(&snatpool, uriLtm, uriSnatpool, name) if err != nil { return nil, err } + if !ok { + return nil, nil + } - return &poolMembers, nil + return &snatpool, nil } -// AddPoolMember adds a node/member to the given pool. must be in the form -// of :, i.e.: "web-server1:443". -func (b *BigIP) AddPoolMember(pool, member string) error { - config := &poolMember{ - Name: member, +func (b *BigIP) DeleteSnatpool(name string) error { + return b.delete(uriLtm, uriSnatpool, name) +} + +// CookiePersistenceProfiles returns a list of cookie persist profiles +func (b *BigIP) CookiePersistenceProfiles() (*CookiePersistenceProfiles, error) { + var cookiePersistenceProfiles CookiePersistenceProfiles + err, _ := b.getForEntity(&cookiePersistenceProfiles, uriLtm, uriPersistence, uriCookie) + if err != nil { + return nil, err } - return b.post(config, uriLtm, uriPool, pool, uriPoolMember) + return &cookiePersistenceProfiles, nil } -// GetPoolMember returns the details of a member in the specified pool. -func (b *BigIP) GetPoolMember(pool string, member string) (*PoolMember, error) { - var poolMember PoolMember - err, ok := b.getForEntity(&poolMember, uriLtm, uriPool, pool, uriPoolMember, member) - +// GetCookiePersistenceProfile gets a single cookie persist profile by name +func (b *BigIP) GetCookiePersistenceProfile(name string) (*CookiePersistenceProfile, error) { + var cookiePersistenceProfile CookiePersistenceProfile + err, ok := b.getForEntity(&cookiePersistenceProfile, uriLtm, uriPersistence, uriCookie, name) if err != nil { return nil, err } + if !ok { return nil, nil } - return &poolMember, nil + return &cookiePersistenceProfile, nil } -// CreatePoolMember creates a pool member for the specified pool. -func (b *BigIP) CreatePoolMember(pool string, config *PoolMember) error { - return b.post(config, uriLtm, uriPool, pool, uriPoolMember) -} - -// ModifyPoolMember will update the configuration of a particular pool member. -func (b *BigIP) ModifyPoolMember(pool string, config *PoolMember) error { - member := config.FullPath - // These fields are not used when modifying a pool member; so omit them. - config.Name = "" - config.Partition = "" - config.FullPath = "" - - // This cannot be modified for an existing pool member. - config.Address = "" - - return b.put(config, uriLtm, uriPool, pool, uriPoolMember, member) -} - -// UpdatePoolMembers does a replace-all-with for the members of a pool. -func (b *BigIP) UpdatePoolMembers(pool string, pm *[]PoolMember) error { - config := &poolMembers{ - Members: *pm, +// CreateCookiePersistenceProfile creates a new cookie persist profile on the BIG-IP system. +func (b *BigIP) CreateCookiePersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, } - return b.put(config, uriLtm, uriPool, pool) -} -// RemovePoolMember removes a pool member from the specified pool. -func (b *BigIP) RemovePoolMember(pool string, config *PoolMember) error { - member := config.FullPath - return b.delete(uriLtm, uriPool, pool, uriPoolMember, member) + return b.post(config, uriLtm, uriPersistence, uriCookie) } -// DeletePoolMember removes a member from the given pool. must be in the form -// of :, i.e.: "web-server1:443". -func (b *BigIP) DeletePoolMember(pool string, member string) error { - return b.delete(uriLtm, uriPool, pool, uriPoolMember, member) +// AddCookiePersistenceProfile adds a cookie persist profile to the BIG-IP system +func (b *BigIP) AddCookiePersistenceProfile(config *CookiePersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriCookie) } -// PoolMemberStatus changes the status of a pool member. can be either -// "enable" or "disable". must be in the form of :, -// i.e.: "web-server1:443". -func (b *BigIP) PoolMemberStatus(pool string, member string, state string) error { - config := &Node{} - - switch state { - case "enable": - // config.State = "unchecked" - config.Session = "user-enabled" - case "disable": - // config.State = "unchecked" - config.Session = "user-disabled" - // case "offline": - // config.State = "user-down" - // config.Session = "user-disabled" - } +// DeleteCookiePersistenceProfile removes a cookie persist profile. +func (b *BigIP) DeleteCookiePersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriCookie, name) +} - return b.put(config, uriLtm, uriPool, pool, uriPoolMember, member) +// ModifyCookiePersistenceProfile allows you to change any attribute of a cookie persist profile. +// Fields that can be modified are referenced in the CookiePersistenceProfile struct. +func (b *BigIP) ModifyCookiePersistenceProfile(name string, config *CookiePersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriCookie, name) } -// CreatePool adds a new pool to the BIG-IP system by name. -func (b *BigIP) CreatePool(name string) error { - config := &Pool{ - Name: name, +// DestAddrPersistenceProfiles returns a list of dest-addr persist profiles +func (b *BigIP) DestAddrPersistenceProfiles() (*DestAddrPersistenceProfiles, error) { + var destAddrPersistenceProfiles DestAddrPersistenceProfiles + err, _ := b.getForEntity(&destAddrPersistenceProfiles, uriLtm, uriPersistence, uriDestAddr) + if err != nil { + return nil, err } - return b.post(config, uriLtm, uriPool) -} - -// AddPool creates a new pool on the BIG-IP system. -func (b *BigIP) AddPool(config *Pool) error { - return b.post(config, uriLtm, uriPool) + return &destAddrPersistenceProfiles, nil } -// Get a Pool by name. Returns nil if the Pool does not exist -func (b *BigIP) GetPool(name string) (*Pool, error) { - var pool Pool - err, ok := b.getForEntity(&pool, uriLtm, uriPool, name) +// GetDestAddrPersistenceProfile gets a single dest-addr persist profile by name +func (b *BigIP) GetDestAddrPersistenceProfile(name string) (*DestAddrPersistenceProfile, error) { + var destAddrPersistenceProfile DestAddrPersistenceProfile + err, ok := b.getForEntity(&destAddrPersistenceProfile, uriLtm, uriPersistence, uriDestAddr, name) if err != nil { return nil, err } + if !ok { return nil, nil } - return &pool, nil + return &destAddrPersistenceProfile, nil } -// DeletePool removes a pool. -func (b *BigIP) DeletePool(name string) error { - return b.delete(uriLtm, uriPool, name) -} +// CreateDestAddrPersistenceProfile creates a new dest-addr persist profile on the BIG-IP system. +func (b *BigIP) CreateDestAddrPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } -// ModifyPool allows you to change any attribute of a pool. Fields that -// can be modified are referenced in the Pool struct. -func (b *BigIP) ModifyPool(name string, config *Pool) error { - return b.put(config, uriLtm, uriPool, name) + return b.post(config, uriLtm, uriPersistence, uriDestAddr) } -// VirtualServers returns a list of virtual servers. -func (b *BigIP) VirtualServers() (*VirtualServers, error) { - var vs VirtualServers - err, _ := b.getForEntity(&vs, uriLtm, uriVirtual) - if err != nil { - return nil, err - } - - return &vs, nil +// AddDestAddrPersistenceProfile adds a dest-addr persist profile to the BIG-IP system +func (b *BigIP) AddDestAddrPersistenceProfile(config *DestAddrPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriDestAddr) } -// CreateVirtualServer adds a new virtual server to the BIG-IP system. can either be -// in CIDR notation or decimal, i.e.: "24" or "255.255.255.0". A CIDR mask of "0" is the same -// as "0.0.0.0". -func (b *BigIP) CreateVirtualServer(name, destination, mask, pool string, vlans_enabled, vlans_disabled bool, port int, translate_address, translate_port string) error { - subnetMask := cidr[mask] +// DeleteDestAddrPersistenceProfile removes a dest-addr persist profile. +func (b *BigIP) DeleteDestAddrPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriDestAddr, name) +} - if strings.Contains(mask, ".") { - subnetMask = mask - } +// ModifyDestAddrPersistenceProfile allows you to change any attribute of a dest-addr persist profile. +// Fields that can be modified are referenced in the DestAddrPersistenceProfile struct. +func (b *BigIP) ModifyDestAddrPersistenceProfile(name string, config *DestAddrPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriDestAddr, name) +} - config := &VirtualServer{ - Name: name, - Destination: fmt.Sprintf("%s:%d", destination, port), - Mask: subnetMask, - Pool: pool, - TranslateAddress: translate_address, - TranslatePort: translate_port, +// HashPersistenceProfiles returns a list of hash persist profiles +func (b *BigIP) HashPersistenceProfiles() (*HashPersistenceProfiles, error) { + var hashPersistenceProfiles HashPersistenceProfiles + err, _ := b.getForEntity(&hashPersistenceProfiles, uriLtm, uriPersistence, uriHash) + if err != nil { + return nil, err } - return b.post(config, uriLtm, uriVirtual) -} - -// AddVirtualServer adds a new virtual server by config to the BIG-IP system. -func (b *BigIP) AddVirtualServer(config *VirtualServer) error { - return b.post(config, uriLtm, uriVirtual) + return &hashPersistenceProfiles, nil } -// GetVirtualServer retrieves a virtual server by name. Returns nil if the virtual server does not exist -func (b *BigIP) GetVirtualServer(name string) (*VirtualServer, error) { - var vs VirtualServer - err, ok := b.getForEntity(&vs, uriLtm, uriVirtual, name) +// GetHashPersistenceProfile gets a single hash persist profile by name +func (b *BigIP) GetHashPersistenceProfile(name string) (*HashPersistenceProfile, error) { + var hashPersistenceProfile HashPersistenceProfile + err, ok := b.getForEntity(&hashPersistenceProfile, uriLtm, uriPersistence, uriHash, name) if err != nil { return nil, err } + if !ok { return nil, nil } - profiles, err := b.VirtualServerProfiles(name) - if err != nil { - return nil, err - } - vs.Profiles = profiles.Profiles + return &hashPersistenceProfile, nil +} - policy_names, err := b.VirtualServerPolicyNames(name) - if err != nil { - return nil, err +// CreateHashPersistenceProfile creates a new hash persist profile on the BIG-IP system. +func (b *BigIP) CreateHashPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, } - vs.Policies = policy_names - return &vs, nil + return b.post(config, uriLtm, uriPersistence, uriHash) } -// DeleteVirtualServer removes a virtual server. -func (b *BigIP) DeleteVirtualServer(name string) error { - return b.delete(uriLtm, uriVirtual, name) +// AddHashPersistenceProfile adds a hash persist profile to the BIG-IP system +func (b *BigIP) AddHashPersistenceProfile(config *HashPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriHash) } -// ModifyVirtualServer allows you to change any attribute of a virtual server. Fields that -// can be modified are referenced in the VirtualServer struct. -func (b *BigIP) ModifyVirtualServer(name string, config *VirtualServer) error { - return b.put(config, uriLtm, uriVirtual, name) +// DeleteHashPersistenceProfile removes a dest-addr persist profile. +func (b *BigIP) DeleteHashPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriHash, name) } -// VirtualServerProfiles gets the profiles currently associated with a virtual server. -func (b *BigIP) VirtualServerProfiles(vs string) (*Profiles, error) { - var p Profiles - err, ok := b.getForEntity(&p, uriLtm, uriVirtual, vs, "profiles") +// ModifyHashPersistenceProfile allows you to change any attribute of a hash persist profile. +// Fields that can be modified are referenced in the HashPersistenceProfile struct. +func (b *BigIP) ModifyHashPersistenceProfile(name string, config *HashPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriHash, name) +} + +// HostPersistenceProfiles returns a list of host persist profiles +func (b *BigIP) HostPersistenceProfiles() (*HostPersistenceProfiles, error) { + var hostPersistenceProfiles HostPersistenceProfiles + err, _ := b.getForEntity(&hostPersistenceProfiles, uriLtm, uriPersistence, uriHost) if err != nil { return nil, err } - if !ok { - return nil, nil - } - return &p, nil + return &hostPersistenceProfiles, nil } -//Get the names of policies associated with a particular virtual server -func (b *BigIP) VirtualServerPolicyNames(vs string) ([]string, error) { - var policies VirtualServerPolicies - err, _ := b.getForEntity(&policies, uriLtm, uriVirtual, vs, "policies") +// GetHostPersistenceProfile gets a single host persist profile by name +func (b *BigIP) GetHostPersistenceProfile(name string) (*HostPersistenceProfile, error) { + var hostPersistenceProfile HostPersistenceProfile + err, ok := b.getForEntity(&hostPersistenceProfile, uriLtm, uriPersistence, uriHost, name) if err != nil { return nil, err } - retval := make([]string, 0, len(policies.PolicyRef.Policies)) - for _, p := range policies.PolicyRef.Policies { - retval = append(retval, p.FullPath) + + if !ok { + return nil, nil } - return retval, nil + + return &hostPersistenceProfile, nil } -// VirtualAddresses returns a list of virtual addresses. -func (b *BigIP) VirtualAddresses() (*VirtualAddresses, error) { - var va VirtualAddresses - err, _ := b.getForEntity(&va, uriLtm, uriVirtualAddress) - if err != nil { - return nil, err +// CreateHostPersistenceProfile creates a new host persist profile on the BIG-IP system. +func (b *BigIP) CreateHostPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, } - return &va, nil + + return b.post(config, uriLtm, uriPersistence, uriHost) } -func (b *BigIP) CreateVirtualAddress(vaddr string, config *VirtualAddress) error { - config.Name = vaddr - return b.post(config, uriLtm, uriVirtualAddress) +// AddHostPersistenceProfile adds a host persist profile to the BIG-IP system +func (b *BigIP) AddHostPersistenceProfile(config *HostPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriHost) } -// VirtualAddressStatus changes the status of a virtual address. can be either -// "enable" or "disable". -func (b *BigIP) VirtualAddressStatus(vaddr, state string) error { - config := &VirtualAddress{} - config.Enabled = (state == ENABLED) - return b.put(config, uriLtm, uriVirtualAddress, vaddr) -} - -// ModifyVirtualAddress allows you to change any attribute of a virtual address. Fields that -// can be modified are referenced in the VirtualAddress struct. -func (b *BigIP) ModifyVirtualAddress(vaddr string, config *VirtualAddress) error { - return b.put(config, uriLtm, uriVirtualAddress, vaddr) -} - -func (b *BigIP) DeleteVirtualAddress(vaddr string) error { - return b.delete(uriLtm, uriVirtualAddress, vaddr) -} - -// Monitors returns a list of all HTTP, HTTPS, Gateway ICMP, ICMP, and Tcp monitors. -func (b *BigIP) Monitors() ([]Monitor, error) { - var monitors []Monitor - monitorUris := []string{ - "gateway-icmp", - "http", - "https", - "icmp", - "inband", - "mysql", - "postgresql", - "tcp", - "udp", - } - - for _, name := range monitorUris { - var m Monitors - err, _ := b.getForEntity(&m, uriLtm, uriMonitor, name) - if err != nil { - return nil, err - } - for _, monitor := range m.Monitors { - monitor.MonitorType = name - monitors = append(monitors, monitor) - } - } - - return monitors, nil -} - -// CreateMonitor adds a new monitor to the BIG-IP system. must be one of "http", "https", -// "icmp", "gateway icmp", "inband", "postgresql", "mysql", "udp" or "tcp". -func (b *BigIP) CreateMonitor(name, parent string, interval, timeout int, send, receive, monitorType string) error { - config := &Monitor{ - Name: name, - ParentMonitor: parent, - Interval: interval, - Timeout: timeout, - SendString: send, - ReceiveString: receive, - } - - return b.AddMonitor(config, monitorType) -} - -// Create a monitor by supplying a config -func (b *BigIP) AddMonitor(config *Monitor, monitorType string) error { - if strings.Contains(config.ParentMonitor, "gateway") { - config.ParentMonitor = "gateway_icmp" - } - - return b.post(config, uriLtm, uriMonitor, monitorType) -} - -// GetVirtualServer retrieves a monitor by name. Returns nil if the monitor does not exist -func (b *BigIP) GetMonitor(name string, parent string) (*Monitor, error) { - // Add a verification that type is an accepted monitor type - var monitor Monitor - err, ok := b.getForEntity(&monitor, uriLtm, uriMonitor, parent, name) - if err != nil { - return nil, err - } - if !ok { - return nil, nil - } - - return &monitor, nil -} - -// DeleteMonitor removes a monitor. -func (b *BigIP) DeleteMonitor(name, parent string) error { - return b.delete(uriLtm, uriMonitor, parent, name) -} - -// ModifyMonitor allows you to change any attribute of a monitor. must -// be one of "http", "https", "icmp", "inband", "gateway icmp", "postgresql", "mysql", "udp" or "tcp". -// Fields that can be modified are referenced in the Monitor struct. -func (b *BigIP) ModifyMonitor(name, monitorType string, config *Monitor) error { - if strings.Contains(config.ParentMonitor, "gateway") { - config.ParentMonitor = "gateway_icmp" - } - - return b.put(config, uriLtm, uriMonitor, monitorType, name) -} - -// AddMonitorToPool assigns the monitor, to the given . -func (b *BigIP) AddMonitorToPool(monitor, pool string) error { - config := &Pool{ - Monitor: monitor, - } - - return b.put(config, uriLtm, uriPool, pool) +// DeleteHashHostPersistenceProfile removes a host persist profile. +func (b *BigIP) DeleteHashHostPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriHost, name) } -// IRules returns a list of irules -func (b *BigIP) IRules() (*IRules, error) { - var rules IRules - err, _ := b.getForEntity(&rules, uriLtm, uriIRule) - if err != nil { - return nil, err - } - - return &rules, nil +// ModifyHostPersistenceProfile allows you to change any attribute of a host persist profile. +// Fields that can be modified are referenced in the HostPersistenceProfile struct. +func (b *BigIP) ModifyHostPersistenceProfile(name string, config *HostPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriHost, name) } -// IRule returns information about the given iRule. -func (b *BigIP) IRule(name string) (*IRule, error) { - var rule IRule - err, ok := b.getForEntity(&rule, uriLtm, uriIRule, name) +// MSRDPPersistenceProfiles returns a list of msrdp persist profiles +func (b *BigIP) MSRDPPersistenceProfiles() (*MSRDPPersistenceProfiles, error) { + var msrdpPersistenceProfiles MSRDPPersistenceProfiles + err, _ := b.getForEntity(&msrdpPersistenceProfiles, uriLtm, uriPersistence, uriMSRDP) if err != nil { return nil, err } - if !ok { - return nil, nil - } - return &rule, nil -} - -// CreateIRule creates a new iRule on the system. -func (b *BigIP) CreateIRule(name, rule string) error { - irule := &IRule{ - Name: name, - Rule: rule, - } - return b.post(irule, uriLtm, uriIRule) -} - -// DeleteIRule removes an iRule from the system. -func (b *BigIP) DeleteIRule(name string) error { - return b.delete(uriLtm, uriIRule, name) -} -// ModifyIRule updates the given iRule with any changed values. -func (b *BigIP) ModifyIRule(name string, irule *IRule) error { - irule.Name = name - return b.put(irule, uriLtm, uriIRule, name) + return &msrdpPersistenceProfiles, nil } -func (b *BigIP) Policies() (*Policies, error) { - var p Policies - err, _ := b.getForEntity(&p, uriLtm, uriPolicy) +// GetMSRDPPersistenceProfile gets a single msrdp persist profile by name +func (b *BigIP) GetMSRDPPersistenceProfile(name string) (*MSRDPPersistenceProfile, error) { + var msrdpPersistenceProfile MSRDPPersistenceProfile + err, ok := b.getForEntity(&msrdpPersistenceProfile, uriLtm, uriPersistence, uriMSRDP, name) if err != nil { return nil, err } - return &p, nil -} - -//Load a fully policy definition. Policies seem to be best dealt with as one big entity. -func (b *BigIP) GetPolicy(name string) (*Policy, error) { - var p Policy - err, ok := b.getForEntity(&p, uriLtm, uriPolicy, name) - if err != nil { - return nil, err - } if !ok { return nil, nil } - var rules PolicyRules - err, _ = b.getForEntity(&rules, uriLtm, uriPolicy, name, "rules") - if err != nil { - return nil, err - } - p.Rules = rules.Items - - for i, _ := range p.Rules { - var a PolicyRuleActions - var c PolicyRuleConditions - - err, _ = b.getForEntity(&a, uriLtm, uriPolicy, name, "rules", p.Rules[i].Name, "actions") - if err != nil { - return nil, err - } - err, _ = b.getForEntity(&c, uriLtm, uriPolicy, name, "rules", p.Rules[i].Name, "conditions") - if err != nil { - return nil, err - } - p.Rules[i].Actions = a.Items - p.Rules[i].Conditions = c.Items - } - - return &p, nil -} - -func normalizePolicy(p *Policy) { - //f5 doesn't seem to automatically handle setting the ordinal - for ri, _ := range p.Rules { - p.Rules[ri].Ordinal = ri - for ai, _ := range p.Rules[ri].Actions { - p.Rules[ri].Actions[ai].Name = fmt.Sprintf("%d", ai) - } - for ci, _ := range p.Rules[ri].Conditions { - p.Rules[ri].Conditions[ci].Name = fmt.Sprintf("%d", ci) - } - } -} - -//Create a new policy. It is not necessary to set the Ordinal fields on subcollections. -func (b *BigIP) CreatePolicy(p *Policy) error { - normalizePolicy(p) - return b.post(p, uriLtm, uriPolicy) -} - -func (b *BigIP) PublishPolicy(name, publish string) error { - config := &Policy{ - PublishCopy: publish, - } - values := []string{} - values = append(values, "~Common~Drafts~") - values = append(values, name) - // Join three strings into one. - result := strings.Join(values, "") - - log.Println( " ================== here in publish ", result, publish) - - return b.patch(config, uriLtm, uriPolicy, result) -} - -//Update an existing policy. - func (b *BigIP) UpdatePolicy(name string, p *Policy) error { - normalizePolicy(p) - values := []string{} - values = append(values, "Drafts/") - values = append(values, name) - // Join three strings into one. - result := strings.Join(values, "") - return b.put(p, uriLtm, uriPolicy, result) -} - -//Delete a policy by name. -func (b *BigIP) DeletePolicy(name string) error { - values := []string{} - values = append(values, "Drafts/") - values = append(values, name) - // Join three strings into one. - result := strings.Join(values, "") -return b.delete(uriLtm, uriPolicy, result) -} - -// Oneconnect profile creation -func (b *BigIP) CreateOneconnect(name, idleTimeoutOverride, partition, defaultsFrom, sharePools, sourceMask string, maxAge, maxReuse, maxSize int) error { - oneconnect := &Oneconnect{ - Name: name, - IdleTimeoutOverride: idleTimeoutOverride, - Partition: partition, - DefaultsFrom: defaultsFrom, - SharePools: sharePools, - SourceMask: sourceMask, - MaxAge: maxAge, - MaxReuse: maxReuse, - MaxSize: maxSize, - } - return b.post(oneconnect, uriLtm, uriProfile, uriOneconnect) -} - -func (b *BigIP) Oneconnect(name string) (*Oneconnects, error) { - var oneconnects Oneconnects - err, _ := b.getForEntity(&oneconnects, uriLtm, uriProfile, uriOneconnect) - - if err != nil { - return nil, err - } - - return &oneconnects, nil -} - -// DeleteOneconnect removes an OneConnect profile from the system. -func (b *BigIP) DeleteOneconnect(name string) error { - return b.delete(uriLtm, uriProfile, uriOneconnect, name) -} - -// ModifyOneconnect updates the given Oneconnect profile with any changed values. -func (b *BigIP) ModifyOneconnect(name string, oneconnect *Oneconnect) error { - oneconnect.Name = name - return b.put(oneconnect, uriLtm, uriProfile, uriOneconnect, name) -} - -// Create TCP profile for WAN or LAN - -func (b *BigIP) CreateTcp(name, partition, defaultsFrom string, idleTimeout, closeWaitTimeout, finWait_2Timeout, finWaitTimeout, keepAliveInterval int, deferredAccept, fastOpen string) error { - tcp := &Tcp{ - Name: name, - Partition: partition, - DefaultsFrom: defaultsFrom, - IdleTimeout: idleTimeout, - CloseWaitTimeout: closeWaitTimeout, - FinWait_2Timeout: finWait_2Timeout, - FinWaitTimeout: finWaitTimeout, - KeepAliveInterval: keepAliveInterval, - DeferredAccept: deferredAccept, - FastOpen: fastOpen, - } - return b.post(tcp, uriLtm, uriProfile, uriTcp) -} - -// DeleteOneconnect removes an OneConnect profile from the system. -func (b *BigIP) DeleteTcp(name string) error { - return b.delete(uriLtm, uriProfile, uriTcp, name) -} - -// ModifyTcp updates the given Oneconnect profile with any changed values. -func (b *BigIP) ModifyTcp(name string, tcp *Tcp) error { - tcp.Name = name - return b.put(tcp, uriLtm, uriProfile, uriTcp, name) -} - -func (b *BigIP) Tcp(name string) (*Tcps, error) { - var tcps Tcps - err, _ := b.getForEntity(&tcps, uriLtm, uriProfile, uriTcp) - - if err != nil { - return nil, err - } - - return &tcps, nil -} - -func (b *BigIP) CreateFasthttp(name, defaultsFrom string, idleTimeout, connpoolIdleTimeoutOverride, connpoolMaxReuse, connpoolMaxSize, connpoolMinSize int, connpoolReplenish string, connpoolStep int, forceHttp_10Response string, maxHeaderSize int) error { - fasthttp := &Fasthttp{ - Name: name, - DefaultsFrom: defaultsFrom, - IdleTimeout: idleTimeout, - ConnpoolIdleTimeoutOverride: connpoolIdleTimeoutOverride, - ConnpoolMaxReuse: connpoolMaxReuse, - ConnpoolMaxSize: connpoolMaxSize, - ConnpoolMinSize: connpoolMinSize, - ConnpoolReplenish: connpoolReplenish, - ConnpoolStep: connpoolStep, - ForceHttp_10Response: forceHttp_10Response, - MaxHeaderSize: maxHeaderSize, - } - return b.post(fasthttp, uriLtm, uriProfile, uriFasthttp) -} - -// Delete Fast http removes an Fasthttp profile from the system. -func (b *BigIP) DeleteFasthttp(name string) error { - return b.delete(uriLtm, uriProfile, uriFasthttp, name) -} - -// ModifyFasthttp updates the given Fasthttp profile with any changed values. -func (b *BigIP) ModifyFasthttp(name string, fasthttp *Fasthttp) error { - fasthttp.Name = name - return b.put(fasthttp, uriLtm, uriProfile, uriFasthttp, name) -} - -func (b *BigIP) Fasthttp() (*Fasthttps, error) { - var fasthttps Fasthttps - err, _ := b.getForEntity(&fasthttps, uriLtm, uriProfile, uriFasthttp) - - if err != nil { - return nil, err - } - - return &fasthttps, nil + return &msrdpPersistenceProfile, nil } -func (b *BigIP) CreateFastl4(name, partition, defaultsFrom string, clientTimeout int, explicitFlowMigration, hardwareSynCookie string, idleTimeout string, ipTosToClient, ipTosToServer, keepAliveInterval string) error { - fastl4 := &Fastl4{ - Name: name, - Partition: partition, - DefaultsFrom: defaultsFrom, - ClientTimeout: clientTimeout, - ExplicitFlowMigration: explicitFlowMigration, - HardwareSynCookie: hardwareSynCookie, - IdleTimeout: idleTimeout, - IpTosToClient: ipTosToClient, - IpTosToServer: ipTosToServer, - KeepAliveInterval: keepAliveInterval, +// CreateMSRDPPersistenceProfile creates a new msrdp persist profile on the BIG-IP system. +func (b *BigIP) CreateMSRDPPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, } - return b.post(fastl4, uriLtm, uriProfile, uriFastl4) -} -// Delete Fast http removes an Fasthttp profile from the system. -func (b *BigIP) DeleteFastl4(name string) error { - return b.delete(uriLtm, uriProfile, uriFastl4, name) -} - -// ModifyFastl4 updates the given Fastl4 profile with any changed values. -func (b *BigIP) ModifyFastl4(name string, fastl4 *Fastl4) error { - fastl4.Name = name - return b.put(fastl4, uriLtm, uriProfile, uriFastl4, name) + return b.post(config, uriLtm, uriPersistence, uriMSRDP) } -func (b *BigIP) Fastl4(name string) (*Fastl4s, error) { - var fastl4s Fastl4s - err, _ := b.getForEntity(&fastl4s, uriLtm, uriProfile, uriFastl4) - - if err != nil { - return nil, err - } - - return &fastl4s, nil +// AddMSRDPPersistenceProfile adds a msrdp persist profile to the BIG-IP system +func (b *BigIP) AddMSRDPPersistenceProfile(config *MSRDPPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriMSRDP) } -// =============== - -func (b *BigIP) CreateHttpcompress(name, defaultsFrom string, uriExclude, uriInclude []string) error { - httpcompress := &Httpcompress{ - Name: name, - DefaultsFrom: defaultsFrom, - UriExclude: uriExclude, - UriInclude: uriInclude, - } - return b.post(httpcompress, uriLtm, uriProfile, uriHttpcompress) +// DeleteMSRDPPersistenceProfile removes a msrdp persist profile. +func (b *BigIP) DeleteMSRDPPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriMSRDP, name) } -// Delete Fast http removes an Fasthttp profile from the system. -func (b *BigIP) DeleteHttpcompress(name string) error { - return b.delete(uriLtm, uriProfile, uriHttpcompress, name) +// ModifyMSRDPPersistenceProfile allows you to change any attribute of a msrdp persist profile. +// Fields that can be modified are referenced in the MSRDPPersistenceProfile struct. +func (b *BigIP) ModifyMSRDPPersistenceProfile(name string, config *MSRDPPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriMSRDP, name) } -// ModifyFastl4 updates the given Fastl4 profile with any changed values. -func (b *BigIP) ModifyHttpcompress(name string, httpcompress *Httpcompress) error { - httpcompress.Name = name - return b.put(httpcompress, uriLtm, uriProfile, uriHttpcompress, name) -} +// SIPPersistenceProfiles returns a list of sip persist profiles +func (b *BigIP) SIPPersistenceProfiles() (*SIPPersistenceProfiles, error) { + var sipPersistenceProfiles SIPPersistenceProfiles + err, _ := b.getForEntity(&sipPersistenceProfiles, uriLtm, uriPersistence, uriSIP) + if err != nil { + return nil, err + } -func (b *BigIP) Httpcompress() (*Httpcompresss, error) { - var httpcompresss Httpcompresss - err, _ := b.getForEntity(&httpcompresss, uriLtm, uriProfile, uriHttpcompress) + return &sipPersistenceProfiles, nil +} +// GetSIPPersistenceProfile gets a single sip persist profile by name +func (b *BigIP) GetSIPPersistenceProfile(name string) (*SIPPersistenceProfile, error) { + var sipPersistenceProfile SIPPersistenceProfile + err, ok := b.getForEntity(&sipPersistenceProfile, uriLtm, uriPersistence, uriSIP, name) if err != nil { return nil, err } - return &httpcompresss, nil + if !ok { + return nil, nil + } + + return &sipPersistenceProfile, nil } -func (b *BigIP) CreateHttp2(name, defaultsFrom string, concurrentStreamsPerConnection, connectionIdleTimeout, headerTableSize int, activationModes []string) error { - http2 := &Http2{ - Name: name, - DefaultsFrom: defaultsFrom, - ConcurrentStreamsPerConnection: concurrentStreamsPerConnection, - ConnectionIdleTimeout: connectionIdleTimeout, - HeaderTableSize: headerTableSize, - ActivationModes: activationModes, +// CreateSIPPersistenceProfile creates a new sip persist profile on the BIG-IP system. +func (b *BigIP) CreateSIPPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, } - return b.post(http2, uriLtm, uriProfile, uriHttp2) + + return b.post(config, uriLtm, uriPersistence, uriSIP) } -// Delete http2 removes an http2 profile from the system. -func (b *BigIP) DeleteHttp2(name string) error { - return b.delete(uriLtm, uriProfile, uriHttp2, name) +// AddSIPPersistenceProfile adds a sip persist profile to the BIG-IP system +func (b *BigIP) AddSIPPersistenceProfile(config *SIPPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriSIP) } -// Modify http2 updates the given http2 profile with any changed values. -func (b *BigIP) ModifyHttp2(name string, http2 *Http2) error { - http2.Name = name - return b.put(http2, uriLtm, uriProfile, uriHttp2, name) +// DeleteSIPPersistenceProfile removes a sip persist profile. +func (b *BigIP) DeleteSIPPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriSIP, name) } -func (b *BigIP) Http2() (*Http2s, error) { - var http2s Http2s - err, _ := b.getForEntity(&http2s, uriLtm, uriProfile, uriHttp2) +// ModifySIPPersistenceProfile allows you to change any attribute of a sip persist profile. +// Fields that can be modified are referenced in the SIPPersistenceProfile struct. +func (b *BigIP) ModifySIPPersistenceProfile(name string, config *SIPPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriSIP, name) +} +// SourceAddrPersistenceProfiles returns a list of source-addr persist profiles +func (b *BigIP) SourceAddrPersistenceProfiles() (*SourceAddrPersistenceProfiles, error) { + var sourceAddrPersistenceProfiles SourceAddrPersistenceProfiles + err, _ := b.getForEntity(&sourceAddrPersistenceProfiles, uriLtm, uriPersistence, uriSourceAddr) if err != nil { return nil, err } - return &http2s, nil + return &sourceAddrPersistenceProfiles, nil } -// Datagroups returns a list of datagroups. -func (b *BigIP) Datagroups(name string) (*Datagroups, error) { - var datagroups Datagroups - err, _ := b.getForEntity(&datagroups, uriLtm, uriDatagroup, uriInternal, name) - +// GetSourceAddrPersistenceProfile gets a single source-addr persist profile by name +func (b *BigIP) GetSourceAddrPersistenceProfile(name string) (*SourceAddrPersistenceProfile, error) { + var sourceAddrPersistenceProfile SourceAddrPersistenceProfile + err, ok := b.getForEntity(&sourceAddrPersistenceProfile, uriLtm, uriPersistence, uriSourceAddr, name) if err != nil { return nil, err } - return &datagroups, nil -} - -// CreateDatagroup adds a new Datagroup to the BIG-IP system. -func (b *BigIP) CreateDatagroup(typo, name string, records []Records) error { - //func (b *BigIP) CreateDatagroup(typo, name string) error { - config := &Datagroup{ - Type: typo, - Name: name, - Records: records, + if !ok { + return nil, nil } - return b.post(config, uriLtm, uriDatagroup, uriInternal) + return &sourceAddrPersistenceProfile, nil } -func (b *BigIP) Records() (*Records, error) { - var records Records - err, _ := b.getForEntity(&records, uriLtm, uriDatagroup, uriInternal) - if err != nil { - return nil, err +// CreateSourceAddrPersistenceProfile creates a new source-addr persist profile on the BIG-IP system. +func (b *BigIP) CreateSourceAddrPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, } - return &records, nil + return b.post(config, uriLtm, uriPersistence, uriSourceAddr) } -func (b *BigIP) DeleteDatagroup(name string) error { - return b.delete(uriLtm, uriDatagroup, uriInternal, name) +// AddSourceAddrPersistenceProfile adds a source-addr persist profile to the BIG-IP system +func (b *BigIP) AddSourceAddrPersistenceProfile(config *SourceAddrPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriSourceAddr) } -func (b *BigIP) AddRecords(name, rname, data string) error { - config := &Records{} - - config.Name = rname - config.Data = data - - return b.post(config, uriLtm, uriDatagroup, uriInternal, "records") +// DeleteSourceAddrPersistenceProfile removes a source-addr persist profile. +func (b *BigIP) DeleteSourceAddrPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriSourceAddr, name) } -// Snats returns a list of snat -/*func (b *BigIP) Snats(name string) (*Snats, error) { - var snats Snats - err, _ := b.getForEntity(&snats, uriLtm, uriSnat, name) +// ModifySourceAddrPersistenceProfile allows you to change any attribute of a source-addr persist profile. +// Fields that can be modified are referenced in the SourceAddrPersistenceProfile struct. +func (b *BigIP) ModifySourceAddrPersistenceProfile(name string, config *SourceAddrPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriSourceAddr, name) +} +// SSLPersistenceProfiles returns a list of ssl persist profiles +func (b *BigIP) SSLPersistenceProfiles() (*SSLPersistenceProfiles, error) { + var sslPersistenceProfiles SSLPersistenceProfiles + err, _ := b.getForEntity(&sslPersistenceProfiles, uriLtm, uriPersistence, uriSSL) if err != nil { return nil, err } - return &snats, nil -}*/ - -/*func (b *BigIP) CreateSnat(name, partition, autoLastHop, sourcePort, translation, snatpool, mirror string, vlansDisabled bool, origins []string) error { - snat := &Snat{ - Name: name, - Partition: partition, - AutoLasthop: autoLastHop, - SourcePort: sourcePort, - Translation: translation, - Snatpool: snatpool, - Mirror: mirror, - VlansDisabled: vlansDisabled, - Origins: origins, - } - log.Println("[INFO] Creating snat ", snat) - return b.post(snat, uriLtm, uriSnat) -} */ -func (b *BigIP) CreateSnat(p *Snat) error { - log.Println(" what is the complete payload ", p) - return b.post(p, uriLtm, uriSnat) -} - -func (b *BigIP) ModifySnat(config *Snat) error { - return b.patch(config, uriLtm, uriSnat) + return &sslPersistenceProfiles, nil } -// Get a Snat list by name. Returns nil if the node does not exist -func (b *BigIP) GetSnat(name string) (*Snat, error) { - var snat Snat - err, ok := b.getForEntity(&snat, uriLtm, uriSnat, name) +// GetSSLPersistenceProfile gets a single ssl persist profile by name +func (b *BigIP) GetSSLPersistenceProfile(name string) (*SSLPersistenceProfile, error) { + var sslPersistenceProfile SSLPersistenceProfile + err, ok := b.getForEntity(&sslPersistenceProfile, uriLtm, uriPersistence, uriSSL, name) if err != nil { return nil, err } + if !ok { return nil, nil } - return &snat, nil + return &sslPersistenceProfile, nil } -func (b *BigIP) DeleteSnat(name string) error { - return b.delete(uriLtm, uriSnat, name) -} +// CreateSSLPersistenceProfile creates a new ssl persist profile on the BIG-IP system. +func (b *BigIP) CreateSSLPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } -func (b *BigIP) UpdateSnat(name string, p *Snat) error { - return b.put(p, uriLtm, uriSnat, name) + return b.post(config, uriLtm, uriPersistence, uriSSL) } -// Snats returns a list of snat -func (b *BigIP) Snatpools(name string) (*Snatpools, error) { - var snatpools Snatpools - err, _ := b.getForEntity(&snatpools, uriLtm, uriSnatpool, name) +// AddSSLPersistenceProfile adds a ssl persist profile to the BIG-IP system +func (b *BigIP) AddSSLPersistenceProfile(config *SSLPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriSSL) +} - if err != nil { - return nil, err - } +// DeleteSSLPersistenceProfile removes a ssl persist profile. +func (b *BigIP) DeleteSSLPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriSSL, name) +} - return &snatpools, nil +// ModifySSLPersistenceProfile allows you to change any attribute of a ssl persist profile. +// Fields that can be modified are referenced in the SSLPersistenceProfile struct. +func (b *BigIP) ModifySSLPersistenceProfile(name string, config *SSLPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriSSL, name) } -func (b *BigIP) CreateSnatpool(name, partition string, members []string) error { - snatpool := &Snatpool{ - Name: name, - Partition: partition, - Members: members, +// UniversalPersistenceProfiles returns a list of universal persist profiles +func (b *BigIP) UniversalPersistenceProfiles() (*UniversalPersistenceProfiles, error) { + var universalPersistenceProfiles UniversalPersistenceProfiles + err, _ := b.getForEntity(&universalPersistenceProfiles, uriLtm, uriPersistence, uriUniversal) + if err != nil { + return nil, err } - log.Println("[INFO] Creating snatpool ", snatpool) - return b.post(snatpool, uriLtm, uriSnatpool) -} -func (b *BigIP) ModifySnatpool(config *Snatpool) error { - return b.put(config, uriLtm, uriSnatpool) + return &universalPersistenceProfiles, nil } -// Get a Snat list by name. Returns nil if the node does not exist -func (b *BigIP) GetSnatpool(name string) (*Snatpool, error) { - var snatpool Snatpool - err, ok := b.getForEntity(&snatpool, uriLtm, uriSnatpool, name) +// GetUniversalPersistenceProfile gets a single universal persist profile by name +func (b *BigIP) GetUniversalPersistenceProfile(name string) (*UniversalPersistenceProfile, error) { + var universalPersistenceProfile UniversalPersistenceProfile + err, ok := b.getForEntity(&universalPersistenceProfile, uriLtm, uriPersistence, uriUniversal, name) if err != nil { return nil, err } + if !ok { return nil, nil } - return &snatpool, nil + return &universalPersistenceProfile, nil } -func (b *BigIP) DeleteSnatpool(name string) error { - return b.delete(uriLtm, uriSnatpool, name) +// CreateUniversalPersistenceProfile creates a new universal persist profile on the BIG-IP system. +func (b *BigIP) CreateUniversalPersistenceProfile(name string, parent string) error { + config := &PersistenceProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriPersistence, uriUniversal) +} + +// AddUniversalPersistenceProfile adds a universal persist profile to the BIG-IP system +func (b *BigIP) AddUniversalPersistenceProfile(config *UniversalPersistenceProfile) error { + return b.post(config, uriLtm, uriPersistence, uriUniversal) +} + +// DeleteUniversalPersistenceProfile removes a universal persist profile. +func (b *BigIP) DeleteUniversalPersistenceProfile(name string) error { + return b.delete(uriLtm, uriPersistence, uriUniversal, name) +} + +// ModifyUniversalPersistenceProfile allows you to change any attribute of a universal persist profile. +// Fields that can be modified are referenced in the UniversalPersistenceProfile struct. +func (b *BigIP) ModifyUniversalPersistenceProfile(name string, config *UniversalPersistenceProfile) error { + return b.put(config, uriLtm, uriPersistence, uriUniversal, name) } From 12ed569bf1803c34dba6831c60c8aa52ae33aaa2 Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 6 Apr 2018 17:09:36 -0700 Subject: [PATCH 33/80] removed ltm_test needs changes --- ltm_test.go | 1505 --------------------------------------------------- 1 file changed, 1505 deletions(-) delete mode 100644 ltm_test.go diff --git a/ltm_test.go b/ltm_test.go deleted file mode 100644 index 208ad9f..0000000 --- a/ltm_test.go +++ /dev/null @@ -1,1505 +0,0 @@ -package bigip - -import ( - "fmt" - "net/http" - "net/http/httptest" - "testing" - - "io/ioutil" - "strings" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/suite" -) - -type LTMTestSuite struct { - suite.Suite - Client *BigIP - Server *httptest.Server - LastRequest *http.Request - LastRequestBody string - ResponseFunc func(http.ResponseWriter, *http.Request) -} - -func (s *LTMTestSuite) SetupSuite() { - s.Server = httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - body, _ := ioutil.ReadAll(r.Body) - s.LastRequestBody = string(body) - s.LastRequest = r - if s.ResponseFunc != nil { - s.ResponseFunc(w, r) - } - })) - - s.Client = NewSession(s.Server.URL, "", "", nil) -} - -func (s *LTMTestSuite) TearDownSuite() { - s.Server.Close() -} - -func (s *LTMTestSuite) SetupTest() { - s.ResponseFunc = nil - s.LastRequest = nil -} - -func TestLtmSuite(t *testing.T) { - suite.Run(t, new(LTMTestSuite)) -} - -func (s *LTMTestSuite) TestIRules() { - s.ResponseFunc = func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(`{"items" : - [ - {"name":"rule1","apiAnonymous":"rule1"}, - {"name":"rule2","apiAnonymous":"this\nis\nrule2"} - ]}`)) - } - - rules, err := s.Client.IRules() - - assert.Nil(s.T(), err, "Error loading rules") - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s", uriLtm, uriIRule), s.LastRequest.URL.Path, "Wrong uri to fetch rules") - assert.Equal(s.T(), 2, len(rules.IRules), "Wrong number of rules") - assert.Equal(s.T(), "rule1", rules.IRules[0].Name) - assert.Equal(s.T(), "rule2", rules.IRules[1].Name) - assert.Equal(s.T(), `this -is -rule2`, rules.IRules[1].Rule, "Multiline rule not unmarshalled") -} - -func (s *LTMTestSuite) TestCreateIRule() { - s.Client.CreateIRule("rule1", `when CLIENT_ACCEPTED { log local0. "test"}`) - - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s", uriLtm, uriIRule), s.LastRequest.URL.Path) - assert.Equal(s.T(), "POST", s.LastRequest.Method) - assert.JSONEq(s.T(), `{"name":"rule1","apiAnonymous":"when CLIENT_ACCEPTED { log local0. \"test\"}"}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestModifyIRule() { - s.Client.ModifyIRule("rule1", &IRule{Rule: "modified"}) - - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriIRule, "rule1"), s.LastRequest.URL.Path) - assert.Equal(s.T(), "PUT", s.LastRequest.Method) - assert.JSONEq(s.T(), `{"name":"rule1","apiAnonymous":"modified"}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestDeleteIRule() { - s.Client.DeleteIRule("rule1") - - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriIRule, "rule1"), s.LastRequest.URL.Path) - assert.Equal(s.T(), "DELETE", s.LastRequest.Method) -} - -func (s *LTMTestSuite) TestModifyVirtualAddress() { - d := &VirtualAddress{} - s.Client.ModifyVirtualAddress("address1", d) - - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriVirtualAddress, "address1"), s.LastRequest.URL.Path) - assert.Equal(s.T(), "PUT", s.LastRequest.Method) -} - -func (s *LTMTestSuite) TestGetPolicies() { - s.ResponseFunc = func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(`{ - "kind": "tm:ltm:policy:policycollectionstate", - "selfLink": "https://localhost/mgmt/tm/ltm/policy?ver=11.5.1", - "items": [ - { - "kind": "tm:ltm:policy:policystate", - "name": "policy1", - "partition": "Common", - "fullPath": "/Common/policy1", - "generation": 1, - "selfLink": "https://localhost/mgmt/tm/ltm/policy/~Common~policy1?ver=11.5.1", - "controls": [ - "forwarding" - ], - "requires": [ - "http", - "client-ssl" - ], - "strategy": "/Common/first-match", - "rulesReference": { - "link": "https://localhost/mgmt/tm/ltm/policy/~Common~policy1/rules?ver=11.5.1", - "isSubcollection": true - } - }, - { - "kind": "tm:ltm:policy:policystate", - "name": "policy2", - "partition": "Common", - "fullPath": "/Common/policy2", - "generation": 1, - "selfLink": "https://localhost/mgmt/tm/ltm/policy/~Common~policy2?ver=11.5.1", - "controls": [ - "classification" - ], - "requires": [ - "ssl-persistence" - ], - "strategy": "/Common/first-match", - "rulesReference": { - "link": "https://localhost/mgmt/tm/ltm/policy/~Common~policy2/rules?ver=11.5.1", - "isSubcollection": true - } - } - ]}`)) - } - - p, e := s.Client.Policies() - - assert.Nil(s.T(), e, "Fetching policy list should not return an error") - assert.Equal(s.T(), 2, len(p.Policies), "Wrong number of policies returned") - assert.Equal(s.T(), "policy1", p.Policies[0].Name) - assert.Equal(s.T(), "Common", p.Policies[0].Partition) - assert.Equal(s.T(), "/Common/first-match", p.Policies[0].Strategy) - assert.EqualValues(s.T(), []string{"http", "client-ssl"}, p.Policies[0].Requires) - assert.EqualValues(s.T(), []string{"forwarding"}, p.Policies[0].Controls) -} - -func (s *LTMTestSuite) TestGetPolicy() { - s.ResponseFunc = func(w http.ResponseWriter, r *http.Request) { - if strings.HasSuffix(r.URL.Path, "rules") { - w.Write([]byte(`{ - "kind": "tm:ltm:policy:rules:rulescollectionstate", - "selfLink": "https://localhost/mgmt/tm/ltm/policy/my_policy/rules?ver=11.5.1", - "items": [ - { - "kind": "tm:ltm:policy:rules:rulesstate", - "name": "rule1", - "fullPath": "rule1", - "generation": 144344, - "selfLink": "https://localhost/mgmt/tm/ltm/policy/my_policy/rules/rule1?ver=11.5.1", - "ordinal": 0, - "actionsReference": { - "link": "https://localhost/mgmt/tm/ltm/policy/my_policy/rules/rule1/actions?ver=11.5.1", - "isSubcollection": true - }, - "conditionsReference": { - "link": "https://localhost/mgmt/tm/ltm/policy/my_policy/rules/rule1/conditions?ver=11.5.1", - "isSubcollection": true - } - } - ] - }`)) - } else if strings.HasSuffix(r.URL.Path, "actions") { - w.Write([]byte(`{ - "kind": "tm:ltm:policy:rules:actions:actionscollectionstate", - "selfLink": "https://localhost/mgmt/tm/ltm/policy/my_policy/rules/rule1/actions?ver=11.5.1", - "items": [ - { - "kind": "tm:ltm:policy:rules:actions:actionsstate", - "name": "0", - "fullPath": "0", - "generation": 144344, - "selfLink": "https://localhost/mgmt/tm/ltm/policy/my_policy/rules/rule1/actions/0?ver=11.5.1", - "code": 0, - "forward": true, - "pool": "/Common/sorry_server", - "port": 0, - "request": true, - "select": true, - "status": 0, - "vlanId": 0 - } - ] - }`)) - } else if strings.HasSuffix(r.URL.Path, "conditions") { - w.Write([]byte(`{ - "kind": "tm:ltm:policy:rules:conditions:conditionscollectionstate", - "selfLink": "https://localhost/mgmt/tm/ltm/policy/my_policy/rules/rule1/conditions?ver=11.5.1", - "items": [ - { - "kind": "tm:ltm:policy:rules:conditions:conditionsstate", - "name": "0", - "fullPath": "0", - "generation": 144344, - "selfLink": "https://localhost/mgmt/tm/ltm/policy/my_policy/rules/rule1/conditions/0?ver=11.5.1", - "all": true, - "caseInsensitive": true, - "external": true, - "httpUri": true, - "index": 0, - "present": true, - "remote": true, - "request": true, - "startsWith": true, - "values": [ - "/foo" - ] - }] - }`)) - } else { - w.Write([]byte(`{ - "kind": "tm:ltm:policy:policystate", - "name": "my_policy", - "fullPath": "my_policy", - "generation": 144344, - "selfLink": "https://localhost/mgmt/tm/ltm/policy/my_policy?ver=11.5.1", - "controls": [ - "forwarding" - ], - "requires": [ - "http" - ], - "strategy": "/Common/first-match", - "rulesReference": { - "link": "https://localhost/mgmt/tm/ltm/policy/~Common~my_policy/rules?ver=11.5.1", - "isSubcollection": true - } - }`)) - } - } - - p, err := s.Client.GetPolicy("my_policy") - - assert.Nil(s.T(), err) - assert.Equal(s.T(), "my_policy", p.Name) - assert.Equal(s.T(), 1, len(p.Rules), "Not enough rules") - assert.Equal(s.T(), 1, len(p.Rules[0].Actions), "Not enough actions") - assert.Equal(s.T(), "/Common/sorry_server", p.Rules[0].Actions[0].Pool) - assert.Equal(s.T(), 1, len(p.Rules[0].Conditions), "Not enough conditions") - assert.Equal(s.T(), []string{"/foo"}, p.Rules[0].Conditions[0].Values) -} - -func (s *LTMTestSuite) TestGetNonExistentPolicy() { - s.ResponseFunc = func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotFound) - } - - p, err := s.Client.GetPolicy("asdf") - - assert.NotNil(s.T(), err, "nil error returned") - assert.Nil(s.T(), p) - assert.True(s.T(), strings.HasPrefix(err.Error(), "HTTP 404"), err.Error()) -} - -func (s *LTMTestSuite) TestCreatePolicy() { - p := Policy{ - Name: "test", - Controls: []string{"forwarding"}, - Requires: []string{"http"}, - Strategy: "/Common/first-match", - Rules: []PolicyRule{ - PolicyRule{ - Name: "rule1", - Actions: []PolicyRuleAction{ - PolicyRuleAction{ - Forward: true, - Pool: "somepool", - }, - PolicyRuleAction{}, - }, - Conditions: []PolicyRuleCondition{ - PolicyRuleCondition{ - CaseInsensitive: true, - Values: []string{"/foo", "/bar"}, - }, - PolicyRuleCondition{}, - }, - }, - PolicyRule{ - Name: "rule2", - }, - }, - } - - s.Client.CreatePolicy(&p) - - assert.Equal(s.T(), "POST", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s", uriLtm, uriPolicy), s.LastRequest.URL.Path) - assert.JSONEq(s.T(), `{"name":"test", - "controls":["forwarding"], - "requires":["http"], - "strategy":"/Common/first-match", - "rulesReference" : {"items":[ - { "name":"rule1", - "ordinal":0, - "actionsReference":{ "items":[ - { - "name":"0", - "pool":"somepool", - "forward":true - }, - { - "name":"1" - } - ]}, - "conditionsReference" : {"items":[ - { - "name":"0", - "caseInsensitive":true, - "values":["/foo","/bar"] - }, - { - "name":"1" - } - ]} - }, - { "name":"rule2", "ordinal":1, "actionsReference":{}, "conditionsReference":{}}]}}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestUpdatePolicy() { - //TODO: test more stuff - s.Client.UpdatePolicy("foo", &Policy{}) - - assert.Equal(s.T(), "PUT", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/foo", uriLtm, uriPolicy), s.LastRequest.URL.Path) -} - -func (s *LTMTestSuite) TestDeletePolicy() { - s.Client.DeletePolicy("foo") - - assert.Equal(s.T(), "DELETE", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/foo", uriLtm, uriPolicy), s.LastRequest.URL.Path) -} - -func (s *LTMTestSuite) TestCreateVitualAddress() { - - s.Client.CreateVirtualAddress("test-va", &VirtualAddress{Address: "10.10.10.10", ARP: true, AutoDelete: false}) - - assert.Equal(s.T(), "POST", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s", uriLtm, uriVirtualAddress), s.LastRequest.URL.Path) - assert.JSONEq(s.T(), ` - {"name":"test-va", - "arp":"enabled", - "autoDelete":"false", - "address" : "10.10.10.10", - "enabled":"no", - "floating":"disabled", - "icmpEcho":"disabled", - "inheritedTrafficGroup":"no", - "routeAdvertisement":"disabled"}`, s.LastRequestBody) - -} - -func (s *LTMTestSuite) TestDeleteVitualAddress() { - - s.Client.DeleteVirtualAddress("test-va") - - assert.Equal(s.T(), "DELETE", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/test-va", uriLtm, uriVirtualAddress), s.LastRequest.URL.Path) -} - -func (s *LTMTestSuite) TestCreateVirtualServer() { - s.Client.CreateVirtualServer("/Common/test-vs", "10.10.10.10", "255.255.255.255", "/Common/test-pool", 80) - - assert.Equal(s.T(), "POST", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s", uriLtm, uriVirtual), s.LastRequest.URL.Path) - assert.Equal(s.T(), `{"name":"/Common/test-vs","destination":"10.10.10.10:80","mask":"255.255.255.255","pool":"/Common/test-pool","sourceAddressTranslation":{}}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestAddVirtualServer() { - config := &VirtualServer{ - Name: "/Common/test-vs", - Destination: "10.10.10.10:80", - Pool: "/Common/test-pool", - } - - s.Client.AddVirtualServer(config) - - assert.Equal(s.T(), "POST", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s", uriLtm, uriVirtual), s.LastRequest.URL.Path) - assert.Equal(s.T(), `{"name":"/Common/test-vs","destination":"10.10.10.10:80","pool":"/Common/test-pool","sourceAddressTranslation":{}}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestModifyVirtualServer() { - vs := &VirtualServer{ - Name: "test", - Profiles: []Profile{ - Profile{Name: "/Common/tcp", Context: CONTEXT_CLIENT}, - Profile{Name: "/Common/tcp", Context: CONTEXT_SERVER}}, - //TODO: test more - } - - s.Client.ModifyVirtualServer("test", vs) - - assert.Equal(s.T(), "PUT", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/test", uriLtm, uriVirtual), s.LastRequest.URL.Path) - assert.JSONEq(s.T(), ` - {"name":"test", - "sourceAddressTranslation":{}, - "profiles":[ - {"name":"/Common/tcp","context":"clientside"}, - {"name":"/Common/tcp","context":"serverside"} - ] - }`, s.LastRequestBody) - -} - -func (s *LTMTestSuite) TestDeleteVirtualServer() { - s.Client.DeleteVirtualServer("/Common/test-vs") - - assert.Equal(s.T(), "DELETE", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriVirtual, "~Common~test-vs"), s.LastRequest.URL.Path) -} - -func (s *LTMTestSuite) TestCreatePool() { - name := "/Common/test-pool" - - s.Client.CreatePool(name) - - assert.Equal(s.T(), "POST", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s", uriLtm, uriPool), s.LastRequest.URL.Path) - assert.Equal(s.T(), `{"name":"/Common/test-pool"}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestAddPool() { - config := &Pool{ - Name: "test-pool", - Partition: "Common", - Monitor: "/Common/http", - } - - s.Client.AddPool(config) - - assert.Equal(s.T(), "POST", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s", uriLtm, uriPool), s.LastRequest.URL.Path) - assert.Equal(s.T(), `{"name":"test-pool","partition":"Common","monitor":"/Common/http"}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestGetPool() { - s.ResponseFunc = func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(`{ - "kind": "tm:ltm:pool:poolstate", - "name": "test-pool", - "partition": "Common", - "fullPath": "/Common/test-pool", - "generation": 3882, - "selfLink": "https://localhost/mgmt/tm/ltm/pool/~Common~test-pool?ver=11.5.3", - "allowNat": "yes", - "allowSnat": "yes", - "ignorePersistedWeight": "disabled", - "ipTosToClient": "pass-through", - "ipTosToServer": "pass-through", - "linkQosToClient": "pass-through", - "linkQosToServer": "pass-through", - "loadBalancingMode": "round-robin", - "minActiveMembers": 0, - "minUpMembers": 0, - "minUpMembersAction": "failover", - "minUpMembersChecking": "disabled", - "monitor": "/Common/http ", - "queueDepthLimit": 0, - "queueOnConnectionLimit": "disabled", - "queueTimeLimit": 0, - "reselectTries": 0, - "slowRampTime": 10, - "membersReference": { - "link": "https://localhost/mgmt/tm/ltm/pool/~Common~test-pool/members?ver=11.5.3", - "isSubcollection": true - } - }`)) - } - - p, err := s.Client.GetPool("/Common/test-pool") - - assert.Nil(s.T(), err) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriPool, "~Common~test-pool"), s.LastRequest.URL.Path) - assert.Equal(s.T(), "test-pool", p.Name) - assert.Equal(s.T(), "Common", p.Partition) - assert.Equal(s.T(), "/Common/test-pool", p.FullPath) - assert.Equal(s.T(), "/Common/http ", p.Monitor) -} - -func (s *LTMTestSuite) TestPools() { - s.ResponseFunc = func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(`{ - "kind": "tm:ltm:pool:poolcollectionstate", - "selfLink": "https://localhost/mgmt/tm/ltm/pool?ver=11.5.3", - "items": [ - { - "kind": "tm:ltm:pool:poolstate", - "name": "test-pool", - "partition": "Common", - "fullPath": "/Common/test-pool", - "generation": 3882, - "selfLink": "https://localhost/mgmt/tm/ltm/pool/~Common~test-pool?ver=11.5.3", - "allowNat": "yes", - "allowSnat": "yes", - "ignorePersistedWeight": "disabled", - "ipTosToClient": "pass-through", - "ipTosToServer": "pass-through", - "linkQosToClient": "pass-through", - "linkQosToServer": "pass-through", - "loadBalancingMode": "round-robin", - "minActiveMembers": 0, - "minUpMembers": 0, - "minUpMembersAction": "failover", - "minUpMembersChecking": "disabled", - "monitor": "/Common/http ", - "queueDepthLimit": 0, - "queueOnConnectionLimit": "disabled", - "queueTimeLimit": 0, - "reselectTries": 0, - "slowRampTime": 10, - "membersReference": { - "link": "https://localhost/mgmt/tm/ltm/pool/~Common~test-pool/members?ver=11.5.3", - "isSubcollection": true - } - }, - { - "kind": "tm:ltm:pool:poolstate", - "name": "test-pool2", - "partition": "Common", - "fullPath": "/Common/test-pool2", - "generation": 3886, - "selfLink": "https://localhost/mgmt/tm/ltm/pool/~Common~test-pool2?ver=11.5.3", - "allowNat": "no", - "allowSnat": "no", - "ignorePersistedWeight": "disabled", - "ipTosToClient": "pass-through", - "ipTosToServer": "pass-through", - "linkQosToClient": "pass-through", - "linkQosToServer": "pass-through", - "loadBalancingMode": "round-robin", - "minActiveMembers": 0, - "minUpMembers": 0, - "minUpMembersAction": "failover", - "minUpMembersChecking": "disabled", - "queueDepthLimit": 0, - "queueOnConnectionLimit": "disabled", - "queueTimeLimit": 0, - "reselectTries": 0, - "slowRampTime": 10, - "membersReference": { - "link": "https://localhost/mgmt/tm/ltm/pool/~Common~test-pool2/members?ver=11.5.3", - "isSubcollection": true - } - } - ] - }`)) - } - - p, err := s.Client.Pools() - - assert.Nil(s.T(), err) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s", uriLtm, uriPool), s.LastRequest.URL.Path) - assert.Equal(s.T(), "/Common/test-pool", p.Pools[0].FullPath) - assert.Equal(s.T(), "/Common/test-pool2", p.Pools[1].FullPath) -} - -func (s *LTMTestSuite) TestDeletePool() { - name := "/Common/test-pool" - s.Client.DeletePool(name) - - assert.Equal(s.T(), "DELETE", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriPool, "~Common~test-pool"), s.LastRequest.URL.Path) -} - -func (s *LTMTestSuite) TestModifyPool() { - config := &Pool{ - Name: "test-pool", - Partition: "Common", - Monitor: "/Common/http", - LoadBalancingMode: "round-robin", - AllowSNAT: "yes", - AllowNAT: "yes", - } - - s.Client.ModifyPool("/Common/test-pool", config) - - assert.Equal(s.T(), "PUT", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriPool, "~Common~test-pool"), s.LastRequest.URL.Path) - assert.Equal(s.T(), `{"name":"test-pool","partition":"Common","allowNat":"yes","allowSnat":"yes","loadBalancingMode":"round-robin","monitor":"/Common/http"}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestAddPoolMember() { - pool := "/Common/test-pool" - poolmember := "/Common/test-pool-member" - - s.Client.AddPoolMember(pool, poolmember) - - assert.Equal(s.T(), "POST", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s/%s", uriLtm, uriPool, "~Common~test-pool", uriPoolMember), s.LastRequest.URL.Path) -} - -func (s *LTMTestSuite) TestCreatePoolMember() { - pool := "/Common/test-pool" - config := &PoolMember{ - Name: "test-pool-member", - Partition: "Common", - Monitor: "/Common/icmp", - } - - s.Client.CreatePoolMember(pool, config) - - assert.Equal(s.T(), "POST", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s/%s", uriLtm, uriPool, "~Common~test-pool", uriPoolMember), s.LastRequest.URL.Path) - assert.Equal(s.T(), `{"name":"test-pool-member","partition":"Common","monitor":"/Common/icmp"}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestGetPoolMember() { - s.ResponseFunc = func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(`{ - "kind": "tm:ltm:pool:members:membersstate", - "name": "test-pool-member:80", - "partition": "Common", - "fullPath": "/Common/test-pool-member:80", - "generation": 5124, - "selfLink": "https://localhost/mgmt/tm/ltm/pool/~Common~test-pool/members/~Common~test-pool-member:80?ver=11.5.3", - "address": "10.10.20.30", - "connectionLimit": 0, - "dynamicRatio": 1, - "inheritProfile": "disabled", - "logging": "disabled", - "monitor": "default", - "priorityGroup": 0, - "rateLimit": "disabled", - "ratio": 1, - "session": "monitor-enabled", - "state": "down" - }`)) - } - - pool := "/Common/test-pool" - poolmember := "/Common/test-pool-member:80" - p, err := s.Client.GetPoolMember(pool, poolmember) - - assert.Nil(s.T(), err) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s/%s/%s", uriLtm, uriPool, "~Common~test-pool", uriPoolMember, "~Common~test-pool-member:80"), s.LastRequest.URL.Path) - assert.Equal(s.T(), "test-pool-member:80", p.Name) - assert.Equal(s.T(), "Common", p.Partition) - assert.Equal(s.T(), "/Common/test-pool-member:80", p.FullPath) - assert.Equal(s.T(), "default", p.Monitor) -} - -func (s *LTMTestSuite) TestPoolMembers() { - s.ResponseFunc = func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(`{ - "kind": "tm:ltm:pool:members:memberscollectionstate", - "selfLink": "https://localhost/mgmt/tm/ltm/pool/~Common~test-pool/members?ver=11.5.3", - "items": [ - { - "kind": "tm:ltm:pool:members:membersstate", - "name": "test-pool-member-1:80", - "partition": "Common", - "fullPath": "/Common/test-pool-member-1:80", - "generation": 5124, - "selfLink": "https://localhost/mgmt/tm/ltm/pool/~Common~test-pool/members/~Common~test-pool-member-1:80?ver=11.5.3", - "address": "10.156.153.10", - "connectionLimit": 0, - "dynamicRatio": 1, - "inheritProfile": "enabled", - "logging": "disabled", - "monitor": "default", - "priorityGroup": 0, - "rateLimit": "disabled", - "ratio": 1, - "session": "monitor-enabled", - "state": "down" - }, - { - "kind": "tm:ltm:pool:members:membersstate", - "name": "test-pool-member-2:80", - "partition": "Common", - "fullPath": "/Common/test-pool-member-2:80", - "generation": 3882, - "selfLink": "https://localhost/mgmt/tm/ltm/pool/~Common~test-pool/members/~Common~test-pool-member-2:80?ver=11.5.3", - "address": "10.10.20.30", - "connectionLimit": 0, - "dynamicRatio": 1, - "inheritProfile": "disabled", - "logging": "disabled", - "monitor": "default", - "priorityGroup": 0, - "rateLimit": "disabled", - "ratio": 1, - "session": "monitor-enabled", - "state": "down" - }, - { - "kind": "tm:ltm:pool:members:membersstate", - "name": "test-pool-member-3:80", - "partition": "Common", - "fullPath": "/Common/test-pool-member-3:80", - "generation": 3862, - "selfLink": "https://localhost/mgmt/tm/ltm/pool/~Common~test-pool/members/~Common~test-pool-member-3:80?ver=11.5.3", - "address": "10.10.20.40", - "connectionLimit": 0, - "dynamicRatio": 1, - "inheritProfile": "enabled", - "logging": "disabled", - "monitor": "/Common/http ", - "priorityGroup": 0, - "rateLimit": "disabled", - "ratio": 1, - "session": "monitor-enabled", - "state": "down" - } - ] - }`)) - } - - pool := "/Common/test-pool" - p, err := s.Client.PoolMembers(pool) - - assert.Nil(s.T(), err) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s/%s", uriLtm, uriPool, "~Common~test-pool", uriPoolMember), s.LastRequest.URL.Path) - assert.Equal(s.T(), "/Common/test-pool-member-1:80", p.PoolMembers[0].FullPath) - assert.Equal(s.T(), "/Common/test-pool-member-2:80", p.PoolMembers[1].FullPath) - assert.Equal(s.T(), "/Common/test-pool-member-3:80", p.PoolMembers[2].FullPath) -} - -func (s *LTMTestSuite) TestDeletePoolMember() { - - pool := "/Common/test-pool" - poolmember := "/Common/test-pool-member:80" - s.Client.DeletePoolMember(pool, poolmember) - - assert.Equal(s.T(), "DELETE", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s/%s/%s", uriLtm, uriPool, "~Common~test-pool", uriPoolMember, "~Common~test-pool-member:80"), s.LastRequest.URL.Path) -} - -func (s *LTMTestSuite) TestRemovePoolMember() { - pool := "/Common/test-pool" - config := &PoolMember{ - Name: "test-pool-member", - Partition: "Common", - Monitor: "/Common/icmp", - } - s.Client.RemovePoolMember(pool, config) - - assert.Equal(s.T(), "DELETE", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s/%s/", uriLtm, uriPool, "~Common~test-pool", uriPoolMember), s.LastRequest.URL.Path) -} - -func (s *LTMTestSuite) TestModifyPoolMember() { - pool := "/Common/test-pool" - config := &PoolMember{ - Name: "test-pool-member:80", - Partition: "Common", - FullPath: "/Common/test-pool-member:80", - Monitor: "/Common/icmp", - } - - s.Client.ModifyPoolMember(pool, config) - - assert.Equal(s.T(), "PUT", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s/%s/%s", uriLtm, uriPool, "~Common~test-pool", uriPoolMember, "~Common~test-pool-member:80"), s.LastRequest.URL.Path) - assert.Equal(s.T(), `{"monitor":"/Common/icmp"}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestCreateMonitor() { - config := &Monitor{ - Name: "test-web-monitor", - ParentMonitor: "http", - Interval: 15, - Timeout: 5, - SendString: "GET /\r\n", - ReceiveString: "200 OK", - } - - s.Client.CreateMonitor(config.Name, config.ParentMonitor, config.Interval, config.Timeout, config.SendString, config.ReceiveString, "http") - - assert.Equal(s.T(), "POST", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriMonitor, config.ParentMonitor), s.LastRequest.URL.Path) - assert.Equal(s.T(), `{"name":"test-web-monitor","defaultsFrom":"http","interval":15,"manualResume":"disabled","recv":"200 OK","reverse":"disabled","send":"GET /\\r\\n","timeout":5,"transparent":"disabled"}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestCreateMonitorSpecialCharacters() { - config := &Monitor{ - Name: "test-web-monitor", - ParentMonitor: "http", - Interval: 15, - Timeout: 5, - SendString: "GET /test&parms=1<2>3\r\n", - ReceiveString: "Response &<>", - } - - s.Client.CreateMonitor(config.Name, config.ParentMonitor, config.Interval, config.Timeout, config.SendString, config.ReceiveString, "http") - - assert.Equal(s.T(), "POST", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriMonitor, config.ParentMonitor), s.LastRequest.URL.Path) - assert.Equal(s.T(), `{"name":"test-web-monitor","defaultsFrom":"http","interval":15,"manualResume":"disabled","recv":"Response &<>","reverse":"disabled","send":"GET /test&parms=1<2>3\\r\\n","timeout":5,"transparent":"disabled"}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestAddMonitor() { - config := &Monitor{ - Name: "test-web-monitor", - ParentMonitor: "http", - Interval: 15, - Timeout: 5, - SendString: "GET /\r\n", - ReceiveString: "200 OK", - Username: "monitoring", - Password: "monitoring", - } - - s.Client.AddMonitor(config, "http") - - assert.Equal(s.T(), "POST", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriMonitor, config.ParentMonitor), s.LastRequest.URL.Path) - assert.Equal(s.T(), `{"name":"test-web-monitor","defaultsFrom":"http","interval":15,"manualResume":"disabled","password":"monitoring","recv":"200 OK","reverse":"disabled","send":"GET /\\r\\n","timeout":5,"transparent":"disabled","username":"monitoring"}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestGetMonitor() { - config := &Monitor{ - Name: "test-web-monitor", - ParentMonitor: "http", - } - - s.Client.GetMonitor(config.Name, config.ParentMonitor) - - assert.Equal(s.T(), "GET", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s/%s", uriLtm, uriMonitor, config.ParentMonitor, config.Name), s.LastRequest.URL.Path) -} - -func (s *LTMTestSuite) TestDeleteMonitor() { - config := &Monitor{ - Name: "test-web-monitor", - ParentMonitor: "http", - } - - s.Client.DeleteMonitor(config.Name, config.ParentMonitor) - - assert.Equal(s.T(), "DELETE", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s/%s", uriLtm, uriMonitor, config.ParentMonitor, config.Name), s.LastRequest.URL.Path) -} - -func (s *LTMTestSuite) TestVirtualServerPolicies() { - s.ResponseFunc = func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(`{ - "kind": "tm:ltm:virtual:policies:policiescollectionstate", - "selfLink": "https://localhost/mgmt/tm/ltm/virtual/foo/policies?ver=11.5.1", - "policiesReference": { - "link": "https://localhost/mgmt/tm/ltm/virtual/foo/policies?ver=11.5.1", - "isSubcollection": true, - "items": [ - { - "kind": "tm:ltm:virtual:policies:policiesstate", - "name": "policy1", - "partition": "Common", - "fullPath": "/Common/policy1", - "generation": 1, - "selfLink": "https://localhost/mgmt/tm/ltm/virtual/foo/policies/~Common~policy1?ver=11.5.1" - }, - { - "kind": "tm:ltm:virtual:policies:policiesstate", - "name": "policy2", - "partition": "Common", - "fullPath": "/Common/policy2", - "generation": 1, - "selfLink": "https://localhost/mgmt/tm/ltm/virtual/foo/policies/~Common~policy2?ver=11.5.1" - } - ] - } - }`)) - } - - p, err := s.Client.VirtualServerPolicyNames("foo") - - assert.Nil(s.T(), err) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/foo/policies", uriLtm, uriVirtual), s.LastRequest.URL.Path) - assert.Equal(s.T(), "/Common/policy1", p[0]) - assert.Equal(s.T(), "/Common/policy2", p[1]) -} - -func (s *LTMTestSuite) TestInternalDataGroups() { - s.ResponseFunc = func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(`{ - "kind": "tm:ltm:data-group:internal:internalcollectionstate", - "selfLink": "https://localhost/mgmt/tm/ltm/data-group/internal?ver=12.1.2", - "items": [ - { - "kind": "tm:ltm:data-group:internal:internalstate", - "name": "some_data_group", - "partition": "Common", - "fullPath": "/Common/api.tv2.dk_host_pool_map", - "generation": 2552, - "selfLink": "https://localhost/mgmt/tm/ltm/data-group/internal/~Common~api.tv2.dk_host_pool_map?ver=12.1.2", - "type": "string", - "records": [ - { - "name": "jens.medister.api.tv2.dk-hest", - "data": "pool-medister" - } - ] - }, - { - "kind": "tm:ltm:data-group:internal:internalstate", - "name": "jenkins_whitelisted_paths", - "partition": "Common", - "fullPath": "/Common/jenkins_whitelisted_paths", - "generation": 41, - "selfLink": "https://localhost/mgmt/tm/ltm/data-group/internal/~Common~jenkins_whitelisted_paths?ver=12.1.2", - "type": "string", - "records": [ - { - "name": "/medister", - "data": "1" - } - ] - } - ] - }`)) - } - - g, err := s.Client.InternalDataGroups() - - assert.Nil(s.T(), err) - assert.Equal(s.T(), "GET", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriDatagroup, uriInternal), s.LastRequest.URL.Path) - assert.Equal(s.T(), "some_data_group", g.DataGroups[0].Name) - assert.Equal(s.T(), "jenkins_whitelisted_paths", g.DataGroups[1].Name) - assert.Equal(s.T(), "/medister", g.DataGroups[1].Records[0].Name) -} - -func (s *LTMTestSuite) TestAddInternalDataGroup() { - config := &DataGroup{ - Name: "test-datagroup", - Type: "string", - Records: []DataGroupRecord{ - DataGroupRecord{ - Name: "name1", - Data: "data1", - }, - DataGroupRecord{ - Name: "name2", - Data: "data2", - }, - }, - } - - s.Client.AddInternalDataGroup(config) - - assert.Equal(s.T(), "POST", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriDatagroup, uriInternal), s.LastRequest.URL.Path) - assert.Equal(s.T(), `{"name":"test-datagroup","type":"string","records":[{"name":"name1","data":"data1"},{"name":"name2","data":"data2"}]}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestModifyInternalDataGroupRecords() { - dataGroup := "test" - - records := &[]DataGroupRecord{ - DataGroupRecord{ - Name: "name1", - Data: "data1", - }, - DataGroupRecord{ - Name: "name42", - Data: "data42", - }, - } - - s.Client.ModifyInternalDataGroupRecords(dataGroup, records) - - assert.Equal(s.T(), "PUT", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s/%s", uriLtm, uriDatagroup, uriInternal, dataGroup), s.LastRequest.URL.Path) - assert.Equal(s.T(), `{"records":[{"name":"name1","data":"data1"},{"name":"name42","data":"data42"}]}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestDeleteInternalDataGroup() { - dataGroup := "test" - s.Client.DeleteInternalDataGroup(dataGroup) - - assert.Equal(s.T(), "DELETE", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s/%s", uriLtm, uriDatagroup, uriInternal, dataGroup), s.LastRequest.URL.Path) -} - -func (s *LTMTestSuite) TestGetInternalDataGroupRecords() { - dataGroup := "test" - s.Client.GetInternalDataGroupRecords(dataGroup) - - assert.Equal(s.T(), "GET", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s/%s", uriLtm, uriDatagroup, uriInternal, dataGroup), s.LastRequest.URL.Path) -} - -func (s *LTMTestSuite) TestSnatPools() { - s.ResponseFunc = func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(`{ - "kind": "tm:ltm:snatpool:snatpoolcollectionstate", - "selfLink": "https://localhost/mgmt/tm/ltm/snatpool?ver=11.5.3", - "items": [{ - "kind": "tm:ltm:snatpool:snatpoolstate", - "name": "mySnatPool", - "partition": "Common", - "fullPath": "/Common/mySnatPool", - "generation": 419, - "selfLink": "https://localhost/mgmt/tm/ltm/snatpool/~Common~mySnatPool?ver=11.5.3", - "members": [ - "/Common/10.0.0.1" - ] - }, { - "kind": "tm:ltm:snatpool:snatpoolstate", - "name": "mySnatPool2", - "partition": "Common", - "fullPath": "/Common/mySnatPool2", - "generation": 477, - "selfLink": "https://localhost/mgmt/tm/ltm/snatpool/~Common~mySnatPool2?ver=11.5.3", - "members": [ - "/Common/10.0.0.2" - ] - }] - }`)) - } - - g, err := s.Client.SnatPools() - - assert.Nil(s.T(), err) - assert.Equal(s.T(), "GET", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s", uriLtm, uriSnatPool), s.LastRequest.URL.Path) - assert.Equal(s.T(), "mySnatPool", g.SnatPools[0].Name) - assert.Equal(s.T(), "mySnatPool2", g.SnatPools[1].Name) -} - -func (s *LTMTestSuite) TestCreateSnatPool() { - - s.Client.CreateSnatPool("mySnatPool", []string{"10.1.1.1", "10.2.2.2"}) - - assert.Equal(s.T(), "POST", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s", uriLtm, uriSnatPool), s.LastRequest.URL.Path) - assert.Equal(s.T(), `{"name":"mySnatPool","members":["10.1.1.1","10.2.2.2"]}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestAddSnatPool() { - - mySnatPool := &SnatPool{Name: "mySnatPool", Members: []string{"10.1.1.1", "10.2.2.2"}} - - s.Client.AddSnatPool(mySnatPool) - - assert.Equal(s.T(), "POST", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s", uriLtm, uriSnatPool), s.LastRequest.URL.Path) - assert.Equal(s.T(), `{"name":"mySnatPool","members":["10.1.1.1","10.2.2.2"]}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestModifySnatPool() { - - snatPool := "mySnatPool" - - myModifedSnatPool := &SnatPool{Members: []string{"10.0.0.1", "10.0.0.2"}} - - s.Client.ModifySnatPool(snatPool, myModifedSnatPool) - - assert.Equal(s.T(), "PUT", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriSnatPool, snatPool), s.LastRequest.URL.Path) - assert.Equal(s.T(), `{"members":["10.0.0.1","10.0.0.2"]}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestDeleteSnatPool() { - snatPool := "mySnatPool" - s.Client.DeleteSnatPool(snatPool) - - assert.Equal(s.T(), "DELETE", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriSnatPool, snatPool), s.LastRequest.URL.Path) -} - -func (s *LTMTestSuite) TestServerSSLProfiles() { - s.ResponseFunc = func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(`{ - "kind": "tm:ltm:profile:server-ssl:server-sslcollectionstate", - "selfLink": "https://localhost/mgmt/tm/ltm/profile/server-ssl?ver=11.5.3", - "items": [{ - "kind": "tm:ltm:profile:server-ssl:server-sslstate", - "name": "myServerSSL", - "partition": "Common", - "fullPath": "/Common/myServerSSL", - "generation": 784, - "selfLink": "https://localhost/mgmt/tm/ltm/profile/server-ssl/~Common~myServerSSL?ver=11.5.3", - "alertTimeout": "10", - "authenticate": "once", - "authenticateDepth": 9, - "cacheSize": 262144, - "cacheTimeout": 3600, - "cert": "/Common/default.crt", - "ciphers": "DEFAULT", - "defaultsFrom": "/Common/serverssl", - "expireCertResponseControl": "drop", - "genericAlert": "enabled", - "handshakeTimeout": "10", - "key": "/Common/default.key", - "modSslMethods": "disabled", - "mode": "enabled", - "tmOptions": [ - "dont-insert-empty-fragments" - ], - "peerCertMode": "ignore", - "proxySsl": "disabled", - "renegotiatePeriod": "indefinite", - "renegotiateSize": "indefinite", - "renegotiation": "enabled", - "retainCertificate": "true", - "secureRenegotiation": "require-strict", - "serverName": "myserver.contoso.com", - "sessionTicket": "disabled", - "sniDefault": "false", - "sniRequire": "false", - "sslForwardProxy": "disabled", - "sslForwardProxyBypass": "disabled", - "sslSignHash": "any", - "strictResume": "disabled", - "uncleanShutdown": "enabled", - "untrustedCertResponseControl": "drop" - }, { - "kind": "tm:ltm:profile:server-ssl:server-sslstate", - "name": "serverssl", - "partition": "Common", - "fullPath": "/Common/serverssl", - "generation": 1, - "selfLink": "https://localhost/mgmt/tm/ltm/profile/server-ssl/~Common~serverssl?ver=11.5.3", - "alertTimeout": "10", - "authenticate": "once", - "authenticateDepth": 9, - "cacheSize": 262144, - "cacheTimeout": 3600, - "ciphers": "DEFAULT", - "expireCertResponseControl": "drop", - "genericAlert": "enabled", - "handshakeTimeout": "10", - "modSslMethods": "disabled", - "mode": "enabled", - "tmOptions": [ - "dont-insert-empty-fragments" - ], - "peerCertMode": "ignore", - "proxySsl": "disabled", - "renegotiatePeriod": "indefinite", - "renegotiateSize": "indefinite", - "renegotiation": "enabled", - "retainCertificate": "true", - "secureRenegotiation": "require-strict", - "sessionTicket": "disabled", - "sniDefault": "false", - "sniRequire": "false", - "sslForwardProxy": "disabled", - "sslForwardProxyBypass": "disabled", - "sslSignHash": "any", - "strictResume": "disabled", - "uncleanShutdown": "enabled", - "untrustedCertResponseControl": "drop" - }, { - "kind": "tm:ltm:profile:server-ssl:server-sslstate", - "name": "serverssl-insecure-compatible", - "partition": "Common", - "fullPath": "/Common/serverssl-insecure-compatible", - "generation": 1, - "selfLink": "https://localhost/mgmt/tm/ltm/profile/server-ssl/~Common~serverssl-insecure-compatible?ver=11.5.3", - "alertTimeout": "10", - "authenticate": "once", - "authenticateDepth": 9, - "cacheSize": 262144, - "cacheTimeout": 3600, - "ciphers": "!SSLv2:!EXPORT:!DH:RSA+RC4:RSA+AES:RSA+DES:RSA+3DES:ECDHE+AES:ECDHE+3DES:@SPEED", - "defaultsFrom": "/Common/serverssl", - "expireCertResponseControl": "drop", - "genericAlert": "enabled", - "handshakeTimeout": "10", - "modSslMethods": "disabled", - "mode": "enabled", - "tmOptions": [ - "dont-insert-empty-fragments" - ], - "peerCertMode": "ignore", - "proxySsl": "disabled", - "renegotiatePeriod": "indefinite", - "renegotiateSize": "indefinite", - "renegotiation": "enabled", - "retainCertificate": "true", - "secureRenegotiation": "request", - "sessionTicket": "disabled", - "sniDefault": "false", - "sniRequire": "false", - "sslForwardProxy": "disabled", - "sslForwardProxyBypass": "disabled", - "sslSignHash": "any", - "strictResume": "disabled", - "uncleanShutdown": "enabled", - "untrustedCertResponseControl": "drop" - }] - }`)) - } - - g, err := s.Client.ServerSSLProfiles() - - assert.Nil(s.T(), err) - assert.Equal(s.T(), "GET", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriProfile, uriServerSSL), s.LastRequest.URL.Path) - assert.Equal(s.T(), "myServerSSL", g.ServerSSLProfiles[0].Name) - assert.Equal(s.T(), "serverssl", g.ServerSSLProfiles[1].Name) - assert.Equal(s.T(), "serverssl-insecure-compatible", g.ServerSSLProfiles[2].Name) -} - -func (s *LTMTestSuite) TestCreateServerSSLProfile() { - s.Client.CreateServerSSLProfile("myServerSSL", "/Common/serverssl") - - assert.Equal(s.T(), "POST", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriProfile, uriServerSSL), s.LastRequest.URL.Path) - assert.Equal(s.T(), `{"name":"myServerSSL","defaultsFrom":"/Common/serverssl"}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestModifyServerSSLProfile() { - serverSSLProfile := "myServerSSL" - myModifedServerSSLProfile := &ServerSSLProfile{Mode: "enabled", Cert: "/Common/default.crt", Key: "/Common/default.key", ServerName: "myserver.contoso.com"} - - s.Client.ModifyServerSSLProfile(serverSSLProfile, myModifedServerSSLProfile) - - assert.Equal(s.T(), "PUT", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s/%s", uriLtm, uriProfile, uriServerSSL, serverSSLProfile), s.LastRequest.URL.Path) - assert.Equal(s.T(), `{"cert":"/Common/default.crt","key":"/Common/default.key","mode":"enabled","serverName":"myserver.contoso.com"}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestDeleteServerSSLProfile() { - serverSSLProfile := "myServerSSL" - s.Client.DeleteServerSSLProfile(serverSSLProfile) - - assert.Equal(s.T(), "DELETE", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s/%s", uriLtm, uriProfile, uriServerSSL, serverSSLProfile), s.LastRequest.URL.Path) -} - -func (s *LTMTestSuite) TestClientSSLProfiles() { - s.ResponseFunc = func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(`{ - "kind": "tm:ltm:profile:client-ssl:client-sslcollectionstate", - "selfLink": "https://localhost/mgmt/tm/ltm/profile/client-ssl?ver=11.5.3", - "items": [{ - "kind": "tm:ltm:profile:client-ssl:client-sslstate", - "name": "clientssl", - "partition": "Common", - "fullPath": "/Common/clientssl", - "generation": 1, - "selfLink": "https://localhost/mgmt/tm/ltm/profile/client-ssl/~Common~clientssl?ver=11.5.3", - "alertTimeout": "10", - "allowNonSsl": "disabled", - "authenticate": "once", - "authenticateDepth": 9, - "cacheSize": 262144, - "cacheTimeout": 3600, - "cert": "/Common/default.crt", - "certExtensionIncludes": [ - "basic-constraints", - "subject-alternative-name" - ], - "certLifespan": 30, - "certLookupByIpaddrPort": "disabled", - "ciphers": "DEFAULT", - "forwardProxyBypassDefaultAction": "intercept", - "genericAlert": "enabled", - "handshakeTimeout": "10", - "inheritCertkeychain": "false", - "key": "/Common/default.key", - "modSslMethods": "disabled", - "mode": "enabled", - "tmOptions": [ - "dont-insert-empty-fragments" - ], - "peerCertMode": "ignore", - "proxySsl": "disabled", - "renegotiateMaxRecordDelay": "indefinite", - "renegotiatePeriod": "indefinite", - "renegotiateSize": "indefinite", - "renegotiation": "enabled", - "retainCertificate": "true", - "secureRenegotiation": "require", - "sessionTicket": "disabled", - "sniDefault": "false", - "sniRequire": "false", - "sslForwardProxy": "disabled", - "sslForwardProxyBypass": "disabled", - "sslSignHash": "any", - "strictResume": "disabled", - "uncleanShutdown": "enabled", - "certKeyChain": [{ - "name": "default", - "cert": "/Common/default.crt", - "key": "/Common/default.key" - }] - }, { - "kind": "tm:ltm:profile:client-ssl:client-sslstate", - "name": "clientssl-insecure-compatible", - "partition": "Common", - "fullPath": "/Common/clientssl-insecure-compatible", - "generation": 1, - "selfLink": "https://localhost/mgmt/tm/ltm/profile/client-ssl/~Common~clientssl-insecure-compatible?ver=11.5.3", - "alertTimeout": "10", - "allowNonSsl": "disabled", - "authenticate": "once", - "authenticateDepth": 9, - "cacheSize": 262144, - "cacheTimeout": 3600, - "cert": "/Common/default.crt", - "certExtensionIncludes": [ - "basic-constraints", - "subject-alternative-name" - ], - "certLifespan": 30, - "certLookupByIpaddrPort": "disabled", - "ciphers": "!SSLv2:ALL:!DH:!ADH:!EDH:@SPEED", - "defaultsFrom": "/Common/clientssl", - "forwardProxyBypassDefaultAction": "intercept", - "genericAlert": "enabled", - "handshakeTimeout": "10", - "inheritCertkeychain": "true", - "key": "/Common/default.key", - "modSslMethods": "disabled", - "mode": "enabled", - "tmOptions": [ - "dont-insert-empty-fragments" - ], - "peerCertMode": "ignore", - "proxySsl": "disabled", - "renegotiateMaxRecordDelay": "indefinite", - "renegotiatePeriod": "indefinite", - "renegotiateSize": "indefinite", - "renegotiation": "enabled", - "retainCertificate": "true", - "secureRenegotiation": "request", - "sessionTicket": "disabled", - "sniDefault": "false", - "sniRequire": "false", - "sslForwardProxy": "disabled", - "sslForwardProxyBypass": "disabled", - "sslSignHash": "any", - "strictResume": "disabled", - "uncleanShutdown": "enabled", - "certKeyChain": [{ - "name": "default", - "cert": "/Common/default.crt", - "key": "/Common/default.key" - }] - }, { - "kind": "tm:ltm:profile:client-ssl:client-sslstate", - "name": "myClientSSL", - "partition": "Common", - "fullPath": "/Common/myClientSSL", - "generation": 727, - "selfLink": "https://localhost/mgmt/tm/ltm/profile/client-ssl/~Common~myClientSSL?ver=11.5.3", - "alertTimeout": "10", - "allowNonSsl": "disabled", - "authenticate": "once", - "authenticateDepth": 9, - "cacheSize": 262144, - "cacheTimeout": 3600, - "certExtensionIncludes": [ - "basic-constraints", - "subject-alternative-name" - ], - "certLifespan": 30, - "certLookupByIpaddrPort": "disabled", - "ciphers": "DEFAULT", - "defaultsFrom": "/Common/clientssl", - "forwardProxyBypassDefaultAction": "intercept", - "genericAlert": "enabled", - "handshakeTimeout": "10", - "inheritCertkeychain": "false", - "modSslMethods": "disabled", - "mode": "enabled", - "tmOptions": [ - "dont-insert-empty-fragments" - ], - "peerCertMode": "ignore", - "proxySsl": "disabled", - "renegotiateMaxRecordDelay": "indefinite", - "renegotiatePeriod": "indefinite", - "renegotiateSize": "indefinite", - "renegotiation": "enabled", - "retainCertificate": "true", - "secureRenegotiation": "require", - "sessionTicket": "disabled", - "sniDefault": "false", - "sniRequire": "false", - "sslForwardProxy": "disabled", - "sslForwardProxyBypass": "disabled", - "sslSignHash": "any", - "strictResume": "disabled", - "uncleanShutdown": "enabled", - "certKeyChain": [{ - "name": "\"\"" - }] - }, { - "kind": "tm:ltm:profile:client-ssl:client-sslstate", - "name": "wom-default-clientssl", - "partition": "Common", - "fullPath": "/Common/wom-default-clientssl", - "generation": 1, - "selfLink": "https://localhost/mgmt/tm/ltm/profile/client-ssl/~Common~wom-default-clientssl?ver=11.5.3", - "alertTimeout": "10", - "allowNonSsl": "enabled", - "authenticate": "once", - "authenticateDepth": 9, - "cacheSize": 262144, - "cacheTimeout": 3600, - "cert": "/Common/default.crt", - "certExtensionIncludes": [ - "basic-constraints", - "subject-alternative-name" - ], - "certLifespan": 30, - "certLookupByIpaddrPort": "disabled", - "ciphers": "DEFAULT", - "defaultsFrom": "/Common/clientssl", - "forwardProxyBypassDefaultAction": "intercept", - "genericAlert": "enabled", - "handshakeTimeout": "10", - "inheritCertkeychain": "true", - "key": "/Common/default.key", - "modSslMethods": "disabled", - "mode": "enabled", - "tmOptions": [ - "dont-insert-empty-fragments" - ], - "peerCertMode": "ignore", - "proxySsl": "disabled", - "renegotiateMaxRecordDelay": "indefinite", - "renegotiatePeriod": "indefinite", - "renegotiateSize": "indefinite", - "renegotiation": "enabled", - "retainCertificate": "true", - "secureRenegotiation": "require", - "sessionTicket": "disabled", - "sniDefault": "false", - "sniRequire": "false", - "sslForwardProxy": "disabled", - "sslForwardProxyBypass": "disabled", - "sslSignHash": "any", - "strictResume": "disabled", - "uncleanShutdown": "enabled", - "certKeyChain": [{ - "name": "default", - "cert": "/Common/default.crt", - "key": "/Common/default.key" - }] - }] - }`)) - } - - g, err := s.Client.ClientSSLProfiles() - - assert.Nil(s.T(), err) - assert.Equal(s.T(), "GET", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriProfile, uriClientSSL), s.LastRequest.URL.Path) - assert.Equal(s.T(), "clientssl", g.ClientSSLProfiles[0].Name) - assert.Equal(s.T(), "clientssl-insecure-compatible", g.ClientSSLProfiles[1].Name) - assert.Equal(s.T(), "myClientSSL", g.ClientSSLProfiles[2].Name) - assert.Equal(s.T(), "wom-default-clientssl", g.ClientSSLProfiles[3].Name) -} - -func (s *LTMTestSuite) TestCreateClientSSLProfile() { - s.Client.CreateClientSSLProfile("myClientSSL", "/Common/clientssl") - - assert.Equal(s.T(), "POST", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s", uriLtm, uriProfile, uriClientSSL), s.LastRequest.URL.Path) - assert.Equal(s.T(), `{"name":"myClientSSL","defaultsFrom":"/Common/clientssl"}`, s.LastRequestBody) -} - -// Add additional test for more complex certKeyChain - -func (s *LTMTestSuite) TestModifyClientSSLProfile() { - clientSSLProfile := "myClientSSL" - myModifedClientSSLProfile := &ClientSSLProfile{Mode: "enabled", Cert: "/Common/default.crt", Key: "/Common/default.key", ServerName: "myserver.contoso.com"} - - s.Client.ModifyClientSSLProfile(clientSSLProfile, myModifedClientSSLProfile) - - assert.Equal(s.T(), "PUT", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s/%s", uriLtm, uriProfile, uriClientSSL, clientSSLProfile), s.LastRequest.URL.Path) - assert.Equal(s.T(), `{"cert":"/Common/default.crt","key":"/Common/default.key","mode":"enabled","serverName":"myserver.contoso.com"}`, s.LastRequestBody) -} - -func (s *LTMTestSuite) TestDeleteClientSSLProfile() { - clientSSLProfile := "myClientSSL" - s.Client.DeleteClientSSLProfile(clientSSLProfile) - - assert.Equal(s.T(), "DELETE", s.LastRequest.Method) - assert.Equal(s.T(), fmt.Sprintf("/mgmt/tm/%s/%s/%s/%s", uriLtm, uriProfile, uriClientSSL, clientSSLProfile), s.LastRequest.URL.Path) -} From 720e297fa927554560b85b17bb9c51024f798a7c Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 6 Apr 2018 18:01:19 -0700 Subject: [PATCH 34/80] removed comments --- ltm.go | 1 - 1 file changed, 1 deletion(-) diff --git a/ltm.go b/ltm.go index cfb7f93..5264100 100644 --- a/ltm.go +++ b/ltm.go @@ -2131,7 +2131,6 @@ func (b *BigIP) AddMonitor(config *Monitor) error { if strings.Contains(config.ParentMonitor, "tcp-half-open") { config.ParentMonitor = "tcp-half-open" } - log.Println( " value of config in create monitor ------------- %+v\n", *config, uriLtm, uriMonitor, config.ParentMonitor) return b.post(config, uriLtm, uriMonitor, config.ParentMonitor) } From d2055da5a701e7970cb194b3f5084bb5b5286094 Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 6 Apr 2018 19:22:27 -0700 Subject: [PATCH 35/80] added application.go for iapp --- application.go | 107 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 application.go diff --git a/application.go b/application.go new file mode 100644 index 0000000..1f9b0e7 --- /dev/null +++ b/application.go @@ -0,0 +1,107 @@ +package bigip + +import ( + //"encoding/json" + "fmt" + "log" + "strings" +) + +// LIC contains device license for BIG-IP system. + +type Iapps struct { + Iapps []Iapp `json:"items"` +} + +type Iapp struct { + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + Description string `json:"description,omitempty"` + DeviceGroup string `json:"deviceGroup,omitempty"` + ExecuteAction string `json:"execute-action,omitempty"` + InheritedDevicegroup string `json:"inheritedDevicegroup,omitempty"` + InheritedTrafficGroup string `json:"inheritedTrafficGroup,omitempty"` + StrictUpdates string `json:"strictUpdates,omitempty"` + Template string `json:"template,omitempty"` + TemplateModified string `json:"templateModified,omitempty"` + TemplatePrerequisiteErrors string `json:"templatePrerequisiteErrors,omitempty"` + TrafficGroup string `json:"trafficGroup,omitempty"` + Jsonfile string `json:"apiAnonymous,omitempty"` + Tables []struct { + ColumnNames []string `json:"columnNames"` + Name string `json:"name"` + Rows []struct { + Row []string `json:"row"` + } `json:"rows"` + } `json:"tables,omitempty"` + + Lists []struct { + Name string `json:"name"` + Encrypted string `json:"encrypted"` + Value []string `json:"value"` + } `json:"lists,omitempty"` + + Variables []struct { + Encrypted string `json:"encrypted"` + Name string `json:"name"` + Value string `json:"value"` + } `json:"variables,omitempty"` + + Metadata []struct { + Persist string `json:"persist"` + Value string `json:"value"` + } `json:"metadata,omitempty"` +} + +const ( + uriApp = "application" + uriService = "service" + uriSysa = "sys" +) + +func (b *BigIP) CreateIapp(p *Iapp) error { + return b.post(p, uriSysa, uriApp, uriService) +} + +func (b *BigIP) UpdateIapp(name string, p *Iapp) error { + + values := []string{} + values = append(values, "~Common~") + values = append(values, name) + values = append(values, ".app~") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") + fmt.Println(result) + return b.patch(p, uriSysa, uriApp, uriService, result) +} + +func (b *BigIP) Iapp(name string) (*Iapp, error) { + var iapp Iapp + log.Println(" Value of iapp before read ", &iapp) + values := []string{} + values = append(values, "~Common~") + values = append(values, name) + values = append(values, ".app~") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") + err, _ := b.getForEntity(&iapp, uriSysa, uriApp, uriService, result) + log.Println(" I am here in sdk with ", err) + if err != nil { + return nil, err + } + log.Println(" Value of iapp after reading ", &iapp) + return &iapp, nil +} + +func (b *BigIP) DeleteIapp(name string) error { + values := []string{} + values = append(values, "~Common~") + values = append(values, name) + values = append(values, ".app~") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") + return b.delete(uriSys, uriApp, uriService, result) +} From 282b1eeb5080efe4086b1db4696b0c835e3ee4b3 Mon Sep 17 00:00:00 2001 From: Sanjay Date: Fri, 6 Apr 2018 19:53:25 -0700 Subject: [PATCH 36/80] added getroute --- net.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/net.go b/net.go index 40509bf..bc795e9 100644 --- a/net.go +++ b/net.go @@ -315,6 +315,24 @@ func (b *BigIP) Routes() (*Routes, error) { return &routes, nil } +func (b *BigIP) GetRoute(name string) (*Route, error) { + var route Route + values := []string{} + values = append(values, "~Common~") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") + err, ok := b.getForEntity(&route, uriNet, uriRoute, result) + if err != nil { + return nil, err + } + if !ok { + return nil, nil + } + + return &route, nil +} + // CreateRoute adds a new static route to the BIG-IP system. must include the // subnet mask in CIDR notation, i.e.: "10.1.1.0/24". func (b *BigIP) CreateRoute(name, dest, gateway string) error { From a05e9e3bf05bc8c43444e7aabd8385df8585823b Mon Sep 17 00:00:00 2001 From: Sanjay Date: Tue, 10 Apr 2018 13:37:25 -0700 Subject: [PATCH 37/80] added profiles struct & funcs --- ltm.go | 348 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 348 insertions(+) diff --git a/ltm.go b/ltm.go index 5264100..19facb5 100644 --- a/ltm.go +++ b/ltm.go @@ -1449,6 +1449,203 @@ func (p *Snatpool) UnmarshalJSON(b []byte) error { //return marshal(p, &dto) return nil } +// TcpProfiles contains a list of every tcp profile on the BIG-IP system. +type TcpProfiles struct { + TcpProfiles []TcpProfile `json:"items"` +} + +type TcpProfile struct { + Abc string `json:"abc,omitempty"` + AckOnPush string `json:"ackOnPush,omitempty"` + AppService string `json:"appService,omitempty"` + AutoProxyBufferSize string `json:"autoProxyBufferSize,omitempty"` + AutoReceiveWindowSize string `json:"autoReceiveWindowSize,omitempty"` + AutoSendBufferSize string `json:"autoSendBufferSize,omitempty"` + CloseWaitTimeout int `json:"closeWaitTimeout,omitempty"` + CmetricsCache string `json:"cmetricsCache,omitempty"` + CmetricsCacheTimeout int `json:"cmetricsCacheTimeout,omitempty"` + CongestionControl string `json:"congestionControl,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + DeferredAccept string `json:"deferredAccept,omitempty"` + DelayWindowControl string `json:"delayWindowControl,omitempty"` + DelayedAcks string `json:"delayedAcks,omitempty"` + Description string `json:"description,omitempty"` + Dsack string `json:"dsack,omitempty"` + EarlyRetransmit string `json:"earlyRetransmit,omitempty"` + Ecn string `json:"ecn,omitempty"` + EnhancedLossRecovery string `json:"enhancedLossRecovery,omitempty"` + FastOpen string `json:"fastOpen,omitempty"` + FastOpenCookieExpiration int `json:"fastOpenCookieExpiration,omitempty"` + FinWait_2Timeout int `json:"finWait_2Timeout,omitempty"` + FinWaitTimeout int `json:"finWaitTimeout,omitempty"` + HardwareSynCookie string `json:"hardwareSynCookie,omitempty"` + IdleTimeout int `json:"idleTimeout,omitempty"` + InitCwnd int `json:"initCwnd,omitempty"` + InitRwnd int `json:"initRwnd,omitempty"` + IpDfMode string `json:"ipDfMode,omitempty"` + IpTosToClient string `json:"ipTosToClient,omitempty"` + IpTtlMode string `json:"ipTtlMode,omitempty"` + IpTtlV4 int `json:"ipTtlV4,omitempty"` + IpTtlV6 int `json:"ipTtlV6,omitempty"` + KeepAliveInterval int `json:"keepAliveInterval,omitempty"` + LimitedTransmit string `json:"limitedTransmit,omitempty"` + LinkQosToClient string `json:"linkQosToClient,omitempty"` + MaxRetrans int `json:"maxRetrans,omitempty"` + MaxSegmentSize int `json:"maxSegmentSize,omitempty"` + Md5Signature string `json:"md5Signature,omitempty"` + Md5SignaturePassphrase string `json:"md5SignaturePassphrase,omitempty"` + MinimumRto int `json:"minimumRto,omitempty"` + Mptcp string `json:"mptcp,omitempty"` + MptcpCsum string `json:"mptcpCsum,omitempty"` + MptcpCsumVerify string `json:"mptcpCsumVerify,omitempty"` + MptcpDebug string `json:"mptcpDebug,omitempty"` + MptcpFallback string `json:"mptcpFallback,omitempty"` + MptcpFastjoin string `json:"mptcpFastjoin,omitempty"` + MptcpIdleTimeout int `json:"mptcpIdleTimeout,omitempty"` + MptcpJoinMax int `json:"mptcpJoinMax,omitempty"` + MptcpMakeafterbreak string `json:"mptcpMakeafterbreak,omitempty"` + MptcpNojoindssack string `json:"mptcpNojoindssack,omitempty"` + MptcpRtomax int `json:"mptcpRtomax,omitempty"` + MptcpRxmitmin int `json:"mptcpRxmitmin,omitempty"` + MptcpSubflowmax int `json:"mptcpSubflowmax,omitempty"` + MptcpTimeout int `json:"mptcpTimeout,omitempty"` + Nagle string `json:"nagle,omitempty"` + Name string `json:"name,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + PktLossIgnoreBurst int `json:"pktLossIgnoreBurst,omitempty"` + PktLossIgnoreRate int `json:"pktLossIgnoreRate,omitempty"` + ProxyBufferHigh int `json:"proxyBufferHigh,omitempty"` + ProxyBufferLow int `json:"proxyBufferLow,omitempty"` + ProxyMss string `json:"proxyMss,omitempty"` + ProxyOptions string `json:"proxyOptions,omitempty"` + RatePace string `json:"ratePace,omitempty"` + RatePaceMaxRate int `json:"ratePaceMaxRate,omitempty"` + ReceiveWindowSize int `json:"receiveWindowSize,omitempty"` + ResetOnTimeout string `json:"resetOnTimeout,omitempty"` + RexmtThresh int `json:"rexmtThresh,omitempty"` + SelectiveAcks string `json:"selectiveAcks,omitempty"` + SelectiveNack string `json:"selectiveNack,omitempty"` + SendBufferSize int `json:"sendBufferSize,omitempty"` + SlowStart string `json:"slowStart,omitempty"` + SynCookieEnable string `json:"synCookieEnable,omitempty"` + SynCookieWhitelist string `json:"synCookieWhitelist,omitempty"` + SynMaxRetrans int `json:"synMaxRetrans,omitempty"` + SynRtoBase int `json:"synRtoBase,omitempty"` + TailLossProbe string `json:"tailLossProbe,omitempty"` + TcpOptions string `json:"tcpOptions,omitempty"` + TimeWaitRecycle string `json:"timeWaitRecycle,omitempty"` + TimeWaitTimeout string `json:"timeWaitTimeout,omitempty"` + Timestamps string `json:"timestamps,omitempty"` + VerifiedAccept string `json:"verifiedAccept,omitempty"` +} +// UdpProfiles contains a list of every tcp profile on the BIG-IP system. +type UdpProfiles struct { + UdpProfiles []UdpProfile `json:"items"` +} + +type UdpProfile struct { + AllowNoPayload string `json:"allowNoPayload,omitempty"` + AppService string `json:"appService,omitempty"` + BufferMaxBytes int `json:"bufferMaxBytes,omitempty"` + BufferMaxPackets int `json:"bufferMaxPackets,omitempty"` + DatagramLoadBalancing string `json:"datagramLoadBalancing,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + IdleTimeout string `json:"idleTimeout,omitempty"` + IpDfMode string `json:"ipDfMode,omitempty"` + IpTosToClient string `json:"ipTosToClient,omitempty"` + IpTtlMode string `json:"ipTtlMode,omitempty"` + IpTtlV4 int `json:"ipTtlV4,omitempty"` + IpTtlV6 int `json:"ipTtlV6,omitempty"` + LinkQosToClient string `json:"linkQosToClient,omitempty"` + Name string `json:"name,omitempty"` + NoChecksum string `json:"noChecksum,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + ProxyMss string `json:"proxyMss,omitempty"` +} + +type HttpProfiles struct { + HttpProfiles []HttpProfile `json:"items"` +} + +type HttpProfile struct { + AcceptXff string `json:"acceptXff,omitempty"` + AppService string `json:"appService,omitempty"` + BasicAuthRealm string `json:"basicAuthRealm,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + EncryptCookieSecret string `json:"encryptCookieSecret,omitempty"` + EncryptCookies string `json:"encryptCookies,omitempty"` + FallbackHost string `json:"fallbackHost,omitempty"` + FallbackStatusCodes string `json:"fallbackStatusCodes,omitempty"` + HeaderErase string `json:"headerErase,omitempty"` + HeaderInsert string `json:"headerInsert,omitempty"` + InsertXforwardedFor string `json:"insertXforwardedFor,omitempty"` + LwsSeparator string `json:"lwsSeparator,omitempty"` + LwsWidth int `json:"lwsWidth,omitempty"` + Name string `json:"name,omitempty"` + OneconnectTransformations string `json:"oneconnectTransformations,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + ProxyType string `json:"proxyType,omitempty"` + RedirectRewrite string `json:"redirectRewrite,omitempty"` + RequestChunking string `json:"requestChunking,omitempty"` + ResponseChunking string `json:"responseChunking,omitempty"` + ResponseHeadersPermitted string `json:"responseHeadersPermitted,omitempty"` + ServerAgentName string `json:"serverAgentName,omitempty"` + ViaHostName string `json:"viaHostName,omitempty"` + ViaRequest string `json:"viaRequest,omitempty"` + ViaResponse string `json:"viaResponse,omitempty"` + XffAlternativeNames string `json:"xffAlternativeNames,omitempty"` +} + +type OneconnectProfiles struct { + OneconnectProfiles []OneconnectProfile `json:"items"` +} + +type OneconnectProfile struct { + AppService string `json:"appService,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + IdleTimeoutOverride string `json:"idleTimeoutOverride,omitempty"` + LimitType string `json:"limitType,omitempty"` + MaxAge int `json:"maxAge,omitempty"` + MaxReuse int `json:"maxReuse,omitempty"` + MaxSize int `json:"maxSize,omitempty"` + Name string `json:"name,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + SharePools string `json:"sharePools,omitempty"` + SourceMask string `json:"sourceMask,omitempty"` +} + +type HttpCompressionProfiles struct { + HttpCompressionProfiles []HttpCompressionProfile `json:"items"` +} + +type HttpCompressionProfile struct { + AllowHttp_10 string `json:"allowHttp_10,omitempty"` + AppService string `json:"appService,omitempty"` + BrowserWorkarounds string `json:"browserWorkarounds,omitempty"` + BufferSize int `json:"bufferSize,omitempty"` + ContentTypeExclude []string `json:"contentTypeExclude,omitempty"` + ContentTypeInclude []string `json:"contentTypeInclude,omitempty"` + CpuSaver string `json:"cpuSaver,omitempty"` + CpuSaverHigh int `json:"cpuSaverHigh,omitempty"` + CpuSaverLow int `json:"cpuSaverLow,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + GzipLevel int `json:"gzipLevel,omitempty"` + GzipMemoryLevel int `json:"gzipMemoryLevel,omitempty"` + GzipWindowSize int `json:"gzipWindowSize,omitempty"` + KeepAcceptEncoding string `json:"keepAcceptEncoding,omitempty"` + MethodPrefer string `json:"methodPrefer,omitempty"` + MinSize int `json:"minSize,omitempty"` + Name string `json:"name,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + Selective string `json:"selective,omitempty"` + UriExclude []string `json:"uriExclude,omitempty"` + UriInclude []string `json:"uriInclude,omitempty"` + VaryHeader string `json:"varyHeader,omitempty"` +} const ( uriLtm = "ltm" @@ -3177,3 +3374,154 @@ func (b *BigIP) DeleteUniversalPersistenceProfile(name string) error { func (b *BigIP) ModifyUniversalPersistenceProfile(name string, config *UniversalPersistenceProfile) error { return b.put(config, uriLtm, uriPersistence, uriUniversal, name) } + + +// HttpProfiles returns a list of HTTP profiles +func (b *BigIP) HttpProfiles() (*HttpProfiles, error) { + var httpProfiles HttpProfiles + err, _ := b.getForEntity(&httpProfiles, uriLtm, uriProfile, uriHttp) + if err != nil { + return nil, err + } + + return &httpProfiles, nil +} + +func (b *BigIP) GetHttpProfile(name string) (*HttpProfile, error) { + var httpProfile HttpProfile + err, ok := b.getForEntity(&httpProfile, uriLtm, uriProfile, uriHttp, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &httpProfile, nil +} + +// CreateHttpProfile creates a new http profile on the BIG-IP system. +func (b *BigIP) CreateHttpProfile(name string, parent string) error { + config := &HttpProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriProfile, uriHttp) +} + +func (b *BigIP) AddHttpProfile(config *HttpProfile) error { + return b.post(config, uriLtm, uriProfile, uriHttp) +} + +// DeleteHttpProfile removes a http profile. +func (b *BigIP) DeleteHttpProfile(name string) error { + return b.delete(uriLtm, uriProfile, uriHttp, name) +} + +// ModifyHttpProfile allows you to change any attribute of a http profile. +// Fields that can be modified are referenced in the HttpProfile struct. +func (b *BigIP) ModifyHttpProfile(name string, config *HttpProfile) error { + return b.put(config, uriLtm, uriProfile, uriHttp, name) +} + +// OneconnectProfiles returns a list of HTTP profiles +func (b *BigIP) OneconnectProfiles() (*OneconnectProfiles, error) { + var oneconnectProfiles OneconnectProfiles + err, _ := b.getForEntity(&oneconnectProfiles, uriLtm, uriProfile, uriOneconnect) + if err != nil { + return nil, err + } + + return &oneconnectProfiles, nil +} + +func (b *BigIP) GetOneconnectProfile(name string) (*OneconnectProfile, error) { + var oneconnectProfile OneconnectProfile + err, ok := b.getForEntity(&oneconnectProfile, uriLtm, uriProfile, uriOneconnect, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &oneconnectProfile, nil +} + +// CreateOneconnectProfile creates a new http profile on the BIG-IP system. +func (b *BigIP) CreateOneconnectProfile(name string, parent string) error { + config := &OneconnectProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriProfile, uriOneconnect) +} + +func (b *BigIP) AddOneconnectProfile(config *OneconnectProfile) error { + return b.post(config, uriLtm, uriProfile, uriOneconnect) +} + +// DeleteOneconnectProfile removes a http profile. +func (b *BigIP) DeleteOneconnectProfile(name string) error { + return b.delete(uriLtm, uriProfile, uriOneconnect, name) +} + +// ModifyOneconnectProfile allows you to change any attribute of a http profile. +// Fields that can be modified are referenced in the OneconnectProfile struct. +func (b *BigIP) ModifyOneconnectProfile(name string, config *OneconnectProfile) error { + return b.put(config, uriLtm, uriProfile, uriOneconnect, name) +} + +// HttpCompressionProfiles returns a list of HTTP profiles +func (b *BigIP) HttpCompressionProfiles() (*HttpCompressionProfiles, error) { + var httpCompressionProfiles HttpCompressionProfiles + err, _ := b.getForEntity(&httpCompressionProfiles, uriLtm, uriProfile, uriHttpcompress) + if err != nil { + return nil, err + } + + return &httpCompressionProfiles, nil +} + +func (b *BigIP) GetHttpCompressionProfile(name string) (*HttpCompressionProfile, error) { + var httpCompressionProfile HttpCompressionProfile + err, ok := b.getForEntity(&httpCompressionProfile, uriLtm, uriProfile, uriHttpcompress, name) + if err != nil { + return nil, err + } + + if !ok { + return nil, nil + } + + return &httpCompressionProfile, nil +} + +// CreateHttpCompressionProfile creates a new http profile on the BIG-IP system. +func (b *BigIP) CreateHttpCompressionProfile(name string, parent string) error { + config := &HttpCompressionProfile{ + Name: name, + DefaultsFrom: parent, + } + + return b.post(config, uriLtm, uriProfile, uriHttpcompress) +} + +func (b *BigIP) AddHttpCompressionProfile(config *HttpCompressionProfile) error { + return b.post(config, uriLtm, uriProfile, uriHttpcompress) +} + +// DeleteHttpCompressionProfile removes a http profile. +func (b *BigIP) DeleteHttpCompressionProfile(name string) error { + return b.delete(uriLtm, uriProfile, uriHttpcompress, name) +} + +// ModifyHttpCompressionProfile allows you to change any attribute of a http profile. +// Fields that can be modified are referenced in the HttpCompressionProfile struct. +func (b *BigIP) ModifyHttpCompressionProfile(name string, config *HttpCompressionProfile) error { + return b.put(config, uriLtm, uriProfile, uriHttpcompress, name) +} From 93aaa86ec4525fa203e023b70dc987104775e364 Mon Sep 17 00:00:00 2001 From: Joseph Lorenzini Date: Sat, 21 Apr 2018 14:24:01 -0500 Subject: [PATCH 38/80] The bigip REST API returns a json document for node where the shape has nested fields fqdn.interval. The interval is an int. However, the node struct expects the field to be a string. Fix is to set the data from a string to an int. --- ltm.go | 109 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/ltm.go b/ltm.go index 19facb5..77661ee 100644 --- a/ltm.go +++ b/ltm.go @@ -155,7 +155,7 @@ type Node struct { AddressFamily string `json:"addressFamily,omitempty"` AutoPopulate string `json:"autopopulate,omitempty"` DownInterval int `json:"downInterval,omitempty"` - Interval string `json:"interval,omitempty"` + Interval int `json:"interval,omitempty"` Name string `json:"tmName,omitempty"` } `json:"fqdn,omitempty"` } @@ -591,42 +591,42 @@ type VirtualServerPolicies struct { } type PolicyPublish struct { - Name string `json:"name"` + Name string `json:"name"` PublishCopy string `json:"publishedCopy"` } type Policy struct { - Name string + Name string PublishCopy string - Partition string - FullPath string - Controls []string - Requires []string - Strategy string - Rules []PolicyRule + Partition string + FullPath string + Controls []string + Requires []string + Strategy string + Rules []PolicyRule } type policyDTO struct { - Name string `json:"name"` - PublishCopy string `json:"publishedCopy"` - Partition string `json:"partition,omitempty"` - Controls []string `json:"controls,omitempty"` - Requires []string `json:"requires,omitempty"` - Strategy string `json:"strategy,omitempty"` - FullPath string `json:"fullPath,omitempty"` - Rules struct { + Name string `json:"name"` + PublishCopy string `json:"publishedCopy"` + Partition string `json:"partition,omitempty"` + Controls []string `json:"controls,omitempty"` + Requires []string `json:"requires,omitempty"` + Strategy string `json:"strategy,omitempty"` + FullPath string `json:"fullPath,omitempty"` + Rules struct { Items []PolicyRule `json:"items,omitempty"` } `json:"rulesReference,omitempty"` } func (p *Policy) MarshalJSON() ([]byte, error) { return json.Marshal(policyDTO{ - Name: p.Name, + Name: p.Name, PublishCopy: p.PublishCopy, - Partition: p.Partition, - Controls: p.Controls, - Requires: p.Requires, - Strategy: p.Strategy, - FullPath: p.FullPath, + Partition: p.Partition, + Controls: p.Controls, + Requires: p.Requires, + Strategy: p.Strategy, + FullPath: p.FullPath, Rules: struct { Items []PolicyRule `json:"items,omitempty"` }{Items: p.Rules}, @@ -915,8 +915,6 @@ type PolicyRuleCondition struct { VlanId bool `json:"vlanId,omitempty"` } - - func (p *VirtualAddress) MarshalJSON() ([]byte, error) { var dto virtualAddressDTO marshal(&dto, p) @@ -960,7 +958,6 @@ type Monitor struct { Transparent string UpInterval int Username string - } type monitorDTO struct { @@ -1449,6 +1446,7 @@ func (p *Snatpool) UnmarshalJSON(b []byte) error { //return marshal(p, &dto) return nil } + // TcpProfiles contains a list of every tcp profile on the BIG-IP system. type TcpProfiles struct { TcpProfiles []TcpProfile `json:"items"` @@ -1538,6 +1536,7 @@ type TcpProfile struct { Timestamps string `json:"timestamps,omitempty"` VerifiedAccept string `json:"verifiedAccept,omitempty"` } + // UdpProfiles contains a list of every tcp profile on the BIG-IP system. type UdpProfiles struct { UdpProfiles []UdpProfile `json:"items"` @@ -1892,13 +1891,13 @@ func (b *BigIP) Nodes() (*Nodes, error) { // CreateNode adds a new IP based node to the BIG-IP system. func (b *BigIP) CreateNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state string) error { config := &Node{ - Name: name, - Address: address, - RateLimit: rate_limit, + Name: name, + Address: address, + RateLimit: rate_limit, ConnectionLimit: connection_limit, - DynamicRatio: dynamic_ratio, - Monitor: monitor, - State: state, + DynamicRatio: dynamic_ratio, + Monitor: monitor, + State: state, } return b.post(config, uriLtm, uriNode) @@ -1907,12 +1906,12 @@ func (b *BigIP) CreateNode(name, address, rate_limit string, connection_limit, d // CreateFQDNNode adds a new FQDN based node to the BIG-IP system. func (b *BigIP) CreateFQDNNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state string) error { config := &Node{ - Name: name, - RateLimit: rate_limit, + Name: name, + RateLimit: rate_limit, ConnectionLimit: connection_limit, - DynamicRatio: dynamic_ratio, - Monitor: monitor, - State: state, + DynamicRatio: dynamic_ratio, + Monitor: monitor, + State: state, } config.FQDN.Name = address @@ -2307,13 +2306,13 @@ func (b *BigIP) Monitors() ([]Monitor, error) { // "icmp", "gateway icmp", or "tcp". func (b *BigIP) CreateMonitor(name, parent, defaults_from string, interval, timeout int, send, receive, receive_disable string) error { config := &Monitor{ - Name: name, - ParentMonitor: parent, - DefaultsFrom: defaults_from, - Interval: interval, - Timeout: timeout, - SendString: send, - ReceiveString: receive, + Name: name, + ParentMonitor: parent, + DefaultsFrom: defaults_from, + Interval: interval, + Timeout: timeout, + SendString: send, + ReceiveString: receive, ReceiveDisable: receive_disable, } @@ -2348,7 +2347,7 @@ func (b *BigIP) GetMonitor(name string, parent string) (*Monitor, error) { // DeleteMonitor removes a monitor. func (b *BigIP) DeleteMonitor(name, parent string) error { - log.Println( " in delete +++++++++++++++++ ", parent, name) + log.Println(" in delete +++++++++++++++++ ", parent, name) return b.delete(uriLtm, uriMonitor, parent, name) } @@ -2495,18 +2494,18 @@ func (b *BigIP) PublishPolicy(name, publish string) error { PublishCopy: publish, } values := []string{} - values = append(values, "~Common~Drafts~") - values = append(values, name) - // Join three strings into one. - result := strings.Join(values, "") + values = append(values, "~Common~Drafts~") + values = append(values, name) + // Join three strings into one. + result := strings.Join(values, "") - log.Println( " ================== here in publish ", result, publish) + log.Println(" ================== here in publish ", result, publish) - return b.patch(config, uriLtm, uriPolicy, result) + return b.patch(config, uriLtm, uriPolicy, result) } //Update an existing policy. - func (b *BigIP) UpdatePolicy(name string, p *Policy) error { +func (b *BigIP) UpdatePolicy(name string, p *Policy) error { normalizePolicy(p) values := []string{} values = append(values, "Drafts/") @@ -2523,9 +2522,10 @@ func (b *BigIP) DeletePolicy(name string) error { values = append(values, name) // Join three strings into one. result := strings.Join(values, "") -return b.delete(uriLtm, uriPolicy, result) + return b.delete(uriLtm, uriPolicy, result) } - // Oneconnect profile creation + +// Oneconnect profile creation func (b *BigIP) CreateOneconnect(name, idleTimeoutOverride, partition, defaultsFrom, sharePools, sourceMask string, maxAge, maxReuse, maxSize int) error { oneconnect := &Oneconnect{ Name: name, @@ -3375,7 +3375,6 @@ func (b *BigIP) ModifyUniversalPersistenceProfile(name string, config *Universal return b.put(config, uriLtm, uriPersistence, uriUniversal, name) } - // HttpProfiles returns a list of HTTP profiles func (b *BigIP) HttpProfiles() (*HttpProfiles, error) { var httpProfiles HttpProfiles From c9a1be2fae19b3282ca78fac99b26d4a88b27be0 Mon Sep 17 00:00:00 2001 From: Tyler Kellen Date: Wed, 23 May 2018 17:44:01 -0400 Subject: [PATCH 39/80] start using dep for vendoring --- Gopkg.lock | 31 + Gopkg.toml | 34 + vendor/github.com/davecgh/go-spew/LICENSE | 15 + .../github.com/davecgh/go-spew/spew/bypass.go | 152 ++ .../davecgh/go-spew/spew/bypasssafe.go | 38 + .../github.com/davecgh/go-spew/spew/common.go | 341 +++++ .../github.com/davecgh/go-spew/spew/config.go | 306 ++++ vendor/github.com/davecgh/go-spew/spew/doc.go | 211 +++ .../github.com/davecgh/go-spew/spew/dump.go | 509 +++++++ .../github.com/davecgh/go-spew/spew/format.go | 419 ++++++ .../github.com/davecgh/go-spew/spew/spew.go | 148 ++ vendor/github.com/pmezard/go-difflib/LICENSE | 27 + .../pmezard/go-difflib/difflib/difflib.go | 772 ++++++++++ vendor/github.com/stretchr/testify/LICENSE | 22 + .../testify/assert/assertion_format.go | 349 +++++ .../testify/assert/assertion_format.go.tmpl | 4 + .../testify/assert/assertion_forward.go | 686 +++++++++ .../testify/assert/assertion_forward.go.tmpl | 4 + .../stretchr/testify/assert/assertions.go | 1256 +++++++++++++++++ .../github.com/stretchr/testify/assert/doc.go | 45 + .../stretchr/testify/assert/errors.go | 10 + .../testify/assert/forward_assertions.go | 16 + .../testify/assert/http_assertions.go | 127 ++ .../stretchr/testify/require/doc.go | 28 + .../testify/require/forward_requirements.go | 16 + .../stretchr/testify/require/require.go | 867 ++++++++++++ .../stretchr/testify/require/require.go.tmpl | 6 + .../testify/require/require_forward.go | 687 +++++++++ .../testify/require/require_forward.go.tmpl | 4 + .../stretchr/testify/require/requirements.go | 9 + .../github.com/stretchr/testify/suite/doc.go | 65 + .../stretchr/testify/suite/interfaces.go | 46 + .../stretchr/testify/suite/suite.go | 136 ++ 33 files changed, 7386 insertions(+) create mode 100644 Gopkg.lock create mode 100644 Gopkg.toml create mode 100644 vendor/github.com/davecgh/go-spew/LICENSE create mode 100644 vendor/github.com/davecgh/go-spew/spew/bypass.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/bypasssafe.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/common.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/config.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/doc.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/dump.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/format.go create mode 100644 vendor/github.com/davecgh/go-spew/spew/spew.go create mode 100644 vendor/github.com/pmezard/go-difflib/LICENSE create mode 100644 vendor/github.com/pmezard/go-difflib/difflib/difflib.go create mode 100644 vendor/github.com/stretchr/testify/LICENSE create mode 100644 vendor/github.com/stretchr/testify/assert/assertion_format.go create mode 100644 vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl create mode 100644 vendor/github.com/stretchr/testify/assert/assertion_forward.go create mode 100644 vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl create mode 100644 vendor/github.com/stretchr/testify/assert/assertions.go create mode 100644 vendor/github.com/stretchr/testify/assert/doc.go create mode 100644 vendor/github.com/stretchr/testify/assert/errors.go create mode 100644 vendor/github.com/stretchr/testify/assert/forward_assertions.go create mode 100644 vendor/github.com/stretchr/testify/assert/http_assertions.go create mode 100644 vendor/github.com/stretchr/testify/require/doc.go create mode 100644 vendor/github.com/stretchr/testify/require/forward_requirements.go create mode 100644 vendor/github.com/stretchr/testify/require/require.go create mode 100644 vendor/github.com/stretchr/testify/require/require.go.tmpl create mode 100644 vendor/github.com/stretchr/testify/require/require_forward.go create mode 100644 vendor/github.com/stretchr/testify/require/require_forward.go.tmpl create mode 100644 vendor/github.com/stretchr/testify/require/requirements.go create mode 100644 vendor/github.com/stretchr/testify/suite/doc.go create mode 100644 vendor/github.com/stretchr/testify/suite/interfaces.go create mode 100644 vendor/github.com/stretchr/testify/suite/suite.go diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 0000000..346921a --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,31 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + version = "v1.1.0" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + name = "github.com/stretchr/testify" + packages = [ + "assert", + "require", + "suite" + ] + revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" + version = "v1.2.1" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "1b10b1e002262a75c43af1c7f27d9a5df6b0662f1d76892ca432e3835a3cc704" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 0000000..55dbd3b --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,34 @@ +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[[constraint]] + name = "github.com/stretchr/testify" + version = "1.2.1" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/davecgh/go-spew/LICENSE b/vendor/github.com/davecgh/go-spew/LICENSE new file mode 100644 index 0000000..c836416 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2012-2016 Dave Collins + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/vendor/github.com/davecgh/go-spew/spew/bypass.go b/vendor/github.com/davecgh/go-spew/spew/bypass.go new file mode 100644 index 0000000..8a4a658 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/bypass.go @@ -0,0 +1,152 @@ +// Copyright (c) 2015-2016 Dave Collins +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +// NOTE: Due to the following build constraints, this file will only be compiled +// when the code is not running on Google App Engine, compiled by GopherJS, and +// "-tags safe" is not added to the go build command line. The "disableunsafe" +// tag is deprecated and thus should not be used. +// +build !js,!appengine,!safe,!disableunsafe + +package spew + +import ( + "reflect" + "unsafe" +) + +const ( + // UnsafeDisabled is a build-time constant which specifies whether or + // not access to the unsafe package is available. + UnsafeDisabled = false + + // ptrSize is the size of a pointer on the current arch. + ptrSize = unsafe.Sizeof((*byte)(nil)) +) + +var ( + // offsetPtr, offsetScalar, and offsetFlag are the offsets for the + // internal reflect.Value fields. These values are valid before golang + // commit ecccf07e7f9d which changed the format. The are also valid + // after commit 82f48826c6c7 which changed the format again to mirror + // the original format. Code in the init function updates these offsets + // as necessary. + offsetPtr = uintptr(ptrSize) + offsetScalar = uintptr(0) + offsetFlag = uintptr(ptrSize * 2) + + // flagKindWidth and flagKindShift indicate various bits that the + // reflect package uses internally to track kind information. + // + // flagRO indicates whether or not the value field of a reflect.Value is + // read-only. + // + // flagIndir indicates whether the value field of a reflect.Value is + // the actual data or a pointer to the data. + // + // These values are valid before golang commit 90a7c3c86944 which + // changed their positions. Code in the init function updates these + // flags as necessary. + flagKindWidth = uintptr(5) + flagKindShift = uintptr(flagKindWidth - 1) + flagRO = uintptr(1 << 0) + flagIndir = uintptr(1 << 1) +) + +func init() { + // Older versions of reflect.Value stored small integers directly in the + // ptr field (which is named val in the older versions). Versions + // between commits ecccf07e7f9d and 82f48826c6c7 added a new field named + // scalar for this purpose which unfortunately came before the flag + // field, so the offset of the flag field is different for those + // versions. + // + // This code constructs a new reflect.Value from a known small integer + // and checks if the size of the reflect.Value struct indicates it has + // the scalar field. When it does, the offsets are updated accordingly. + vv := reflect.ValueOf(0xf00) + if unsafe.Sizeof(vv) == (ptrSize * 4) { + offsetScalar = ptrSize * 2 + offsetFlag = ptrSize * 3 + } + + // Commit 90a7c3c86944 changed the flag positions such that the low + // order bits are the kind. This code extracts the kind from the flags + // field and ensures it's the correct type. When it's not, the flag + // order has been changed to the newer format, so the flags are updated + // accordingly. + upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag) + upfv := *(*uintptr)(upf) + flagKindMask := uintptr((1<>flagKindShift != uintptr(reflect.Int) { + flagKindShift = 0 + flagRO = 1 << 5 + flagIndir = 1 << 6 + + // Commit adf9b30e5594 modified the flags to separate the + // flagRO flag into two bits which specifies whether or not the + // field is embedded. This causes flagIndir to move over a bit + // and means that flagRO is the combination of either of the + // original flagRO bit and the new bit. + // + // This code detects the change by extracting what used to be + // the indirect bit to ensure it's set. When it's not, the flag + // order has been changed to the newer format, so the flags are + // updated accordingly. + if upfv&flagIndir == 0 { + flagRO = 3 << 5 + flagIndir = 1 << 7 + } + } +} + +// unsafeReflectValue converts the passed reflect.Value into a one that bypasses +// the typical safety restrictions preventing access to unaddressable and +// unexported data. It works by digging the raw pointer to the underlying +// value out of the protected value and generating a new unprotected (unsafe) +// reflect.Value to it. +// +// This allows us to check for implementations of the Stringer and error +// interfaces to be used for pretty printing ordinarily unaddressable and +// inaccessible values such as unexported struct fields. +func unsafeReflectValue(v reflect.Value) (rv reflect.Value) { + indirects := 1 + vt := v.Type() + upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr) + rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag)) + if rvf&flagIndir != 0 { + vt = reflect.PtrTo(v.Type()) + indirects++ + } else if offsetScalar != 0 { + // The value is in the scalar field when it's not one of the + // reference types. + switch vt.Kind() { + case reflect.Uintptr: + case reflect.Chan: + case reflect.Func: + case reflect.Map: + case reflect.Ptr: + case reflect.UnsafePointer: + default: + upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + + offsetScalar) + } + } + + pv := reflect.NewAt(vt, upv) + rv = pv + for i := 0; i < indirects; i++ { + rv = rv.Elem() + } + return rv +} diff --git a/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go new file mode 100644 index 0000000..1fe3cf3 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go @@ -0,0 +1,38 @@ +// Copyright (c) 2015-2016 Dave Collins +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +// NOTE: Due to the following build constraints, this file will only be compiled +// when the code is running on Google App Engine, compiled by GopherJS, or +// "-tags safe" is added to the go build command line. The "disableunsafe" +// tag is deprecated and thus should not be used. +// +build js appengine safe disableunsafe + +package spew + +import "reflect" + +const ( + // UnsafeDisabled is a build-time constant which specifies whether or + // not access to the unsafe package is available. + UnsafeDisabled = true +) + +// unsafeReflectValue typically converts the passed reflect.Value into a one +// that bypasses the typical safety restrictions preventing access to +// unaddressable and unexported data. However, doing this relies on access to +// the unsafe package. This is a stub version which simply returns the passed +// reflect.Value when the unsafe package is not available. +func unsafeReflectValue(v reflect.Value) reflect.Value { + return v +} diff --git a/vendor/github.com/davecgh/go-spew/spew/common.go b/vendor/github.com/davecgh/go-spew/spew/common.go new file mode 100644 index 0000000..7c519ff --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/common.go @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "fmt" + "io" + "reflect" + "sort" + "strconv" +) + +// Some constants in the form of bytes to avoid string overhead. This mirrors +// the technique used in the fmt package. +var ( + panicBytes = []byte("(PANIC=") + plusBytes = []byte("+") + iBytes = []byte("i") + trueBytes = []byte("true") + falseBytes = []byte("false") + interfaceBytes = []byte("(interface {})") + commaNewlineBytes = []byte(",\n") + newlineBytes = []byte("\n") + openBraceBytes = []byte("{") + openBraceNewlineBytes = []byte("{\n") + closeBraceBytes = []byte("}") + asteriskBytes = []byte("*") + colonBytes = []byte(":") + colonSpaceBytes = []byte(": ") + openParenBytes = []byte("(") + closeParenBytes = []byte(")") + spaceBytes = []byte(" ") + pointerChainBytes = []byte("->") + nilAngleBytes = []byte("") + maxNewlineBytes = []byte("\n") + maxShortBytes = []byte("") + circularBytes = []byte("") + circularShortBytes = []byte("") + invalidAngleBytes = []byte("") + openBracketBytes = []byte("[") + closeBracketBytes = []byte("]") + percentBytes = []byte("%") + precisionBytes = []byte(".") + openAngleBytes = []byte("<") + closeAngleBytes = []byte(">") + openMapBytes = []byte("map[") + closeMapBytes = []byte("]") + lenEqualsBytes = []byte("len=") + capEqualsBytes = []byte("cap=") +) + +// hexDigits is used to map a decimal value to a hex digit. +var hexDigits = "0123456789abcdef" + +// catchPanic handles any panics that might occur during the handleMethods +// calls. +func catchPanic(w io.Writer, v reflect.Value) { + if err := recover(); err != nil { + w.Write(panicBytes) + fmt.Fprintf(w, "%v", err) + w.Write(closeParenBytes) + } +} + +// handleMethods attempts to call the Error and String methods on the underlying +// type the passed reflect.Value represents and outputes the result to Writer w. +// +// It handles panics in any called methods by catching and displaying the error +// as the formatted value. +func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) { + // We need an interface to check if the type implements the error or + // Stringer interface. However, the reflect package won't give us an + // interface on certain things like unexported struct fields in order + // to enforce visibility rules. We use unsafe, when it's available, + // to bypass these restrictions since this package does not mutate the + // values. + if !v.CanInterface() { + if UnsafeDisabled { + return false + } + + v = unsafeReflectValue(v) + } + + // Choose whether or not to do error and Stringer interface lookups against + // the base type or a pointer to the base type depending on settings. + // Technically calling one of these methods with a pointer receiver can + // mutate the value, however, types which choose to satisify an error or + // Stringer interface with a pointer receiver should not be mutating their + // state inside these interface methods. + if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() { + v = unsafeReflectValue(v) + } + if v.CanAddr() { + v = v.Addr() + } + + // Is it an error or Stringer? + switch iface := v.Interface().(type) { + case error: + defer catchPanic(w, v) + if cs.ContinueOnMethod { + w.Write(openParenBytes) + w.Write([]byte(iface.Error())) + w.Write(closeParenBytes) + w.Write(spaceBytes) + return false + } + + w.Write([]byte(iface.Error())) + return true + + case fmt.Stringer: + defer catchPanic(w, v) + if cs.ContinueOnMethod { + w.Write(openParenBytes) + w.Write([]byte(iface.String())) + w.Write(closeParenBytes) + w.Write(spaceBytes) + return false + } + w.Write([]byte(iface.String())) + return true + } + return false +} + +// printBool outputs a boolean value as true or false to Writer w. +func printBool(w io.Writer, val bool) { + if val { + w.Write(trueBytes) + } else { + w.Write(falseBytes) + } +} + +// printInt outputs a signed integer value to Writer w. +func printInt(w io.Writer, val int64, base int) { + w.Write([]byte(strconv.FormatInt(val, base))) +} + +// printUint outputs an unsigned integer value to Writer w. +func printUint(w io.Writer, val uint64, base int) { + w.Write([]byte(strconv.FormatUint(val, base))) +} + +// printFloat outputs a floating point value using the specified precision, +// which is expected to be 32 or 64bit, to Writer w. +func printFloat(w io.Writer, val float64, precision int) { + w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision))) +} + +// printComplex outputs a complex value using the specified float precision +// for the real and imaginary parts to Writer w. +func printComplex(w io.Writer, c complex128, floatPrecision int) { + r := real(c) + w.Write(openParenBytes) + w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision))) + i := imag(c) + if i >= 0 { + w.Write(plusBytes) + } + w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision))) + w.Write(iBytes) + w.Write(closeParenBytes) +} + +// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x' +// prefix to Writer w. +func printHexPtr(w io.Writer, p uintptr) { + // Null pointer. + num := uint64(p) + if num == 0 { + w.Write(nilAngleBytes) + return + } + + // Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix + buf := make([]byte, 18) + + // It's simpler to construct the hex string right to left. + base := uint64(16) + i := len(buf) - 1 + for num >= base { + buf[i] = hexDigits[num%base] + num /= base + i-- + } + buf[i] = hexDigits[num] + + // Add '0x' prefix. + i-- + buf[i] = 'x' + i-- + buf[i] = '0' + + // Strip unused leading bytes. + buf = buf[i:] + w.Write(buf) +} + +// valuesSorter implements sort.Interface to allow a slice of reflect.Value +// elements to be sorted. +type valuesSorter struct { + values []reflect.Value + strings []string // either nil or same len and values + cs *ConfigState +} + +// newValuesSorter initializes a valuesSorter instance, which holds a set of +// surrogate keys on which the data should be sorted. It uses flags in +// ConfigState to decide if and how to populate those surrogate keys. +func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface { + vs := &valuesSorter{values: values, cs: cs} + if canSortSimply(vs.values[0].Kind()) { + return vs + } + if !cs.DisableMethods { + vs.strings = make([]string, len(values)) + for i := range vs.values { + b := bytes.Buffer{} + if !handleMethods(cs, &b, vs.values[i]) { + vs.strings = nil + break + } + vs.strings[i] = b.String() + } + } + if vs.strings == nil && cs.SpewKeys { + vs.strings = make([]string, len(values)) + for i := range vs.values { + vs.strings[i] = Sprintf("%#v", vs.values[i].Interface()) + } + } + return vs +} + +// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted +// directly, or whether it should be considered for sorting by surrogate keys +// (if the ConfigState allows it). +func canSortSimply(kind reflect.Kind) bool { + // This switch parallels valueSortLess, except for the default case. + switch kind { + case reflect.Bool: + return true + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + return true + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + return true + case reflect.Float32, reflect.Float64: + return true + case reflect.String: + return true + case reflect.Uintptr: + return true + case reflect.Array: + return true + } + return false +} + +// Len returns the number of values in the slice. It is part of the +// sort.Interface implementation. +func (s *valuesSorter) Len() int { + return len(s.values) +} + +// Swap swaps the values at the passed indices. It is part of the +// sort.Interface implementation. +func (s *valuesSorter) Swap(i, j int) { + s.values[i], s.values[j] = s.values[j], s.values[i] + if s.strings != nil { + s.strings[i], s.strings[j] = s.strings[j], s.strings[i] + } +} + +// valueSortLess returns whether the first value should sort before the second +// value. It is used by valueSorter.Less as part of the sort.Interface +// implementation. +func valueSortLess(a, b reflect.Value) bool { + switch a.Kind() { + case reflect.Bool: + return !a.Bool() && b.Bool() + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + return a.Int() < b.Int() + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + return a.Uint() < b.Uint() + case reflect.Float32, reflect.Float64: + return a.Float() < b.Float() + case reflect.String: + return a.String() < b.String() + case reflect.Uintptr: + return a.Uint() < b.Uint() + case reflect.Array: + // Compare the contents of both arrays. + l := a.Len() + for i := 0; i < l; i++ { + av := a.Index(i) + bv := b.Index(i) + if av.Interface() == bv.Interface() { + continue + } + return valueSortLess(av, bv) + } + } + return a.String() < b.String() +} + +// Less returns whether the value at index i should sort before the +// value at index j. It is part of the sort.Interface implementation. +func (s *valuesSorter) Less(i, j int) bool { + if s.strings == nil { + return valueSortLess(s.values[i], s.values[j]) + } + return s.strings[i] < s.strings[j] +} + +// sortValues is a sort function that handles both native types and any type that +// can be converted to error or Stringer. Other inputs are sorted according to +// their Value.String() value to ensure display stability. +func sortValues(values []reflect.Value, cs *ConfigState) { + if len(values) == 0 { + return + } + sort.Sort(newValuesSorter(values, cs)) +} diff --git a/vendor/github.com/davecgh/go-spew/spew/config.go b/vendor/github.com/davecgh/go-spew/spew/config.go new file mode 100644 index 0000000..2e3d22f --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/config.go @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "fmt" + "io" + "os" +) + +// ConfigState houses the configuration options used by spew to format and +// display values. There is a global instance, Config, that is used to control +// all top-level Formatter and Dump functionality. Each ConfigState instance +// provides methods equivalent to the top-level functions. +// +// The zero value for ConfigState provides no indentation. You would typically +// want to set it to a space or a tab. +// +// Alternatively, you can use NewDefaultConfig to get a ConfigState instance +// with default settings. See the documentation of NewDefaultConfig for default +// values. +type ConfigState struct { + // Indent specifies the string to use for each indentation level. The + // global config instance that all top-level functions use set this to a + // single space by default. If you would like more indentation, you might + // set this to a tab with "\t" or perhaps two spaces with " ". + Indent string + + // MaxDepth controls the maximum number of levels to descend into nested + // data structures. The default, 0, means there is no limit. + // + // NOTE: Circular data structures are properly detected, so it is not + // necessary to set this value unless you specifically want to limit deeply + // nested data structures. + MaxDepth int + + // DisableMethods specifies whether or not error and Stringer interfaces are + // invoked for types that implement them. + DisableMethods bool + + // DisablePointerMethods specifies whether or not to check for and invoke + // error and Stringer interfaces on types which only accept a pointer + // receiver when the current type is not a pointer. + // + // NOTE: This might be an unsafe action since calling one of these methods + // with a pointer receiver could technically mutate the value, however, + // in practice, types which choose to satisify an error or Stringer + // interface with a pointer receiver should not be mutating their state + // inside these interface methods. As a result, this option relies on + // access to the unsafe package, so it will not have any effect when + // running in environments without access to the unsafe package such as + // Google App Engine or with the "safe" build tag specified. + DisablePointerMethods bool + + // DisablePointerAddresses specifies whether to disable the printing of + // pointer addresses. This is useful when diffing data structures in tests. + DisablePointerAddresses bool + + // DisableCapacities specifies whether to disable the printing of capacities + // for arrays, slices, maps and channels. This is useful when diffing + // data structures in tests. + DisableCapacities bool + + // ContinueOnMethod specifies whether or not recursion should continue once + // a custom error or Stringer interface is invoked. The default, false, + // means it will print the results of invoking the custom error or Stringer + // interface and return immediately instead of continuing to recurse into + // the internals of the data type. + // + // NOTE: This flag does not have any effect if method invocation is disabled + // via the DisableMethods or DisablePointerMethods options. + ContinueOnMethod bool + + // SortKeys specifies map keys should be sorted before being printed. Use + // this to have a more deterministic, diffable output. Note that only + // native types (bool, int, uint, floats, uintptr and string) and types + // that support the error or Stringer interfaces (if methods are + // enabled) are supported, with other types sorted according to the + // reflect.Value.String() output which guarantees display stability. + SortKeys bool + + // SpewKeys specifies that, as a last resort attempt, map keys should + // be spewed to strings and sorted by those strings. This is only + // considered if SortKeys is true. + SpewKeys bool +} + +// Config is the active configuration of the top-level functions. +// The configuration can be changed by modifying the contents of spew.Config. +var Config = ConfigState{Indent: " "} + +// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the formatted string as a value that satisfies error. See NewFormatter +// for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) { + return fmt.Errorf(format, c.convertArgs(a)...) +} + +// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprint(w, c.convertArgs(a)...) +} + +// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { + return fmt.Fprintf(w, format, c.convertArgs(a)...) +} + +// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it +// passed with a Formatter interface returned by c.NewFormatter. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprintln(w, c.convertArgs(a)...) +} + +// Print is a wrapper for fmt.Print that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Print(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Print(a ...interface{}) (n int, err error) { + return fmt.Print(c.convertArgs(a)...) +} + +// Printf is a wrapper for fmt.Printf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) { + return fmt.Printf(format, c.convertArgs(a)...) +} + +// Println is a wrapper for fmt.Println that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Println(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Println(a ...interface{}) (n int, err error) { + return fmt.Println(c.convertArgs(a)...) +} + +// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Sprint(a ...interface{}) string { + return fmt.Sprint(c.convertArgs(a)...) +} + +// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Sprintf(format string, a ...interface{}) string { + return fmt.Sprintf(format, c.convertArgs(a)...) +} + +// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it +// were passed with a Formatter interface returned by c.NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Sprintln(a ...interface{}) string { + return fmt.Sprintln(c.convertArgs(a)...) +} + +/* +NewFormatter returns a custom formatter that satisfies the fmt.Formatter +interface. As a result, it integrates cleanly with standard fmt package +printing functions. The formatter is useful for inline printing of smaller data +types similar to the standard %v format specifier. + +The custom formatter only responds to the %v (most compact), %+v (adds pointer +addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb +combinations. Any other verbs such as %x and %q will be sent to the the +standard fmt package for formatting. In addition, the custom formatter ignores +the width and precision arguments (however they will still work on the format +specifiers not handled by the custom formatter). + +Typically this function shouldn't be called directly. It is much easier to make +use of the custom formatter by calling one of the convenience functions such as +c.Printf, c.Println, or c.Printf. +*/ +func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter { + return newFormatter(c, v) +} + +// Fdump formats and displays the passed arguments to io.Writer w. It formats +// exactly the same as Dump. +func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) { + fdump(c, w, a...) +} + +/* +Dump displays the passed parameters to standard out with newlines, customizable +indentation, and additional debug information such as complete types and all +pointer addresses used to indirect to the final value. It provides the +following features over the built-in printing facilities provided by the fmt +package: + + * Pointers are dereferenced and followed + * Circular data structures are detected and handled properly + * Custom Stringer/error interfaces are optionally invoked, including + on unexported types + * Custom types which only implement the Stringer/error interfaces via + a pointer receiver are optionally invoked when passing non-pointer + variables + * Byte arrays and slices are dumped like the hexdump -C command which + includes offsets, byte values in hex, and ASCII output + +The configuration options are controlled by modifying the public members +of c. See ConfigState for options documentation. + +See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to +get the formatted result as a string. +*/ +func (c *ConfigState) Dump(a ...interface{}) { + fdump(c, os.Stdout, a...) +} + +// Sdump returns a string with the passed arguments formatted exactly the same +// as Dump. +func (c *ConfigState) Sdump(a ...interface{}) string { + var buf bytes.Buffer + fdump(c, &buf, a...) + return buf.String() +} + +// convertArgs accepts a slice of arguments and returns a slice of the same +// length with each argument converted to a spew Formatter interface using +// the ConfigState associated with s. +func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) { + formatters = make([]interface{}, len(args)) + for index, arg := range args { + formatters[index] = newFormatter(c, arg) + } + return formatters +} + +// NewDefaultConfig returns a ConfigState with the following default settings. +// +// Indent: " " +// MaxDepth: 0 +// DisableMethods: false +// DisablePointerMethods: false +// ContinueOnMethod: false +// SortKeys: false +func NewDefaultConfig() *ConfigState { + return &ConfigState{Indent: " "} +} diff --git a/vendor/github.com/davecgh/go-spew/spew/doc.go b/vendor/github.com/davecgh/go-spew/spew/doc.go new file mode 100644 index 0000000..aacaac6 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/doc.go @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* +Package spew implements a deep pretty printer for Go data structures to aid in +debugging. + +A quick overview of the additional features spew provides over the built-in +printing facilities for Go data types are as follows: + + * Pointers are dereferenced and followed + * Circular data structures are detected and handled properly + * Custom Stringer/error interfaces are optionally invoked, including + on unexported types + * Custom types which only implement the Stringer/error interfaces via + a pointer receiver are optionally invoked when passing non-pointer + variables + * Byte arrays and slices are dumped like the hexdump -C command which + includes offsets, byte values in hex, and ASCII output (only when using + Dump style) + +There are two different approaches spew allows for dumping Go data structures: + + * Dump style which prints with newlines, customizable indentation, + and additional debug information such as types and all pointer addresses + used to indirect to the final value + * A custom Formatter interface that integrates cleanly with the standard fmt + package and replaces %v, %+v, %#v, and %#+v to provide inline printing + similar to the default %v while providing the additional functionality + outlined above and passing unsupported format verbs such as %x and %q + along to fmt + +Quick Start + +This section demonstrates how to quickly get started with spew. See the +sections below for further details on formatting and configuration options. + +To dump a variable with full newlines, indentation, type, and pointer +information use Dump, Fdump, or Sdump: + spew.Dump(myVar1, myVar2, ...) + spew.Fdump(someWriter, myVar1, myVar2, ...) + str := spew.Sdump(myVar1, myVar2, ...) + +Alternatively, if you would prefer to use format strings with a compacted inline +printing style, use the convenience wrappers Printf, Fprintf, etc with +%v (most compact), %+v (adds pointer addresses), %#v (adds types), or +%#+v (adds types and pointer addresses): + spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + +Configuration Options + +Configuration of spew is handled by fields in the ConfigState type. For +convenience, all of the top-level functions use a global state available +via the spew.Config global. + +It is also possible to create a ConfigState instance that provides methods +equivalent to the top-level functions. This allows concurrent configuration +options. See the ConfigState documentation for more details. + +The following configuration options are available: + * Indent + String to use for each indentation level for Dump functions. + It is a single space by default. A popular alternative is "\t". + + * MaxDepth + Maximum number of levels to descend into nested data structures. + There is no limit by default. + + * DisableMethods + Disables invocation of error and Stringer interface methods. + Method invocation is enabled by default. + + * DisablePointerMethods + Disables invocation of error and Stringer interface methods on types + which only accept pointer receivers from non-pointer variables. + Pointer method invocation is enabled by default. + + * DisablePointerAddresses + DisablePointerAddresses specifies whether to disable the printing of + pointer addresses. This is useful when diffing data structures in tests. + + * DisableCapacities + DisableCapacities specifies whether to disable the printing of + capacities for arrays, slices, maps and channels. This is useful when + diffing data structures in tests. + + * ContinueOnMethod + Enables recursion into types after invoking error and Stringer interface + methods. Recursion after method invocation is disabled by default. + + * SortKeys + Specifies map keys should be sorted before being printed. Use + this to have a more deterministic, diffable output. Note that + only native types (bool, int, uint, floats, uintptr and string) + and types which implement error or Stringer interfaces are + supported with other types sorted according to the + reflect.Value.String() output which guarantees display + stability. Natural map order is used by default. + + * SpewKeys + Specifies that, as a last resort attempt, map keys should be + spewed to strings and sorted by those strings. This is only + considered if SortKeys is true. + +Dump Usage + +Simply call spew.Dump with a list of variables you want to dump: + + spew.Dump(myVar1, myVar2, ...) + +You may also call spew.Fdump if you would prefer to output to an arbitrary +io.Writer. For example, to dump to standard error: + + spew.Fdump(os.Stderr, myVar1, myVar2, ...) + +A third option is to call spew.Sdump to get the formatted output as a string: + + str := spew.Sdump(myVar1, myVar2, ...) + +Sample Dump Output + +See the Dump example for details on the setup of the types and variables being +shown here. + + (main.Foo) { + unexportedField: (*main.Bar)(0xf84002e210)({ + flag: (main.Flag) flagTwo, + data: (uintptr) + }), + ExportedField: (map[interface {}]interface {}) (len=1) { + (string) (len=3) "one": (bool) true + } + } + +Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C +command as shown. + ([]uint8) (len=32 cap=32) { + 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... | + 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| + 00000020 31 32 |12| + } + +Custom Formatter + +Spew provides a custom formatter that implements the fmt.Formatter interface +so that it integrates cleanly with standard fmt package printing functions. The +formatter is useful for inline printing of smaller data types similar to the +standard %v format specifier. + +The custom formatter only responds to the %v (most compact), %+v (adds pointer +addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb +combinations. Any other verbs such as %x and %q will be sent to the the +standard fmt package for formatting. In addition, the custom formatter ignores +the width and precision arguments (however they will still work on the format +specifiers not handled by the custom formatter). + +Custom Formatter Usage + +The simplest way to make use of the spew custom formatter is to call one of the +convenience functions such as spew.Printf, spew.Println, or spew.Printf. The +functions have syntax you are most likely already familiar with: + + spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + spew.Println(myVar, myVar2) + spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) + spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) + +See the Index for the full list convenience functions. + +Sample Formatter Output + +Double pointer to a uint8: + %v: <**>5 + %+v: <**>(0xf8400420d0->0xf8400420c8)5 + %#v: (**uint8)5 + %#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5 + +Pointer to circular struct with a uint8 field and a pointer to itself: + %v: <*>{1 <*>} + %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)} + %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)} + %#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)} + +See the Printf example for details on the setup of variables being shown +here. + +Errors + +Since it is possible for custom Stringer/error interfaces to panic, spew +detects them and handles them internally by printing the panic information +inline with the output. Since spew is intended to provide deep pretty printing +capabilities on structures, it intentionally does not return any errors. +*/ +package spew diff --git a/vendor/github.com/davecgh/go-spew/spew/dump.go b/vendor/github.com/davecgh/go-spew/spew/dump.go new file mode 100644 index 0000000..df1d582 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/dump.go @@ -0,0 +1,509 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "encoding/hex" + "fmt" + "io" + "os" + "reflect" + "regexp" + "strconv" + "strings" +) + +var ( + // uint8Type is a reflect.Type representing a uint8. It is used to + // convert cgo types to uint8 slices for hexdumping. + uint8Type = reflect.TypeOf(uint8(0)) + + // cCharRE is a regular expression that matches a cgo char. + // It is used to detect character arrays to hexdump them. + cCharRE = regexp.MustCompile("^.*\\._Ctype_char$") + + // cUnsignedCharRE is a regular expression that matches a cgo unsigned + // char. It is used to detect unsigned character arrays to hexdump + // them. + cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$") + + // cUint8tCharRE is a regular expression that matches a cgo uint8_t. + // It is used to detect uint8_t arrays to hexdump them. + cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$") +) + +// dumpState contains information about the state of a dump operation. +type dumpState struct { + w io.Writer + depth int + pointers map[uintptr]int + ignoreNextType bool + ignoreNextIndent bool + cs *ConfigState +} + +// indent performs indentation according to the depth level and cs.Indent +// option. +func (d *dumpState) indent() { + if d.ignoreNextIndent { + d.ignoreNextIndent = false + return + } + d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth)) +} + +// unpackValue returns values inside of non-nil interfaces when possible. +// This is useful for data types like structs, arrays, slices, and maps which +// can contain varying types packed inside an interface. +func (d *dumpState) unpackValue(v reflect.Value) reflect.Value { + if v.Kind() == reflect.Interface && !v.IsNil() { + v = v.Elem() + } + return v +} + +// dumpPtr handles formatting of pointers by indirecting them as necessary. +func (d *dumpState) dumpPtr(v reflect.Value) { + // Remove pointers at or below the current depth from map used to detect + // circular refs. + for k, depth := range d.pointers { + if depth >= d.depth { + delete(d.pointers, k) + } + } + + // Keep list of all dereferenced pointers to show later. + pointerChain := make([]uintptr, 0) + + // Figure out how many levels of indirection there are by dereferencing + // pointers and unpacking interfaces down the chain while detecting circular + // references. + nilFound := false + cycleFound := false + indirects := 0 + ve := v + for ve.Kind() == reflect.Ptr { + if ve.IsNil() { + nilFound = true + break + } + indirects++ + addr := ve.Pointer() + pointerChain = append(pointerChain, addr) + if pd, ok := d.pointers[addr]; ok && pd < d.depth { + cycleFound = true + indirects-- + break + } + d.pointers[addr] = d.depth + + ve = ve.Elem() + if ve.Kind() == reflect.Interface { + if ve.IsNil() { + nilFound = true + break + } + ve = ve.Elem() + } + } + + // Display type information. + d.w.Write(openParenBytes) + d.w.Write(bytes.Repeat(asteriskBytes, indirects)) + d.w.Write([]byte(ve.Type().String())) + d.w.Write(closeParenBytes) + + // Display pointer information. + if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 { + d.w.Write(openParenBytes) + for i, addr := range pointerChain { + if i > 0 { + d.w.Write(pointerChainBytes) + } + printHexPtr(d.w, addr) + } + d.w.Write(closeParenBytes) + } + + // Display dereferenced value. + d.w.Write(openParenBytes) + switch { + case nilFound == true: + d.w.Write(nilAngleBytes) + + case cycleFound == true: + d.w.Write(circularBytes) + + default: + d.ignoreNextType = true + d.dump(ve) + } + d.w.Write(closeParenBytes) +} + +// dumpSlice handles formatting of arrays and slices. Byte (uint8 under +// reflection) arrays and slices are dumped in hexdump -C fashion. +func (d *dumpState) dumpSlice(v reflect.Value) { + // Determine whether this type should be hex dumped or not. Also, + // for types which should be hexdumped, try to use the underlying data + // first, then fall back to trying to convert them to a uint8 slice. + var buf []uint8 + doConvert := false + doHexDump := false + numEntries := v.Len() + if numEntries > 0 { + vt := v.Index(0).Type() + vts := vt.String() + switch { + // C types that need to be converted. + case cCharRE.MatchString(vts): + fallthrough + case cUnsignedCharRE.MatchString(vts): + fallthrough + case cUint8tCharRE.MatchString(vts): + doConvert = true + + // Try to use existing uint8 slices and fall back to converting + // and copying if that fails. + case vt.Kind() == reflect.Uint8: + // We need an addressable interface to convert the type + // to a byte slice. However, the reflect package won't + // give us an interface on certain things like + // unexported struct fields in order to enforce + // visibility rules. We use unsafe, when available, to + // bypass these restrictions since this package does not + // mutate the values. + vs := v + if !vs.CanInterface() || !vs.CanAddr() { + vs = unsafeReflectValue(vs) + } + if !UnsafeDisabled { + vs = vs.Slice(0, numEntries) + + // Use the existing uint8 slice if it can be + // type asserted. + iface := vs.Interface() + if slice, ok := iface.([]uint8); ok { + buf = slice + doHexDump = true + break + } + } + + // The underlying data needs to be converted if it can't + // be type asserted to a uint8 slice. + doConvert = true + } + + // Copy and convert the underlying type if needed. + if doConvert && vt.ConvertibleTo(uint8Type) { + // Convert and copy each element into a uint8 byte + // slice. + buf = make([]uint8, numEntries) + for i := 0; i < numEntries; i++ { + vv := v.Index(i) + buf[i] = uint8(vv.Convert(uint8Type).Uint()) + } + doHexDump = true + } + } + + // Hexdump the entire slice as needed. + if doHexDump { + indent := strings.Repeat(d.cs.Indent, d.depth) + str := indent + hex.Dump(buf) + str = strings.Replace(str, "\n", "\n"+indent, -1) + str = strings.TrimRight(str, d.cs.Indent) + d.w.Write([]byte(str)) + return + } + + // Recursively call dump for each item. + for i := 0; i < numEntries; i++ { + d.dump(d.unpackValue(v.Index(i))) + if i < (numEntries - 1) { + d.w.Write(commaNewlineBytes) + } else { + d.w.Write(newlineBytes) + } + } +} + +// dump is the main workhorse for dumping a value. It uses the passed reflect +// value to figure out what kind of object we are dealing with and formats it +// appropriately. It is a recursive function, however circular data structures +// are detected and handled properly. +func (d *dumpState) dump(v reflect.Value) { + // Handle invalid reflect values immediately. + kind := v.Kind() + if kind == reflect.Invalid { + d.w.Write(invalidAngleBytes) + return + } + + // Handle pointers specially. + if kind == reflect.Ptr { + d.indent() + d.dumpPtr(v) + return + } + + // Print type information unless already handled elsewhere. + if !d.ignoreNextType { + d.indent() + d.w.Write(openParenBytes) + d.w.Write([]byte(v.Type().String())) + d.w.Write(closeParenBytes) + d.w.Write(spaceBytes) + } + d.ignoreNextType = false + + // Display length and capacity if the built-in len and cap functions + // work with the value's kind and the len/cap itself is non-zero. + valueLen, valueCap := 0, 0 + switch v.Kind() { + case reflect.Array, reflect.Slice, reflect.Chan: + valueLen, valueCap = v.Len(), v.Cap() + case reflect.Map, reflect.String: + valueLen = v.Len() + } + if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 { + d.w.Write(openParenBytes) + if valueLen != 0 { + d.w.Write(lenEqualsBytes) + printInt(d.w, int64(valueLen), 10) + } + if !d.cs.DisableCapacities && valueCap != 0 { + if valueLen != 0 { + d.w.Write(spaceBytes) + } + d.w.Write(capEqualsBytes) + printInt(d.w, int64(valueCap), 10) + } + d.w.Write(closeParenBytes) + d.w.Write(spaceBytes) + } + + // Call Stringer/error interfaces if they exist and the handle methods flag + // is enabled + if !d.cs.DisableMethods { + if (kind != reflect.Invalid) && (kind != reflect.Interface) { + if handled := handleMethods(d.cs, d.w, v); handled { + return + } + } + } + + switch kind { + case reflect.Invalid: + // Do nothing. We should never get here since invalid has already + // been handled above. + + case reflect.Bool: + printBool(d.w, v.Bool()) + + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + printInt(d.w, v.Int(), 10) + + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + printUint(d.w, v.Uint(), 10) + + case reflect.Float32: + printFloat(d.w, v.Float(), 32) + + case reflect.Float64: + printFloat(d.w, v.Float(), 64) + + case reflect.Complex64: + printComplex(d.w, v.Complex(), 32) + + case reflect.Complex128: + printComplex(d.w, v.Complex(), 64) + + case reflect.Slice: + if v.IsNil() { + d.w.Write(nilAngleBytes) + break + } + fallthrough + + case reflect.Array: + d.w.Write(openBraceNewlineBytes) + d.depth++ + if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { + d.indent() + d.w.Write(maxNewlineBytes) + } else { + d.dumpSlice(v) + } + d.depth-- + d.indent() + d.w.Write(closeBraceBytes) + + case reflect.String: + d.w.Write([]byte(strconv.Quote(v.String()))) + + case reflect.Interface: + // The only time we should get here is for nil interfaces due to + // unpackValue calls. + if v.IsNil() { + d.w.Write(nilAngleBytes) + } + + case reflect.Ptr: + // Do nothing. We should never get here since pointers have already + // been handled above. + + case reflect.Map: + // nil maps should be indicated as different than empty maps + if v.IsNil() { + d.w.Write(nilAngleBytes) + break + } + + d.w.Write(openBraceNewlineBytes) + d.depth++ + if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { + d.indent() + d.w.Write(maxNewlineBytes) + } else { + numEntries := v.Len() + keys := v.MapKeys() + if d.cs.SortKeys { + sortValues(keys, d.cs) + } + for i, key := range keys { + d.dump(d.unpackValue(key)) + d.w.Write(colonSpaceBytes) + d.ignoreNextIndent = true + d.dump(d.unpackValue(v.MapIndex(key))) + if i < (numEntries - 1) { + d.w.Write(commaNewlineBytes) + } else { + d.w.Write(newlineBytes) + } + } + } + d.depth-- + d.indent() + d.w.Write(closeBraceBytes) + + case reflect.Struct: + d.w.Write(openBraceNewlineBytes) + d.depth++ + if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { + d.indent() + d.w.Write(maxNewlineBytes) + } else { + vt := v.Type() + numFields := v.NumField() + for i := 0; i < numFields; i++ { + d.indent() + vtf := vt.Field(i) + d.w.Write([]byte(vtf.Name)) + d.w.Write(colonSpaceBytes) + d.ignoreNextIndent = true + d.dump(d.unpackValue(v.Field(i))) + if i < (numFields - 1) { + d.w.Write(commaNewlineBytes) + } else { + d.w.Write(newlineBytes) + } + } + } + d.depth-- + d.indent() + d.w.Write(closeBraceBytes) + + case reflect.Uintptr: + printHexPtr(d.w, uintptr(v.Uint())) + + case reflect.UnsafePointer, reflect.Chan, reflect.Func: + printHexPtr(d.w, v.Pointer()) + + // There were not any other types at the time this code was written, but + // fall back to letting the default fmt package handle it in case any new + // types are added. + default: + if v.CanInterface() { + fmt.Fprintf(d.w, "%v", v.Interface()) + } else { + fmt.Fprintf(d.w, "%v", v.String()) + } + } +} + +// fdump is a helper function to consolidate the logic from the various public +// methods which take varying writers and config states. +func fdump(cs *ConfigState, w io.Writer, a ...interface{}) { + for _, arg := range a { + if arg == nil { + w.Write(interfaceBytes) + w.Write(spaceBytes) + w.Write(nilAngleBytes) + w.Write(newlineBytes) + continue + } + + d := dumpState{w: w, cs: cs} + d.pointers = make(map[uintptr]int) + d.dump(reflect.ValueOf(arg)) + d.w.Write(newlineBytes) + } +} + +// Fdump formats and displays the passed arguments to io.Writer w. It formats +// exactly the same as Dump. +func Fdump(w io.Writer, a ...interface{}) { + fdump(&Config, w, a...) +} + +// Sdump returns a string with the passed arguments formatted exactly the same +// as Dump. +func Sdump(a ...interface{}) string { + var buf bytes.Buffer + fdump(&Config, &buf, a...) + return buf.String() +} + +/* +Dump displays the passed parameters to standard out with newlines, customizable +indentation, and additional debug information such as complete types and all +pointer addresses used to indirect to the final value. It provides the +following features over the built-in printing facilities provided by the fmt +package: + + * Pointers are dereferenced and followed + * Circular data structures are detected and handled properly + * Custom Stringer/error interfaces are optionally invoked, including + on unexported types + * Custom types which only implement the Stringer/error interfaces via + a pointer receiver are optionally invoked when passing non-pointer + variables + * Byte arrays and slices are dumped like the hexdump -C command which + includes offsets, byte values in hex, and ASCII output + +The configuration options are controlled by an exported package global, +spew.Config. See ConfigState for options documentation. + +See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to +get the formatted result as a string. +*/ +func Dump(a ...interface{}) { + fdump(&Config, os.Stdout, a...) +} diff --git a/vendor/github.com/davecgh/go-spew/spew/format.go b/vendor/github.com/davecgh/go-spew/spew/format.go new file mode 100644 index 0000000..c49875b --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/format.go @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "bytes" + "fmt" + "reflect" + "strconv" + "strings" +) + +// supportedFlags is a list of all the character flags supported by fmt package. +const supportedFlags = "0-+# " + +// formatState implements the fmt.Formatter interface and contains information +// about the state of a formatting operation. The NewFormatter function can +// be used to get a new Formatter which can be used directly as arguments +// in standard fmt package printing calls. +type formatState struct { + value interface{} + fs fmt.State + depth int + pointers map[uintptr]int + ignoreNextType bool + cs *ConfigState +} + +// buildDefaultFormat recreates the original format string without precision +// and width information to pass in to fmt.Sprintf in the case of an +// unrecognized type. Unless new types are added to the language, this +// function won't ever be called. +func (f *formatState) buildDefaultFormat() (format string) { + buf := bytes.NewBuffer(percentBytes) + + for _, flag := range supportedFlags { + if f.fs.Flag(int(flag)) { + buf.WriteRune(flag) + } + } + + buf.WriteRune('v') + + format = buf.String() + return format +} + +// constructOrigFormat recreates the original format string including precision +// and width information to pass along to the standard fmt package. This allows +// automatic deferral of all format strings this package doesn't support. +func (f *formatState) constructOrigFormat(verb rune) (format string) { + buf := bytes.NewBuffer(percentBytes) + + for _, flag := range supportedFlags { + if f.fs.Flag(int(flag)) { + buf.WriteRune(flag) + } + } + + if width, ok := f.fs.Width(); ok { + buf.WriteString(strconv.Itoa(width)) + } + + if precision, ok := f.fs.Precision(); ok { + buf.Write(precisionBytes) + buf.WriteString(strconv.Itoa(precision)) + } + + buf.WriteRune(verb) + + format = buf.String() + return format +} + +// unpackValue returns values inside of non-nil interfaces when possible and +// ensures that types for values which have been unpacked from an interface +// are displayed when the show types flag is also set. +// This is useful for data types like structs, arrays, slices, and maps which +// can contain varying types packed inside an interface. +func (f *formatState) unpackValue(v reflect.Value) reflect.Value { + if v.Kind() == reflect.Interface { + f.ignoreNextType = false + if !v.IsNil() { + v = v.Elem() + } + } + return v +} + +// formatPtr handles formatting of pointers by indirecting them as necessary. +func (f *formatState) formatPtr(v reflect.Value) { + // Display nil if top level pointer is nil. + showTypes := f.fs.Flag('#') + if v.IsNil() && (!showTypes || f.ignoreNextType) { + f.fs.Write(nilAngleBytes) + return + } + + // Remove pointers at or below the current depth from map used to detect + // circular refs. + for k, depth := range f.pointers { + if depth >= f.depth { + delete(f.pointers, k) + } + } + + // Keep list of all dereferenced pointers to possibly show later. + pointerChain := make([]uintptr, 0) + + // Figure out how many levels of indirection there are by derferencing + // pointers and unpacking interfaces down the chain while detecting circular + // references. + nilFound := false + cycleFound := false + indirects := 0 + ve := v + for ve.Kind() == reflect.Ptr { + if ve.IsNil() { + nilFound = true + break + } + indirects++ + addr := ve.Pointer() + pointerChain = append(pointerChain, addr) + if pd, ok := f.pointers[addr]; ok && pd < f.depth { + cycleFound = true + indirects-- + break + } + f.pointers[addr] = f.depth + + ve = ve.Elem() + if ve.Kind() == reflect.Interface { + if ve.IsNil() { + nilFound = true + break + } + ve = ve.Elem() + } + } + + // Display type or indirection level depending on flags. + if showTypes && !f.ignoreNextType { + f.fs.Write(openParenBytes) + f.fs.Write(bytes.Repeat(asteriskBytes, indirects)) + f.fs.Write([]byte(ve.Type().String())) + f.fs.Write(closeParenBytes) + } else { + if nilFound || cycleFound { + indirects += strings.Count(ve.Type().String(), "*") + } + f.fs.Write(openAngleBytes) + f.fs.Write([]byte(strings.Repeat("*", indirects))) + f.fs.Write(closeAngleBytes) + } + + // Display pointer information depending on flags. + if f.fs.Flag('+') && (len(pointerChain) > 0) { + f.fs.Write(openParenBytes) + for i, addr := range pointerChain { + if i > 0 { + f.fs.Write(pointerChainBytes) + } + printHexPtr(f.fs, addr) + } + f.fs.Write(closeParenBytes) + } + + // Display dereferenced value. + switch { + case nilFound == true: + f.fs.Write(nilAngleBytes) + + case cycleFound == true: + f.fs.Write(circularShortBytes) + + default: + f.ignoreNextType = true + f.format(ve) + } +} + +// format is the main workhorse for providing the Formatter interface. It +// uses the passed reflect value to figure out what kind of object we are +// dealing with and formats it appropriately. It is a recursive function, +// however circular data structures are detected and handled properly. +func (f *formatState) format(v reflect.Value) { + // Handle invalid reflect values immediately. + kind := v.Kind() + if kind == reflect.Invalid { + f.fs.Write(invalidAngleBytes) + return + } + + // Handle pointers specially. + if kind == reflect.Ptr { + f.formatPtr(v) + return + } + + // Print type information unless already handled elsewhere. + if !f.ignoreNextType && f.fs.Flag('#') { + f.fs.Write(openParenBytes) + f.fs.Write([]byte(v.Type().String())) + f.fs.Write(closeParenBytes) + } + f.ignoreNextType = false + + // Call Stringer/error interfaces if they exist and the handle methods + // flag is enabled. + if !f.cs.DisableMethods { + if (kind != reflect.Invalid) && (kind != reflect.Interface) { + if handled := handleMethods(f.cs, f.fs, v); handled { + return + } + } + } + + switch kind { + case reflect.Invalid: + // Do nothing. We should never get here since invalid has already + // been handled above. + + case reflect.Bool: + printBool(f.fs, v.Bool()) + + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + printInt(f.fs, v.Int(), 10) + + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + printUint(f.fs, v.Uint(), 10) + + case reflect.Float32: + printFloat(f.fs, v.Float(), 32) + + case reflect.Float64: + printFloat(f.fs, v.Float(), 64) + + case reflect.Complex64: + printComplex(f.fs, v.Complex(), 32) + + case reflect.Complex128: + printComplex(f.fs, v.Complex(), 64) + + case reflect.Slice: + if v.IsNil() { + f.fs.Write(nilAngleBytes) + break + } + fallthrough + + case reflect.Array: + f.fs.Write(openBracketBytes) + f.depth++ + if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { + f.fs.Write(maxShortBytes) + } else { + numEntries := v.Len() + for i := 0; i < numEntries; i++ { + if i > 0 { + f.fs.Write(spaceBytes) + } + f.ignoreNextType = true + f.format(f.unpackValue(v.Index(i))) + } + } + f.depth-- + f.fs.Write(closeBracketBytes) + + case reflect.String: + f.fs.Write([]byte(v.String())) + + case reflect.Interface: + // The only time we should get here is for nil interfaces due to + // unpackValue calls. + if v.IsNil() { + f.fs.Write(nilAngleBytes) + } + + case reflect.Ptr: + // Do nothing. We should never get here since pointers have already + // been handled above. + + case reflect.Map: + // nil maps should be indicated as different than empty maps + if v.IsNil() { + f.fs.Write(nilAngleBytes) + break + } + + f.fs.Write(openMapBytes) + f.depth++ + if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { + f.fs.Write(maxShortBytes) + } else { + keys := v.MapKeys() + if f.cs.SortKeys { + sortValues(keys, f.cs) + } + for i, key := range keys { + if i > 0 { + f.fs.Write(spaceBytes) + } + f.ignoreNextType = true + f.format(f.unpackValue(key)) + f.fs.Write(colonBytes) + f.ignoreNextType = true + f.format(f.unpackValue(v.MapIndex(key))) + } + } + f.depth-- + f.fs.Write(closeMapBytes) + + case reflect.Struct: + numFields := v.NumField() + f.fs.Write(openBraceBytes) + f.depth++ + if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { + f.fs.Write(maxShortBytes) + } else { + vt := v.Type() + for i := 0; i < numFields; i++ { + if i > 0 { + f.fs.Write(spaceBytes) + } + vtf := vt.Field(i) + if f.fs.Flag('+') || f.fs.Flag('#') { + f.fs.Write([]byte(vtf.Name)) + f.fs.Write(colonBytes) + } + f.format(f.unpackValue(v.Field(i))) + } + } + f.depth-- + f.fs.Write(closeBraceBytes) + + case reflect.Uintptr: + printHexPtr(f.fs, uintptr(v.Uint())) + + case reflect.UnsafePointer, reflect.Chan, reflect.Func: + printHexPtr(f.fs, v.Pointer()) + + // There were not any other types at the time this code was written, but + // fall back to letting the default fmt package handle it if any get added. + default: + format := f.buildDefaultFormat() + if v.CanInterface() { + fmt.Fprintf(f.fs, format, v.Interface()) + } else { + fmt.Fprintf(f.fs, format, v.String()) + } + } +} + +// Format satisfies the fmt.Formatter interface. See NewFormatter for usage +// details. +func (f *formatState) Format(fs fmt.State, verb rune) { + f.fs = fs + + // Use standard formatting for verbs that are not v. + if verb != 'v' { + format := f.constructOrigFormat(verb) + fmt.Fprintf(fs, format, f.value) + return + } + + if f.value == nil { + if fs.Flag('#') { + fs.Write(interfaceBytes) + } + fs.Write(nilAngleBytes) + return + } + + f.format(reflect.ValueOf(f.value)) +} + +// newFormatter is a helper function to consolidate the logic from the various +// public methods which take varying config states. +func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter { + fs := &formatState{value: v, cs: cs} + fs.pointers = make(map[uintptr]int) + return fs +} + +/* +NewFormatter returns a custom formatter that satisfies the fmt.Formatter +interface. As a result, it integrates cleanly with standard fmt package +printing functions. The formatter is useful for inline printing of smaller data +types similar to the standard %v format specifier. + +The custom formatter only responds to the %v (most compact), %+v (adds pointer +addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb +combinations. Any other verbs such as %x and %q will be sent to the the +standard fmt package for formatting. In addition, the custom formatter ignores +the width and precision arguments (however they will still work on the format +specifiers not handled by the custom formatter). + +Typically this function shouldn't be called directly. It is much easier to make +use of the custom formatter by calling one of the convenience functions such as +Printf, Println, or Fprintf. +*/ +func NewFormatter(v interface{}) fmt.Formatter { + return newFormatter(&Config, v) +} diff --git a/vendor/github.com/davecgh/go-spew/spew/spew.go b/vendor/github.com/davecgh/go-spew/spew/spew.go new file mode 100644 index 0000000..32c0e33 --- /dev/null +++ b/vendor/github.com/davecgh/go-spew/spew/spew.go @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2013-2016 Dave Collins + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package spew + +import ( + "fmt" + "io" +) + +// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the formatted string as a value that satisfies error. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Errorf(format string, a ...interface{}) (err error) { + return fmt.Errorf(format, convertArgs(a)...) +} + +// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b)) +func Fprint(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprint(w, convertArgs(a)...) +} + +// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { + return fmt.Fprintf(w, format, convertArgs(a)...) +} + +// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it +// passed with a default Formatter interface returned by NewFormatter. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b)) +func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprintln(w, convertArgs(a)...) +} + +// Print is a wrapper for fmt.Print that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b)) +func Print(a ...interface{}) (n int, err error) { + return fmt.Print(convertArgs(a)...) +} + +// Printf is a wrapper for fmt.Printf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Printf(format string, a ...interface{}) (n int, err error) { + return fmt.Printf(format, convertArgs(a)...) +} + +// Println is a wrapper for fmt.Println that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b)) +func Println(a ...interface{}) (n int, err error) { + return fmt.Println(convertArgs(a)...) +} + +// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b)) +func Sprint(a ...interface{}) string { + return fmt.Sprint(convertArgs(a)...) +} + +// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were +// passed with a default Formatter interface returned by NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b)) +func Sprintf(format string, a ...interface{}) string { + return fmt.Sprintf(format, convertArgs(a)...) +} + +// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it +// were passed with a default Formatter interface returned by NewFormatter. It +// returns the resulting string. See NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b)) +func Sprintln(a ...interface{}) string { + return fmt.Sprintln(convertArgs(a)...) +} + +// convertArgs accepts a slice of arguments and returns a slice of the same +// length with each argument converted to a default spew Formatter interface. +func convertArgs(args []interface{}) (formatters []interface{}) { + formatters = make([]interface{}, len(args)) + for index, arg := range args { + formatters[index] = NewFormatter(arg) + } + return formatters +} diff --git a/vendor/github.com/pmezard/go-difflib/LICENSE b/vendor/github.com/pmezard/go-difflib/LICENSE new file mode 100644 index 0000000..c67dad6 --- /dev/null +++ b/vendor/github.com/pmezard/go-difflib/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013, Patrick Mezard +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + The names of its contributors may not be used to endorse or promote +products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/pmezard/go-difflib/difflib/difflib.go b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go new file mode 100644 index 0000000..003e99f --- /dev/null +++ b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go @@ -0,0 +1,772 @@ +// Package difflib is a partial port of Python difflib module. +// +// It provides tools to compare sequences of strings and generate textual diffs. +// +// The following class and functions have been ported: +// +// - SequenceMatcher +// +// - unified_diff +// +// - context_diff +// +// Getting unified diffs was the main goal of the port. Keep in mind this code +// is mostly suitable to output text differences in a human friendly way, there +// are no guarantees generated diffs are consumable by patch(1). +package difflib + +import ( + "bufio" + "bytes" + "fmt" + "io" + "strings" +) + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func calculateRatio(matches, length int) float64 { + if length > 0 { + return 2.0 * float64(matches) / float64(length) + } + return 1.0 +} + +type Match struct { + A int + B int + Size int +} + +type OpCode struct { + Tag byte + I1 int + I2 int + J1 int + J2 int +} + +// SequenceMatcher compares sequence of strings. The basic +// algorithm predates, and is a little fancier than, an algorithm +// published in the late 1980's by Ratcliff and Obershelp under the +// hyperbolic name "gestalt pattern matching". The basic idea is to find +// the longest contiguous matching subsequence that contains no "junk" +// elements (R-O doesn't address junk). The same idea is then applied +// recursively to the pieces of the sequences to the left and to the right +// of the matching subsequence. This does not yield minimal edit +// sequences, but does tend to yield matches that "look right" to people. +// +// SequenceMatcher tries to compute a "human-friendly diff" between two +// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the +// longest *contiguous* & junk-free matching subsequence. That's what +// catches peoples' eyes. The Windows(tm) windiff has another interesting +// notion, pairing up elements that appear uniquely in each sequence. +// That, and the method here, appear to yield more intuitive difference +// reports than does diff. This method appears to be the least vulnerable +// to synching up on blocks of "junk lines", though (like blank lines in +// ordinary text files, or maybe "

" lines in HTML files). That may be +// because this is the only method of the 3 that has a *concept* of +// "junk" . +// +// Timing: Basic R-O is cubic time worst case and quadratic time expected +// case. SequenceMatcher is quadratic time for the worst case and has +// expected-case behavior dependent in a complicated way on how many +// elements the sequences have in common; best case time is linear. +type SequenceMatcher struct { + a []string + b []string + b2j map[string][]int + IsJunk func(string) bool + autoJunk bool + bJunk map[string]struct{} + matchingBlocks []Match + fullBCount map[string]int + bPopular map[string]struct{} + opCodes []OpCode +} + +func NewMatcher(a, b []string) *SequenceMatcher { + m := SequenceMatcher{autoJunk: true} + m.SetSeqs(a, b) + return &m +} + +func NewMatcherWithJunk(a, b []string, autoJunk bool, + isJunk func(string) bool) *SequenceMatcher { + + m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk} + m.SetSeqs(a, b) + return &m +} + +// Set two sequences to be compared. +func (m *SequenceMatcher) SetSeqs(a, b []string) { + m.SetSeq1(a) + m.SetSeq2(b) +} + +// Set the first sequence to be compared. The second sequence to be compared is +// not changed. +// +// SequenceMatcher computes and caches detailed information about the second +// sequence, so if you want to compare one sequence S against many sequences, +// use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other +// sequences. +// +// See also SetSeqs() and SetSeq2(). +func (m *SequenceMatcher) SetSeq1(a []string) { + if &a == &m.a { + return + } + m.a = a + m.matchingBlocks = nil + m.opCodes = nil +} + +// Set the second sequence to be compared. The first sequence to be compared is +// not changed. +func (m *SequenceMatcher) SetSeq2(b []string) { + if &b == &m.b { + return + } + m.b = b + m.matchingBlocks = nil + m.opCodes = nil + m.fullBCount = nil + m.chainB() +} + +func (m *SequenceMatcher) chainB() { + // Populate line -> index mapping + b2j := map[string][]int{} + for i, s := range m.b { + indices := b2j[s] + indices = append(indices, i) + b2j[s] = indices + } + + // Purge junk elements + m.bJunk = map[string]struct{}{} + if m.IsJunk != nil { + junk := m.bJunk + for s, _ := range b2j { + if m.IsJunk(s) { + junk[s] = struct{}{} + } + } + for s, _ := range junk { + delete(b2j, s) + } + } + + // Purge remaining popular elements + popular := map[string]struct{}{} + n := len(m.b) + if m.autoJunk && n >= 200 { + ntest := n/100 + 1 + for s, indices := range b2j { + if len(indices) > ntest { + popular[s] = struct{}{} + } + } + for s, _ := range popular { + delete(b2j, s) + } + } + m.bPopular = popular + m.b2j = b2j +} + +func (m *SequenceMatcher) isBJunk(s string) bool { + _, ok := m.bJunk[s] + return ok +} + +// Find longest matching block in a[alo:ahi] and b[blo:bhi]. +// +// If IsJunk is not defined: +// +// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where +// alo <= i <= i+k <= ahi +// blo <= j <= j+k <= bhi +// and for all (i',j',k') meeting those conditions, +// k >= k' +// i <= i' +// and if i == i', j <= j' +// +// In other words, of all maximal matching blocks, return one that +// starts earliest in a, and of all those maximal matching blocks that +// start earliest in a, return the one that starts earliest in b. +// +// If IsJunk is defined, first the longest matching block is +// determined as above, but with the additional restriction that no +// junk element appears in the block. Then that block is extended as +// far as possible by matching (only) junk elements on both sides. So +// the resulting block never matches on junk except as identical junk +// happens to be adjacent to an "interesting" match. +// +// If no blocks match, return (alo, blo, 0). +func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match { + // CAUTION: stripping common prefix or suffix would be incorrect. + // E.g., + // ab + // acab + // Longest matching block is "ab", but if common prefix is + // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so + // strip, so ends up claiming that ab is changed to acab by + // inserting "ca" in the middle. That's minimal but unintuitive: + // "it's obvious" that someone inserted "ac" at the front. + // Windiff ends up at the same place as diff, but by pairing up + // the unique 'b's and then matching the first two 'a's. + besti, bestj, bestsize := alo, blo, 0 + + // find longest junk-free match + // during an iteration of the loop, j2len[j] = length of longest + // junk-free match ending with a[i-1] and b[j] + j2len := map[int]int{} + for i := alo; i != ahi; i++ { + // look at all instances of a[i] in b; note that because + // b2j has no junk keys, the loop is skipped if a[i] is junk + newj2len := map[int]int{} + for _, j := range m.b2j[m.a[i]] { + // a[i] matches b[j] + if j < blo { + continue + } + if j >= bhi { + break + } + k := j2len[j-1] + 1 + newj2len[j] = k + if k > bestsize { + besti, bestj, bestsize = i-k+1, j-k+1, k + } + } + j2len = newj2len + } + + // Extend the best by non-junk elements on each end. In particular, + // "popular" non-junk elements aren't in b2j, which greatly speeds + // the inner loop above, but also means "the best" match so far + // doesn't contain any junk *or* popular non-junk elements. + for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) && + m.a[besti-1] == m.b[bestj-1] { + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + } + for besti+bestsize < ahi && bestj+bestsize < bhi && + !m.isBJunk(m.b[bestj+bestsize]) && + m.a[besti+bestsize] == m.b[bestj+bestsize] { + bestsize += 1 + } + + // Now that we have a wholly interesting match (albeit possibly + // empty!), we may as well suck up the matching junk on each + // side of it too. Can't think of a good reason not to, and it + // saves post-processing the (possibly considerable) expense of + // figuring out what to do with it. In the case of an empty + // interesting match, this is clearly the right thing to do, + // because no other kind of match is possible in the regions. + for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) && + m.a[besti-1] == m.b[bestj-1] { + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + } + for besti+bestsize < ahi && bestj+bestsize < bhi && + m.isBJunk(m.b[bestj+bestsize]) && + m.a[besti+bestsize] == m.b[bestj+bestsize] { + bestsize += 1 + } + + return Match{A: besti, B: bestj, Size: bestsize} +} + +// Return list of triples describing matching subsequences. +// +// Each triple is of the form (i, j, n), and means that +// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in +// i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are +// adjacent triples in the list, and the second is not the last triple in the +// list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe +// adjacent equal blocks. +// +// The last triple is a dummy, (len(a), len(b), 0), and is the only +// triple with n==0. +func (m *SequenceMatcher) GetMatchingBlocks() []Match { + if m.matchingBlocks != nil { + return m.matchingBlocks + } + + var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match + matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match { + match := m.findLongestMatch(alo, ahi, blo, bhi) + i, j, k := match.A, match.B, match.Size + if match.Size > 0 { + if alo < i && blo < j { + matched = matchBlocks(alo, i, blo, j, matched) + } + matched = append(matched, match) + if i+k < ahi && j+k < bhi { + matched = matchBlocks(i+k, ahi, j+k, bhi, matched) + } + } + return matched + } + matched := matchBlocks(0, len(m.a), 0, len(m.b), nil) + + // It's possible that we have adjacent equal blocks in the + // matching_blocks list now. + nonAdjacent := []Match{} + i1, j1, k1 := 0, 0, 0 + for _, b := range matched { + // Is this block adjacent to i1, j1, k1? + i2, j2, k2 := b.A, b.B, b.Size + if i1+k1 == i2 && j1+k1 == j2 { + // Yes, so collapse them -- this just increases the length of + // the first block by the length of the second, and the first + // block so lengthened remains the block to compare against. + k1 += k2 + } else { + // Not adjacent. Remember the first block (k1==0 means it's + // the dummy we started with), and make the second block the + // new block to compare against. + if k1 > 0 { + nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) + } + i1, j1, k1 = i2, j2, k2 + } + } + if k1 > 0 { + nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) + } + + nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0}) + m.matchingBlocks = nonAdjacent + return m.matchingBlocks +} + +// Return list of 5-tuples describing how to turn a into b. +// +// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple +// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the +// tuple preceding it, and likewise for j1 == the previous j2. +// +// The tags are characters, with these meanings: +// +// 'r' (replace): a[i1:i2] should be replaced by b[j1:j2] +// +// 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case. +// +// 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case. +// +// 'e' (equal): a[i1:i2] == b[j1:j2] +func (m *SequenceMatcher) GetOpCodes() []OpCode { + if m.opCodes != nil { + return m.opCodes + } + i, j := 0, 0 + matching := m.GetMatchingBlocks() + opCodes := make([]OpCode, 0, len(matching)) + for _, m := range matching { + // invariant: we've pumped out correct diffs to change + // a[:i] into b[:j], and the next matching block is + // a[ai:ai+size] == b[bj:bj+size]. So we need to pump + // out a diff to change a[i:ai] into b[j:bj], pump out + // the matching block, and move (i,j) beyond the match + ai, bj, size := m.A, m.B, m.Size + tag := byte(0) + if i < ai && j < bj { + tag = 'r' + } else if i < ai { + tag = 'd' + } else if j < bj { + tag = 'i' + } + if tag > 0 { + opCodes = append(opCodes, OpCode{tag, i, ai, j, bj}) + } + i, j = ai+size, bj+size + // the list of matching blocks is terminated by a + // sentinel with size 0 + if size > 0 { + opCodes = append(opCodes, OpCode{'e', ai, i, bj, j}) + } + } + m.opCodes = opCodes + return m.opCodes +} + +// Isolate change clusters by eliminating ranges with no changes. +// +// Return a generator of groups with up to n lines of context. +// Each group is in the same format as returned by GetOpCodes(). +func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { + if n < 0 { + n = 3 + } + codes := m.GetOpCodes() + if len(codes) == 0 { + codes = []OpCode{OpCode{'e', 0, 1, 0, 1}} + } + // Fixup leading and trailing groups if they show no changes. + if codes[0].Tag == 'e' { + c := codes[0] + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2} + } + if codes[len(codes)-1].Tag == 'e' { + c := codes[len(codes)-1] + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)} + } + nn := n + n + groups := [][]OpCode{} + group := []OpCode{} + for _, c := range codes { + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + // End the current group and start a new one whenever + // there is a large range with no changes. + if c.Tag == 'e' && i2-i1 > nn { + group = append(group, OpCode{c.Tag, i1, min(i2, i1+n), + j1, min(j2, j1+n)}) + groups = append(groups, group) + group = []OpCode{} + i1, j1 = max(i1, i2-n), max(j1, j2-n) + } + group = append(group, OpCode{c.Tag, i1, i2, j1, j2}) + } + if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') { + groups = append(groups, group) + } + return groups +} + +// Return a measure of the sequences' similarity (float in [0,1]). +// +// Where T is the total number of elements in both sequences, and +// M is the number of matches, this is 2.0*M / T. +// Note that this is 1 if the sequences are identical, and 0 if +// they have nothing in common. +// +// .Ratio() is expensive to compute if you haven't already computed +// .GetMatchingBlocks() or .GetOpCodes(), in which case you may +// want to try .QuickRatio() or .RealQuickRation() first to get an +// upper bound. +func (m *SequenceMatcher) Ratio() float64 { + matches := 0 + for _, m := range m.GetMatchingBlocks() { + matches += m.Size + } + return calculateRatio(matches, len(m.a)+len(m.b)) +} + +// Return an upper bound on ratio() relatively quickly. +// +// This isn't defined beyond that it is an upper bound on .Ratio(), and +// is faster to compute. +func (m *SequenceMatcher) QuickRatio() float64 { + // viewing a and b as multisets, set matches to the cardinality + // of their intersection; this counts the number of matches + // without regard to order, so is clearly an upper bound + if m.fullBCount == nil { + m.fullBCount = map[string]int{} + for _, s := range m.b { + m.fullBCount[s] = m.fullBCount[s] + 1 + } + } + + // avail[x] is the number of times x appears in 'b' less the + // number of times we've seen it in 'a' so far ... kinda + avail := map[string]int{} + matches := 0 + for _, s := range m.a { + n, ok := avail[s] + if !ok { + n = m.fullBCount[s] + } + avail[s] = n - 1 + if n > 0 { + matches += 1 + } + } + return calculateRatio(matches, len(m.a)+len(m.b)) +} + +// Return an upper bound on ratio() very quickly. +// +// This isn't defined beyond that it is an upper bound on .Ratio(), and +// is faster to compute than either .Ratio() or .QuickRatio(). +func (m *SequenceMatcher) RealQuickRatio() float64 { + la, lb := len(m.a), len(m.b) + return calculateRatio(min(la, lb), la+lb) +} + +// Convert range to the "ed" format +func formatRangeUnified(start, stop int) string { + // Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning := start + 1 // lines start numbering with one + length := stop - start + if length == 1 { + return fmt.Sprintf("%d", beginning) + } + if length == 0 { + beginning -= 1 // empty ranges begin at line just before the range + } + return fmt.Sprintf("%d,%d", beginning, length) +} + +// Unified diff parameters +type UnifiedDiff struct { + A []string // First sequence lines + FromFile string // First file name + FromDate string // First file time + B []string // Second sequence lines + ToFile string // Second file name + ToDate string // Second file time + Eol string // Headers end of line, defaults to LF + Context int // Number of context lines +} + +// Compare two sequences of lines; generate the delta as a unified diff. +// +// Unified diffs are a compact way of showing line changes and a few +// lines of context. The number of context lines is set by 'n' which +// defaults to three. +// +// By default, the diff control lines (those with ---, +++, or @@) are +// created with a trailing newline. This is helpful so that inputs +// created from file.readlines() result in diffs that are suitable for +// file.writelines() since both the inputs and outputs have trailing +// newlines. +// +// For inputs that do not have trailing newlines, set the lineterm +// argument to "" so that the output will be uniformly newline free. +// +// The unidiff format normally has a header for filenames and modification +// times. Any or all of these may be specified using strings for +// 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. +// The modification times are normally expressed in the ISO 8601 format. +func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { + buf := bufio.NewWriter(writer) + defer buf.Flush() + wf := func(format string, args ...interface{}) error { + _, err := buf.WriteString(fmt.Sprintf(format, args...)) + return err + } + ws := func(s string) error { + _, err := buf.WriteString(s) + return err + } + + if len(diff.Eol) == 0 { + diff.Eol = "\n" + } + + started := false + m := NewMatcher(diff.A, diff.B) + for _, g := range m.GetGroupedOpCodes(diff.Context) { + if !started { + started = true + fromDate := "" + if len(diff.FromDate) > 0 { + fromDate = "\t" + diff.FromDate + } + toDate := "" + if len(diff.ToDate) > 0 { + toDate = "\t" + diff.ToDate + } + if diff.FromFile != "" || diff.ToFile != "" { + err := wf("--- %s%s%s", diff.FromFile, fromDate, diff.Eol) + if err != nil { + return err + } + err = wf("+++ %s%s%s", diff.ToFile, toDate, diff.Eol) + if err != nil { + return err + } + } + } + first, last := g[0], g[len(g)-1] + range1 := formatRangeUnified(first.I1, last.I2) + range2 := formatRangeUnified(first.J1, last.J2) + if err := wf("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil { + return err + } + for _, c := range g { + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + if c.Tag == 'e' { + for _, line := range diff.A[i1:i2] { + if err := ws(" " + line); err != nil { + return err + } + } + continue + } + if c.Tag == 'r' || c.Tag == 'd' { + for _, line := range diff.A[i1:i2] { + if err := ws("-" + line); err != nil { + return err + } + } + } + if c.Tag == 'r' || c.Tag == 'i' { + for _, line := range diff.B[j1:j2] { + if err := ws("+" + line); err != nil { + return err + } + } + } + } + } + return nil +} + +// Like WriteUnifiedDiff but returns the diff a string. +func GetUnifiedDiffString(diff UnifiedDiff) (string, error) { + w := &bytes.Buffer{} + err := WriteUnifiedDiff(w, diff) + return string(w.Bytes()), err +} + +// Convert range to the "ed" format. +func formatRangeContext(start, stop int) string { + // Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning := start + 1 // lines start numbering with one + length := stop - start + if length == 0 { + beginning -= 1 // empty ranges begin at line just before the range + } + if length <= 1 { + return fmt.Sprintf("%d", beginning) + } + return fmt.Sprintf("%d,%d", beginning, beginning+length-1) +} + +type ContextDiff UnifiedDiff + +// Compare two sequences of lines; generate the delta as a context diff. +// +// Context diffs are a compact way of showing line changes and a few +// lines of context. The number of context lines is set by diff.Context +// which defaults to three. +// +// By default, the diff control lines (those with *** or ---) are +// created with a trailing newline. +// +// For inputs that do not have trailing newlines, set the diff.Eol +// argument to "" so that the output will be uniformly newline free. +// +// The context diff format normally has a header for filenames and +// modification times. Any or all of these may be specified using +// strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate. +// The modification times are normally expressed in the ISO 8601 format. +// If not specified, the strings default to blanks. +func WriteContextDiff(writer io.Writer, diff ContextDiff) error { + buf := bufio.NewWriter(writer) + defer buf.Flush() + var diffErr error + wf := func(format string, args ...interface{}) { + _, err := buf.WriteString(fmt.Sprintf(format, args...)) + if diffErr == nil && err != nil { + diffErr = err + } + } + ws := func(s string) { + _, err := buf.WriteString(s) + if diffErr == nil && err != nil { + diffErr = err + } + } + + if len(diff.Eol) == 0 { + diff.Eol = "\n" + } + + prefix := map[byte]string{ + 'i': "+ ", + 'd': "- ", + 'r': "! ", + 'e': " ", + } + + started := false + m := NewMatcher(diff.A, diff.B) + for _, g := range m.GetGroupedOpCodes(diff.Context) { + if !started { + started = true + fromDate := "" + if len(diff.FromDate) > 0 { + fromDate = "\t" + diff.FromDate + } + toDate := "" + if len(diff.ToDate) > 0 { + toDate = "\t" + diff.ToDate + } + if diff.FromFile != "" || diff.ToFile != "" { + wf("*** %s%s%s", diff.FromFile, fromDate, diff.Eol) + wf("--- %s%s%s", diff.ToFile, toDate, diff.Eol) + } + } + + first, last := g[0], g[len(g)-1] + ws("***************" + diff.Eol) + + range1 := formatRangeContext(first.I1, last.I2) + wf("*** %s ****%s", range1, diff.Eol) + for _, c := range g { + if c.Tag == 'r' || c.Tag == 'd' { + for _, cc := range g { + if cc.Tag == 'i' { + continue + } + for _, line := range diff.A[cc.I1:cc.I2] { + ws(prefix[cc.Tag] + line) + } + } + break + } + } + + range2 := formatRangeContext(first.J1, last.J2) + wf("--- %s ----%s", range2, diff.Eol) + for _, c := range g { + if c.Tag == 'r' || c.Tag == 'i' { + for _, cc := range g { + if cc.Tag == 'd' { + continue + } + for _, line := range diff.B[cc.J1:cc.J2] { + ws(prefix[cc.Tag] + line) + } + } + break + } + } + } + return diffErr +} + +// Like WriteContextDiff but returns the diff a string. +func GetContextDiffString(diff ContextDiff) (string, error) { + w := &bytes.Buffer{} + err := WriteContextDiff(w, diff) + return string(w.Bytes()), err +} + +// Split a string on "\n" while preserving them. The output can be used +// as input for UnifiedDiff and ContextDiff structures. +func SplitLines(s string) []string { + lines := strings.SplitAfter(s, "\n") + lines[len(lines)-1] += "\n" + return lines +} diff --git a/vendor/github.com/stretchr/testify/LICENSE b/vendor/github.com/stretchr/testify/LICENSE new file mode 100644 index 0000000..473b670 --- /dev/null +++ b/vendor/github.com/stretchr/testify/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell + +Please consider promoting this project if you find it useful. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go new file mode 100644 index 0000000..ae06a54 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go @@ -0,0 +1,349 @@ +/* +* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen +* THIS FILE MUST NOT BE EDITED BY HAND + */ + +package assert + +import ( + http "net/http" + url "net/url" + time "time" +) + +// Conditionf uses a Comparison to assert a complex condition. +func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool { + return Condition(t, comp, append([]interface{}{msg}, args...)...) +} + +// Containsf asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") +// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") +// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") +func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { + return Contains(t, s, contains, append([]interface{}{msg}, args...)...) +} + +// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. +func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool { + return DirExists(t, path, append([]interface{}{msg}, args...)...) +} + +// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") +func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool { + return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...) +} + +// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// assert.Emptyf(t, obj, "error message %s", "formatted") +func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + return Empty(t, object, append([]interface{}{msg}, args...)...) +} + +// Equalf asserts that two objects are equal. +// +// assert.Equalf(t, 123, 123, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + return Equal(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// EqualErrorf asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") +func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool { + return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...) +} + +// EqualValuesf asserts that two objects are equal or convertable to the same types +// and equal. +// +// assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123)) +func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// Errorf asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if assert.Errorf(t, err, "error message %s", "formatted") { +// assert.Equal(t, expectedErrorf, err) +// } +func Errorf(t TestingT, err error, msg string, args ...interface{}) bool { + return Error(t, err, append([]interface{}{msg}, args...)...) +} + +// Exactlyf asserts that two objects are equal in value and type. +// +// assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123)) +func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// Failf reports a failure through +func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { + return Fail(t, failureMessage, append([]interface{}{msg}, args...)...) +} + +// FailNowf fails test +func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { + return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...) +} + +// Falsef asserts that the specified value is false. +// +// assert.Falsef(t, myBool, "error message %s", "formatted") +func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool { + return False(t, value, append([]interface{}{msg}, args...)...) +} + +// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. +func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool { + return FileExists(t, path, append([]interface{}{msg}, args...)...) +} + +// HTTPBodyContainsf asserts that a specified handler returns a +// body that contains a string. +// +// assert.HTTPBodyContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + return HTTPBodyContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) +} + +// HTTPBodyNotContainsf asserts that a specified handler returns a +// body that does not contain a string. +// +// assert.HTTPBodyNotContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + return HTTPBodyNotContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) +} + +// HTTPErrorf asserts that a specified handler returns an error status code. +// +// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + return HTTPError(t, handler, method, url, values, append([]interface{}{msg}, args...)...) +} + +// HTTPRedirectf asserts that a specified handler returns a redirect status code. +// +// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...) +} + +// HTTPSuccessf asserts that a specified handler returns a success status code. +// +// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + return HTTPSuccess(t, handler, method, url, values, append([]interface{}{msg}, args...)...) +} + +// Implementsf asserts that an object is implemented by the specified interface. +// +// assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) +func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) +} + +// InDeltaf asserts that the two numerals are within delta of each other. +// +// assert.InDeltaf(t, math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) +func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...) +} + +// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + return InDeltaMapValues(t, expected, actual, delta, append([]interface{}{msg}, args...)...) +} + +// InDeltaSlicef is the same as InDelta, except it compares two slices. +func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...) +} + +// InEpsilonf asserts that expected and actual have a relative error less than epsilon +func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) +} + +// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. +func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) +} + +// IsTypef asserts that the specified objects are of the same type. +func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { + return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...) +} + +// JSONEqf asserts that two JSON strings are equivalent. +// +// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") +func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool { + return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// Lenf asserts that the specified object has specific length. +// Lenf also fails if the object has a type that len() not accept. +// +// assert.Lenf(t, mySlice, 3, "error message %s", "formatted") +func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool { + return Len(t, object, length, append([]interface{}{msg}, args...)...) +} + +// Nilf asserts that the specified object is nil. +// +// assert.Nilf(t, err, "error message %s", "formatted") +func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + return Nil(t, object, append([]interface{}{msg}, args...)...) +} + +// NoErrorf asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if assert.NoErrorf(t, err, "error message %s", "formatted") { +// assert.Equal(t, expectedObj, actualObj) +// } +func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool { + return NoError(t, err, append([]interface{}{msg}, args...)...) +} + +// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") +// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") +// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") +func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { + return NotContains(t, s, contains, append([]interface{}{msg}, args...)...) +} + +// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if assert.NotEmptyf(t, obj, "error message %s", "formatted") { +// assert.Equal(t, "two", obj[1]) +// } +func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + return NotEmpty(t, object, append([]interface{}{msg}, args...)...) +} + +// NotEqualf asserts that the specified values are NOT equal. +// +// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// NotNilf asserts that the specified object is not nil. +// +// assert.NotNilf(t, err, "error message %s", "formatted") +func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + return NotNil(t, object, append([]interface{}{msg}, args...)...) +} + +// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") +func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { + return NotPanics(t, f, append([]interface{}{msg}, args...)...) +} + +// NotRegexpf asserts that a specified regexp does not match a string. +// +// assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") +// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") +func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { + return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...) +} + +// NotSubsetf asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { + return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...) +} + +// NotZerof asserts that i is not the zero value for its type. +func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { + return NotZero(t, i, append([]interface{}{msg}, args...)...) +} + +// Panicsf asserts that the code inside the specified PanicTestFunc panics. +// +// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") +func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { + return Panics(t, f, append([]interface{}{msg}, args...)...) +} + +// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { + return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...) +} + +// Regexpf asserts that a specified regexp matches a string. +// +// assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") +// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") +func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { + return Regexp(t, rx, str, append([]interface{}{msg}, args...)...) +} + +// Subsetf asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { + return Subset(t, list, subset, append([]interface{}{msg}, args...)...) +} + +// Truef asserts that the specified value is true. +// +// assert.Truef(t, myBool, "error message %s", "formatted") +func Truef(t TestingT, value bool, msg string, args ...interface{}) bool { + return True(t, value, append([]interface{}{msg}, args...)...) +} + +// WithinDurationf asserts that the two times are within duration delta of each other. +// +// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") +func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { + return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...) +} + +// Zerof asserts that i is the zero value for its type. +func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { + return Zero(t, i, append([]interface{}{msg}, args...)...) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl b/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl new file mode 100644 index 0000000..c5cc66f --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl @@ -0,0 +1,4 @@ +{{.CommentFormat}} +func {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool { + return {{.DocInfo.Name}}(t, {{.ForwardedParamsFormat}}) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go new file mode 100644 index 0000000..ffa5428 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go @@ -0,0 +1,686 @@ +/* +* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen +* THIS FILE MUST NOT BE EDITED BY HAND + */ + +package assert + +import ( + http "net/http" + url "net/url" + time "time" +) + +// Condition uses a Comparison to assert a complex condition. +func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool { + return Condition(a.t, comp, msgAndArgs...) +} + +// Conditionf uses a Comparison to assert a complex condition. +func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}) bool { + return Conditionf(a.t, comp, msg, args...) +} + +// Contains asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// a.Contains("Hello World", "World") +// a.Contains(["Hello", "World"], "World") +// a.Contains({"Hello": "World"}, "Hello") +func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { + return Contains(a.t, s, contains, msgAndArgs...) +} + +// Containsf asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// a.Containsf("Hello World", "World", "error message %s", "formatted") +// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") +// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") +func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { + return Containsf(a.t, s, contains, msg, args...) +} + +// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. +func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) bool { + return DirExists(a.t, path, msgAndArgs...) +} + +// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. +func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bool { + return DirExistsf(a.t, path, msg, args...) +} + +// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]) +func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool { + return ElementsMatch(a.t, listA, listB, msgAndArgs...) +} + +// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") +func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool { + return ElementsMatchf(a.t, listA, listB, msg, args...) +} + +// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// a.Empty(obj) +func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { + return Empty(a.t, object, msgAndArgs...) +} + +// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// a.Emptyf(obj, "error message %s", "formatted") +func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool { + return Emptyf(a.t, object, msg, args...) +} + +// Equal asserts that two objects are equal. +// +// a.Equal(123, 123) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + return Equal(a.t, expected, actual, msgAndArgs...) +} + +// EqualError asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// a.EqualError(err, expectedErrorString) +func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool { + return EqualError(a.t, theError, errString, msgAndArgs...) +} + +// EqualErrorf asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") +func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool { + return EqualErrorf(a.t, theError, errString, msg, args...) +} + +// EqualValues asserts that two objects are equal or convertable to the same types +// and equal. +// +// a.EqualValues(uint32(123), int32(123)) +func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + return EqualValues(a.t, expected, actual, msgAndArgs...) +} + +// EqualValuesf asserts that two objects are equal or convertable to the same types +// and equal. +// +// a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123)) +func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + return EqualValuesf(a.t, expected, actual, msg, args...) +} + +// Equalf asserts that two objects are equal. +// +// a.Equalf(123, 123, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + return Equalf(a.t, expected, actual, msg, args...) +} + +// Error asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if a.Error(err) { +// assert.Equal(t, expectedError, err) +// } +func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool { + return Error(a.t, err, msgAndArgs...) +} + +// Errorf asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if a.Errorf(err, "error message %s", "formatted") { +// assert.Equal(t, expectedErrorf, err) +// } +func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool { + return Errorf(a.t, err, msg, args...) +} + +// Exactly asserts that two objects are equal in value and type. +// +// a.Exactly(int32(123), int64(123)) +func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + return Exactly(a.t, expected, actual, msgAndArgs...) +} + +// Exactlyf asserts that two objects are equal in value and type. +// +// a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123)) +func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + return Exactlyf(a.t, expected, actual, msg, args...) +} + +// Fail reports a failure through +func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool { + return Fail(a.t, failureMessage, msgAndArgs...) +} + +// FailNow fails test +func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool { + return FailNow(a.t, failureMessage, msgAndArgs...) +} + +// FailNowf fails test +func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) bool { + return FailNowf(a.t, failureMessage, msg, args...) +} + +// Failf reports a failure through +func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) bool { + return Failf(a.t, failureMessage, msg, args...) +} + +// False asserts that the specified value is false. +// +// a.False(myBool) +func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool { + return False(a.t, value, msgAndArgs...) +} + +// Falsef asserts that the specified value is false. +// +// a.Falsef(myBool, "error message %s", "formatted") +func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool { + return Falsef(a.t, value, msg, args...) +} + +// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. +func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) bool { + return FileExists(a.t, path, msgAndArgs...) +} + +// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. +func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) bool { + return FileExistsf(a.t, path, msg, args...) +} + +// HTTPBodyContains asserts that a specified handler returns a +// body that contains a string. +// +// a.HTTPBodyContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + return HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) +} + +// HTTPBodyContainsf asserts that a specified handler returns a +// body that contains a string. +// +// a.HTTPBodyContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + return HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) +} + +// HTTPBodyNotContains asserts that a specified handler returns a +// body that does not contain a string. +// +// a.HTTPBodyNotContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + return HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) +} + +// HTTPBodyNotContainsf asserts that a specified handler returns a +// body that does not contain a string. +// +// a.HTTPBodyNotContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + return HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) +} + +// HTTPError asserts that a specified handler returns an error status code. +// +// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { + return HTTPError(a.t, handler, method, url, values, msgAndArgs...) +} + +// HTTPErrorf asserts that a specified handler returns an error status code. +// +// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + return HTTPErrorf(a.t, handler, method, url, values, msg, args...) +} + +// HTTPRedirect asserts that a specified handler returns a redirect status code. +// +// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { + return HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) +} + +// HTTPRedirectf asserts that a specified handler returns a redirect status code. +// +// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + return HTTPRedirectf(a.t, handler, method, url, values, msg, args...) +} + +// HTTPSuccess asserts that a specified handler returns a success status code. +// +// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { + return HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) +} + +// HTTPSuccessf asserts that a specified handler returns a success status code. +// +// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + return HTTPSuccessf(a.t, handler, method, url, values, msg, args...) +} + +// Implements asserts that an object is implemented by the specified interface. +// +// a.Implements((*MyInterface)(nil), new(MyObject)) +func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + return Implements(a.t, interfaceObject, object, msgAndArgs...) +} + +// Implementsf asserts that an object is implemented by the specified interface. +// +// a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) +func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + return Implementsf(a.t, interfaceObject, object, msg, args...) +} + +// InDelta asserts that the two numerals are within delta of each other. +// +// a.InDelta(math.Pi, (22 / 7.0), 0.01) +func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + return InDelta(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + return InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + return InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) +} + +// InDeltaSlice is the same as InDelta, except it compares two slices. +func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDeltaSlicef is the same as InDelta, except it compares two slices. +func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + return InDeltaSlicef(a.t, expected, actual, delta, msg, args...) +} + +// InDeltaf asserts that the two numerals are within delta of each other. +// +// a.InDeltaf(math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) +func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + return InDeltaf(a.t, expected, actual, delta, msg, args...) +} + +// InEpsilon asserts that expected and actual have a relative error less than epsilon +func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) +} + +// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. +func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) +} + +// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. +func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + return InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) +} + +// InEpsilonf asserts that expected and actual have a relative error less than epsilon +func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + return InEpsilonf(a.t, expected, actual, epsilon, msg, args...) +} + +// IsType asserts that the specified objects are of the same type. +func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { + return IsType(a.t, expectedType, object, msgAndArgs...) +} + +// IsTypef asserts that the specified objects are of the same type. +func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { + return IsTypef(a.t, expectedType, object, msg, args...) +} + +// JSONEq asserts that two JSON strings are equivalent. +// +// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) +func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool { + return JSONEq(a.t, expected, actual, msgAndArgs...) +} + +// JSONEqf asserts that two JSON strings are equivalent. +// +// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") +func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool { + return JSONEqf(a.t, expected, actual, msg, args...) +} + +// Len asserts that the specified object has specific length. +// Len also fails if the object has a type that len() not accept. +// +// a.Len(mySlice, 3) +func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool { + return Len(a.t, object, length, msgAndArgs...) +} + +// Lenf asserts that the specified object has specific length. +// Lenf also fails if the object has a type that len() not accept. +// +// a.Lenf(mySlice, 3, "error message %s", "formatted") +func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool { + return Lenf(a.t, object, length, msg, args...) +} + +// Nil asserts that the specified object is nil. +// +// a.Nil(err) +func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool { + return Nil(a.t, object, msgAndArgs...) +} + +// Nilf asserts that the specified object is nil. +// +// a.Nilf(err, "error message %s", "formatted") +func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool { + return Nilf(a.t, object, msg, args...) +} + +// NoError asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if a.NoError(err) { +// assert.Equal(t, expectedObj, actualObj) +// } +func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool { + return NoError(a.t, err, msgAndArgs...) +} + +// NoErrorf asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if a.NoErrorf(err, "error message %s", "formatted") { +// assert.Equal(t, expectedObj, actualObj) +// } +func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool { + return NoErrorf(a.t, err, msg, args...) +} + +// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// a.NotContains("Hello World", "Earth") +// a.NotContains(["Hello", "World"], "Earth") +// a.NotContains({"Hello": "World"}, "Earth") +func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { + return NotContains(a.t, s, contains, msgAndArgs...) +} + +// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") +// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") +// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") +func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { + return NotContainsf(a.t, s, contains, msg, args...) +} + +// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if a.NotEmpty(obj) { +// assert.Equal(t, "two", obj[1]) +// } +func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool { + return NotEmpty(a.t, object, msgAndArgs...) +} + +// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if a.NotEmptyf(obj, "error message %s", "formatted") { +// assert.Equal(t, "two", obj[1]) +// } +func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool { + return NotEmptyf(a.t, object, msg, args...) +} + +// NotEqual asserts that the specified values are NOT equal. +// +// a.NotEqual(obj1, obj2) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + return NotEqual(a.t, expected, actual, msgAndArgs...) +} + +// NotEqualf asserts that the specified values are NOT equal. +// +// a.NotEqualf(obj1, obj2, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + return NotEqualf(a.t, expected, actual, msg, args...) +} + +// NotNil asserts that the specified object is not nil. +// +// a.NotNil(err) +func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool { + return NotNil(a.t, object, msgAndArgs...) +} + +// NotNilf asserts that the specified object is not nil. +// +// a.NotNilf(err, "error message %s", "formatted") +func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool { + return NotNilf(a.t, object, msg, args...) +} + +// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// a.NotPanics(func(){ RemainCalm() }) +func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool { + return NotPanics(a.t, f, msgAndArgs...) +} + +// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") +func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool { + return NotPanicsf(a.t, f, msg, args...) +} + +// NotRegexp asserts that a specified regexp does not match a string. +// +// a.NotRegexp(regexp.MustCompile("starts"), "it's starting") +// a.NotRegexp("^start", "it's not starting") +func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + return NotRegexp(a.t, rx, str, msgAndArgs...) +} + +// NotRegexpf asserts that a specified regexp does not match a string. +// +// a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") +// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") +func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { + return NotRegexpf(a.t, rx, str, msg, args...) +} + +// NotSubset asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { + return NotSubset(a.t, list, subset, msgAndArgs...) +} + +// NotSubsetf asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { + return NotSubsetf(a.t, list, subset, msg, args...) +} + +// NotZero asserts that i is not the zero value for its type. +func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool { + return NotZero(a.t, i, msgAndArgs...) +} + +// NotZerof asserts that i is not the zero value for its type. +func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bool { + return NotZerof(a.t, i, msg, args...) +} + +// Panics asserts that the code inside the specified PanicTestFunc panics. +// +// a.Panics(func(){ GoCrazy() }) +func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool { + return Panics(a.t, f, msgAndArgs...) +} + +// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// a.PanicsWithValue("crazy error", func(){ GoCrazy() }) +func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { + return PanicsWithValue(a.t, expected, f, msgAndArgs...) +} + +// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { + return PanicsWithValuef(a.t, expected, f, msg, args...) +} + +// Panicsf asserts that the code inside the specified PanicTestFunc panics. +// +// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") +func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool { + return Panicsf(a.t, f, msg, args...) +} + +// Regexp asserts that a specified regexp matches a string. +// +// a.Regexp(regexp.MustCompile("start"), "it's starting") +// a.Regexp("start...$", "it's not starting") +func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + return Regexp(a.t, rx, str, msgAndArgs...) +} + +// Regexpf asserts that a specified regexp matches a string. +// +// a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") +// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") +func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { + return Regexpf(a.t, rx, str, msg, args...) +} + +// Subset asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { + return Subset(a.t, list, subset, msgAndArgs...) +} + +// Subsetf asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { + return Subsetf(a.t, list, subset, msg, args...) +} + +// True asserts that the specified value is true. +// +// a.True(myBool) +func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool { + return True(a.t, value, msgAndArgs...) +} + +// Truef asserts that the specified value is true. +// +// a.Truef(myBool, "error message %s", "formatted") +func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool { + return Truef(a.t, value, msg, args...) +} + +// WithinDuration asserts that the two times are within duration delta of each other. +// +// a.WithinDuration(time.Now(), time.Now(), 10*time.Second) +func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { + return WithinDuration(a.t, expected, actual, delta, msgAndArgs...) +} + +// WithinDurationf asserts that the two times are within duration delta of each other. +// +// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") +func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { + return WithinDurationf(a.t, expected, actual, delta, msg, args...) +} + +// Zero asserts that i is the zero value for its type. +func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool { + return Zero(a.t, i, msgAndArgs...) +} + +// Zerof asserts that i is the zero value for its type. +func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) bool { + return Zerof(a.t, i, msg, args...) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl b/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl new file mode 100644 index 0000000..99f9acf --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl @@ -0,0 +1,4 @@ +{{.CommentWithoutT "a"}} +func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool { + return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go new file mode 100644 index 0000000..47bda77 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertions.go @@ -0,0 +1,1256 @@ +package assert + +import ( + "bufio" + "bytes" + "encoding/json" + "errors" + "fmt" + "math" + "os" + "reflect" + "regexp" + "runtime" + "strings" + "time" + "unicode" + "unicode/utf8" + + "github.com/davecgh/go-spew/spew" + "github.com/pmezard/go-difflib/difflib" +) + +//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_format.go.tmpl + +// TestingT is an interface wrapper around *testing.T +type TestingT interface { + Errorf(format string, args ...interface{}) +} + +// Comparison a custom function that returns true on success and false on failure +type Comparison func() (success bool) + +/* + Helper functions +*/ + +// ObjectsAreEqual determines if two objects are considered equal. +// +// This function does no assertion of any kind. +func ObjectsAreEqual(expected, actual interface{}) bool { + + if expected == nil || actual == nil { + return expected == actual + } + if exp, ok := expected.([]byte); ok { + act, ok := actual.([]byte) + if !ok { + return false + } else if exp == nil || act == nil { + return exp == nil && act == nil + } + return bytes.Equal(exp, act) + } + return reflect.DeepEqual(expected, actual) + +} + +// ObjectsAreEqualValues gets whether two objects are equal, or if their +// values are equal. +func ObjectsAreEqualValues(expected, actual interface{}) bool { + if ObjectsAreEqual(expected, actual) { + return true + } + + actualType := reflect.TypeOf(actual) + if actualType == nil { + return false + } + expectedValue := reflect.ValueOf(expected) + if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) { + // Attempt comparison after type conversion + return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual) + } + + return false +} + +/* CallerInfo is necessary because the assert functions use the testing object +internally, causing it to print the file:line of the assert method, rather than where +the problem actually occurred in calling code.*/ + +// CallerInfo returns an array of strings containing the file and line number +// of each stack frame leading from the current test to the assert call that +// failed. +func CallerInfo() []string { + + pc := uintptr(0) + file := "" + line := 0 + ok := false + name := "" + + callers := []string{} + for i := 0; ; i++ { + pc, file, line, ok = runtime.Caller(i) + if !ok { + // The breaks below failed to terminate the loop, and we ran off the + // end of the call stack. + break + } + + // This is a huge edge case, but it will panic if this is the case, see #180 + if file == "" { + break + } + + f := runtime.FuncForPC(pc) + if f == nil { + break + } + name = f.Name() + + // testing.tRunner is the standard library function that calls + // tests. Subtests are called directly by tRunner, without going through + // the Test/Benchmark/Example function that contains the t.Run calls, so + // with subtests we should break when we hit tRunner, without adding it + // to the list of callers. + if name == "testing.tRunner" { + break + } + + parts := strings.Split(file, "/") + file = parts[len(parts)-1] + if len(parts) > 1 { + dir := parts[len(parts)-2] + if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" { + callers = append(callers, fmt.Sprintf("%s:%d", file, line)) + } + } + + // Drop the package + segments := strings.Split(name, ".") + name = segments[len(segments)-1] + if isTest(name, "Test") || + isTest(name, "Benchmark") || + isTest(name, "Example") { + break + } + } + + return callers +} + +// Stolen from the `go test` tool. +// isTest tells whether name looks like a test (or benchmark, according to prefix). +// It is a Test (say) if there is a character after Test that is not a lower-case letter. +// We don't want TesticularCancer. +func isTest(name, prefix string) bool { + if !strings.HasPrefix(name, prefix) { + return false + } + if len(name) == len(prefix) { // "Test" is ok + return true + } + rune, _ := utf8.DecodeRuneInString(name[len(prefix):]) + return !unicode.IsLower(rune) +} + +// getWhitespaceString returns a string that is long enough to overwrite the default +// output from the go testing framework. +func getWhitespaceString() string { + + _, file, line, ok := runtime.Caller(1) + if !ok { + return "" + } + parts := strings.Split(file, "/") + file = parts[len(parts)-1] + + return strings.Repeat(" ", len(fmt.Sprintf("%s:%d: ", file, line))) + +} + +func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { + if len(msgAndArgs) == 0 || msgAndArgs == nil { + return "" + } + if len(msgAndArgs) == 1 { + return msgAndArgs[0].(string) + } + if len(msgAndArgs) > 1 { + return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) + } + return "" +} + +// Aligns the provided message so that all lines after the first line start at the same location as the first line. +// Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab). +// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the +// basis on which the alignment occurs). +func indentMessageLines(message string, longestLabelLen int) string { + outBuf := new(bytes.Buffer) + + for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ { + // no need to align first line because it starts at the correct location (after the label) + if i != 0 { + // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab + outBuf.WriteString("\n\r\t" + strings.Repeat(" ", longestLabelLen+1) + "\t") + } + outBuf.WriteString(scanner.Text()) + } + + return outBuf.String() +} + +type failNower interface { + FailNow() +} + +// FailNow fails test +func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { + Fail(t, failureMessage, msgAndArgs...) + + // We cannot extend TestingT with FailNow() and + // maintain backwards compatibility, so we fallback + // to panicking when FailNow is not available in + // TestingT. + // See issue #263 + + if t, ok := t.(failNower); ok { + t.FailNow() + } else { + panic("test failed and t is missing `FailNow()`") + } + return false +} + +// Fail reports a failure through +func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { + content := []labeledContent{ + {"Error Trace", strings.Join(CallerInfo(), "\n\r\t\t\t")}, + {"Error", failureMessage}, + } + + // Add test name if the Go version supports it + if n, ok := t.(interface { + Name() string + }); ok { + content = append(content, labeledContent{"Test", n.Name()}) + } + + message := messageFromMsgAndArgs(msgAndArgs...) + if len(message) > 0 { + content = append(content, labeledContent{"Messages", message}) + } + + t.Errorf("%s", "\r"+getWhitespaceString()+labeledOutput(content...)) + + return false +} + +type labeledContent struct { + label string + content string +} + +// labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner: +// +// \r\t{{label}}:{{align_spaces}}\t{{content}}\n +// +// The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label. +// If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this +// alignment is achieved, "\t{{content}}\n" is added for the output. +// +// If the content of the labeledOutput contains line breaks, the subsequent lines are aligned so that they start at the same location as the first line. +func labeledOutput(content ...labeledContent) string { + longestLabel := 0 + for _, v := range content { + if len(v.label) > longestLabel { + longestLabel = len(v.label) + } + } + var output string + for _, v := range content { + output += "\r\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n" + } + return output +} + +// Implements asserts that an object is implemented by the specified interface. +// +// assert.Implements(t, (*MyInterface)(nil), new(MyObject)) +func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + interfaceType := reflect.TypeOf(interfaceObject).Elem() + + if object == nil { + return Fail(t, fmt.Sprintf("Cannot check if nil implements %v", interfaceType), msgAndArgs...) + } + if !reflect.TypeOf(object).Implements(interfaceType) { + return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...) + } + + return true +} + +// IsType asserts that the specified objects are of the same type. +func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { + + if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) { + return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...) + } + + return true +} + +// Equal asserts that two objects are equal. +// +// assert.Equal(t, 123, 123) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if err := validateEqualArgs(expected, actual); err != nil { + return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)", + expected, actual, err), msgAndArgs...) + } + + if !ObjectsAreEqual(expected, actual) { + diff := diff(expected, actual) + expected, actual = formatUnequalValues(expected, actual) + return Fail(t, fmt.Sprintf("Not equal: \n"+ + "expected: %s\n"+ + "actual : %s%s", expected, actual, diff), msgAndArgs...) + } + + return true + +} + +// formatUnequalValues takes two values of arbitrary types and returns string +// representations appropriate to be presented to the user. +// +// If the values are not of like type, the returned strings will be prefixed +// with the type name, and the value will be enclosed in parenthesis similar +// to a type conversion in the Go grammar. +func formatUnequalValues(expected, actual interface{}) (e string, a string) { + if reflect.TypeOf(expected) != reflect.TypeOf(actual) { + return fmt.Sprintf("%T(%#v)", expected, expected), + fmt.Sprintf("%T(%#v)", actual, actual) + } + + return fmt.Sprintf("%#v", expected), + fmt.Sprintf("%#v", actual) +} + +// EqualValues asserts that two objects are equal or convertable to the same types +// and equal. +// +// assert.EqualValues(t, uint32(123), int32(123)) +func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + + if !ObjectsAreEqualValues(expected, actual) { + diff := diff(expected, actual) + expected, actual = formatUnequalValues(expected, actual) + return Fail(t, fmt.Sprintf("Not equal: \n"+ + "expected: %s\n"+ + "actual : %s%s", expected, actual, diff), msgAndArgs...) + } + + return true + +} + +// Exactly asserts that two objects are equal in value and type. +// +// assert.Exactly(t, int32(123), int64(123)) +func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + + aType := reflect.TypeOf(expected) + bType := reflect.TypeOf(actual) + + if aType != bType { + return Fail(t, fmt.Sprintf("Types expected to match exactly\n\r\t%v != %v", aType, bType), msgAndArgs...) + } + + return Equal(t, expected, actual, msgAndArgs...) + +} + +// NotNil asserts that the specified object is not nil. +// +// assert.NotNil(t, err) +func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if !isNil(object) { + return true + } + return Fail(t, "Expected value not to be nil.", msgAndArgs...) +} + +// isNil checks if a specified object is nil or not, without Failing. +func isNil(object interface{}) bool { + if object == nil { + return true + } + + value := reflect.ValueOf(object) + kind := value.Kind() + if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() { + return true + } + + return false +} + +// Nil asserts that the specified object is nil. +// +// assert.Nil(t, err) +func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if isNil(object) { + return true + } + return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...) +} + +// isEmpty gets whether the specified object is considered empty or not. +func isEmpty(object interface{}) bool { + + // get nil case out of the way + if object == nil { + return true + } + + objValue := reflect.ValueOf(object) + + switch objValue.Kind() { + // collection types are empty when they have no element + case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice: + return objValue.Len() == 0 + // pointers are empty if nil or if the value they point to is empty + case reflect.Ptr: + if objValue.IsNil() { + return true + } + deref := objValue.Elem().Interface() + return isEmpty(deref) + // for all other types, compare against the zero value + default: + zero := reflect.Zero(objValue.Type()) + return reflect.DeepEqual(object, zero.Interface()) + } +} + +// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// assert.Empty(t, obj) +func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + + pass := isEmpty(object) + if !pass { + Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...) + } + + return pass + +} + +// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if assert.NotEmpty(t, obj) { +// assert.Equal(t, "two", obj[1]) +// } +func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + + pass := !isEmpty(object) + if !pass { + Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...) + } + + return pass + +} + +// getLen try to get length of object. +// return (false, 0) if impossible. +func getLen(x interface{}) (ok bool, length int) { + v := reflect.ValueOf(x) + defer func() { + if e := recover(); e != nil { + ok = false + } + }() + return true, v.Len() +} + +// Len asserts that the specified object has specific length. +// Len also fails if the object has a type that len() not accept. +// +// assert.Len(t, mySlice, 3) +func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool { + ok, l := getLen(object) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...) + } + + if l != length { + return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) + } + return true +} + +// True asserts that the specified value is true. +// +// assert.True(t, myBool) +func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { + + if value != true { + return Fail(t, "Should be true", msgAndArgs...) + } + + return true + +} + +// False asserts that the specified value is false. +// +// assert.False(t, myBool) +func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { + + if value != false { + return Fail(t, "Should be false", msgAndArgs...) + } + + return true + +} + +// NotEqual asserts that the specified values are NOT equal. +// +// assert.NotEqual(t, obj1, obj2) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if err := validateEqualArgs(expected, actual); err != nil { + return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)", + expected, actual, err), msgAndArgs...) + } + + if ObjectsAreEqual(expected, actual) { + return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) + } + + return true + +} + +// containsElement try loop over the list check if the list includes the element. +// return (false, false) if impossible. +// return (true, false) if element was not found. +// return (true, true) if element was found. +func includeElement(list interface{}, element interface{}) (ok, found bool) { + + listValue := reflect.ValueOf(list) + elementValue := reflect.ValueOf(element) + defer func() { + if e := recover(); e != nil { + ok = false + found = false + } + }() + + if reflect.TypeOf(list).Kind() == reflect.String { + return true, strings.Contains(listValue.String(), elementValue.String()) + } + + if reflect.TypeOf(list).Kind() == reflect.Map { + mapKeys := listValue.MapKeys() + for i := 0; i < len(mapKeys); i++ { + if ObjectsAreEqual(mapKeys[i].Interface(), element) { + return true, true + } + } + return true, false + } + + for i := 0; i < listValue.Len(); i++ { + if ObjectsAreEqual(listValue.Index(i).Interface(), element) { + return true, true + } + } + return true, false + +} + +// Contains asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// assert.Contains(t, "Hello World", "World") +// assert.Contains(t, ["Hello", "World"], "World") +// assert.Contains(t, {"Hello": "World"}, "Hello") +func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { + + ok, found := includeElement(s, contains) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) + } + if !found { + return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...) + } + + return true + +} + +// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// assert.NotContains(t, "Hello World", "Earth") +// assert.NotContains(t, ["Hello", "World"], "Earth") +// assert.NotContains(t, {"Hello": "World"}, "Earth") +func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { + + ok, found := includeElement(s, contains) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) + } + if found { + return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...) + } + + return true + +} + +// Subset asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { + if subset == nil { + return true // we consider nil to be equal to the nil set + } + + subsetValue := reflect.ValueOf(subset) + defer func() { + if e := recover(); e != nil { + ok = false + } + }() + + listKind := reflect.TypeOf(list).Kind() + subsetKind := reflect.TypeOf(subset).Kind() + + if listKind != reflect.Array && listKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) + } + + if subsetKind != reflect.Array && subsetKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) + } + + for i := 0; i < subsetValue.Len(); i++ { + element := subsetValue.Index(i).Interface() + ok, found := includeElement(list, element) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) + } + if !found { + return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", list, element), msgAndArgs...) + } + } + + return true +} + +// NotSubset asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { + if subset == nil { + return Fail(t, fmt.Sprintf("nil is the empty set which is a subset of every set"), msgAndArgs...) + } + + subsetValue := reflect.ValueOf(subset) + defer func() { + if e := recover(); e != nil { + ok = false + } + }() + + listKind := reflect.TypeOf(list).Kind() + subsetKind := reflect.TypeOf(subset).Kind() + + if listKind != reflect.Array && listKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) + } + + if subsetKind != reflect.Array && subsetKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) + } + + for i := 0; i < subsetValue.Len(); i++ { + element := subsetValue.Index(i).Interface() + ok, found := includeElement(list, element) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) + } + if !found { + return true + } + } + + return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...) +} + +// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) +func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) { + if isEmpty(listA) && isEmpty(listB) { + return true + } + + aKind := reflect.TypeOf(listA).Kind() + bKind := reflect.TypeOf(listB).Kind() + + if aKind != reflect.Array && aKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listA, aKind), msgAndArgs...) + } + + if bKind != reflect.Array && bKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listB, bKind), msgAndArgs...) + } + + aValue := reflect.ValueOf(listA) + bValue := reflect.ValueOf(listB) + + aLen := aValue.Len() + bLen := bValue.Len() + + if aLen != bLen { + return Fail(t, fmt.Sprintf("lengths don't match: %d != %d", aLen, bLen), msgAndArgs...) + } + + // Mark indexes in bValue that we already used + visited := make([]bool, bLen) + for i := 0; i < aLen; i++ { + element := aValue.Index(i).Interface() + found := false + for j := 0; j < bLen; j++ { + if visited[j] { + continue + } + if ObjectsAreEqual(bValue.Index(j).Interface(), element) { + visited[j] = true + found = true + break + } + } + if !found { + return Fail(t, fmt.Sprintf("element %s appears more times in %s than in %s", element, aValue, bValue), msgAndArgs...) + } + } + + return true +} + +// Condition uses a Comparison to assert a complex condition. +func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { + result := comp() + if !result { + Fail(t, "Condition failed!", msgAndArgs...) + } + return result +} + +// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics +// methods, and represents a simple func that takes no arguments, and returns nothing. +type PanicTestFunc func() + +// didPanic returns true if the function passed to it panics. Otherwise, it returns false. +func didPanic(f PanicTestFunc) (bool, interface{}) { + + didPanic := false + var message interface{} + func() { + + defer func() { + if message = recover(); message != nil { + didPanic = true + } + }() + + // call the target function + f() + + }() + + return didPanic, message + +} + +// Panics asserts that the code inside the specified PanicTestFunc panics. +// +// assert.Panics(t, func(){ GoCrazy() }) +func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { + + if funcDidPanic, panicValue := didPanic(f); !funcDidPanic { + return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...) + } + + return true +} + +// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) +func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { + + funcDidPanic, panicValue := didPanic(f) + if !funcDidPanic { + return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...) + } + if panicValue != expected { + return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%v\n\r\tPanic value:\t%v", f, expected, panicValue), msgAndArgs...) + } + + return true +} + +// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// assert.NotPanics(t, func(){ RemainCalm() }) +func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { + + if funcDidPanic, panicValue := didPanic(f); funcDidPanic { + return Fail(t, fmt.Sprintf("func %#v should not panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...) + } + + return true +} + +// WithinDuration asserts that the two times are within duration delta of each other. +// +// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) +func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { + + dt := expected.Sub(actual) + if dt < -delta || dt > delta { + return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) + } + + return true +} + +func toFloat(x interface{}) (float64, bool) { + var xf float64 + xok := true + + switch xn := x.(type) { + case uint8: + xf = float64(xn) + case uint16: + xf = float64(xn) + case uint32: + xf = float64(xn) + case uint64: + xf = float64(xn) + case int: + xf = float64(xn) + case int8: + xf = float64(xn) + case int16: + xf = float64(xn) + case int32: + xf = float64(xn) + case int64: + xf = float64(xn) + case float32: + xf = float64(xn) + case float64: + xf = float64(xn) + case time.Duration: + xf = float64(xn) + default: + xok = false + } + + return xf, xok +} + +// InDelta asserts that the two numerals are within delta of each other. +// +// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01) +func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + + af, aok := toFloat(expected) + bf, bok := toFloat(actual) + + if !aok || !bok { + return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...) + } + + if math.IsNaN(af) { + return Fail(t, fmt.Sprintf("Expected must not be NaN"), msgAndArgs...) + } + + if math.IsNaN(bf) { + return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...) + } + + dt := af - bf + if dt < -delta || dt > delta { + return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) + } + + return true +} + +// InDeltaSlice is the same as InDelta, except it compares two slices. +func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if expected == nil || actual == nil || + reflect.TypeOf(actual).Kind() != reflect.Slice || + reflect.TypeOf(expected).Kind() != reflect.Slice { + return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) + } + + actualSlice := reflect.ValueOf(actual) + expectedSlice := reflect.ValueOf(expected) + + for i := 0; i < actualSlice.Len(); i++ { + result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta, msgAndArgs...) + if !result { + return result + } + } + + return true +} + +// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if expected == nil || actual == nil || + reflect.TypeOf(actual).Kind() != reflect.Map || + reflect.TypeOf(expected).Kind() != reflect.Map { + return Fail(t, "Arguments must be maps", msgAndArgs...) + } + + expectedMap := reflect.ValueOf(expected) + actualMap := reflect.ValueOf(actual) + + if expectedMap.Len() != actualMap.Len() { + return Fail(t, "Arguments must have the same number of keys", msgAndArgs...) + } + + for _, k := range expectedMap.MapKeys() { + ev := expectedMap.MapIndex(k) + av := actualMap.MapIndex(k) + + if !ev.IsValid() { + return Fail(t, fmt.Sprintf("missing key %q in expected map", k), msgAndArgs...) + } + + if !av.IsValid() { + return Fail(t, fmt.Sprintf("missing key %q in actual map", k), msgAndArgs...) + } + + if !InDelta( + t, + ev.Interface(), + av.Interface(), + delta, + msgAndArgs..., + ) { + return false + } + } + + return true +} + +func calcRelativeError(expected, actual interface{}) (float64, error) { + af, aok := toFloat(expected) + if !aok { + return 0, fmt.Errorf("expected value %q cannot be converted to float", expected) + } + if af == 0 { + return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error") + } + bf, bok := toFloat(actual) + if !bok { + return 0, fmt.Errorf("actual value %q cannot be converted to float", actual) + } + + return math.Abs(af-bf) / math.Abs(af), nil +} + +// InEpsilon asserts that expected and actual have a relative error less than epsilon +func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + actualEpsilon, err := calcRelativeError(expected, actual) + if err != nil { + return Fail(t, err.Error(), msgAndArgs...) + } + if actualEpsilon > epsilon { + return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+ + " < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...) + } + + return true +} + +// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. +func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if expected == nil || actual == nil || + reflect.TypeOf(actual).Kind() != reflect.Slice || + reflect.TypeOf(expected).Kind() != reflect.Slice { + return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) + } + + actualSlice := reflect.ValueOf(actual) + expectedSlice := reflect.ValueOf(expected) + + for i := 0; i < actualSlice.Len(); i++ { + result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon) + if !result { + return result + } + } + + return true +} + +/* + Errors +*/ + +// NoError asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if assert.NoError(t, err) { +// assert.Equal(t, expectedObj, actualObj) +// } +func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { + if err != nil { + return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...) + } + + return true +} + +// Error asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if assert.Error(t, err) { +// assert.Equal(t, expectedError, err) +// } +func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { + + if err == nil { + return Fail(t, "An error is expected but got nil.", msgAndArgs...) + } + + return true +} + +// EqualError asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// assert.EqualError(t, err, expectedErrorString) +func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool { + if !Error(t, theError, msgAndArgs...) { + return false + } + expected := errString + actual := theError.Error() + // don't need to use deep equals here, we know they are both strings + if expected != actual { + return Fail(t, fmt.Sprintf("Error message not equal:\n"+ + "expected: %q\n"+ + "actual : %q", expected, actual), msgAndArgs...) + } + return true +} + +// matchRegexp return true if a specified regexp matches a string. +func matchRegexp(rx interface{}, str interface{}) bool { + + var r *regexp.Regexp + if rr, ok := rx.(*regexp.Regexp); ok { + r = rr + } else { + r = regexp.MustCompile(fmt.Sprint(rx)) + } + + return (r.FindStringIndex(fmt.Sprint(str)) != nil) + +} + +// Regexp asserts that a specified regexp matches a string. +// +// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") +// assert.Regexp(t, "start...$", "it's not starting") +func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + + match := matchRegexp(rx, str) + + if !match { + Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...) + } + + return match +} + +// NotRegexp asserts that a specified regexp does not match a string. +// +// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") +// assert.NotRegexp(t, "^start", "it's not starting") +func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + match := matchRegexp(rx, str) + + if match { + Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...) + } + + return !match + +} + +// Zero asserts that i is the zero value for its type. +func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { + if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { + return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...) + } + return true +} + +// NotZero asserts that i is not the zero value for its type. +func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { + if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { + return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...) + } + return true +} + +// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. +func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { + info, err := os.Lstat(path) + if err != nil { + if os.IsNotExist(err) { + return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) + } + return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) + } + if info.IsDir() { + return Fail(t, fmt.Sprintf("%q is a directory", path), msgAndArgs...) + } + return true +} + +// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. +func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { + info, err := os.Lstat(path) + if err != nil { + if os.IsNotExist(err) { + return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) + } + return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) + } + if !info.IsDir() { + return Fail(t, fmt.Sprintf("%q is a file", path), msgAndArgs...) + } + return true +} + +// JSONEq asserts that two JSON strings are equivalent. +// +// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) +func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { + var expectedJSONAsInterface, actualJSONAsInterface interface{} + + if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil { + return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...) + } + + if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil { + return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...) + } + + return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...) +} + +func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { + t := reflect.TypeOf(v) + k := t.Kind() + + if k == reflect.Ptr { + t = t.Elem() + k = t.Kind() + } + return t, k +} + +// diff returns a diff of both values as long as both are of the same type and +// are a struct, map, slice or array. Otherwise it returns an empty string. +func diff(expected interface{}, actual interface{}) string { + if expected == nil || actual == nil { + return "" + } + + et, ek := typeAndKind(expected) + at, _ := typeAndKind(actual) + + if et != at { + return "" + } + + if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array { + return "" + } + + e := spewConfig.Sdump(expected) + a := spewConfig.Sdump(actual) + + diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ + A: difflib.SplitLines(e), + B: difflib.SplitLines(a), + FromFile: "Expected", + FromDate: "", + ToFile: "Actual", + ToDate: "", + Context: 1, + }) + + return "\n\nDiff:\n" + diff +} + +// validateEqualArgs checks whether provided arguments can be safely used in the +// Equal/NotEqual functions. +func validateEqualArgs(expected, actual interface{}) error { + if isFunction(expected) || isFunction(actual) { + return errors.New("cannot take func type as argument") + } + return nil +} + +func isFunction(arg interface{}) bool { + if arg == nil { + return false + } + return reflect.TypeOf(arg).Kind() == reflect.Func +} + +var spewConfig = spew.ConfigState{ + Indent: " ", + DisablePointerAddresses: true, + DisableCapacities: true, + SortKeys: true, +} diff --git a/vendor/github.com/stretchr/testify/assert/doc.go b/vendor/github.com/stretchr/testify/assert/doc.go new file mode 100644 index 0000000..c9dccc4 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/doc.go @@ -0,0 +1,45 @@ +// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. +// +// Example Usage +// +// The following is a complete example using assert in a standard test function: +// import ( +// "testing" +// "github.com/stretchr/testify/assert" +// ) +// +// func TestSomething(t *testing.T) { +// +// var a string = "Hello" +// var b string = "Hello" +// +// assert.Equal(t, a, b, "The two words should be the same.") +// +// } +// +// if you assert many times, use the format below: +// +// import ( +// "testing" +// "github.com/stretchr/testify/assert" +// ) +// +// func TestSomething(t *testing.T) { +// assert := assert.New(t) +// +// var a string = "Hello" +// var b string = "Hello" +// +// assert.Equal(a, b, "The two words should be the same.") +// } +// +// Assertions +// +// Assertions allow you to easily write test code, and are global funcs in the `assert` package. +// All assertion functions take, as the first argument, the `*testing.T` object provided by the +// testing framework. This allows the assertion funcs to write the failings and other details to +// the correct place. +// +// Every assertion function also takes an optional string message as the final argument, +// allowing custom error messages to be appended to the message the assertion method outputs. +package assert diff --git a/vendor/github.com/stretchr/testify/assert/errors.go b/vendor/github.com/stretchr/testify/assert/errors.go new file mode 100644 index 0000000..ac9dc9d --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/errors.go @@ -0,0 +1,10 @@ +package assert + +import ( + "errors" +) + +// AnError is an error instance useful for testing. If the code does not care +// about error specifics, and only needs to return the error for example, this +// error should be used to make the test code more readable. +var AnError = errors.New("assert.AnError general error for testing") diff --git a/vendor/github.com/stretchr/testify/assert/forward_assertions.go b/vendor/github.com/stretchr/testify/assert/forward_assertions.go new file mode 100644 index 0000000..9ad5685 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/forward_assertions.go @@ -0,0 +1,16 @@ +package assert + +// Assertions provides assertion methods around the +// TestingT interface. +type Assertions struct { + t TestingT +} + +// New makes a new Assertions object for the specified TestingT. +func New(t TestingT) *Assertions { + return &Assertions{ + t: t, + } +} + +//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions.go b/vendor/github.com/stretchr/testify/assert/http_assertions.go new file mode 100644 index 0000000..3101e78 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/http_assertions.go @@ -0,0 +1,127 @@ +package assert + +import ( + "fmt" + "net/http" + "net/http/httptest" + "net/url" + "strings" +) + +// httpCode is a helper that returns HTTP code of the response. It returns -1 and +// an error if building a new request fails. +func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) { + w := httptest.NewRecorder() + req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) + if err != nil { + return -1, err + } + handler(w, req) + return w.Code, nil +} + +// HTTPSuccess asserts that a specified handler returns a success status code. +// +// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { + code, err := httpCode(handler, method, url, values) + if err != nil { + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + return false + } + + isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent + if !isSuccessCode { + Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code)) + } + + return isSuccessCode +} + +// HTTPRedirect asserts that a specified handler returns a redirect status code. +// +// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { + code, err := httpCode(handler, method, url, values) + if err != nil { + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + return false + } + + isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect + if !isRedirectCode { + Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code)) + } + + return isRedirectCode +} + +// HTTPError asserts that a specified handler returns an error status code. +// +// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { + code, err := httpCode(handler, method, url, values) + if err != nil { + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + return false + } + + isErrorCode := code >= http.StatusBadRequest + if !isErrorCode { + Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code)) + } + + return isErrorCode +} + +// HTTPBody is a helper that returns HTTP body of the response. It returns +// empty string if building a new request fails. +func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { + w := httptest.NewRecorder() + req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) + if err != nil { + return "" + } + handler(w, req) + return w.Body.String() +} + +// HTTPBodyContains asserts that a specified handler returns a +// body that contains a string. +// +// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + body := HTTPBody(handler, method, url, values) + + contains := strings.Contains(body, fmt.Sprint(str)) + if !contains { + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + } + + return contains +} + +// HTTPBodyNotContains asserts that a specified handler returns a +// body that does not contain a string. +// +// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + body := HTTPBody(handler, method, url, values) + + contains := strings.Contains(body, fmt.Sprint(str)) + if contains { + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + } + + return !contains +} diff --git a/vendor/github.com/stretchr/testify/require/doc.go b/vendor/github.com/stretchr/testify/require/doc.go new file mode 100644 index 0000000..169de39 --- /dev/null +++ b/vendor/github.com/stretchr/testify/require/doc.go @@ -0,0 +1,28 @@ +// Package require implements the same assertions as the `assert` package but +// stops test execution when a test fails. +// +// Example Usage +// +// The following is a complete example using require in a standard test function: +// import ( +// "testing" +// "github.com/stretchr/testify/require" +// ) +// +// func TestSomething(t *testing.T) { +// +// var a string = "Hello" +// var b string = "Hello" +// +// require.Equal(t, a, b, "The two words should be the same.") +// +// } +// +// Assertions +// +// The `require` package have same global functions as in the `assert` package, +// but instead of returning a boolean result they call `t.FailNow()`. +// +// Every assertion function also takes an optional string message as the final argument, +// allowing custom error messages to be appended to the message the assertion method outputs. +package require diff --git a/vendor/github.com/stretchr/testify/require/forward_requirements.go b/vendor/github.com/stretchr/testify/require/forward_requirements.go new file mode 100644 index 0000000..ac71d40 --- /dev/null +++ b/vendor/github.com/stretchr/testify/require/forward_requirements.go @@ -0,0 +1,16 @@ +package require + +// Assertions provides assertion methods around the +// TestingT interface. +type Assertions struct { + t TestingT +} + +// New makes a new Assertions object for the specified TestingT. +func New(t TestingT) *Assertions { + return &Assertions{ + t: t, + } +} + +//go:generate go run ../_codegen/main.go -output-package=require -template=require_forward.go.tmpl -include-format-funcs diff --git a/vendor/github.com/stretchr/testify/require/require.go b/vendor/github.com/stretchr/testify/require/require.go new file mode 100644 index 0000000..ac3c308 --- /dev/null +++ b/vendor/github.com/stretchr/testify/require/require.go @@ -0,0 +1,867 @@ +/* +* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen +* THIS FILE MUST NOT BE EDITED BY HAND + */ + +package require + +import ( + assert "github.com/stretchr/testify/assert" + http "net/http" + url "net/url" + time "time" +) + +// Condition uses a Comparison to assert a complex condition. +func Condition(t TestingT, comp assert.Comparison, msgAndArgs ...interface{}) { + if !assert.Condition(t, comp, msgAndArgs...) { + t.FailNow() + } +} + +// Conditionf uses a Comparison to assert a complex condition. +func Conditionf(t TestingT, comp assert.Comparison, msg string, args ...interface{}) { + if !assert.Conditionf(t, comp, msg, args...) { + t.FailNow() + } +} + +// Contains asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// assert.Contains(t, "Hello World", "World") +// assert.Contains(t, ["Hello", "World"], "World") +// assert.Contains(t, {"Hello": "World"}, "Hello") +func Contains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { + if !assert.Contains(t, s, contains, msgAndArgs...) { + t.FailNow() + } +} + +// Containsf asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") +// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") +// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") +func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { + if !assert.Containsf(t, s, contains, msg, args...) { + t.FailNow() + } +} + +// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. +func DirExists(t TestingT, path string, msgAndArgs ...interface{}) { + if !assert.DirExists(t, path, msgAndArgs...) { + t.FailNow() + } +} + +// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. +func DirExistsf(t TestingT, path string, msg string, args ...interface{}) { + if !assert.DirExistsf(t, path, msg, args...) { + t.FailNow() + } +} + +// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) +func ElementsMatch(t TestingT, listA interface{}, listB interface{}, msgAndArgs ...interface{}) { + if !assert.ElementsMatch(t, listA, listB, msgAndArgs...) { + t.FailNow() + } +} + +// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") +func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) { + if !assert.ElementsMatchf(t, listA, listB, msg, args...) { + t.FailNow() + } +} + +// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// assert.Empty(t, obj) +func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) { + if !assert.Empty(t, object, msgAndArgs...) { + t.FailNow() + } +} + +// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// assert.Emptyf(t, obj, "error message %s", "formatted") +func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) { + if !assert.Emptyf(t, object, msg, args...) { + t.FailNow() + } +} + +// Equal asserts that two objects are equal. +// +// assert.Equal(t, 123, 123) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func Equal(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if !assert.Equal(t, expected, actual, msgAndArgs...) { + t.FailNow() + } +} + +// EqualError asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// assert.EqualError(t, err, expectedErrorString) +func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) { + if !assert.EqualError(t, theError, errString, msgAndArgs...) { + t.FailNow() + } +} + +// EqualErrorf asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") +func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) { + if !assert.EqualErrorf(t, theError, errString, msg, args...) { + t.FailNow() + } +} + +// EqualValues asserts that two objects are equal or convertable to the same types +// and equal. +// +// assert.EqualValues(t, uint32(123), int32(123)) +func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if !assert.EqualValues(t, expected, actual, msgAndArgs...) { + t.FailNow() + } +} + +// EqualValuesf asserts that two objects are equal or convertable to the same types +// and equal. +// +// assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123)) +func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { + if !assert.EqualValuesf(t, expected, actual, msg, args...) { + t.FailNow() + } +} + +// Equalf asserts that two objects are equal. +// +// assert.Equalf(t, 123, 123, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { + if !assert.Equalf(t, expected, actual, msg, args...) { + t.FailNow() + } +} + +// Error asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if assert.Error(t, err) { +// assert.Equal(t, expectedError, err) +// } +func Error(t TestingT, err error, msgAndArgs ...interface{}) { + if !assert.Error(t, err, msgAndArgs...) { + t.FailNow() + } +} + +// Errorf asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if assert.Errorf(t, err, "error message %s", "formatted") { +// assert.Equal(t, expectedErrorf, err) +// } +func Errorf(t TestingT, err error, msg string, args ...interface{}) { + if !assert.Errorf(t, err, msg, args...) { + t.FailNow() + } +} + +// Exactly asserts that two objects are equal in value and type. +// +// assert.Exactly(t, int32(123), int64(123)) +func Exactly(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if !assert.Exactly(t, expected, actual, msgAndArgs...) { + t.FailNow() + } +} + +// Exactlyf asserts that two objects are equal in value and type. +// +// assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123)) +func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { + if !assert.Exactlyf(t, expected, actual, msg, args...) { + t.FailNow() + } +} + +// Fail reports a failure through +func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) { + if !assert.Fail(t, failureMessage, msgAndArgs...) { + t.FailNow() + } +} + +// FailNow fails test +func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) { + if !assert.FailNow(t, failureMessage, msgAndArgs...) { + t.FailNow() + } +} + +// FailNowf fails test +func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) { + if !assert.FailNowf(t, failureMessage, msg, args...) { + t.FailNow() + } +} + +// Failf reports a failure through +func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) { + if !assert.Failf(t, failureMessage, msg, args...) { + t.FailNow() + } +} + +// False asserts that the specified value is false. +// +// assert.False(t, myBool) +func False(t TestingT, value bool, msgAndArgs ...interface{}) { + if !assert.False(t, value, msgAndArgs...) { + t.FailNow() + } +} + +// Falsef asserts that the specified value is false. +// +// assert.Falsef(t, myBool, "error message %s", "formatted") +func Falsef(t TestingT, value bool, msg string, args ...interface{}) { + if !assert.Falsef(t, value, msg, args...) { + t.FailNow() + } +} + +// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. +func FileExists(t TestingT, path string, msgAndArgs ...interface{}) { + if !assert.FileExists(t, path, msgAndArgs...) { + t.FailNow() + } +} + +// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. +func FileExistsf(t TestingT, path string, msg string, args ...interface{}) { + if !assert.FileExistsf(t, path, msg, args...) { + t.FailNow() + } +} + +// HTTPBodyContains asserts that a specified handler returns a +// body that contains a string. +// +// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { + if !assert.HTTPBodyContains(t, handler, method, url, values, str, msgAndArgs...) { + t.FailNow() + } +} + +// HTTPBodyContainsf asserts that a specified handler returns a +// body that contains a string. +// +// assert.HTTPBodyContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { + if !assert.HTTPBodyContainsf(t, handler, method, url, values, str, msg, args...) { + t.FailNow() + } +} + +// HTTPBodyNotContains asserts that a specified handler returns a +// body that does not contain a string. +// +// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { + if !assert.HTTPBodyNotContains(t, handler, method, url, values, str, msgAndArgs...) { + t.FailNow() + } +} + +// HTTPBodyNotContainsf asserts that a specified handler returns a +// body that does not contain a string. +// +// assert.HTTPBodyNotContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { + if !assert.HTTPBodyNotContainsf(t, handler, method, url, values, str, msg, args...) { + t.FailNow() + } +} + +// HTTPError asserts that a specified handler returns an error status code. +// +// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { + if !assert.HTTPError(t, handler, method, url, values, msgAndArgs...) { + t.FailNow() + } +} + +// HTTPErrorf asserts that a specified handler returns an error status code. +// +// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { + if !assert.HTTPErrorf(t, handler, method, url, values, msg, args...) { + t.FailNow() + } +} + +// HTTPRedirect asserts that a specified handler returns a redirect status code. +// +// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { + if !assert.HTTPRedirect(t, handler, method, url, values, msgAndArgs...) { + t.FailNow() + } +} + +// HTTPRedirectf asserts that a specified handler returns a redirect status code. +// +// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { + if !assert.HTTPRedirectf(t, handler, method, url, values, msg, args...) { + t.FailNow() + } +} + +// HTTPSuccess asserts that a specified handler returns a success status code. +// +// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { + if !assert.HTTPSuccess(t, handler, method, url, values, msgAndArgs...) { + t.FailNow() + } +} + +// HTTPSuccessf asserts that a specified handler returns a success status code. +// +// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { + if !assert.HTTPSuccessf(t, handler, method, url, values, msg, args...) { + t.FailNow() + } +} + +// Implements asserts that an object is implemented by the specified interface. +// +// assert.Implements(t, (*MyInterface)(nil), new(MyObject)) +func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { + if !assert.Implements(t, interfaceObject, object, msgAndArgs...) { + t.FailNow() + } +} + +// Implementsf asserts that an object is implemented by the specified interface. +// +// assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) +func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { + if !assert.Implementsf(t, interfaceObject, object, msg, args...) { + t.FailNow() + } +} + +// InDelta asserts that the two numerals are within delta of each other. +// +// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01) +func InDelta(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { + if !assert.InDelta(t, expected, actual, delta, msgAndArgs...) { + t.FailNow() + } +} + +// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func InDeltaMapValues(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { + if !assert.InDeltaMapValues(t, expected, actual, delta, msgAndArgs...) { + t.FailNow() + } +} + +// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { + if !assert.InDeltaMapValuesf(t, expected, actual, delta, msg, args...) { + t.FailNow() + } +} + +// InDeltaSlice is the same as InDelta, except it compares two slices. +func InDeltaSlice(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { + if !assert.InDeltaSlice(t, expected, actual, delta, msgAndArgs...) { + t.FailNow() + } +} + +// InDeltaSlicef is the same as InDelta, except it compares two slices. +func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { + if !assert.InDeltaSlicef(t, expected, actual, delta, msg, args...) { + t.FailNow() + } +} + +// InDeltaf asserts that the two numerals are within delta of each other. +// +// assert.InDeltaf(t, math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) +func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { + if !assert.InDeltaf(t, expected, actual, delta, msg, args...) { + t.FailNow() + } +} + +// InEpsilon asserts that expected and actual have a relative error less than epsilon +func InEpsilon(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { + if !assert.InEpsilon(t, expected, actual, epsilon, msgAndArgs...) { + t.FailNow() + } +} + +// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. +func InEpsilonSlice(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { + if !assert.InEpsilonSlice(t, expected, actual, epsilon, msgAndArgs...) { + t.FailNow() + } +} + +// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. +func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { + if !assert.InEpsilonSlicef(t, expected, actual, epsilon, msg, args...) { + t.FailNow() + } +} + +// InEpsilonf asserts that expected and actual have a relative error less than epsilon +func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { + if !assert.InEpsilonf(t, expected, actual, epsilon, msg, args...) { + t.FailNow() + } +} + +// IsType asserts that the specified objects are of the same type. +func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { + if !assert.IsType(t, expectedType, object, msgAndArgs...) { + t.FailNow() + } +} + +// IsTypef asserts that the specified objects are of the same type. +func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) { + if !assert.IsTypef(t, expectedType, object, msg, args...) { + t.FailNow() + } +} + +// JSONEq asserts that two JSON strings are equivalent. +// +// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) +func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) { + if !assert.JSONEq(t, expected, actual, msgAndArgs...) { + t.FailNow() + } +} + +// JSONEqf asserts that two JSON strings are equivalent. +// +// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") +func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) { + if !assert.JSONEqf(t, expected, actual, msg, args...) { + t.FailNow() + } +} + +// Len asserts that the specified object has specific length. +// Len also fails if the object has a type that len() not accept. +// +// assert.Len(t, mySlice, 3) +func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) { + if !assert.Len(t, object, length, msgAndArgs...) { + t.FailNow() + } +} + +// Lenf asserts that the specified object has specific length. +// Lenf also fails if the object has a type that len() not accept. +// +// assert.Lenf(t, mySlice, 3, "error message %s", "formatted") +func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) { + if !assert.Lenf(t, object, length, msg, args...) { + t.FailNow() + } +} + +// Nil asserts that the specified object is nil. +// +// assert.Nil(t, err) +func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) { + if !assert.Nil(t, object, msgAndArgs...) { + t.FailNow() + } +} + +// Nilf asserts that the specified object is nil. +// +// assert.Nilf(t, err, "error message %s", "formatted") +func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) { + if !assert.Nilf(t, object, msg, args...) { + t.FailNow() + } +} + +// NoError asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if assert.NoError(t, err) { +// assert.Equal(t, expectedObj, actualObj) +// } +func NoError(t TestingT, err error, msgAndArgs ...interface{}) { + if !assert.NoError(t, err, msgAndArgs...) { + t.FailNow() + } +} + +// NoErrorf asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if assert.NoErrorf(t, err, "error message %s", "formatted") { +// assert.Equal(t, expectedObj, actualObj) +// } +func NoErrorf(t TestingT, err error, msg string, args ...interface{}) { + if !assert.NoErrorf(t, err, msg, args...) { + t.FailNow() + } +} + +// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// assert.NotContains(t, "Hello World", "Earth") +// assert.NotContains(t, ["Hello", "World"], "Earth") +// assert.NotContains(t, {"Hello": "World"}, "Earth") +func NotContains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { + if !assert.NotContains(t, s, contains, msgAndArgs...) { + t.FailNow() + } +} + +// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") +// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") +// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") +func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { + if !assert.NotContainsf(t, s, contains, msg, args...) { + t.FailNow() + } +} + +// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if assert.NotEmpty(t, obj) { +// assert.Equal(t, "two", obj[1]) +// } +func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) { + if !assert.NotEmpty(t, object, msgAndArgs...) { + t.FailNow() + } +} + +// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if assert.NotEmptyf(t, obj, "error message %s", "formatted") { +// assert.Equal(t, "two", obj[1]) +// } +func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) { + if !assert.NotEmptyf(t, object, msg, args...) { + t.FailNow() + } +} + +// NotEqual asserts that the specified values are NOT equal. +// +// assert.NotEqual(t, obj1, obj2) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func NotEqual(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if !assert.NotEqual(t, expected, actual, msgAndArgs...) { + t.FailNow() + } +} + +// NotEqualf asserts that the specified values are NOT equal. +// +// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { + if !assert.NotEqualf(t, expected, actual, msg, args...) { + t.FailNow() + } +} + +// NotNil asserts that the specified object is not nil. +// +// assert.NotNil(t, err) +func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) { + if !assert.NotNil(t, object, msgAndArgs...) { + t.FailNow() + } +} + +// NotNilf asserts that the specified object is not nil. +// +// assert.NotNilf(t, err, "error message %s", "formatted") +func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) { + if !assert.NotNilf(t, object, msg, args...) { + t.FailNow() + } +} + +// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// assert.NotPanics(t, func(){ RemainCalm() }) +func NotPanics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { + if !assert.NotPanics(t, f, msgAndArgs...) { + t.FailNow() + } +} + +// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") +func NotPanicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { + if !assert.NotPanicsf(t, f, msg, args...) { + t.FailNow() + } +} + +// NotRegexp asserts that a specified regexp does not match a string. +// +// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") +// assert.NotRegexp(t, "^start", "it's not starting") +func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { + if !assert.NotRegexp(t, rx, str, msgAndArgs...) { + t.FailNow() + } +} + +// NotRegexpf asserts that a specified regexp does not match a string. +// +// assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") +// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") +func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { + if !assert.NotRegexpf(t, rx, str, msg, args...) { + t.FailNow() + } +} + +// NotSubset asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { + if !assert.NotSubset(t, list, subset, msgAndArgs...) { + t.FailNow() + } +} + +// NotSubsetf asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { + if !assert.NotSubsetf(t, list, subset, msg, args...) { + t.FailNow() + } +} + +// NotZero asserts that i is not the zero value for its type. +func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) { + if !assert.NotZero(t, i, msgAndArgs...) { + t.FailNow() + } +} + +// NotZerof asserts that i is not the zero value for its type. +func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) { + if !assert.NotZerof(t, i, msg, args...) { + t.FailNow() + } +} + +// Panics asserts that the code inside the specified PanicTestFunc panics. +// +// assert.Panics(t, func(){ GoCrazy() }) +func Panics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { + if !assert.Panics(t, f, msgAndArgs...) { + t.FailNow() + } +} + +// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) +func PanicsWithValue(t TestingT, expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { + if !assert.PanicsWithValue(t, expected, f, msgAndArgs...) { + t.FailNow() + } +} + +// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +func PanicsWithValuef(t TestingT, expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { + if !assert.PanicsWithValuef(t, expected, f, msg, args...) { + t.FailNow() + } +} + +// Panicsf asserts that the code inside the specified PanicTestFunc panics. +// +// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") +func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { + if !assert.Panicsf(t, f, msg, args...) { + t.FailNow() + } +} + +// Regexp asserts that a specified regexp matches a string. +// +// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") +// assert.Regexp(t, "start...$", "it's not starting") +func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { + if !assert.Regexp(t, rx, str, msgAndArgs...) { + t.FailNow() + } +} + +// Regexpf asserts that a specified regexp matches a string. +// +// assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") +// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") +func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { + if !assert.Regexpf(t, rx, str, msg, args...) { + t.FailNow() + } +} + +// Subset asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { + if !assert.Subset(t, list, subset, msgAndArgs...) { + t.FailNow() + } +} + +// Subsetf asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { + if !assert.Subsetf(t, list, subset, msg, args...) { + t.FailNow() + } +} + +// True asserts that the specified value is true. +// +// assert.True(t, myBool) +func True(t TestingT, value bool, msgAndArgs ...interface{}) { + if !assert.True(t, value, msgAndArgs...) { + t.FailNow() + } +} + +// Truef asserts that the specified value is true. +// +// assert.Truef(t, myBool, "error message %s", "formatted") +func Truef(t TestingT, value bool, msg string, args ...interface{}) { + if !assert.Truef(t, value, msg, args...) { + t.FailNow() + } +} + +// WithinDuration asserts that the two times are within duration delta of each other. +// +// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) +func WithinDuration(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { + if !assert.WithinDuration(t, expected, actual, delta, msgAndArgs...) { + t.FailNow() + } +} + +// WithinDurationf asserts that the two times are within duration delta of each other. +// +// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") +func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { + if !assert.WithinDurationf(t, expected, actual, delta, msg, args...) { + t.FailNow() + } +} + +// Zero asserts that i is the zero value for its type. +func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) { + if !assert.Zero(t, i, msgAndArgs...) { + t.FailNow() + } +} + +// Zerof asserts that i is the zero value for its type. +func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) { + if !assert.Zerof(t, i, msg, args...) { + t.FailNow() + } +} diff --git a/vendor/github.com/stretchr/testify/require/require.go.tmpl b/vendor/github.com/stretchr/testify/require/require.go.tmpl new file mode 100644 index 0000000..d2c38f6 --- /dev/null +++ b/vendor/github.com/stretchr/testify/require/require.go.tmpl @@ -0,0 +1,6 @@ +{{.Comment}} +func {{.DocInfo.Name}}(t TestingT, {{.Params}}) { + if !assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { + t.FailNow() + } +} diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go b/vendor/github.com/stretchr/testify/require/require_forward.go new file mode 100644 index 0000000..299ceb9 --- /dev/null +++ b/vendor/github.com/stretchr/testify/require/require_forward.go @@ -0,0 +1,687 @@ +/* +* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen +* THIS FILE MUST NOT BE EDITED BY HAND + */ + +package require + +import ( + assert "github.com/stretchr/testify/assert" + http "net/http" + url "net/url" + time "time" +) + +// Condition uses a Comparison to assert a complex condition. +func (a *Assertions) Condition(comp assert.Comparison, msgAndArgs ...interface{}) { + Condition(a.t, comp, msgAndArgs...) +} + +// Conditionf uses a Comparison to assert a complex condition. +func (a *Assertions) Conditionf(comp assert.Comparison, msg string, args ...interface{}) { + Conditionf(a.t, comp, msg, args...) +} + +// Contains asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// a.Contains("Hello World", "World") +// a.Contains(["Hello", "World"], "World") +// a.Contains({"Hello": "World"}, "Hello") +func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { + Contains(a.t, s, contains, msgAndArgs...) +} + +// Containsf asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// a.Containsf("Hello World", "World", "error message %s", "formatted") +// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") +// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") +func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) { + Containsf(a.t, s, contains, msg, args...) +} + +// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. +func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) { + DirExists(a.t, path, msgAndArgs...) +} + +// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. +func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) { + DirExistsf(a.t, path, msg, args...) +} + +// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]) +func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) { + ElementsMatch(a.t, listA, listB, msgAndArgs...) +} + +// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") +func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) { + ElementsMatchf(a.t, listA, listB, msg, args...) +} + +// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// a.Empty(obj) +func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) { + Empty(a.t, object, msgAndArgs...) +} + +// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// a.Emptyf(obj, "error message %s", "formatted") +func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) { + Emptyf(a.t, object, msg, args...) +} + +// Equal asserts that two objects are equal. +// +// a.Equal(123, 123) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + Equal(a.t, expected, actual, msgAndArgs...) +} + +// EqualError asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// a.EqualError(err, expectedErrorString) +func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) { + EqualError(a.t, theError, errString, msgAndArgs...) +} + +// EqualErrorf asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") +func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) { + EqualErrorf(a.t, theError, errString, msg, args...) +} + +// EqualValues asserts that two objects are equal or convertable to the same types +// and equal. +// +// a.EqualValues(uint32(123), int32(123)) +func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + EqualValues(a.t, expected, actual, msgAndArgs...) +} + +// EqualValuesf asserts that two objects are equal or convertable to the same types +// and equal. +// +// a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123)) +func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) { + EqualValuesf(a.t, expected, actual, msg, args...) +} + +// Equalf asserts that two objects are equal. +// +// a.Equalf(123, 123, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) { + Equalf(a.t, expected, actual, msg, args...) +} + +// Error asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if a.Error(err) { +// assert.Equal(t, expectedError, err) +// } +func (a *Assertions) Error(err error, msgAndArgs ...interface{}) { + Error(a.t, err, msgAndArgs...) +} + +// Errorf asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if a.Errorf(err, "error message %s", "formatted") { +// assert.Equal(t, expectedErrorf, err) +// } +func (a *Assertions) Errorf(err error, msg string, args ...interface{}) { + Errorf(a.t, err, msg, args...) +} + +// Exactly asserts that two objects are equal in value and type. +// +// a.Exactly(int32(123), int64(123)) +func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + Exactly(a.t, expected, actual, msgAndArgs...) +} + +// Exactlyf asserts that two objects are equal in value and type. +// +// a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123)) +func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) { + Exactlyf(a.t, expected, actual, msg, args...) +} + +// Fail reports a failure through +func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) { + Fail(a.t, failureMessage, msgAndArgs...) +} + +// FailNow fails test +func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) { + FailNow(a.t, failureMessage, msgAndArgs...) +} + +// FailNowf fails test +func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) { + FailNowf(a.t, failureMessage, msg, args...) +} + +// Failf reports a failure through +func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) { + Failf(a.t, failureMessage, msg, args...) +} + +// False asserts that the specified value is false. +// +// a.False(myBool) +func (a *Assertions) False(value bool, msgAndArgs ...interface{}) { + False(a.t, value, msgAndArgs...) +} + +// Falsef asserts that the specified value is false. +// +// a.Falsef(myBool, "error message %s", "formatted") +func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) { + Falsef(a.t, value, msg, args...) +} + +// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. +func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) { + FileExists(a.t, path, msgAndArgs...) +} + +// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. +func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) { + FileExistsf(a.t, path, msg, args...) +} + +// HTTPBodyContains asserts that a specified handler returns a +// body that contains a string. +// +// a.HTTPBodyContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { + HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) +} + +// HTTPBodyContainsf asserts that a specified handler returns a +// body that contains a string. +// +// a.HTTPBodyContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { + HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) +} + +// HTTPBodyNotContains asserts that a specified handler returns a +// body that does not contain a string. +// +// a.HTTPBodyNotContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { + HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) +} + +// HTTPBodyNotContainsf asserts that a specified handler returns a +// body that does not contain a string. +// +// a.HTTPBodyNotContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { + HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) +} + +// HTTPError asserts that a specified handler returns an error status code. +// +// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { + HTTPError(a.t, handler, method, url, values, msgAndArgs...) +} + +// HTTPErrorf asserts that a specified handler returns an error status code. +// +// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { + HTTPErrorf(a.t, handler, method, url, values, msg, args...) +} + +// HTTPRedirect asserts that a specified handler returns a redirect status code. +// +// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { + HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) +} + +// HTTPRedirectf asserts that a specified handler returns a redirect status code. +// +// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { + HTTPRedirectf(a.t, handler, method, url, values, msg, args...) +} + +// HTTPSuccess asserts that a specified handler returns a success status code. +// +// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { + HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) +} + +// HTTPSuccessf asserts that a specified handler returns a success status code. +// +// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { + HTTPSuccessf(a.t, handler, method, url, values, msg, args...) +} + +// Implements asserts that an object is implemented by the specified interface. +// +// a.Implements((*MyInterface)(nil), new(MyObject)) +func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { + Implements(a.t, interfaceObject, object, msgAndArgs...) +} + +// Implementsf asserts that an object is implemented by the specified interface. +// +// a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) +func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { + Implementsf(a.t, interfaceObject, object, msg, args...) +} + +// InDelta asserts that the two numerals are within delta of each other. +// +// a.InDelta(math.Pi, (22 / 7.0), 0.01) +func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { + InDelta(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { + InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { + InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) +} + +// InDeltaSlice is the same as InDelta, except it compares two slices. +func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { + InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDeltaSlicef is the same as InDelta, except it compares two slices. +func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { + InDeltaSlicef(a.t, expected, actual, delta, msg, args...) +} + +// InDeltaf asserts that the two numerals are within delta of each other. +// +// a.InDeltaf(math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) +func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { + InDeltaf(a.t, expected, actual, delta, msg, args...) +} + +// InEpsilon asserts that expected and actual have a relative error less than epsilon +func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { + InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) +} + +// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. +func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { + InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) +} + +// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. +func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { + InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) +} + +// InEpsilonf asserts that expected and actual have a relative error less than epsilon +func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { + InEpsilonf(a.t, expected, actual, epsilon, msg, args...) +} + +// IsType asserts that the specified objects are of the same type. +func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { + IsType(a.t, expectedType, object, msgAndArgs...) +} + +// IsTypef asserts that the specified objects are of the same type. +func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) { + IsTypef(a.t, expectedType, object, msg, args...) +} + +// JSONEq asserts that two JSON strings are equivalent. +// +// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) +func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) { + JSONEq(a.t, expected, actual, msgAndArgs...) +} + +// JSONEqf asserts that two JSON strings are equivalent. +// +// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") +func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) { + JSONEqf(a.t, expected, actual, msg, args...) +} + +// Len asserts that the specified object has specific length. +// Len also fails if the object has a type that len() not accept. +// +// a.Len(mySlice, 3) +func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) { + Len(a.t, object, length, msgAndArgs...) +} + +// Lenf asserts that the specified object has specific length. +// Lenf also fails if the object has a type that len() not accept. +// +// a.Lenf(mySlice, 3, "error message %s", "formatted") +func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) { + Lenf(a.t, object, length, msg, args...) +} + +// Nil asserts that the specified object is nil. +// +// a.Nil(err) +func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) { + Nil(a.t, object, msgAndArgs...) +} + +// Nilf asserts that the specified object is nil. +// +// a.Nilf(err, "error message %s", "formatted") +func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) { + Nilf(a.t, object, msg, args...) +} + +// NoError asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if a.NoError(err) { +// assert.Equal(t, expectedObj, actualObj) +// } +func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) { + NoError(a.t, err, msgAndArgs...) +} + +// NoErrorf asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if a.NoErrorf(err, "error message %s", "formatted") { +// assert.Equal(t, expectedObj, actualObj) +// } +func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) { + NoErrorf(a.t, err, msg, args...) +} + +// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// a.NotContains("Hello World", "Earth") +// a.NotContains(["Hello", "World"], "Earth") +// a.NotContains({"Hello": "World"}, "Earth") +func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { + NotContains(a.t, s, contains, msgAndArgs...) +} + +// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") +// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") +// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") +func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) { + NotContainsf(a.t, s, contains, msg, args...) +} + +// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if a.NotEmpty(obj) { +// assert.Equal(t, "two", obj[1]) +// } +func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) { + NotEmpty(a.t, object, msgAndArgs...) +} + +// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if a.NotEmptyf(obj, "error message %s", "formatted") { +// assert.Equal(t, "two", obj[1]) +// } +func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) { + NotEmptyf(a.t, object, msg, args...) +} + +// NotEqual asserts that the specified values are NOT equal. +// +// a.NotEqual(obj1, obj2) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + NotEqual(a.t, expected, actual, msgAndArgs...) +} + +// NotEqualf asserts that the specified values are NOT equal. +// +// a.NotEqualf(obj1, obj2, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) { + NotEqualf(a.t, expected, actual, msg, args...) +} + +// NotNil asserts that the specified object is not nil. +// +// a.NotNil(err) +func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) { + NotNil(a.t, object, msgAndArgs...) +} + +// NotNilf asserts that the specified object is not nil. +// +// a.NotNilf(err, "error message %s", "formatted") +func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) { + NotNilf(a.t, object, msg, args...) +} + +// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// a.NotPanics(func(){ RemainCalm() }) +func (a *Assertions) NotPanics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { + NotPanics(a.t, f, msgAndArgs...) +} + +// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") +func (a *Assertions) NotPanicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { + NotPanicsf(a.t, f, msg, args...) +} + +// NotRegexp asserts that a specified regexp does not match a string. +// +// a.NotRegexp(regexp.MustCompile("starts"), "it's starting") +// a.NotRegexp("^start", "it's not starting") +func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { + NotRegexp(a.t, rx, str, msgAndArgs...) +} + +// NotRegexpf asserts that a specified regexp does not match a string. +// +// a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") +// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") +func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { + NotRegexpf(a.t, rx, str, msg, args...) +} + +// NotSubset asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { + NotSubset(a.t, list, subset, msgAndArgs...) +} + +// NotSubsetf asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { + NotSubsetf(a.t, list, subset, msg, args...) +} + +// NotZero asserts that i is not the zero value for its type. +func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) { + NotZero(a.t, i, msgAndArgs...) +} + +// NotZerof asserts that i is not the zero value for its type. +func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) { + NotZerof(a.t, i, msg, args...) +} + +// Panics asserts that the code inside the specified PanicTestFunc panics. +// +// a.Panics(func(){ GoCrazy() }) +func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { + Panics(a.t, f, msgAndArgs...) +} + +// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// a.PanicsWithValue("crazy error", func(){ GoCrazy() }) +func (a *Assertions) PanicsWithValue(expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { + PanicsWithValue(a.t, expected, f, msgAndArgs...) +} + +// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +func (a *Assertions) PanicsWithValuef(expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { + PanicsWithValuef(a.t, expected, f, msg, args...) +} + +// Panicsf asserts that the code inside the specified PanicTestFunc panics. +// +// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") +func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { + Panicsf(a.t, f, msg, args...) +} + +// Regexp asserts that a specified regexp matches a string. +// +// a.Regexp(regexp.MustCompile("start"), "it's starting") +// a.Regexp("start...$", "it's not starting") +func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { + Regexp(a.t, rx, str, msgAndArgs...) +} + +// Regexpf asserts that a specified regexp matches a string. +// +// a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") +// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") +func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { + Regexpf(a.t, rx, str, msg, args...) +} + +// Subset asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { + Subset(a.t, list, subset, msgAndArgs...) +} + +// Subsetf asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { + Subsetf(a.t, list, subset, msg, args...) +} + +// True asserts that the specified value is true. +// +// a.True(myBool) +func (a *Assertions) True(value bool, msgAndArgs ...interface{}) { + True(a.t, value, msgAndArgs...) +} + +// Truef asserts that the specified value is true. +// +// a.Truef(myBool, "error message %s", "formatted") +func (a *Assertions) Truef(value bool, msg string, args ...interface{}) { + Truef(a.t, value, msg, args...) +} + +// WithinDuration asserts that the two times are within duration delta of each other. +// +// a.WithinDuration(time.Now(), time.Now(), 10*time.Second) +func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { + WithinDuration(a.t, expected, actual, delta, msgAndArgs...) +} + +// WithinDurationf asserts that the two times are within duration delta of each other. +// +// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") +func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { + WithinDurationf(a.t, expected, actual, delta, msg, args...) +} + +// Zero asserts that i is the zero value for its type. +func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) { + Zero(a.t, i, msgAndArgs...) +} + +// Zerof asserts that i is the zero value for its type. +func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) { + Zerof(a.t, i, msg, args...) +} diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl b/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl new file mode 100644 index 0000000..b93569e --- /dev/null +++ b/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl @@ -0,0 +1,4 @@ +{{.CommentWithoutT "a"}} +func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) { + {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) +} diff --git a/vendor/github.com/stretchr/testify/require/requirements.go b/vendor/github.com/stretchr/testify/require/requirements.go new file mode 100644 index 0000000..e404f01 --- /dev/null +++ b/vendor/github.com/stretchr/testify/require/requirements.go @@ -0,0 +1,9 @@ +package require + +// TestingT is an interface wrapper around *testing.T +type TestingT interface { + Errorf(format string, args ...interface{}) + FailNow() +} + +//go:generate go run ../_codegen/main.go -output-package=require -template=require.go.tmpl -include-format-funcs diff --git a/vendor/github.com/stretchr/testify/suite/doc.go b/vendor/github.com/stretchr/testify/suite/doc.go new file mode 100644 index 0000000..f91a245 --- /dev/null +++ b/vendor/github.com/stretchr/testify/suite/doc.go @@ -0,0 +1,65 @@ +// Package suite contains logic for creating testing suite structs +// and running the methods on those structs as tests. The most useful +// piece of this package is that you can create setup/teardown methods +// on your testing suites, which will run before/after the whole suite +// or individual tests (depending on which interface(s) you +// implement). +// +// A testing suite is usually built by first extending the built-in +// suite functionality from suite.Suite in testify. Alternatively, +// you could reproduce that logic on your own if you wanted (you +// just need to implement the TestingSuite interface from +// suite/interfaces.go). +// +// After that, you can implement any of the interfaces in +// suite/interfaces.go to add setup/teardown functionality to your +// suite, and add any methods that start with "Test" to add tests. +// Methods that do not match any suite interfaces and do not begin +// with "Test" will not be run by testify, and can safely be used as +// helper methods. +// +// Once you've built your testing suite, you need to run the suite +// (using suite.Run from testify) inside any function that matches the +// identity that "go test" is already looking for (i.e. +// func(*testing.T)). +// +// Regular expression to select test suites specified command-line +// argument "-run". Regular expression to select the methods +// of test suites specified command-line argument "-m". +// Suite object has assertion methods. +// +// A crude example: +// // Basic imports +// import ( +// "testing" +// "github.com/stretchr/testify/assert" +// "github.com/stretchr/testify/suite" +// ) +// +// // Define the suite, and absorb the built-in basic suite +// // functionality from testify - including a T() method which +// // returns the current testing context +// type ExampleTestSuite struct { +// suite.Suite +// VariableThatShouldStartAtFive int +// } +// +// // Make sure that VariableThatShouldStartAtFive is set to five +// // before each test +// func (suite *ExampleTestSuite) SetupTest() { +// suite.VariableThatShouldStartAtFive = 5 +// } +// +// // All methods that begin with "Test" are run as tests within a +// // suite. +// func (suite *ExampleTestSuite) TestExample() { +// assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive) +// suite.Equal(5, suite.VariableThatShouldStartAtFive) +// } +// +// // In order for 'go test' to run this suite, we need to create +// // a normal test function and pass our suite to suite.Run +// func TestExampleTestSuite(t *testing.T) { +// suite.Run(t, new(ExampleTestSuite)) +// } +package suite diff --git a/vendor/github.com/stretchr/testify/suite/interfaces.go b/vendor/github.com/stretchr/testify/suite/interfaces.go new file mode 100644 index 0000000..b37cb04 --- /dev/null +++ b/vendor/github.com/stretchr/testify/suite/interfaces.go @@ -0,0 +1,46 @@ +package suite + +import "testing" + +// TestingSuite can store and return the current *testing.T context +// generated by 'go test'. +type TestingSuite interface { + T() *testing.T + SetT(*testing.T) +} + +// SetupAllSuite has a SetupSuite method, which will run before the +// tests in the suite are run. +type SetupAllSuite interface { + SetupSuite() +} + +// SetupTestSuite has a SetupTest method, which will run before each +// test in the suite. +type SetupTestSuite interface { + SetupTest() +} + +// TearDownAllSuite has a TearDownSuite method, which will run after +// all the tests in the suite have been run. +type TearDownAllSuite interface { + TearDownSuite() +} + +// TearDownTestSuite has a TearDownTest method, which will run after +// each test in the suite. +type TearDownTestSuite interface { + TearDownTest() +} + +// BeforeTest has a function to be executed right before the test +// starts and receives the suite and test names as input +type BeforeTest interface { + BeforeTest(suiteName, testName string) +} + +// AfterTest has a function to be executed right after the test +// finishes and receives the suite and test names as input +type AfterTest interface { + AfterTest(suiteName, testName string) +} diff --git a/vendor/github.com/stretchr/testify/suite/suite.go b/vendor/github.com/stretchr/testify/suite/suite.go new file mode 100644 index 0000000..e20afbc --- /dev/null +++ b/vendor/github.com/stretchr/testify/suite/suite.go @@ -0,0 +1,136 @@ +package suite + +import ( + "flag" + "fmt" + "os" + "reflect" + "regexp" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var allTestsFilter = func(_, _ string) (bool, error) { return true, nil } +var matchMethod = flag.String("testify.m", "", "regular expression to select tests of the testify suite to run") + +// Suite is a basic testing suite with methods for storing and +// retrieving the current *testing.T context. +type Suite struct { + *assert.Assertions + require *require.Assertions + t *testing.T +} + +// T retrieves the current *testing.T context. +func (suite *Suite) T() *testing.T { + return suite.t +} + +// SetT sets the current *testing.T context. +func (suite *Suite) SetT(t *testing.T) { + suite.t = t + suite.Assertions = assert.New(t) + suite.require = require.New(t) +} + +// Require returns a require context for suite. +func (suite *Suite) Require() *require.Assertions { + if suite.require == nil { + suite.require = require.New(suite.T()) + } + return suite.require +} + +// Assert returns an assert context for suite. Normally, you can call +// `suite.NoError(expected, actual)`, but for situations where the embedded +// methods are overridden (for example, you might want to override +// assert.Assertions with require.Assertions), this method is provided so you +// can call `suite.Assert().NoError()`. +func (suite *Suite) Assert() *assert.Assertions { + if suite.Assertions == nil { + suite.Assertions = assert.New(suite.T()) + } + return suite.Assertions +} + +// Run takes a testing suite and runs all of the tests attached +// to it. +func Run(t *testing.T, suite TestingSuite) { + suite.SetT(t) + + if setupAllSuite, ok := suite.(SetupAllSuite); ok { + setupAllSuite.SetupSuite() + } + defer func() { + if tearDownAllSuite, ok := suite.(TearDownAllSuite); ok { + tearDownAllSuite.TearDownSuite() + } + }() + + methodFinder := reflect.TypeOf(suite) + tests := []testing.InternalTest{} + for index := 0; index < methodFinder.NumMethod(); index++ { + method := methodFinder.Method(index) + ok, err := methodFilter(method.Name) + if err != nil { + fmt.Fprintf(os.Stderr, "testify: invalid regexp for -m: %s\n", err) + os.Exit(1) + } + if ok { + test := testing.InternalTest{ + Name: method.Name, + F: func(t *testing.T) { + parentT := suite.T() + suite.SetT(t) + if setupTestSuite, ok := suite.(SetupTestSuite); ok { + setupTestSuite.SetupTest() + } + if beforeTestSuite, ok := suite.(BeforeTest); ok { + beforeTestSuite.BeforeTest(methodFinder.Elem().Name(), method.Name) + } + defer func() { + if afterTestSuite, ok := suite.(AfterTest); ok { + afterTestSuite.AfterTest(methodFinder.Elem().Name(), method.Name) + } + if tearDownTestSuite, ok := suite.(TearDownTestSuite); ok { + tearDownTestSuite.TearDownTest() + } + suite.SetT(parentT) + }() + method.Func.Call([]reflect.Value{reflect.ValueOf(suite)}) + }, + } + tests = append(tests, test) + } + } + runTests(t, tests) +} + +func runTests(t testing.TB, tests []testing.InternalTest) { + r, ok := t.(runner) + if !ok { // backwards compatibility with Go 1.6 and below + if !testing.RunTests(allTestsFilter, tests) { + t.Fail() + } + return + } + + for _, test := range tests { + r.Run(test.Name, test.F) + } +} + +// Filtering method according to set regular expression +// specified command-line argument -m +func methodFilter(name string) (bool, error) { + if ok, _ := regexp.MatchString("^Test", name); !ok { + return false, nil + } + return regexp.MatchString(*matchMethod, name) +} + +type runner interface { + Run(name string, f func(t *testing.T)) bool +} From bee34fd3cb9f1ef94fa45f588789b565f33e3a11 Mon Sep 17 00:00:00 2001 From: Tyler Kellen Date: Wed, 23 May 2018 17:44:40 -0400 Subject: [PATCH 40/80] changes requested in f5devcentral/terraform-provider-bigip#86 --- ltm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ltm.go b/ltm.go index 77661ee..716e78c 100644 --- a/ltm.go +++ b/ltm.go @@ -155,7 +155,7 @@ type Node struct { AddressFamily string `json:"addressFamily,omitempty"` AutoPopulate string `json:"autopopulate,omitempty"` DownInterval int `json:"downInterval,omitempty"` - Interval int `json:"interval,omitempty"` + Interval string `json:"interval,omitempty"` Name string `json:"tmName,omitempty"` } `json:"fqdn,omitempty"` } From 97b238b34cbbb09bd2cbecaa3ce9273190985e85 Mon Sep 17 00:00:00 2001 From: Danny Kulchinsky Date: Thu, 24 May 2018 21:55:06 -0400 Subject: [PATCH 41/80] Add ~Common~ only when partition name not provided --- net.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net.go b/net.go index bc795e9..d834ac1 100644 --- a/net.go +++ b/net.go @@ -318,9 +318,13 @@ func (b *BigIP) Routes() (*Routes, error) { func (b *BigIP) GetRoute(name string) (*Route, error) { var route Route values := []string{} - values = append(values, "~Common~") + regex := regexp.MustCompile(`^(\/.+\/)?(.+)`) + match := regex.FindStringSubmatch(name) + if match[1] == "" { + values = append(values, "~Common~") + } values = append(values, name) - // Join three strings into one. + // Join the strings into one. result := strings.Join(values, "") err, ok := b.getForEntity(&route, uriNet, uriRoute, result) if err != nil { From a489c06fbe1fff53fdf74cb07a2565c599d2943c Mon Sep 17 00:00:00 2001 From: Danny Kulchinsky Date: Thu, 24 May 2018 22:12:48 -0400 Subject: [PATCH 42/80] Missing import --- net.go | 1 + 1 file changed, 1 insertion(+) diff --git a/net.go b/net.go index d834ac1..e9e04bc 100644 --- a/net.go +++ b/net.go @@ -2,6 +2,7 @@ package bigip import ( "strings" + "regexp" ) // Interfaces contains a list of every interface on the BIG-IP system. From 6b592e5587cca6b997c4f7b6e13d8b52080770a9 Mon Sep 17 00:00:00 2001 From: Sanjay Shitole Date: Fri, 15 Jun 2018 15:13:04 -0700 Subject: [PATCH 43/80] new license resource --- sys.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/sys.go b/sys.go index 362dad8..60ef03f 100644 --- a/sys.go +++ b/sys.go @@ -151,6 +151,7 @@ const ( uriSyslog = "syslog" uriSnmp = "snmp" uriTraps = "traps" + uriLicense = "license" ) func (b *BigIP) CreateNTP(description string, servers []string, timezone string) error { @@ -379,3 +380,27 @@ func (b *BigIP) TRAPs() (*TRAP, error) { func (b *BigIP) DeleteTRAP(name string) error { return b.delete(uriSys, uriSnmp, uriTraps, name) } + +func (b *BigIP) Bigiplicenses() (*Bigiplicense, error) { + var bigiplicense Bigiplicense + err, _ := b.getForEntity(&bigiplicense, uriSys, uriLicense) + + if err != nil { + return nil, err + } + + return &bigiplicense, nil +} + +func (b *BigIP) CreateBigiplicense(command, registration_key string) error { + config := &Bigiplicense{ + Command: command, + Registration_key: registration_key, + } + + return b.post(config, uriSys, uriLicense) +} + +func (b *BigIP) ModifyBigiplicense(config *Bigiplicense) error { + return b.put(config, uriSys, uriLicense) +} From 516d8470f371405cb5dcc4f1f1cf3789b9c9a25b Mon Sep 17 00:00:00 2001 From: Sanjay Shitole Date: Fri, 15 Jun 2018 15:23:19 -0700 Subject: [PATCH 44/80] updated sys.go --- sys.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sys.go b/sys.go index 60ef03f..829480b 100644 --- a/sys.go +++ b/sys.go @@ -138,6 +138,15 @@ type TRAP struct { Version string `json:"version,omitempty"` } +type Bigiplicenses struct { + Bigiplicenses []Bigiplicense `json:"items"` +} + +type Bigiplicense struct { + Registration_key string `json:"registrationKey,omitempty"` + Command string `json:"command,omitempty"` +} + const ( uriSys = "sys" uriNtp = "ntp" From c5fdfcd4ea53b7648d7037c52329d0b0bef51ffe Mon Sep 17 00:00:00 2001 From: Danny Kulchinsky Date: Fri, 6 Jul 2018 08:17:22 -0400 Subject: [PATCH 45/80] Add support for data group resource --- ltm.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/ltm.go b/ltm.go index 716e78c..2d1fcf9 100644 --- a/ltm.go +++ b/ltm.go @@ -1983,13 +1983,27 @@ func (b *BigIP) DeleteInternalDataGroup(name string) error { } // Modify a named internal data group, REPLACING all the records -func (b *BigIP) ModifyInternalDataGroupRecords(name string, records *[]DataGroupRecord) error { +func (b *BigIP) ModifyInternalDataGroupRecords(name string, records []DataGroupRecord) error { config := &DataGroup{ - Records: *records, + Records: records, } return b.put(config, uriLtm, uriDatagroup, uriInternal, name) } +// Get an internal data group by name, returns nil if the data group does not exist +func (b *BigIP) GetInternalDatagroup(name string) (*DataGroup, error) { + var datagroup DataGroup + err, ok := b.getForEntity(&datagroup, uriLtm, uriDatagroup, uriInternal, name) + if err != nil { + return nil, err + } + if !ok { + return nil, nil + } + + return &datagroup, nil +} + // Get the internal data group records for a named internal data group func (b *BigIP) GetInternalDataGroupRecords(name string) (*[]DataGroupRecord, error) { var dataGroup DataGroup From 9afdd6bfc57134e1122e5fa094cc44b2e4e09126 Mon Sep 17 00:00:00 2001 From: Danny Kulchinsky Date: Fri, 6 Jul 2018 08:35:23 -0400 Subject: [PATCH 46/80] small typo --- ltm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ltm.go b/ltm.go index 2d1fcf9..2ff6ca7 100644 --- a/ltm.go +++ b/ltm.go @@ -1991,7 +1991,7 @@ func (b *BigIP) ModifyInternalDataGroupRecords(name string, records []DataGroupR } // Get an internal data group by name, returns nil if the data group does not exist -func (b *BigIP) GetInternalDatagroup(name string) (*DataGroup, error) { +func (b *BigIP) GetInternalDataGroup(name string) (*DataGroup, error) { var datagroup DataGroup err, ok := b.getForEntity(&datagroup, uriLtm, uriDatagroup, uriInternal, name) if err != nil { From d54c551d89db96bc07faea78af614b00cd669376 Mon Sep 17 00:00:00 2001 From: scshitole Date: Mon, 9 Jul 2018 11:26:39 -0700 Subject: [PATCH 47/80] Revert "Add support for data group resource" --- ltm.go | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/ltm.go b/ltm.go index 2ff6ca7..716e78c 100644 --- a/ltm.go +++ b/ltm.go @@ -1983,27 +1983,13 @@ func (b *BigIP) DeleteInternalDataGroup(name string) error { } // Modify a named internal data group, REPLACING all the records -func (b *BigIP) ModifyInternalDataGroupRecords(name string, records []DataGroupRecord) error { +func (b *BigIP) ModifyInternalDataGroupRecords(name string, records *[]DataGroupRecord) error { config := &DataGroup{ - Records: records, + Records: *records, } return b.put(config, uriLtm, uriDatagroup, uriInternal, name) } -// Get an internal data group by name, returns nil if the data group does not exist -func (b *BigIP) GetInternalDataGroup(name string) (*DataGroup, error) { - var datagroup DataGroup - err, ok := b.getForEntity(&datagroup, uriLtm, uriDatagroup, uriInternal, name) - if err != nil { - return nil, err - } - if !ok { - return nil, nil - } - - return &datagroup, nil -} - // Get the internal data group records for a named internal data group func (b *BigIP) GetInternalDataGroupRecords(name string) (*[]DataGroupRecord, error) { var dataGroup DataGroup From c7511d7aba92352c2db000334a3de1f17596c4b3 Mon Sep 17 00:00:00 2001 From: scshitole Date: Tue, 10 Jul 2018 14:50:43 -0700 Subject: [PATCH 48/80] Revert "Revert "Add support for data group resource"" --- ltm.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/ltm.go b/ltm.go index 716e78c..2ff6ca7 100644 --- a/ltm.go +++ b/ltm.go @@ -1983,13 +1983,27 @@ func (b *BigIP) DeleteInternalDataGroup(name string) error { } // Modify a named internal data group, REPLACING all the records -func (b *BigIP) ModifyInternalDataGroupRecords(name string, records *[]DataGroupRecord) error { +func (b *BigIP) ModifyInternalDataGroupRecords(name string, records []DataGroupRecord) error { config := &DataGroup{ - Records: *records, + Records: records, } return b.put(config, uriLtm, uriDatagroup, uriInternal, name) } +// Get an internal data group by name, returns nil if the data group does not exist +func (b *BigIP) GetInternalDataGroup(name string) (*DataGroup, error) { + var datagroup DataGroup + err, ok := b.getForEntity(&datagroup, uriLtm, uriDatagroup, uriInternal, name) + if err != nil { + return nil, err + } + if !ok { + return nil, nil + } + + return &datagroup, nil +} + // Get the internal data group records for a named internal data group func (b *BigIP) GetInternalDataGroupRecords(name string) (*[]DataGroupRecord, error) { var dataGroup DataGroup From 52adf0a49f0661111008482cd176239ef0c09008 Mon Sep 17 00:00:00 2001 From: Sanjay Shitole Date: Tue, 28 Aug 2018 14:43:22 -0700 Subject: [PATCH 49/80] removed vlans_disabled for ltm --- ltm.go | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/ltm.go b/ltm.go index 2ff6ca7..e890646 100644 --- a/ltm.go +++ b/ltm.go @@ -527,7 +527,6 @@ type VirtualServer struct { TranslateAddress string `json:"translateAddress,omitempty"` TranslatePort string `json:"translatePort,omitempty"` VlansEnabled bool `json:"vlansEnabled,omitempty"` - VlansDisabled bool `json:"vlansDisabled,omitempty"` VSIndex int `json:"vsIndex,omitempty"` Vlans []string `json:"vlans,omitempty"` Rules []string `json:"rules,omitempty"` @@ -1992,16 +1991,16 @@ func (b *BigIP) ModifyInternalDataGroupRecords(name string, records []DataGroupR // Get an internal data group by name, returns nil if the data group does not exist func (b *BigIP) GetInternalDataGroup(name string) (*DataGroup, error) { - var datagroup DataGroup - err, ok := b.getForEntity(&datagroup, uriLtm, uriDatagroup, uriInternal, name) - if err != nil { - return nil, err - } - if !ok { - return nil, nil - } + var datagroup DataGroup + err, ok := b.getForEntity(&datagroup, uriLtm, uriDatagroup, uriInternal, name) + if err != nil { + return nil, err + } + if !ok { + return nil, nil + } - return &datagroup, nil + return &datagroup, nil } // Get the internal data group records for a named internal data group @@ -2175,7 +2174,7 @@ func (b *BigIP) VirtualServers() (*VirtualServers, error) { // CreateVirtualServer adds a new virtual server to the BIG-IP system. can either be // in CIDR notation or decimal, i.e.: "24" or "255.255.255.0". A CIDR mask of "0" is the same // as "0.0.0.0". -func (b *BigIP) CreateVirtualServer(name, destination, mask, pool string, vlans_enabled, vlans_disabled bool, port int, translate_address, translate_port string) error { +func (b *BigIP) CreateVirtualServer(name, destination, mask, pool string, vlans_enabled bool, port int, translate_address, translate_port string) error { subnetMask := cidr[mask] if strings.Contains(mask, ".") { From 8496344055ed09642c30281353cf6f946d40d4b0 Mon Sep 17 00:00:00 2001 From: zhangxiaopeng Date: Tue, 4 Sep 2018 09:57:38 +0000 Subject: [PATCH 50/80] fix monitor type of gateway --- ltm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ltm.go b/ltm.go index e890646..2e4ef1c 100644 --- a/ltm.go +++ b/ltm.go @@ -2335,7 +2335,7 @@ func (b *BigIP) CreateMonitor(name, parent, defaults_from string, interval, time // Create a monitor by supplying a config func (b *BigIP) AddMonitor(config *Monitor) error { if strings.Contains(config.ParentMonitor, "gateway") { - config.ParentMonitor = "gateway_icmp" + config.ParentMonitor = "gatewayIcmp" } if strings.Contains(config.ParentMonitor, "tcp-half-open") { config.ParentMonitor = "tcp-half-open" From 4f200918a110d98f05b86a1224cee97fa41e63df Mon Sep 17 00:00:00 2001 From: Ken Maglio Date: Mon, 10 Sep 2018 13:05:53 -0500 Subject: [PATCH 51/80] Adds GetVirtualAddress method for ltm BigIP --- ltm.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ltm.go b/ltm.go index e890646..d3dee3a 100644 --- a/ltm.go +++ b/ltm.go @@ -2273,6 +2273,16 @@ func (b *BigIP) VirtualAddresses() (*VirtualAddresses, error) { return &va, nil } +// GetVirtualAddress retrieves a VirtualAddress by name. Returns nil if the VirtualAddress does not exist +func (b *BigIP) GetVirtualAddress(vaddr string) (*VirtualAddress, error) { + var virtualAddress VirtualAddress + err, _ := b.getForEntity(&virtualAddress, uriLtm, uriVirtualAddress, vaddr) + if err != nil { + return nil, err + } + return &virtualAddress, nil +} + func (b *BigIP) CreateVirtualAddress(vaddr string, config *VirtualAddress) error { config.Name = vaddr return b.post(config, uriLtm, uriVirtualAddress) From b1466543b86539155efa8a5b2bf351a044c5deaf Mon Sep 17 00:00:00 2001 From: Ken Maglio Date: Mon, 10 Sep 2018 13:45:34 -0500 Subject: [PATCH 52/80] Adds a new node method on BIG-IP to accept via a node ppec --- ltm.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ltm.go b/ltm.go index d3dee3a..4a33806 100644 --- a/ltm.go +++ b/ltm.go @@ -1887,6 +1887,11 @@ func (b *BigIP) Nodes() (*Nodes, error) { return &nodes, nil } +// AddNode adds a new node to the BIG-IP system using the Node Spec +func (b *BigIP) AddNode(config *Node) error { + return b.post(config, uriLtm, uriNode) +} + // CreateNode adds a new IP based node to the BIG-IP system. func (b *BigIP) CreateNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state string) error { config := &Node{ From 063947021e6df8d3b978bd7d0b7db01971e312fa Mon Sep 17 00:00:00 2001 From: Danny Kulchinsky Date: Mon, 17 Sep 2018 17:40:55 -0400 Subject: [PATCH 53/80] Fix datagroup DTO to properly transfer records attribute --- ltm.go | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/ltm.go b/ltm.go index e890646..ad89f83 100644 --- a/ltm.go +++ b/ltm.go @@ -175,24 +175,18 @@ type DataGroup struct { Records []DataGroupRecord } -type DataGroupRecords struct { - Items []DataGroupRecord `json:"items,omitempty"` -} - type DataGroupRecord struct { Name string `json:"name,omitempty"` Data string `json:"data,omitempty"` } type dataGroupDTO struct { - Name string `json:"name,omitempty"` - Partition string `json:"partition,omitempty"` - FullPath string `json:"fullPath,omitempty"` - Generation int `json:"generation,omitempty"` - Type string `json:"type,omitempty"` - Records struct { - Items []DataGroupRecord `json:"items,omitempty"` - } `json:"recordsReference,omitempty"` + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` + Generation int `json:"generation,omitempty"` + Type string `json:"type,omitempty"` + Records []DataGroupRecord `json:"records,omitempty"` } func (p *DataGroup) MarshalJSON() ([]byte, error) { @@ -202,9 +196,7 @@ func (p *DataGroup) MarshalJSON() ([]byte, error) { FullPath: p.FullPath, Generation: p.Generation, Type: p.Type, - Records: struct { - Items []DataGroupRecord `json:"items,omitempty"` - }{Items: p.Records}, + Records: p.Records, }) } @@ -220,7 +212,7 @@ func (p *DataGroup) UnmarshalJSON(b []byte) error { p.Type = dto.Type p.FullPath = dto.FullPath p.Generation = dto.Generation - p.Records = dto.Records.Items + p.Records = dto.Records return nil } From 7141bf0813f4f669a860d94af2a4c96458e49160 Mon Sep 17 00:00:00 2001 From: Danny Kulchinsky Date: Thu, 27 Sep 2018 00:58:48 -0400 Subject: [PATCH 54/80] Adding GetVlanInterfaces method --- net.go | 73 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/net.go b/net.go index e9e04bc..be9e42b 100644 --- a/net.go +++ b/net.go @@ -1,8 +1,8 @@ package bigip import ( - "strings" "regexp" + "strings" ) // Interfaces contains a list of every interface on the BIG-IP system. @@ -117,6 +117,11 @@ type Vlan struct { Tag int `json:"tag,omitempty"` } +// VlanInterfaces contains a list of Interface(s) attached to a VLAN. +type VlanInterfaces struct { + VlanInterfaces []VlanInterface `json:"items"` +} + // VlanInterface contains fields to be used when adding an interface to a VLAN. type VlanInterface struct { Name string `json:"name,omitempty"` @@ -159,13 +164,14 @@ type RouteDomain struct { } const ( - uriNet = "net" - uriInterface = "interface" - uriSelf = "self" - uriTrunk = "trunk" - uriVlan = "vlan" - uriRoute = "route" - uriRouteDomain = "route-domain" + uriNet = "net" + uriInterface = "interface" + uriSelf = "self" + uriTrunk = "trunk" + uriVlan = "vlan" + uriVlanInterfaces = "interfaces" + uriRoute = "route" + uriRouteDomain = "route-domain" ) // Interfaces returns a list of interfaces. @@ -191,7 +197,18 @@ func (b *BigIP) AddInterfaceToVlan(vlan, iface string, tagged bool) error { config.Untagged = true } - return b.post(config, uriNet, uriVlan, vlan, "interfaces") + return b.post(config, uriNet, uriVlan, vlan, uriVlanInterfaces) +} + +// GetVlanInterfaces returns a list of interface associated to the specified VLAN. +func (b *BigIP) GetVlanInterfaces(vlan string) (*VlanInterfaces, error) { + var vlanInterfaces VlanInterfaces + err, _ := b.getForEntity(&vlanInterfaces, uriNet, uriVlan, vlan, uriVlanInterfaces) + if err != nil { + return nil, err + } + + return &vlanInterfaces, nil } // SelfIPs returns a list of self IP's. @@ -317,25 +334,25 @@ func (b *BigIP) Routes() (*Routes, error) { } func (b *BigIP) GetRoute(name string) (*Route, error) { - var route Route - values := []string{} - regex := regexp.MustCompile(`^(\/.+\/)?(.+)`) - match := regex.FindStringSubmatch(name) - if match[1] == "" { - values = append(values, "~Common~") - } - values = append(values, name) - // Join the strings into one. - result := strings.Join(values, "") - err, ok := b.getForEntity(&route, uriNet, uriRoute, result) - if err != nil { - return nil, err - } - if !ok { - return nil, nil - } - - return &route, nil + var route Route + values := []string{} + regex := regexp.MustCompile(`^(\/.+\/)?(.+)`) + match := regex.FindStringSubmatch(name) + if match[1] == "" { + values = append(values, "~Common~") + } + values = append(values, name) + // Join the strings into one. + result := strings.Join(values, "") + err, ok := b.getForEntity(&route, uriNet, uriRoute, result) + if err != nil { + return nil, err + } + if !ok { + return nil, nil + } + + return &route, nil } // CreateRoute adds a new static route to the BIG-IP system. must include the From 06e040bd457d35c8d4f41008ea3ad52f88897412 Mon Sep 17 00:00:00 2001 From: Danny Kulchinsky Date: Thu, 27 Sep 2018 15:16:51 -0400 Subject: [PATCH 55/80] Add SelfIP and Vlan methods --- net.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/net.go b/net.go index be9e42b..7bebd69 100644 --- a/net.go +++ b/net.go @@ -222,6 +222,17 @@ func (b *BigIP) SelfIPs() (*SelfIPs, error) { return &self, nil } +// SelfIP returns a named Self IP. +func (b *BigIP) SelfIP(selfip string) (*SelfIP, error) { + var self SelfIP + err, _ := b.getForEntity(&self, uriNet, uriSelf, selfip) + if err != nil { + return nil, err + } + + return &self, nil +} + // CreateSelfIP adds a new self IP to the BIG-IP system. For

, you // must include the subnet mask in CIDR notation, i.e.: "10.1.1.1/24". func (b *BigIP) CreateSelfIP(name, address, vlan string) error { @@ -301,6 +312,18 @@ func (b *BigIP) Vlans() (*Vlans, error) { return &vlans, nil } +// Vlan returns a named vlan. +func (b *BigIP) Vlans(name string) (*Vlan, error) { + var vlan Vlan + err, _ := b.getForEntity(&vlans, uriNet, uriVlan, name) + + if err != nil { + return nil, err + } + + return &vlan, nil +} + // CreateVlan adds a new VLAN to the BIG-IP system. func (b *BigIP) CreateVlan(name string, tag int) error { config := &Vlan{ From 8c9df386b2e81bdef6fe924f97b243cc982986c5 Mon Sep 17 00:00:00 2001 From: Danny Kulchinsky Date: Thu, 27 Sep 2018 15:21:07 -0400 Subject: [PATCH 56/80] typo --- net.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net.go b/net.go index 7bebd69..4c1826a 100644 --- a/net.go +++ b/net.go @@ -313,7 +313,7 @@ func (b *BigIP) Vlans() (*Vlans, error) { } // Vlan returns a named vlan. -func (b *BigIP) Vlans(name string) (*Vlan, error) { +func (b *BigIP) Vlan(name string) (*Vlan, error) { var vlan Vlan err, _ := b.getForEntity(&vlans, uriNet, uriVlan, name) From 18f2750ccfcd5b978c7b84928261fb8869fa54f5 Mon Sep 17 00:00:00 2001 From: Danny Kulchinsky Date: Thu, 27 Sep 2018 15:22:18 -0400 Subject: [PATCH 57/80] one more typo --- net.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net.go b/net.go index 4c1826a..a7f3489 100644 --- a/net.go +++ b/net.go @@ -315,7 +315,7 @@ func (b *BigIP) Vlans() (*Vlans, error) { // Vlan returns a named vlan. func (b *BigIP) Vlan(name string) (*Vlan, error) { var vlan Vlan - err, _ := b.getForEntity(&vlans, uriNet, uriVlan, name) + err, _ := b.getForEntity(&vlan, uriNet, uriVlan, name) if err != nil { return nil, err From 16738c80d22ce6a697f57fb67a423dd51955099f Mon Sep 17 00:00:00 2001 From: Sanjay Shitole Date: Fri, 12 Oct 2018 12:31:02 -0700 Subject: [PATCH 58/80] added interval for node fqdn issue #9 --- ltm.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ltm.go b/ltm.go index 1c67ec0..05a7c90 100644 --- a/ltm.go +++ b/ltm.go @@ -1900,7 +1900,7 @@ func (b *BigIP) CreateNode(name, address, rate_limit string, connection_limit, d } // CreateFQDNNode adds a new FQDN based node to the BIG-IP system. -func (b *BigIP) CreateFQDNNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state string) error { +func (b *BigIP) CreateFQDNNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state, interval string) error { config := &Node{ Name: name, RateLimit: rate_limit, @@ -1910,6 +1910,7 @@ func (b *BigIP) CreateFQDNNode(name, address, rate_limit string, connection_limi State: state, } config.FQDN.Name = address + config.FQDN.Interval = interval return b.post(config, uriLtm, uriNode) } From b06cf17a8ec8cb2452643c6a15159ea136996630 Mon Sep 17 00:00:00 2001 From: Sanjay Shitole Date: Thu, 25 Oct 2018 13:00:19 -0700 Subject: [PATCH 59/80] added feilds for address_family, downinterval etc --- ltm.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ltm.go b/ltm.go index 05a7c90..e8cb2f2 100644 --- a/ltm.go +++ b/ltm.go @@ -1900,7 +1900,7 @@ func (b *BigIP) CreateNode(name, address, rate_limit string, connection_limit, d } // CreateFQDNNode adds a new FQDN based node to the BIG-IP system. -func (b *BigIP) CreateFQDNNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state, interval string) error { +func (b *BigIP) CreateFQDNNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state, interval, address_family, autopopulate string, downinterval int) error { config := &Node{ Name: name, RateLimit: rate_limit, @@ -1911,6 +1911,9 @@ func (b *BigIP) CreateFQDNNode(name, address, rate_limit string, connection_limi } config.FQDN.Name = address config.FQDN.Interval = interval + config.FQDN.AddressFamily = address_family + config.FQDN.AutoPopulate = autopopulate + config.FQDN.DownInterval = downinterval return b.post(config, uriLtm, uriNode) } From 400a456566098a7d10767e757892ab9ae4df1b6e Mon Sep 17 00:00:00 2001 From: Sanjay Shitole Date: Tue, 6 Nov 2018 15:09:06 -0800 Subject: [PATCH 60/80] added funcs for publisher, logs in sys.go --- sys.go | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 129 insertions(+), 13 deletions(-) diff --git a/sys.go b/sys.go index 829480b..d5097a3 100644 --- a/sys.go +++ b/sys.go @@ -147,20 +147,79 @@ type Bigiplicense struct { Command string `json:"command,omitempty"` } +type LogIPFIXs struct { + LogIPFIXs []LogIPFIX `json:"items"` +} +type LogIPFIX struct { + AppService string `json:"appService,omitempty"` + Name string `json:"name,omitempty"` + PoolName string `json:"poolName,omitempty"` + ProtocolVersion string `json:"protocolVersion,omitempty"` + ServersslProfile string `json:"serversslProfile,omitempty"` + TemplateDeleteDelay int `json:"templateDeleteDelay,omitempty"` + TemplateRetransmitInterval int `json:"templateRetransmitInterval,omitempty"` + TransportProfile string `json:"transportProfile,omitempty"` +} +type LogPublishers struct { + LogPublishers []LogPublisher `json:"items"` +} +type LogPublisher struct { + Name string `json:"name,omitempty"` + Dests []Destinations +} + +type Destinations struct { + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` +} + +type destinationsDTO struct { + Name string `json:"name,omitempty"` + Partition string `json:"partition,omitempty"` + Dests struct { + Items []Destinations `json:"items,omitempty"` + } `json:"destinationsReference,omitempty"` +} + +func (p *LogPublisher) MarshalJSON() ([]byte, error) { + return json.Marshal(destinationsDTO{ + Name: p.Name, + Dests: struct { + Items []Destinations `json:"items,omitempty"` + }{Items: p.Dests}, + }) +} + +func (p *LogPublisher) UnmarshalJSON(b []byte) error { + var dto destinationsDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + + p.Name = dto.Name + p.Dests = dto.Dests.Items + return nil +} + const ( - uriSys = "sys" - uriNtp = "ntp" - uriDNS = "dns" - uriProvision = "provision" - uriAfm = "afm" - uriAsm = "asm" - uriApm = "apm" - uriAvr = "avr" - uriIlx = "ilx" - uriSyslog = "syslog" - uriSnmp = "snmp" - uriTraps = "traps" - uriLicense = "license" + uriSys = "sys" + uriNtp = "ntp" + uriDNS = "dns" + uriProvision = "provision" + uriAfm = "afm" + uriAsm = "asm" + uriApm = "apm" + uriAvr = "avr" + uriIlx = "ilx" + uriSyslog = "syslog" + uriSnmp = "snmp" + uriTraps = "traps" + uriLicense = "license" + uriLogConfig = "logConfig" + uriDestination = "destination" + uriIPFIX = "ipfix" + uriPublisher = "publisher" ) func (b *BigIP) CreateNTP(description string, servers []string, timezone string) error { @@ -413,3 +472,60 @@ func (b *BigIP) CreateBigiplicense(command, registration_key string) error { func (b *BigIP) ModifyBigiplicense(config *Bigiplicense) error { return b.put(config, uriSys, uriLicense) } + +func (b *BigIP) LogIPFIXs() (*LogIPFIX, error) { + var logipfix LogIPFIX + err, _ := b.getForEntity(&logipfix, uriSys, uriLogConfig, uriDestination, uriIPFIX) + + if err != nil { + return nil, err + } + + return &logipfix, nil +} + +func (b *BigIP) CreateLogIPFIX(name, appService, poolName, protocolVersion, serversslProfile string, templateDeleteDelay, templateRetransmitInterval int, transportProfile string) error { + config := &LogIPFIX{ + Name: name, + AppService: appService, + PoolName: poolName, + ProtocolVersion: protocolVersion, + ServersslProfile: serversslProfile, + TemplateDeleteDelay: templateDeleteDelay, + TemplateRetransmitInterval: templateRetransmitInterval, + TransportProfile: transportProfile, + } + + return b.post(config, uriSys, uriLogConfig, uriDestination, uriIPFIX) +} + +func (b *BigIP) ModifyLogIPFIX(config *LogIPFIX) error { + return b.put(config, uriSys, uriLogConfig, uriDestination, uriIPFIX) +} + +func (b *BigIP) DeleteLogIPFIX(name string) error { + return b.delete(uriSys, uriLogConfig, uriDestination, uriIPFIX, name) +} + +func (b *BigIP) LogPublisher() (*LogPublisher, error) { + var logpublisher LogPublisher + err, _ := b.getForEntity(&logpublisher, uriSys, uriLogConfig, uriPublisher) + + if err != nil { + return nil, err + } + + return &logpublisher, nil +} + +func (b *BigIP) CreateLogPublisher(r *LogPublisher) error { + return b.post(r, uriSys, uriLogConfig, uriPublisher) +} + +func (b *BigIP) ModifyLogPublisher(r *LogPublisher) error { + return b.put(r, uriSys, uriLogConfig, uriPublisher) +} + +func (b *BigIP) DeleteLogPublisher(name string) error { + return b.delete(uriSys, uriLogConfig, uriPublisher, name) +} From 91447b7d4f4d5f7b32a930a93559a68b9e715ecf Mon Sep 17 00:00:00 2001 From: Sanjay Shitole Date: Fri, 4 Jan 2019 11:24:48 -0800 Subject: [PATCH 61/80] add contentInclude - Exclude fields to httpcompress struct --- ltm.go | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/ltm.go b/ltm.go index e8cb2f2..601319e 100644 --- a/ltm.go +++ b/ltm.go @@ -1117,10 +1117,12 @@ type Fastl4 struct { } type httpcompressDTO struct { - Name string `json:"name,omitempty"` - DefaultsFrom string `json:"defaultsFrom,omitempty"` - UriExclude []string `json:"uriExclude,omitempty"` - UriInclude []string `json:"uriInclude,omitempty"` + Name string `json:"name,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + UriExclude []string `json:"uriExclude,omitempty"` + UriInclude []string `json:"uriInclude,omitempty"` + ContentTypeInclude []string `json:"contentTypeInclude,omitempty"` + ContentTypeExclude []string `json:"contentTypeExclude,omitempty"` } type Httpcompresss struct { @@ -1128,10 +1130,12 @@ type Httpcompresss struct { } type Httpcompress struct { - Name string - DefaultsFrom string - UriExclude []string - UriInclude []string + Name string + DefaultsFrom string + UriExclude []string + UriInclude []string + ContentTypeInclude []string + ContentTypeExclude []string } type http2DTO struct { @@ -2712,12 +2716,14 @@ func (b *BigIP) GetFastl4(name string) (*Fastl4, error) { // =============== -func (b *BigIP) CreateHttpcompress(name, defaultsFrom string, uriExclude, uriInclude []string) error { +func (b *BigIP) CreateHttpcompress(name, defaultsFrom string, uriExclude, uriInclude, contentTypeInclude, contentTypeExclude []string) error { httpcompress := &Httpcompress{ - Name: name, - DefaultsFrom: defaultsFrom, - UriExclude: uriExclude, - UriInclude: uriInclude, + Name: name, + DefaultsFrom: defaultsFrom, + UriExclude: uriExclude, + UriInclude: uriInclude, + ContentTypeInclude: contentTypeInclude, + ContentTypeExclude: contentTypeExclude, } return b.post(httpcompress, uriLtm, uriProfile, uriHttpcompress) } From 6bc0199d7291917deeb0511cbfd5f1abfaf51950 Mon Sep 17 00:00:00 2001 From: Sanjay Shitole Date: Fri, 4 Jan 2019 16:10:09 -0800 Subject: [PATCH 62/80] added vlans to snat struct --- ltm.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ltm.go b/ltm.go index 601319e..f0873f3 100644 --- a/ltm.go +++ b/ltm.go @@ -1344,6 +1344,7 @@ type Snat struct { Translation string Snatpool string VlansDisabled bool + Vlans []string Origins []Originsrecord } @@ -1356,6 +1357,7 @@ type snatDTO struct { SourcePort string `json:"sourePort,omitempty"` Translation string `json:"translation,omitempty"` Snatpool string `json:"snatpool,omitempty"` + Vlans []string `json:"vlans,omitempty"` VlansDisabled bool `json:"vlansDisabled,omitempty" bool:"disabled"` Origins struct { Items []Originsrecord `json:"items,omitempty"` @@ -1381,6 +1383,7 @@ func (p *Snat) MarshalJSON() ([]byte, error) { Translation: p.Translation, Snatpool: p.Snatpool, VlansDisabled: p.VlansDisabled, + Vlans: p.Vlans, Origins: struct { Items []Originsrecord `json:"items,omitempty"` }{Items: p.Origins}, @@ -1403,6 +1406,7 @@ func (p *Snat) UnmarshalJSON(b []byte) error { p.Translation = dto.Translation p.Snatpool = dto.Snatpool p.VlansDisabled = dto.VlansDisabled + p.Vlans = dto.Vlans p.Origins = dto.Origins.Items return nil From 90b36a87a93bee6524af85a86d8c7324765955b5 Mon Sep 17 00:00:00 2001 From: Sanjay Shitole Date: Mon, 14 Jan 2019 11:59:44 -0800 Subject: [PATCH 63/80] ran go fmt & added compatibility field in ltm.go --- ltm.go | 30 ++++++++++++++++-------------- sys.go | 2 +- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/ltm.go b/ltm.go index f0873f3..4bd3de8 100644 --- a/ltm.go +++ b/ltm.go @@ -949,6 +949,7 @@ type Monitor struct { Transparent string UpInterval int Username string + Compatibility string } type monitorDTO struct { @@ -973,6 +974,7 @@ type monitorDTO struct { Transparent string `json:"transparent,omitempty"` UpInterval int `json:"upInterval,omitempty"` Username string `json:"username,omitempty"` + Compatibility string `json:"compatibility,omitempty"` } type Profiles struct { @@ -1344,21 +1346,21 @@ type Snat struct { Translation string Snatpool string VlansDisabled bool - Vlans []string + Vlans []string Origins []Originsrecord } type snatDTO struct { - Name string `json:"name"` - Partition string `json:"partition,omitempty"` - FullPath string `json:"fullPath,omitempty"` - AutoLasthop string `json:"autoLastHop,omitempty"` - Mirror string `json:"mirror,omitempty"` - SourcePort string `json:"sourePort,omitempty"` - Translation string `json:"translation,omitempty"` - Snatpool string `json:"snatpool,omitempty"` - Vlans []string `json:"vlans,omitempty"` - VlansDisabled bool `json:"vlansDisabled,omitempty" bool:"disabled"` + Name string `json:"name"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` + AutoLasthop string `json:"autoLastHop,omitempty"` + Mirror string `json:"mirror,omitempty"` + SourcePort string `json:"sourePort,omitempty"` + Translation string `json:"translation,omitempty"` + Snatpool string `json:"snatpool,omitempty"` + Vlans []string `json:"vlans,omitempty"` + VlansDisabled bool `json:"vlansDisabled,omitempty" bool:"disabled"` Origins struct { Items []Originsrecord `json:"items,omitempty"` } `json:"originsReference,omitempty"` @@ -1383,7 +1385,7 @@ func (p *Snat) MarshalJSON() ([]byte, error) { Translation: p.Translation, Snatpool: p.Snatpool, VlansDisabled: p.VlansDisabled, - Vlans: p.Vlans, + Vlans: p.Vlans, Origins: struct { Items []Originsrecord `json:"items,omitempty"` }{Items: p.Origins}, @@ -2336,7 +2338,7 @@ func (b *BigIP) Monitors() ([]Monitor, error) { // CreateMonitor adds a new monitor to the BIG-IP system. must be one of "http", "https", // "icmp", "gateway icmp", or "tcp". -func (b *BigIP) CreateMonitor(name, parent, defaults_from string, interval, timeout int, send, receive, receive_disable string) error { +func (b *BigIP) CreateMonitor(name, parent, defaults_from string, interval, timeout int, send, receive, receive_disable, compatibility string) error { config := &Monitor{ Name: name, ParentMonitor: parent, @@ -2346,6 +2348,7 @@ func (b *BigIP) CreateMonitor(name, parent, defaults_from string, interval, time SendString: send, ReceiveString: receive, ReceiveDisable: receive_disable, + Compatibility: compatibility, } return b.AddMonitor(config) @@ -2379,7 +2382,6 @@ func (b *BigIP) GetMonitor(name string, parent string) (*Monitor, error) { // DeleteMonitor removes a monitor. func (b *BigIP) DeleteMonitor(name, parent string) error { - log.Println(" in delete +++++++++++++++++ ", parent, name) return b.delete(uriLtm, uriMonitor, parent, name) } diff --git a/sys.go b/sys.go index d5097a3..8d6d77e 100644 --- a/sys.go +++ b/sys.go @@ -411,7 +411,7 @@ func (b *BigIP) SNMPs() (*SNMP, error) { func (b *BigIP) CreateTRAP(name string, authPasswordEncrypted string, authProtocol string, community string, description string, engineId string, host string, port int, privacyPassword string, privacyPasswordEncrypted string, privacyProtocol string, securityLevel string, securityName string, version string) error { config := &TRAP{ - Name: name, + Name: name, AuthPasswordEncrypted: authPasswordEncrypted, AuthProtocol: authProtocol, Community: community, From 400e5566eac053b131c3351bea8f1890211950b2 Mon Sep 17 00:00:00 2001 From: Sanjay Shitole Date: Thu, 14 Feb 2019 17:09:39 -0800 Subject: [PATCH 64/80] added monitor fields for ftp --- ltm.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/ltm.go b/ltm.go index 4bd3de8..a18021d 100644 --- a/ltm.go +++ b/ltm.go @@ -950,6 +950,10 @@ type Monitor struct { UpInterval int Username string Compatibility string + Filename string + Mode string + Adaptive string + AdaptiveLimit int } type monitorDTO struct { @@ -975,6 +979,10 @@ type monitorDTO struct { UpInterval int `json:"upInterval,omitempty"` Username string `json:"username,omitempty"` Compatibility string `json:"compatibility,omitempty"` + Filename string `json:"filename,omitempty"` + Mode string `json:"mode,omitempty"` + Adaptive string `json:"adaptive,omitempty"` + AdaptiveLimit int `json:"adaptiveLimit,omitempty"` } type Profiles struct { @@ -2320,7 +2328,7 @@ func (b *BigIP) DeleteVirtualAddress(vaddr string) error { // Monitors returns a list of all HTTP, HTTPS, Gateway ICMP, ICMP, and TCP monitors. func (b *BigIP) Monitors() ([]Monitor, error) { var monitors []Monitor - monitorUris := []string{"http", "https", "icmp", "gateway-icmp", "tcp", "tcp-half-open"} + monitorUris := []string{"http", "https", "icmp", "gateway-icmp", "tcp", "tcp-half-open", "ftp"} for _, name := range monitorUris { var m Monitors @@ -2362,6 +2370,9 @@ func (b *BigIP) AddMonitor(config *Monitor) error { if strings.Contains(config.ParentMonitor, "tcp-half-open") { config.ParentMonitor = "tcp-half-open" } + if strings.Contains(config.ParentMonitor, "ftp") { + config.ParentMonitor = "ftp" + } return b.post(config, uriLtm, uriMonitor, config.ParentMonitor) } @@ -2395,6 +2406,9 @@ func (b *BigIP) ModifyMonitor(name, parent string, config *Monitor) error { if strings.Contains(config.ParentMonitor, "tcp-half-open") { config.ParentMonitor = "tcp-half-open" } + if strings.Contains(config.ParentMonitor, "ftp") { + config.ParentMonitor = "ftp" + } return b.put(config, uriLtm, uriMonitor, parent, name) } From 33678a24794b0be6c06dfb3dd9f2be79cc0653eb Mon Sep 17 00:00:00 2001 From: Sanjay Shitole Date: Fri, 22 Mar 2019 11:16:32 -0700 Subject: [PATCH 65/80] updated struct for http profile --- ltm.go | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/ltm.go b/ltm.go index a18021d..eb78ec6 100644 --- a/ltm.go +++ b/ltm.go @@ -1577,33 +1577,33 @@ type HttpProfiles struct { } type HttpProfile struct { - AcceptXff string `json:"acceptXff,omitempty"` - AppService string `json:"appService,omitempty"` - BasicAuthRealm string `json:"basicAuthRealm,omitempty"` - DefaultsFrom string `json:"defaultsFrom,omitempty"` - Description string `json:"description,omitempty"` - EncryptCookieSecret string `json:"encryptCookieSecret,omitempty"` - EncryptCookies string `json:"encryptCookies,omitempty"` - FallbackHost string `json:"fallbackHost,omitempty"` - FallbackStatusCodes string `json:"fallbackStatusCodes,omitempty"` - HeaderErase string `json:"headerErase,omitempty"` - HeaderInsert string `json:"headerInsert,omitempty"` - InsertXforwardedFor string `json:"insertXforwardedFor,omitempty"` - LwsSeparator string `json:"lwsSeparator,omitempty"` - LwsWidth int `json:"lwsWidth,omitempty"` - Name string `json:"name,omitempty"` - OneconnectTransformations string `json:"oneconnectTransformations,omitempty"` - TmPartition string `json:"tmPartition,omitempty"` - ProxyType string `json:"proxyType,omitempty"` - RedirectRewrite string `json:"redirectRewrite,omitempty"` - RequestChunking string `json:"requestChunking,omitempty"` - ResponseChunking string `json:"responseChunking,omitempty"` - ResponseHeadersPermitted string `json:"responseHeadersPermitted,omitempty"` - ServerAgentName string `json:"serverAgentName,omitempty"` - ViaHostName string `json:"viaHostName,omitempty"` - ViaRequest string `json:"viaRequest,omitempty"` - ViaResponse string `json:"viaResponse,omitempty"` - XffAlternativeNames string `json:"xffAlternativeNames,omitempty"` + AcceptXff string `json:"acceptXff,omitempty"` + AppService string `json:"appService,omitempty"` + BasicAuthRealm string `json:"basicAuthRealm,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + EncryptCookieSecret string `json:"encryptCookieSecret,omitempty"` + EncryptCookies []string `json:"encryptCookies,omitempty"` + FallbackHost string `json:"fallbackHost,omitempty"` + FallbackStatusCodes []string `json:"fallbackStatusCodes,omitempty"` + HeaderErase string `json:"headerErase,omitempty"` + HeaderInsert string `json:"headerInsert,omitempty"` + InsertXforwardedFor string `json:"insertXforwardedFor,omitempty"` + LwsSeparator string `json:"lwsSeparator,omitempty"` + LwsWidth int `json:"lwsWidth,omitempty"` + Name string `json:"name,omitempty"` + OneconnectTransformations string `json:"oneconnectTransformations,omitempty"` + TmPartition string `json:"tmPartition,omitempty"` + ProxyType string `json:"proxyType,omitempty"` + RedirectRewrite string `json:"redirectRewrite,omitempty"` + RequestChunking string `json:"requestChunking,omitempty"` + ResponseChunking string `json:"responseChunking,omitempty"` + ResponseHeadersPermitted []string `json:"responseHeadersPermitted,omitempty"` + ServerAgentName string `json:"serverAgentName,omitempty"` + ViaHostName string `json:"viaHostName,omitempty"` + ViaRequest string `json:"viaRequest,omitempty"` + ViaResponse string `json:"viaResponse,omitempty"` + XffAlternativeNames []string `json:"xffAlternativeNames,omitempty"` } type OneconnectProfiles struct { From 071d11dbe2583d314891f4d5f5edf63ff6c9c457 Mon Sep 17 00:00:00 2001 From: Sanjay Shitole Date: Tue, 2 Apr 2019 14:27:25 -0700 Subject: [PATCH 66/80] as3 sdk file --- app.go | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 app.go diff --git a/app.go b/app.go new file mode 100644 index 0000000..810a9c0 --- /dev/null +++ b/app.go @@ -0,0 +1,168 @@ +/* +AS3 uses a declarative model, meaning you provide a JSON declaration rather than a set of imperative commands. The declaration represents the configuration which AS3 is responsible for creating on a BIG-IP system. AS3 is well-defined according to the rules of JSON Schema, and declarations validate according to JSON Schema. AS3 accepts declaration updates via REST (push), reference (pull), or CLI (flat file editing). +To read more about As3 check https://clouddocs.f5.com/products/extensions/f5-appsvcs-extension/latest/userguide/ */ +package bigip + +import ( + "log" +) + +type Appsvcs struct { + Appsvcs []Appsvc01 `json:"items"` +} +type Appsvc01 struct { + Class string `json:"class"` + Action string `json:"action"` + Persist bool `json:"persist"` + Declaration struct { + Class string `json:"class"` + SchemaVersion string `json:"schemaVersion"` + ID string `json:"id"` + Label string `json:"label"` + Remark string `json:"remark"` + Sample01 struct { + Class string `json:"class"` + DefaultRouteDomain int `json:"defaultRouteDomain"` + Application1 struct { + Class string `json:"class"` + Template string `json:"template"` + ServiceMain struct { + Class string `json:"class"` + VirtualAddresses []string `json:"virtualAddresses"` + Pool string `json:"pool"` + } `json:"serviceMain"` + WebPool struct { + Class string `json:"class"` + Monitors []string `json:"monitors"` + Members []struct { + ServicePort int `json:"servicePort"` + ServerAddresses []string `json:"serverAddresses"` + } `json:"members"` + } `json:"web_pool"` + } `json:"Application_1"` + } `json:"Sample_01,omitempty"` + } `json:"declaration,omitempty"` +} + +type Appsvc02 struct { + Class string `json:"class"` + Action string `json:"action"` + Persist bool `json:"persist"` + Declaration struct { + Class string `json:"class"` + SchemaVersion string `json:"schemaVersion"` + ID string `json:"id"` + Label string `json:"label"` + Remark string `json:"remark"` + Sample02 struct { + Class string `json:"class"` + A1 struct { + Class string `json:"class"` + Template string `json:"template"` + ServiceMain struct { + Class string `json:"class"` + VirtualAddresses []string `json:"virtualAddresses"` + Pool string `json:"pool"` + ServerTLS string `json:"serverTLS"` + } `json:"serviceMain"` + WebPool struct { + Class string `json:"class"` + LoadBalancingMode string `json:"loadBalancingMode"` + Monitors []string `json:"monitors"` + Members []struct { + ServicePort int `json:"servicePort"` + ServerAddresses []string `json:"serverAddresses"` + } `json:"members"` + } `json:"web_pool"` + Webtls struct { + Class string `json:"class"` + Certificates []struct { + Certificate string `json:"certificate"` + } `json:"certificates"` + } `json:"webtls"` + Webcert struct { + Class string `json:"class"` + Remark string `json:"remark"` + Certificate string `json:"certificate"` + PrivateKey string `json:"privateKey"` + Passphrase struct { + Ciphertext string `json:"ciphertext"` + Protected string `json:"protected"` + } `json:"passphrase"` + } `json:"webcert"` + } `json:"A1"` + } `json:"Sample_02"` + } `json:"declaration"` +} + +const ( + uriSha = "shared" + uriAppsvcs = "appsvcs" + uriDecl = "declare" + uriSam01 = "Sample_01" + uriSam02 = "Sample_02" +) + +// Appsvcss returns a list of appsvcs +func (b *BigIP) Appsvc01() (*Appsvc01, error) { + var appsvc01 Appsvc01 + err, _ := b.getForEntity(uriSam01, uriSha, uriAppsvcs, uriDecl) + log.Printf("i am here in sdk %+v ", appsvc01) + if err != nil { + return nil, err + } + + return &appsvc01, nil +} +func (b *BigIP) Appsvc02() (*Appsvc02, error) { + var appsvc02 Appsvc02 + err, _ := b.getForEntity(uriSam02, uriSha, uriAppsvcs, uriDecl) + log.Printf("i am here in sdk %+v ", appsvc02) + if err != nil { + return nil, err + } + + return &appsvc02, nil +} + +// CreateAppsvcs creates a new iAppsvcs on the system. +func (b *BigIP) CreateAppsvc01(p *Appsvc01) error { + log.Printf("++++++ Here is what terraform is sending to bigip ................ : %+v ", p) + err := b.post(p, uriMgmt, uriSha, uriAppsvcs, uriDecl) + if err != nil { + log.Println(" API call not successfull %v ", err) + } + return nil +} +func (b *BigIP) CreateAppsvc02(p *Appsvc02) error { + log.Printf("++++++ Here is what terraform is sending to bigip ................ : %+v ", p) + err := b.post(p, uriMgmt, uriSha, uriAppsvcs, uriDecl) + if err != nil { + log.Println(" API call not successfull %v ", err) + } + return nil +} +func (b *BigIP) DeleteAppsvc01() error { + return b.delete(uriMgmt, uriSha, uriAppsvcs, uriDecl, uriSam01) +} +func (b *BigIP) DeleteAppsvc02() error { + return b.delete(uriMgmt, uriSha, uriAppsvcs, uriDecl, uriSam02) +} + +func (b *BigIP) ModifyAppsvc01(p *Appsvc01) error { + log.Printf("++++++ Here is what terraform is sending to bigip ................ : %+v ", p) + err := b.patch(p, uriMgmt, uriSha, uriAppsvcs, uriDecl) + log.Printf("value of p in modify +++++++++++++++", p) + if err != nil { + log.Println(" API call not successfull %v ", err) + } + return nil +} +func (b *BigIP) ModifyAppsvc02(p *Appsvc02) error { + log.Printf("++++++ Here is what terraform is sending to bigip ................ : %+v ", p) + err := b.patch(p, uriMgmt, uriSha, uriAppsvcs, uriDecl) + if err != nil { + log.Println(" API call not successfull %v ", err) + } + return nil +} From a7a17001a8820e74b92b1d661a6b5820dad6121f Mon Sep 17 00:00:00 2001 From: Girish Kalele Date: Fri, 12 Apr 2019 11:10:04 -0700 Subject: [PATCH 67/80] Getter for the tmPartition entity --- partitions.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 partitions.go diff --git a/partitions.go b/partitions.go new file mode 100644 index 0000000..88e1896 --- /dev/null +++ b/partitions.go @@ -0,0 +1,23 @@ +package bigip + +// TMPartitions contains a list of all partitions on the BIG-IP system. +type TMPartitions struct { + TMPartitions []*TMPartition `json:"items"` +} + +type TMPartition struct { + Name string `json:"name,omitempty"` + Kind string `json:"kind,omitempty"` + DefaultRouteDomain int `json:"defaultRouteDomain,omitempty"` + FullPath string `json:"fullPath,omitempty"` + SelfLink string `json:"selfLink,omitempty"` +} + +// TMPartitions returns a list of partitions. +func (b *BigIP) TMPartitions() (*TMPartitions, error) { + var pList TMPartitions + if err, _ := b.getForEntity(&pList, "auth", "tmPartition"); err != nil { + return nil, err + } + return &pList, nil +} From f59cf74357c0fe5ca4b9693314c4790fc415a323 Mon Sep 17 00:00:00 2001 From: Mike Pescetto Date: Mon, 15 Apr 2019 14:37:01 -0500 Subject: [PATCH 68/80] Ignore VIM swp files. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 7d4df8a..a5bba21 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .idea *.iml *.back +*.swp From 28228229e0f1c1d4841c36efb2be7deb52cde071 Mon Sep 17 00:00:00 2001 From: Mike Pescetto Date: Mon, 15 Apr 2019 14:37:26 -0500 Subject: [PATCH 69/80] Update println to concatinate values --- app.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app.go b/app.go index 810a9c0..155abbc 100644 --- a/app.go +++ b/app.go @@ -130,7 +130,7 @@ func (b *BigIP) CreateAppsvc01(p *Appsvc01) error { log.Printf("++++++ Here is what terraform is sending to bigip ................ : %+v ", p) err := b.post(p, uriMgmt, uriSha, uriAppsvcs, uriDecl) if err != nil { - log.Println(" API call not successfull %v ", err) + log.Println(" API call not successfull ", err) } return nil } @@ -138,7 +138,7 @@ func (b *BigIP) CreateAppsvc02(p *Appsvc02) error { log.Printf("++++++ Here is what terraform is sending to bigip ................ : %+v ", p) err := b.post(p, uriMgmt, uriSha, uriAppsvcs, uriDecl) if err != nil { - log.Println(" API call not successfull %v ", err) + log.Println(" API call not successfull ", err) } return nil } @@ -152,9 +152,9 @@ func (b *BigIP) DeleteAppsvc02() error { func (b *BigIP) ModifyAppsvc01(p *Appsvc01) error { log.Printf("++++++ Here is what terraform is sending to bigip ................ : %+v ", p) err := b.patch(p, uriMgmt, uriSha, uriAppsvcs, uriDecl) - log.Printf("value of p in modify +++++++++++++++", p) + log.Println("value of p in modify +++++++++++++++", p) if err != nil { - log.Println(" API call not successfull %v ", err) + log.Println(" API call not successfull ", err) } return nil } @@ -162,7 +162,7 @@ func (b *BigIP) ModifyAppsvc02(p *Appsvc02) error { log.Printf("++++++ Here is what terraform is sending to bigip ................ : %+v ", p) err := b.patch(p, uriMgmt, uriSha, uriAppsvcs, uriDecl) if err != nil { - log.Println(" API call not successfull %v ", err) + log.Println(" API call not successfull ", err) } return nil } From 8653982e3a0f672ecdae9b43955df5880c20a805 Mon Sep 17 00:00:00 2001 From: Mike Pescetto Date: Mon, 15 Apr 2019 15:03:31 -0500 Subject: [PATCH 70/80] Add new Tunnel CRUD functions and tests --- net.go | 85 ++++++++++++++++++++++++++++++++++ net_test.go | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 214 insertions(+) diff --git a/net.go b/net.go index a7f3489..99a57aa 100644 --- a/net.go +++ b/net.go @@ -163,11 +163,42 @@ type RouteDomain struct { Vlans []string `json:"vlans,omitempty"` } +// Tunnels contains a list of tunnel objects on the BIG-IP system. +type Tunnels struct { + Tunnels []Tunnel `json:"items"` +} + +// Tunnel contains information on the tunnel. +// https://devcentral.f5.com/wiki/iControlREST.APIRef_tm_net_tunnels_tunnel.ashx +type Tunnel struct { + Name string `json:"name,omitempty"` + AppService string `json:"appService,omitempty"` + AutoLasthop string `json:"autoLasthop,omitempty"` + Description string `json:"description,omitempty"` + IdleTimeout int `json:"idleTimeout,omitempty"` + IfIndex int `json:"ifIndex,omitempty"` + Key int `json:"key,omitempty"` + LocalAddress string `json:"localAddress,omitempty"` + Mode string `json:"mode,omitempty"` + Mtu int `json:"mtu,omitempty"` + Partition string `json:"partition,omitempty"` + Profile string `json:"profile,omitempty"` + RemoteAddress string `json:"remoteAddress,omitempty"` + SecondaryAddress string `json:"secondaryAddress,omitempty"` + Tos string `json:"tos,omitempty"` + TrafficGroup string `json:"trafficGroup,omitempty"` + Transparent string `json:"transparent,omitempty"` + UsePmtu string `json:"usePmtu,omitempty"` +} + const ( uriNet = "net" uriInterface = "interface" uriSelf = "self" uriTrunk = "trunk" + uriTunnels = "tunnels" + uriTunnel = "tunnel" + uriVxlan = "vxlan" uriVlan = "vlan" uriVlanInterfaces = "interfaces" uriRoute = "route" @@ -448,3 +479,57 @@ func (b *BigIP) DeleteRouteDomain(name string) error { func (b *BigIP) ModifyRouteDomain(name string, config *RouteDomain) error { return b.put(config, uriNet, uriRouteDomain, name) } + +// Tunnels returns a list of tunnels. +func (b *BigIP) Tunnels() (*Tunnels, error) { + var tunnels Tunnels + err, _ := b.getForEntity(&tunnels, uriNet, uriTunnels, uriTunnel) + if err != nil { + return nil, err + } + + return &tunnels, nil +} + +// GetTunnel fetches the tunnel by it's name. +func (b *BigIP) GetTunnel(name string) (*Tunnel, error) { + var tunnel Tunnel + values := []string{} + regex := regexp.MustCompile(`^(\/.+\/)?(.+)`) + match := regex.FindStringSubmatch(name) + if match[1] == "" { + values = append(values, "~Common~") + } + values = append(values, name) + // Join the strings into one. + result := strings.Join(values, "") + err, ok := b.getForEntity(&tunnel, uriNet, uriTunnels, uriTunnel, result) + if err != nil { + return nil, err + } + if !ok { + return nil, nil + } + + return &tunnel, nil +} + +// CreateTunnel adds a new tunnel to the BIG-IP system. +func (b *BigIP) CreateTunnel(name, profile string) error { + config := &Tunnel{ + Name: name, + Profile: profile, + } + + return b.post(config, uriNet, uriTunnels, uriTunnel) +} + +// DeleteTunnel removes a tunnel. +func (b *BigIP) DeleteTunnel(name string) error { + return b.delete(uriNet, uriTunnels, uriTunnel, name) +} + +// ModifyTunnel allows you to change any attribute of a tunnel. +func (b *BigIP) ModifyTunnel(name string, config *Tunnel) error { + return b.put(config, uriNet, uriTunnels, uriTunnel, name) +} diff --git a/net_test.go b/net_test.go index 3034b22..aa6f95c 100644 --- a/net_test.go +++ b/net_test.go @@ -380,3 +380,132 @@ func assertRestCall(s *NetTestSuite, method, path, body string) { assert.JSONEq(s.T(), body, s.LastRequestBody) } } + +func (s *NetTestSuite) TestTunnels() { + s.ResponseFunc = func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(`{ + "kind": "tm:net:tunnels:tunnel:tunnelcollectionstate", + "selfLink": "https://localhost/mgmt/tm/net/tunnels/tunnel?ver=13.1.1.2", + "items": [ + { + "kind": "tm:net:tunnels:tunnel:tunnelstate", + "name": "http-tunnel", + "partition": "Common", + "fullPath": "/Common/http-tunnel", + "generation": 1, + "selfLink": "https://localhost/mgmt/tm/net/tunnels/tunnel/~Common~http-tunnel?ver=13.1.1.2", + "autoLasthop": "default", + "description": "Tunnel for http-explicit profile", + "idleTimeout": 300, + "ifIndex": 912, + "key": 0, + "localAddress": "any6", + "mode": "bidirectional", + "mtu": 0, + "profile": "/Common/tcp-forward", + "profileReference": { + "link": "https://localhost/mgmt/tm/net/tunnels/tcp-forward/~Common~tcp-forward?ver=13.1.1.2" + }, + "remoteAddress": "any6", + "secondaryAddress": "any6", + "tos": "preserve", + "transparent": "disabled", + "usePmtu": "enabled" + }, + { + "kind": "tm:net:tunnels:tunnel:tunnelstate", + "name": "socks-tunnel", + "partition": "Common", + "fullPath": "/Common/socks-tunnel", + "generation": 1, + "selfLink": "https://localhost/mgmt/tm/net/tunnels/tunnel/~Common~socks-tunnel?ver=13.1.1.2", + "autoLasthop": "default", + "description": "Tunnel for socks profile", + "idleTimeout": 300, + "ifIndex": 928, + "key": 0, + "localAddress": "any6", + "mode": "bidirectional", + "mtu": 0, + "profile": "/Common/tcp-forward", + "profileReference": { + "link": "https://localhost/mgmt/tm/net/tunnels/tcp-forward/~Common~tcp-forward?ver=13.1.1.2" + }, + "remoteAddress": "any6", + "secondaryAddress": "any6", + "tos": "preserve", + "transparent": "disabled", + "usePmtu": "enabled" + } + ] +}`)) + } + + tunnels, err := s.Client.Tunnels() + + assert.Nil(s.T(), err) + assertRestCall(s, "GET", "/mgmt/tm/net/tunnels/tunnel", "") + assert.Equal(s.T(), 2, len(tunnels.Tunnels)) + assert.Equal(s.T(), "http-tunnel", tunnels.Tunnels[0].Name) + assert.Equal(s.T(), "socks-tunnel", tunnels.Tunnels[1].Name) +} + +func (s *NetTestSuite) TestGetTunnel() { + s.ResponseFunc = func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(`{ + "autoLasthop": "default", + "description": "Tunnel for http-explicit profile", + "fullPath": "/Common/http-tunnel", + "generation": 1, + "idleTimeout": 300, + "ifIndex": 112, + "key": 0, + "kind": "tm:net:tunnels:tunnel:tunnelstate", + "localAddress": "any6", + "mode": "bidirectional", + "mtu": 0, + "name": "http-tunnel", + "partition": "Common", + "profile": "/Common/tcp-forward", + "profileReference": { + "link": "https://localhost/mgmt/tm/net/tunnels/tcp-forward/~Common~tcp-forward?ver=14.1.0.3" + }, + "remoteAddress": "any6", + "secondaryAddress": "any6", + "selfLink": "https://localhost/mgmt/tm/net/tunnels/tunnel/~Common~http-tunnel?ver=14.1.0.3", + "tos": "preserve", + "transparent": "disabled", + "usePmtu": "enabled" +}`)) + } + + tunnel, err := s.Client.GetTunnel("http-tunnel") + + assert.Nil(s.T(), err) + assertRestCall(s, "GET", "/mgmt/tm/net/tunnels/tunnel/~Common~http-tunnel", "") + assert.Equal(s.T(), "http-tunnel", tunnel.Name) + assert.Equal(s.T(), "/Common/tcp-forward", tunnel.Profile) +} + +func (s *NetTestSuite) TestCreateTunnel() { + err := s.Client.CreateTunnel("some-foo-tunnel", "/Common/some-foo-profile") + + assert.Nil(s.T(), err) + assertRestCall(s, "POST", "/mgmt/tm/net/tunnels/tunnel", `{"name":"some-foo-tunnel", "profile":"/Common/some-foo-profile"}`) +} + +func (s *NetTestSuite) TestDeleteTunnel() { + err := s.Client.DeleteTunnel("some-foo-tunnel") + + assert.Nil(s.T(), err) + assertRestCall(s, "DELETE", "/mgmt/tm/net/tunnels/tunnel/some-foo-tunnel", "") +} + +func (s *NetTestSuite) TestModifyTunnel() { + tunnel := &Tunnel{Transparent: "enabled"} + + err := s.Client.ModifyTunnel("some-foo-tunnel", tunnel) + + assert.Nil(s.T(), err) + assertRestCall(s, "PUT", "/mgmt/tm/net/tunnels/tunnel/some-foo-tunnel", `{"transparent":"enabled"}`) +} From 62f2a154e92f8634b9668518619d02f20755d79e Mon Sep 17 00:00:00 2001 From: Mike Pescetto Date: Tue, 16 Apr 2019 21:15:18 -0500 Subject: [PATCH 71/80] Add the GetDevices function --- device.go | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/device.go b/device.go index 7675a7e..68f9306 100644 --- a/device.go +++ b/device.go @@ -46,11 +46,53 @@ type Devices struct { Devices []Device `json:"items"` } +// UnicastAddress is an abstraction and used by Device +type UnicastAddress struct { + EffectiveIP string `json:"effectiveIp"` + EffectivePort int `json:"effectivePort"` + IP string `json:"ip"` + Port int `json:"port"` +} + +// Device represents an individual bigip as viewed from the cluster +// see: https://devcentral.f5.com/Wiki/iControlREST.APIRef_tm_cm_device.ashx type Device struct { - ConfigsyncIp string `json:"configsyncIp,omitempty"` - Name string `json:"name,omitempty"` - MirrorIp string `json:"mirrorIp,omitempty"` - MirrorSecondaryIp string `json:"mirrorSecondaryIp,omitempty"` + ConfigsyncIp string `json:"configsyncIp,omitempty"` + Name string `json:"name,omitempty"` + MirrorIp string `json:"mirrorIp,omitempty"` + MirrorSecondaryIp string `json:"mirrorSecondaryIp,omitempty"` + ActiveModules []string `json:"activeModules,omitempty"` + AppService string `json:"appService,omitempty"` + BaseMac string `json:"baseMac,omitempty"` + Build string `json:"build,omitempty"` + Cert string `json:"cert,omitempty"` + ChassisID string `json:"chassisId,omitempty"` + ChassisType string `json:"chassisType,omitempty"` + Comment string `json:"comment,omitempty"` + ConfigsyncIP string `json:"configsyncIp,omitempty"` + Contact string `json:"contact,omitempty"` + Description string `json:"description,omitempty"` + Edition string `json:"edition,omitempty"` + FailoverState string `json:"failoverState,omitempty"` + HaCapacity int `json:"haCapacity,omitempty"` + Hostname string `json:"hostname,omitempty"` + InactiveModules string `json:"inactiveModules,omitempty"` + Key string `json:"key,omitempty"` + Location string `json:"location,omitempty"` + ManagementIP string `json:"managementIp,omitempty"` + MarketingName string `json:"marketingName,omitempty"` + MulticastInterface string `json:"multicastInterface,omitempty"` + MulticastIP string `json:"multicastIp,omitempty"` + MulticastPort int `json:"multicastPort,omitempty"` + OptionalModules []string `json:"optionalModules,omitempty"` + Partition string `json:"partition,omitempty"` + PlatformID string `json:"platformId,omitempty"` + Product string `json:"product,omitempty"` + SelfDevice string `json:"selfDevice,omitempty"` + TimeLimitedModules []string `json:"timeLimitedModules,omitempty"` + TimeZone string `json:"timeZone,omitempty"` + Version string `json:"version,omitempty"` + UnicastAddress []UnicastAddress } type Devicegroups struct { @@ -260,6 +302,18 @@ func (b *BigIP) Devices(name string) (*Device, error) { return &device, nil } +// GetDevices returns a list of the bigip's in the cluster. +func (b *BigIP) GetDevices() ([]Device, error) { + var devices Devices + err, _ := b.getForEntity(&devices, uriCm, uriDiv) + + if err != nil { + return nil, err + } + + return devices.Devices, nil +} + func (b *BigIP) CreateDevicegroup(p *Devicegroup) error { return b.post(p, uriCm, uriDG) } From 935ed48042d32b3259b8dd86a8193d55eb209859 Mon Sep 17 00:00:00 2001 From: Mike Pescetto Date: Tue, 16 Apr 2019 21:15:40 -0500 Subject: [PATCH 72/80] Add the test for GetDevices --- device_test.go | 189 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 device_test.go diff --git a/device_test.go b/device_test.go new file mode 100644 index 0000000..3937f5b --- /dev/null +++ b/device_test.go @@ -0,0 +1,189 @@ +package bigip + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" + "io/ioutil" +) + +var goodDeviceResponse = `{ + "items": [ + { + "activeModules": [ + "APM, Base, VE GBB (500 CCU, 2500 Access Sessions)|XFLGBEL-BRZXIDZ|Anti-Virus Checks|Base Endpoint Security Checks|Firewall Checks|Network Access|Secure Virtual Keyboard|APM, Web Application|Machine Certificate Checks|Protected Workspace|Remote Desktop|App Tunnel" + ], + "baseMac": "aa:aa:aa:aa:aa:aa", + "build": "0.0.4", + "cert": "/Common/dtdi.crt", + "certReference": { + "link": "https://localhost/mgmt/tm/cm/cert/~Common~dtdi.crt?ver=13.1.1.2" + }, + "chassisId": "foo", + "chassisType": "individual", + "configsyncIp": "10.1.1.10", + "edition": "Point Release 2", + "failoverState": "active", + "fullPath": "/Common/foo.f5.com", + "generation": 1, + "haCapacity": 0, + "hostname": "foo.f5.com", + "key": "/Common/dtdi.key", + "keyReference": { + "link": "https://localhost/mgmt/tm/cm/key/~Common~dtdi.key?ver=13.1.1.2" + }, + "kind": "tm:cm:device:devicestate", + "managementIp": "172.16.1.10", + "marketingName": "BIG-IP Virtual Edition", + "mirrorIp": "10.1.1.10", + "mirrorSecondaryIp": "any6", + "multicastIp": "any6", + "multicastPort": 0, + "name": "foo.f5.com", + "optionalModules": [ + "Advanced Protocols, VE", + "URL Filtering, VE-25M-1G, 500 Sessions, 3Yr" + ], + "partition": "Common", + "platformId": "foo", + "product": "BIG-IP", + "selfDevice": "true", + "selfLink": "https://localhost/mgmt/tm/cm/device/~Common~foo.f5.com?ver=13.1.1.2", + "timeZone": "Europe/Rome", + "unicastAddress": [ + { + "effectiveIp": "management-ip", + "effectivePort": 123, + "ip": "management-ip", + "port": 123 + }, + { + "effectiveIp": "10.1.1.10", + "effectivePort": 456, + "ip": "10.1.1.10", + "port": 456 + } + ], + "version": "13.1.1.2" + }, + { + "activeModules": [ + "APM, Base, VE GBB (500 CCU, 2500 Access Sessions)|UEMOINR-IPCMIEL|Anti-Virus Checks|Base Endpoint Security Checks|Firewall Checks|Network Access|Secure Virtual Keyboard|APM, Web Application|Machine Certificate Checks|Protected Workspace|Remote Desktop|App Tunnel" + ], + "baseMac": "bb:bb:bb:bb:bb:bb", + "build": "0.0.4", + "chassisId": "bar", + "chassisType": "individual", + "configsyncIp": "10.1.1.11", + "edition": "Point Release 2", + "failoverState": "standby", + "fullPath": "/Common/bar.f5.com", + "generation": 2, + "haCapacity": 0, + "hostname": "bar.f5.com", + "kind": "tm:cm:device:devicestate", + "managementIp": "172.16.1.11", + "marketingName": "BIG-IP Virtual Edition", + "mirrorIp": "10.1.1.11", + "mirrorSecondaryIp": "any6", + "multicastIp": "any6", + "multicastPort": 0, + "name": "bar.f5.com", + "optionalModules": [ + "Advanced Protocols, VE", + "URL Filtering, VE-25M-1G, 500 Sessions, 3Yr" + ], + "partition": "Common", + "platformId": "Z100", + "product": "BIG-IP", + "selfDevice": "false", + "selfLink": "https://localhost/mgmt/tm/cm/device/~Common~bar.f5.com?ver=13.1.1.2", + "timeZone": "Europe/Rome", + "unicastAddress": [ + { + "effectiveIp": "management-ip", + "effectivePort": 123, + "ip": "management-ip", + "port": 123 + }, + { + "effectiveIp": "10.1.1.11", + "effectivePort": 456, + "ip": "10.1.1.11", + "port": 456 + } + ], + "version": "13.1.1.2" + } + ], + "kind": "tm:cm:device:devicecollectionstate", + "selfLink": "https://localhost/mgmt/tm/cm/device?ver=13.1.1.2" +}` + +// assertDeviceRestCall verifies that the DeviceTestSuite receives an +// http request with a matching method, URI, and body. +func assertDeviceRestCall(s *DeviceTestSuite, method, path, body string) { + assert.Equal(s.T(), method, s.LastRequest.Method) + assert.Equal(s.T(), path, s.LastRequest.URL.Path) + if body != "" { + assert.JSONEq(s.T(), body, s.LastRequestBody) + } +} + +// Setup the TestSuite + +type DeviceTestSuite struct { + suite.Suite + Client *BigIP + Server *httptest.Server + LastRequest *http.Request + LastRequestBody string + ResponseFunc func(http.ResponseWriter, *http.Request) +} + +func (s *DeviceTestSuite) SetupSuite() { + s.Server = httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + body, _ := ioutil.ReadAll(r.Body) + s.LastRequestBody = string(body) + s.LastRequest = r + if s.ResponseFunc != nil { + s.ResponseFunc(w, r) + } + })) + + s.Client = NewSession(s.Server.URL, "", "", nil) +} + +func (s *DeviceTestSuite) TearDownSuite() { + s.Server.Close() +} + +func (s *DeviceTestSuite) SetupTest() { + s.ResponseFunc = nil + s.LastRequest = nil +} + +func TestDeviceSuite(t *testing.T) { + suite.Run(t, new(DeviceTestSuite)) +} + +func (s *DeviceTestSuite) TestGetDevices() { + s.ResponseFunc = func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(goodDeviceResponse)) + } + + devices, err := s.Client.GetDevices() + + assert.Nil(s.T(), err) + assertDeviceRestCall(s, "GET", "/mgmt/tm/cm/device", "") + assert.Equal(s.T(), 2, len(devices)) + + assert.Equal(s.T(), "foo.f5.com", devices[0].Name) + assert.Equal(s.T(), "bar.f5.com", devices[1].Name) + + assert.Equal(s.T(), "active", devices[0].FailoverState) + assert.Equal(s.T(), "standby", devices[1].FailoverState) +} From 118c248daf2a98bbb05a25ff3fa285245253fcff Mon Sep 17 00:00:00 2001 From: Mike Pescetto Date: Tue, 16 Apr 2019 22:15:23 -0500 Subject: [PATCH 73/80] Add the vxlan CRUD functions --- net.go | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 9 deletions(-) diff --git a/net.go b/net.go index 99a57aa..629298d 100644 --- a/net.go +++ b/net.go @@ -191,6 +191,24 @@ type Tunnel struct { UsePmtu string `json:"usePmtu,omitempty"` } +// Vxlans contains a list of vlxan profiles on the BIG-IP system. +type Vxlans struct { + Vxlans []Vxlan `json:"items"` +} + +// Vxlan is the structure for the VXLAN profile on the bigip. +// https://devcentral.f5.com/wiki/iControlREST.APIRef_tm_net_tunnels_vxlan.ashx +type Vxlan struct { + Name string `json:"name,omitempty"` + AppService string `json:"appService,omitempty"` + DefaultsFrom string `json:"defaultsFrom,omitempty"` + Description string `json:"description,omitempty"` + EncapsulationType string `json:"encapsulationType,omitempty"` + FloodingType string `json:"floodingType,omitempty"` + Partition string `json:"partition,omitempty"` + Port int `json:"port,omitempty"` +} + const ( uriNet = "net" uriInterface = "interface" @@ -205,6 +223,20 @@ const ( uriRouteDomain = "route-domain" ) +// formatResourceID takes the resource name to +// ensure theres a partition for the Resource ID +func formatResourceID(name string) string { + values := []string{} + regex := regexp.MustCompile(`^(\/.+\/)?(.+)`) + match := regex.FindStringSubmatch(name) + if match[1] == "" { + values = append(values, "~Common~") + } + values = append(values, name) + // Join the strings into one. + return strings.Join(values, "") +} + // Interfaces returns a list of interfaces. func (b *BigIP) Interfaces() (*Interfaces, error) { var interfaces Interfaces @@ -494,15 +526,7 @@ func (b *BigIP) Tunnels() (*Tunnels, error) { // GetTunnel fetches the tunnel by it's name. func (b *BigIP) GetTunnel(name string) (*Tunnel, error) { var tunnel Tunnel - values := []string{} - regex := regexp.MustCompile(`^(\/.+\/)?(.+)`) - match := regex.FindStringSubmatch(name) - if match[1] == "" { - values = append(values, "~Common~") - } - values = append(values, name) - // Join the strings into one. - result := strings.Join(values, "") + result := formatResourceID(name) err, ok := b.getForEntity(&tunnel, uriNet, uriTunnels, uriTunnel, result) if err != nil { return nil, err @@ -533,3 +557,53 @@ func (b *BigIP) DeleteTunnel(name string) error { func (b *BigIP) ModifyTunnel(name string, config *Tunnel) error { return b.put(config, uriNet, uriTunnels, uriTunnel, name) } + +// Vxlans returns a list of vxlan profiles. +func (b *BigIP) Vxlans() ([]Vxlan, error) { + var vxlans Vxlans + err, _ := b.getForEntity(&vxlans, uriNet, uriTunnels, uriVxlan) + if err != nil { + return nil, err + } + + return vxlans.Vxlans, nil +} + +// GetVxlan fetches the vxlan profile by it's name. +func (b *BigIP) GetVxlan(name string) (*Vxlan, error) { + var vxlan Vxlan + result := formatResourceID(name) + err, ok := b.getForEntity(&vxlan, uriNet, uriTunnels, uriVxlan, result) + if err != nil { + return nil, err + } + if !ok { + return nil, nil + } + + return &vxlan, nil +} + +// AddVxlan adds a new vxlan profile to the BIG-IP system. +func (b *BigIP) AddVxlan(config *Vxlan) error { + return b.post(config, uriNet, uriTunnels, uriVxlan) +} + +// CreateVxlan adds a new vxlan profile to the BIG-IP system. +func (b *BigIP) CreateVxlan(name string) error { + config := &Vxlan{ + Name: name, + } + + return b.post(config, uriNet, uriTunnels, uriVxlan) +} + +// DeleteVxlan removes a vxlan profile. +func (b *BigIP) DeleteVxlan(name string) error { + return b.delete(uriNet, uriTunnels, uriVxlan, name) +} + +// ModifyVxlan allows you to change any attribute of a vxlan profile. +func (b *BigIP) ModifyVxlan(name string, config *Vxlan) error { + return b.put(config, uriNet, uriTunnels, uriVxlan, name) +} From f78d2d1c776806f3ddd50bee299f1309e46edce1 Mon Sep 17 00:00:00 2001 From: Mike Pescetto Date: Tue, 16 Apr 2019 22:16:03 -0500 Subject: [PATCH 74/80] Add AddTunnel func --- net.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net.go b/net.go index 629298d..24bcf91 100644 --- a/net.go +++ b/net.go @@ -538,6 +538,11 @@ func (b *BigIP) GetTunnel(name string) (*Tunnel, error) { return &tunnel, nil } +// AddTunnel adds a new tunnel to the BIG-IP system from a config. +func (b *BigIP) AddTunnel(config *Tunnel) error { + return b.post(config, uriNet, uriTunnels, uriTunnel) +} + // CreateTunnel adds a new tunnel to the BIG-IP system. func (b *BigIP) CreateTunnel(name, profile string) error { config := &Tunnel{ From 4adf46dc35ea6b2edb757b23d8da1967fc6d4f4c Mon Sep 17 00:00:00 2001 From: Mike Pescetto Date: Tue, 16 Apr 2019 22:33:25 -0500 Subject: [PATCH 75/80] Add test for AddTunnel func --- net_test.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/net_test.go b/net_test.go index aa6f95c..9fa7f5b 100644 --- a/net_test.go +++ b/net_test.go @@ -494,6 +494,33 @@ func (s *NetTestSuite) TestCreateTunnel() { assertRestCall(s, "POST", "/mgmt/tm/net/tunnels/tunnel", `{"name":"some-foo-tunnel", "profile":"/Common/some-foo-profile"}`) } +func (s *NetTestSuite) TestAddTunnel() { + someTunnel := Tunnel{ + Name: "foo-tunnel", + AppService: "foo-appservice", + AutoLasthop: "foo-lasthop", + Description: "foo-desc", + IdleTimeout: 123, + IfIndex: 456, + Key: 789, + LocalAddress: "foo-local-address", + Mode: "foo-mode", + Mtu: 1440, + Partition: "foo-partition", + Profile: "foo-profile", + RemoteAddress: "foo-remoteaddr", + SecondaryAddress: "foo-secondaddr", + Tos: "foo-tos", + TrafficGroup: "foo-tg", + Transparent: "foo-transparent", + UsePmtu: "foo-pmtu", + } + err := s.Client.AddTunnel(&someTunnel) + + assert.Nil(s.T(), err) + assertRestCall(s, "POST", "/mgmt/tm/net/tunnels/tunnel", `{"appService":"foo-appservice", "autoLasthop":"foo-lasthop", "description":"foo-desc", "idleTimeout":123, "ifIndex":456, "key":789, "localAddress":"foo-local-address", "mode":"foo-mode", "mtu":1440, "name":"foo-tunnel", "partition":"foo-partition", "profile":"foo-profile", "remoteAddress":"foo-remoteaddr", "secondaryAddress":"foo-secondaddr", "tos":"foo-tos", "trafficGroup":"foo-tg", "transparent":"foo-transparent", "usePmtu":"foo-pmtu"}`) +} + func (s *NetTestSuite) TestDeleteTunnel() { err := s.Client.DeleteTunnel("some-foo-tunnel") From 172388c8e9abaa59a7f507c44de416aee0399f4f Mon Sep 17 00:00:00 2001 From: Mike Pescetto Date: Wed, 17 Apr 2019 09:49:05 -0500 Subject: [PATCH 76/80] add a function to format the resource_id to ensure partition is encluded --- net.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/net.go b/net.go index 24bcf91..2f6d3f2 100644 --- a/net.go +++ b/net.go @@ -226,15 +226,16 @@ const ( // formatResourceID takes the resource name to // ensure theres a partition for the Resource ID func formatResourceID(name string) string { - values := []string{} - regex := regexp.MustCompile(`^(\/.+\/)?(.+)`) - match := regex.FindStringSubmatch(name) - if match[1] == "" { - values = append(values, "~Common~") + // If the name specifies the partition already, then + // just hand it back. + regex := regexp.MustCompile(`^~([a-zA-Z0-9-.]+)~`) + if regex.MatchString(name) { + return name } - values = append(values, name) - // Join the strings into one. - return strings.Join(values, "") + + // Otherwise, tack on the Common partition + // for best practices with the resource_id. + return "~Common~" + name } // Interfaces returns a list of interfaces. From e843c237dd74dc8fd96e611412db0d4ae18663a6 Mon Sep 17 00:00:00 2001 From: Mike Pescetto Date: Wed, 17 Apr 2019 09:49:18 -0500 Subject: [PATCH 77/80] Add tests for Vxlan CRUD functions. --- net_test.go | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/net_test.go b/net_test.go index 9fa7f5b..bf9ad8a 100644 --- a/net_test.go +++ b/net_test.go @@ -536,3 +536,123 @@ func (s *NetTestSuite) TestModifyTunnel() { assert.Nil(s.T(), err) assertRestCall(s, "PUT", "/mgmt/tm/net/tunnels/tunnel/some-foo-tunnel", `{"transparent":"enabled"}`) } + +var goodVxlansRespnse = `{ + "items": [ + { + "defaultsFrom": "/Common/vxlan", + "defaultsFromReference": { + "link": "https://localhost/mgmt/tm/net/tunnels/vxlan/~Common~vxlan?ver=13.1.1.2" + }, + "encapsulationType": "vxlan", + "floodingType": "multipoint", + "fullPath": "/Common/vxlan-foo", + "generation": 1, + "kind": "tm:net:tunnels:vxlan:vxlanstate", + "name": "vxlan-foo", + "partition": "foo", + "port": 4789, + "selfLink": "https://localhost/mgmt/tm/net/tunnels/vxlan/~foo~vxlan-foo?ver=13.1.1.2" + }, + { + "defaultsFrom": "/Common/vxlan", + "defaultsFromReference": { + "link": "https://localhost/mgmt/tm/net/tunnels/vxlan/~Common~vxlan?ver=13.1.1.2" + }, + "encapsulationType": "vxlan", + "floodingType": "none", + "fullPath": "/Common/vxlan-bar", + "generation": 1, + "kind": "tm:net:tunnels:vxlan:vxlanstate", + "name": "vxlan-bar", + "partition": "bar", + "port": 4789, + "selfLink": "https://localhost/mgmt/tm/net/tunnels/vxlan/~bar~vxlan-bar?ver=13.1.1.2" + } + ], + "kind": "tm:net:tunnels:vxlan:vxlancollectionstate", + "selfLink": "https://localhost/mgmt/tm/net/tunnels/vxlan?ver=13.1.1.2" +}` + +var goodVxlanRespnse = `{ + "defaultsFrom": "/Common/vxlan", + "defaultsFromReference": { + "link": "https://localhost/mgmt/tm/net/tunnels/vxlan/~Common~vxlan?ver=13.1.1.2" + }, + "encapsulationType": "vxlan", + "floodingType": "multipoint", + "fullPath": "/Common/vxlan-foo", + "generation": 1, + "kind": "tm:net:tunnels:vxlan:vxlanstate", + "name": "vxlan-foo", + "partition": "foo", + "port": 4789, + "selfLink": "https://localhost/mgmt/tm/net/tunnels/vxlan/~foo~vxlan-foo?ver=13.1.1.2" +}` + +func (s *NetTestSuite) TestVxlans() { + s.ResponseFunc = func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(goodVxlansRespnse)) + } + + vxlans, err := s.Client.Vxlans() + + assert.Nil(s.T(), err) + assertRestCall(s, "GET", "/mgmt/tm/net/tunnels/vxlan", "") + assert.Equal(s.T(), 2, len(vxlans)) + assert.Equal(s.T(), "vxlan-foo", vxlans[0].Name) + assert.Equal(s.T(), "vxlan-bar", vxlans[1].Name) +} + +func (s *NetTestSuite) TestGetVxlan() { + s.ResponseFunc = func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(goodVxlanRespnse)) + } + + vxlan, err := s.Client.GetVxlan("~foo~vxlan-foo") + + assert.Nil(s.T(), err) + assertRestCall(s, "GET", "/mgmt/tm/net/tunnels/vxlan/~foo~vxlan-foo", "") + assert.Equal(s.T(), "vxlan-foo", vxlan.Name) + assert.Equal(s.T(), 4789, vxlan.Port) +} + +func (s *NetTestSuite) TestCreateVxlan() { + err := s.Client.CreateVxlan("some-foo-vxlan") + + assert.Nil(s.T(), err) + assertRestCall(s, "POST", "/mgmt/tm/net/tunnels/vxlan", `{"name":"some-foo-vxlan"}`) +} + +func (s *NetTestSuite) TestAddVxlan() { + someVxlan := Vxlan{ + Name: "foo-vxlan", + AppService: "foo-appservice", + Description: "foo-desc", + DefaultsFrom: "foo-base-profile", + EncapsulationType: "foo-encap", + FloodingType: "foo-ft", + Partition: "foo-partition", + Port: 123, + } + err := s.Client.AddVxlan(&someVxlan) + + assert.Nil(s.T(), err) + assertRestCall(s, "POST", "/mgmt/tm/net/tunnels/vxlan", `{"appService":"foo-appservice", "defaultsFrom":"foo-base-profile", "description":"foo-desc", "encapsulationType":"foo-encap", "floodingType":"foo-ft", "name":"foo-vxlan", "partition":"foo-partition", "port":123}`) +} + +func (s *NetTestSuite) TestDeleteVxlan() { + err := s.Client.DeleteVxlan("some-foo-vxlan") + + assert.Nil(s.T(), err) + assertRestCall(s, "DELETE", "/mgmt/tm/net/tunnels/vxlan/some-foo-vxlan", "") +} + +func (s *NetTestSuite) TestModifyVxlan() { + vxlan := &Vxlan{Port: 456} + + err := s.Client.ModifyVxlan("some-foo-vxlan", vxlan) + + assert.Nil(s.T(), err) + assertRestCall(s, "PUT", "/mgmt/tm/net/tunnels/vxlan/some-foo-vxlan", `{"port":456}`) +} From 5b5cd206c143c8fa665c91f95e31e81dc999f06f Mon Sep 17 00:00:00 2001 From: Mike Pescetto Date: Wed, 1 May 2019 14:07:17 -0500 Subject: [PATCH 78/80] Remove the duplicated and incorrect ConfigsyncIP attribute --- device.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/device.go b/device.go index 68f9306..50c2cd0 100644 --- a/device.go +++ b/device.go @@ -57,7 +57,6 @@ type UnicastAddress struct { // Device represents an individual bigip as viewed from the cluster // see: https://devcentral.f5.com/Wiki/iControlREST.APIRef_tm_cm_device.ashx type Device struct { - ConfigsyncIp string `json:"configsyncIp,omitempty"` Name string `json:"name,omitempty"` MirrorIp string `json:"mirrorIp,omitempty"` MirrorSecondaryIp string `json:"mirrorSecondaryIp,omitempty"` @@ -68,8 +67,8 @@ type Device struct { Cert string `json:"cert,omitempty"` ChassisID string `json:"chassisId,omitempty"` ChassisType string `json:"chassisType,omitempty"` + ConfigsyncIp string `json:"configsyncIp,omitempty"` Comment string `json:"comment,omitempty"` - ConfigsyncIP string `json:"configsyncIp,omitempty"` Contact string `json:"contact,omitempty"` Description string `json:"description,omitempty"` Edition string `json:"edition,omitempty"` From 748ca333e85317c6297062f20781ee34e87bb591 Mon Sep 17 00:00:00 2001 From: Sanjay Shitole Date: Fri, 10 May 2019 15:09:45 -0700 Subject: [PATCH 79/80] create changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..0d6bd01 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,10 @@ +## 0.1.1 (Unreleased) + +## 0.1.0 +- Added app.go +- Added vxlan in net.go +- Added net_test.go +- Updated device.go +- Added device_test.go + + From be255699d72f7c36fe537c8f53db52f9b2d1864d Mon Sep 17 00:00:00 2001 From: Sanjay Shitole Date: Fri, 9 Aug 2019 09:51:30 -0700 Subject: [PATCH 80/80] changes to ltm node --- ltm.go | 67 +++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/ltm.go b/ltm.go index eb78ec6..e9184fb 100644 --- a/ltm.go +++ b/ltm.go @@ -141,6 +141,7 @@ type Node struct { Name string `json:"name,omitempty"` Partition string `json:"partition,omitempty"` FullPath string `json:"fullPath,omitempty"` + Description string `json:"description,omitempty"` Generation int `json:"generation,omitempty"` Address string `json:"address,omitempty"` ConnectionLimit int `json:"connectionLimit,omitempty"` @@ -242,6 +243,7 @@ type Pool struct { Name string `json:"name,omitempty"` Partition string `json:"partition,omitempty"` FullPath string `json:"fullPath,omitempty"` + Description string `json:"description,omitempty"` Generation int `json:"generation,omitempty"` AllowNAT string `json:"allowNat,omitempty"` AllowSNAT string `json:"allowSnat,omitempty"` @@ -304,6 +306,7 @@ type poolDTO struct { Name string `json:"name,omitempty"` Partition string `json:"partition,omitempty"` FullPath string `json:"fullPath,omitempty"` + Description string `json:"description,omitempty"` Generation int `json:"generation,omitempty"` AllowNAT string `json:"allowNat,omitempty"` AllowSNAT string `json:"allowSnat,omitempty"` @@ -491,6 +494,7 @@ type VirtualServer struct { Partition string `json:"partition,omitempty"` FullPath string `json:"fullPath,omitempty"` Generation int `json:"generation,omitempty"` + Description string `json:"description,omitempty"` AddressStatus string `json:"addressStatus,omitempty"` AutoLastHop string `json:"autoLastHop,omitempty"` CMPEnabled string `json:"cmpEnabled,omitempty"` @@ -578,12 +582,32 @@ type Policies struct { } type VirtualServerPolicies struct { - PolicyRef Policies `json:"policiesReference"` + PolicyRef []VirtualServerPolicy `json:"items"` } type PolicyPublish struct { + Name string + Command string +} +type PolicyPublishDTO struct { Name string `json:"name"` - PublishCopy string `json:"publishedCopy"` + Command string `json:"command"` +} +func (p *PolicyPublish) MarshalJSON() ([]byte, error) { + return json.Marshal(PolicyPublishDTO{ + Name: p.Name, + Command: p.Command, + }) +} +func (p *PolicyPublish) UnmarshalJSON(b []byte) error { + var dto PolicyPublishDTO + err := json.Unmarshal(b, &dto) + if err != nil { + return err + } + p.Name = dto.Name + p.Command = dto.Command + return nil } type Policy struct { Name string @@ -595,7 +619,6 @@ type Policy struct { Strategy string Rules []PolicyRule } - type policyDTO struct { Name string `json:"name"` PublishCopy string `json:"publishedCopy"` @@ -643,6 +666,17 @@ func (p *Policy) UnmarshalJSON(b []byte) error { return nil } +type VirtualServerPolicy struct { + Name string + Partition string + FullPath string +} +type VirtualServerPolicyDTO struct { + Name string `json:"name"` + Partition string `json:"partition,omitempty"` + FullPath string `json:"fullPath,omitempty"` +} + type PolicyRules struct { Items []PolicyRule `json:"items,omitempty"` } @@ -1903,7 +1937,7 @@ func (b *BigIP) AddNode(config *Node) error { } // CreateNode adds a new IP based node to the BIG-IP system. -func (b *BigIP) CreateNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state string) error { +func (b *BigIP) CreateNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state ,description string) error { config := &Node{ Name: name, Address: address, @@ -1912,13 +1946,14 @@ func (b *BigIP) CreateNode(name, address, rate_limit string, connection_limit, d DynamicRatio: dynamic_ratio, Monitor: monitor, State: state, + Description: description, } return b.post(config, uriLtm, uriNode) } // CreateFQDNNode adds a new FQDN based node to the BIG-IP system. -func (b *BigIP) CreateFQDNNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state, interval, address_family, autopopulate string, downinterval int) error { +func (b *BigIP) CreateFQDNNode(name, address, rate_limit string, connection_limit, dynamic_ratio int, monitor, state, description, interval, address_family, autopopulate string, downinterval int) error { config := &Node{ Name: name, RateLimit: rate_limit, @@ -1926,6 +1961,7 @@ func (b *BigIP) CreateFQDNNode(name, address, rate_limit string, connection_limi DynamicRatio: dynamic_ratio, Monitor: monitor, State: state, + Description: description, } config.FQDN.Name = address config.FQDN.Interval = interval @@ -2275,9 +2311,9 @@ func (b *BigIP) VirtualServerPolicyNames(vs string) ([]string, error) { if err != nil { return nil, err } - retval := make([]string, 0, len(policies.PolicyRef.Policies)) - for _, p := range policies.PolicyRef.Policies { - retval = append(retval, p.FullPath) + retval := make([]string, 0, len(policies.PolicyRef)) + for _, p := range policies.PolicyRef { + retval = append(retval, p.Name) } return retval, nil } @@ -2483,8 +2519,8 @@ func (b *BigIP) GetPolicy(name string) (*Policy, error) { values = append(values, "Drafts/") values = append(values, name) // Join three strings into one. - result := strings.Join(values, "") - err, ok := b.getForEntity(&p, uriLtm, uriPolicy, result) + //result := strings.Join(values, "") + err, ok := b.getForEntity(&p, uriLtm, uriPolicy, name) if err != nil { return nil, err } @@ -2538,8 +2574,9 @@ func (b *BigIP) CreatePolicy(p *Policy) error { } func (b *BigIP) PublishPolicy(name, publish string) error { - config := &Policy{ - PublishCopy: publish, + config := &PolicyPublish{ + Name: publish, + Command: "publish", } values := []string{} values = append(values, "~Common~Drafts~") @@ -2549,7 +2586,7 @@ func (b *BigIP) PublishPolicy(name, publish string) error { log.Println(" ================== here in publish ", result, publish) - return b.patch(config, uriLtm, uriPolicy, result) + return b.post(config, uriLtm, uriPolicy) } //Update an existing policy. @@ -2569,8 +2606,8 @@ func (b *BigIP) DeletePolicy(name string) error { values = append(values, "Drafts/") values = append(values, name) // Join three strings into one. - result := strings.Join(values, "") - return b.delete(uriLtm, uriPolicy, result) + //result := strings.Join(values, "") + return b.delete(uriLtm, uriPolicy, name) } // Oneconnect profile creation