diff --git a/.gitignore b/.gitignore index 485dee6..bbb4ddb 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,24 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib +bin +testbin/* + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Kubernetes Generated files - skip generated files, except for vendored files + +!vendor/**/zz_generated.* + +# editor and IDE paraphernalia .idea +*.swp +*.swo +*~ diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..d6adf95 --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,41 @@ +run: + timeout: 1m +linters: + enable: + - asciicheck + - deadcode + - depguard + - dogsled + - durationcheck + - errcheck + - errorlint + - exportloopref + - gci + - gofmt + - gofumpt + - goimports + - gosec + - gosimple + - govet + - importas + - ineffassign + - megacheck + - misspell + - nakedret + - nolintlint + - revive + - staticcheck + - typecheck + - unconvert + - unused + - varcheck + disable: + # https://github.com/golangci/golangci-lint/issues/2649 + - structcheck +linters-settings: + gosec: + # Exclude generated files + exclude-generated: true + gofmt: + # simplify code: gofmt with `-s` option, true by default + simplify: true \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2e1dadd --- /dev/null +++ b/Makefile @@ -0,0 +1,106 @@ +# VERSION defines the project version for the bundle. +# Update this value when you upgrade the version of your project. +# To re-generate a bundle for another specific version without changing the standard setup, you can: +# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) +# - use environment variables to overwrite this value (e.g export VERSION=0.0.2) +VERSION ?= 0.0.1 + +# CHANNELS define the bundle channels used in the bundle. +# Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable") +# To re-generate a bundle for other specific channels without changing the standard setup, you can: +# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=candidate,fast,stable) +# - use environment variables to overwrite this value (e.g export CHANNELS="candidate,fast,stable") +ifneq ($(origin CHANNELS), undefined) +BUNDLE_CHANNELS := --channels=$(CHANNELS) +endif + +# DEFAULT_CHANNEL defines the default channel used in the bundle. +# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = "stable") +# To re-generate a bundle for any other default channel without changing the default setup, you can: +# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable) +# - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL="stable") +ifneq ($(origin DEFAULT_CHANNEL), undefined) +BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) +endif +BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) + +# IMAGE_TAG_BASE defines the docker.io namespace and part of the image name for remote images. +# This variable is used to construct full image tags for bundle and catalog images. +# +# For example, running 'make bundle-build bundle-push catalog-build catalog-push' will build and push both +# six-group.com/acos-client-go-bundle:$VERSION and six-group.com/acos-client-go-catalog:$VERSION. +IMAGE_TAG_BASE ?= six-group.com/acos-client-go + +# BUNDLE_IMG defines the image:tag used for the bundle. +# You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=/:) +BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION) + +# Image URL to use all building/pushing image targets +IMG ?= controller:latest +# Produce CRDs that work back to Kubernetes 1.11 (no version conversion) +CRD_OPTIONS ?= "crd" + +# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) +ifeq (,$(shell go env GOBIN)) +GOBIN=$(shell go env GOPATH)/bin +else +GOBIN=$(shell go env GOBIN) +endif + +# Setting SHELL to bash allows bash commands to be executed by recipes. +# This is a requirement for 'setup-envtest.sh' in the test target. +# Options are set to exit when a recipe line exits non-zero or a piped command fails. +SHELL = /usr/bin/env bash -o pipefail +.SHELLFLAGS = -ec + +all: build + +##@ General + +# The help target prints out all targets with their descriptions organized +# beneath their categories. The categories are represented by '##@' and the +# target descriptions by '##'. The awk commands is responsible for reading the +# entire set of makefiles included in this invocation, looking for lines of the +# file as xyz: ## something, and then pretty-format the target and help. Then, +# if there's a line with ##@ something, that gets pretty-printed as a category. +# More info on the usage of ANSI control characters for terminal formatting: +# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters +# More info on the awk command: +# http://linuxcommand.org/lc3_adv_awk.php + +help: ## Display this help. + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +##@ Development + +test: golint test-ci +test-ci: unit-test + +golint: colanci-lint-bin ## Run go golangci-lint against code. + $(GOLANGCI_LINT) run --timeout 5m0s + +unit-test: mocks + go test -v ./... --vet=off + +# Generate mocks +mocks: mockgen + $(MOCKGEN) -source utils/http.go -destination pkg/mocks/utils/mock.go HttpClient + +GOLANGCI_LINT = ./bin/golangci-lint +colanci-lint-bin: ## Download golangci-lint locally if necessary. + $(call go-get-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint@v1.46.2) + +MOCKGEN = ./bin/mockgen +mockgen: ## Download mockgen locally if necessary. + $(call go-get-tool,$(MOCKGEN),github.com/golang/mock/mockgen@v1.6.0) + +# go-get-tool will 'go get' any package $2 and install it to $1. +PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) +define go-get-tool +@[ -f $(1) ] || { \ +set -e ;\ +echo "Downloading $(2)" ;\ +GOBIN=$(PROJECT_DIR)/bin go install $(2) ;\ +} +endef + diff --git a/example/main.go b/example/main.go index 63bffb1..d3f91a3 100644 --- a/example/main.go +++ b/example/main.go @@ -1,15 +1,14 @@ package main import ( - "github.com/ureuzy/acos-client-go/pkg/axapi/slb/virtualserver" - "github.com/ureuzy/acos-client-go/pkg/axapi/slb/virtualserverport" "log" + "github.com/ureuzy/acos-client-go/pkg/axapi/slb/virtualserver" + "github.com/ureuzy/acos-client-go/pkg/axapi/slb/virtualserverport" "github.com/ureuzy/acos-client-go/pkg/client" ) func main() { - config := client.Config{Host: "", User: "", Pass: "", Debug: false} c, err := client.New(config, client.InsecureSkipVerify(true)) if err != nil { @@ -20,16 +19,18 @@ func main() { ip := "192.168.0.10" virtualServer, err := c.Slb.VirtualServer.Create(&virtualserver.Body{ - Object: virtualserver.Object{Name: name, IPAddress: ip}}) + Object: virtualserver.Object{Name: name, IPAddress: ip}, + }) if err != nil { log.Fatal(err) } - _, err = c.Slb.VirtualServerPort.CreateList(virtualServer.Name, &virtualserverport.ListBody{ + _, err = c.Slb.VirtualServerPort.CreateList(&virtualserverport.ListBody{ ListObjects: virtualserverport.ListObjects{ virtualserverport.Object{PortNumber: 80, Protocol: "http"}, virtualserverport.Object{PortNumber: 443, Protocol: "https"}, - }}) + }, + }, virtualServer.Name) if err != nil { log.Fatal(err) } diff --git a/go.mod b/go.mod index 23175f1..f2dd12d 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,15 @@ module github.com/ureuzy/acos-client-go -go 1.17 +go 1.18 + +require ( + github.com/golang/mock v1.6.0 + github.com/onsi/gomega v1.20.0 +) + +require ( + github.com/google/go-cmp v0.5.8 // indirect + golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect + golang.org/x/text v0.3.7 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum index e69de29..8ba69bd 100644 --- a/go.sum +++ b/go.sum @@ -0,0 +1,39 @@ +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= +github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q= +github.com/onsi/gomega v1.20.0/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/axapi/activepartition/partition.go b/pkg/axapi/activepartition/partition.go new file mode 100644 index 0000000..025baf5 --- /dev/null +++ b/pkg/axapi/activepartition/partition.go @@ -0,0 +1,40 @@ +package activepartition + +import ( + "github.com/ureuzy/acos-client-go/pkg/axapi/errors" + "github.com/ureuzy/acos-client-go/utils" +) + +// Docs: https://acos.docs.a10networks.com/axapi/521p2/axapiv3/active_partition.html + +type operator struct { + utils.HTTPClient + basePath string +} + +type Operator interface { + Set(object Partition) error +} + +func New(c utils.HTTPClient) Operator { + const path = "active-partition" + return &operator{HTTPClient: c, basePath: path} +} + +func (o *operator) Set(object Partition) error { + err := errors.EmptyStringError(object.CurrentPartitionName) + if err != nil { + return err + } + + res, err := o.POST(o.basePath, object) + if err != nil { + return err + } + + if res.HasError() { + return errors.Handle(res) + } + + return nil +} diff --git a/pkg/axapi/activepartition/types.go b/pkg/axapi/activepartition/types.go new file mode 100644 index 0000000..db516b8 --- /dev/null +++ b/pkg/axapi/activepartition/types.go @@ -0,0 +1,6 @@ +package activepartition + +type Partition struct { + CurrentPartitionName string `json:"curr_part_name"` + Shared bool `json:"shared"` +} diff --git a/pkg/axapi/auth/auth.go b/pkg/axapi/auth/auth.go index 0c379a1..1bbe1bd 100644 --- a/pkg/axapi/auth/auth.go +++ b/pkg/axapi/auth/auth.go @@ -5,27 +5,29 @@ import ( ) type operator struct { - utils.HttpClient + utils.HTTPClient + basePath string } type Operator interface { - Request(req *Request) (*AuthResponse, error) + Request(req *Request) (*Body, error) } -func New(c utils.HttpClient) Operator { - return &operator{c} +func New(c utils.HTTPClient) Operator { + const path = "auth" + return &operator{HTTPClient: c, basePath: path} } -func (o *operator) Request(req *Request) (*AuthResponse, error) { - res, err := o.POST("/auth", req) +func (o *operator) Request(req *Request) (*Body, error) { + res, err := o.POST(o.basePath, req) if err != nil { return nil, err } var response Response - if err = res.UnmarshalJson(&response); err != nil { + if err = res.UnmarshalJSON(&response); err != nil { return nil, err } - return response.AuthResponse, nil + return response.Body, nil } diff --git a/pkg/axapi/auth/types.go b/pkg/axapi/auth/types.go index c79a5c8..0537d4c 100644 --- a/pkg/axapi/auth/types.go +++ b/pkg/axapi/auth/types.go @@ -10,10 +10,10 @@ type Credentials struct { } type Response struct { - *AuthResponse `json:"authresponse"` + *Body `json:"authresponse"` } -type AuthResponse struct { +type Body struct { Signature string `json:"signature"` Description string `json:"description"` } diff --git a/pkg/axapi/errors/errors.go b/pkg/axapi/errors/errors.go index 890a6da..6578822 100644 --- a/pkg/axapi/errors/errors.go +++ b/pkg/axapi/errors/errors.go @@ -39,7 +39,7 @@ func EmptyStringError(s string) error { func Handle(response *utils.Response) error { var errResponse ResponseBody - if err := response.UnmarshalJson(&errResponse); err != nil { + if err := response.UnmarshalJSON(&errResponse); err != nil { return err } return &errResponse diff --git a/pkg/axapi/gslb/gslb.go b/pkg/axapi/gslb/gslb.go new file mode 100644 index 0000000..6819a1a --- /dev/null +++ b/pkg/axapi/gslb/gslb.go @@ -0,0 +1,28 @@ +package gslb + +import ( + "github.com/ureuzy/acos-client-go/pkg/axapi/gslb/policy" + "github.com/ureuzy/acos-client-go/pkg/axapi/gslb/serviceip" + "github.com/ureuzy/acos-client-go/pkg/axapi/gslb/site" + "github.com/ureuzy/acos-client-go/pkg/axapi/gslb/zone" + "github.com/ureuzy/acos-client-go/pkg/rest" + "github.com/ureuzy/acos-client-go/utils" +) + +const path = "gslb" + +type Operator struct { + Policy rest.Operator[policy.Body, policy.ListBody] + ServiceIP rest.Operator[serviceip.Body, serviceip.ListBody] + Site rest.Operator[site.Body, site.ListBody] + Zone rest.Operator[zone.Body, zone.ListBody] +} + +func New(c utils.HTTPClient) *Operator { + return &Operator{ + Policy: policy.New(c, path), + ServiceIP: serviceip.New(c, path), + Site: site.New(c, path), + Zone: zone.New(c, path), + } +} diff --git a/pkg/axapi/gslb/gslb_test.go b/pkg/axapi/gslb/gslb_test.go new file mode 100644 index 0000000..bf1aacd --- /dev/null +++ b/pkg/axapi/gslb/gslb_test.go @@ -0,0 +1,106 @@ +package gslb_test + +import ( + "github.com/ureuzy/acos-client-go/pkg/axapi/gslb" + "io" + "net/http" + "strings" + "testing" + + "github.com/golang/mock/gomock" + . "github.com/onsi/gomega" + mockutils "github.com/ureuzy/acos-client-go/pkg/mocks/utils" + "github.com/ureuzy/acos-client-go/utils" +) + +func TestGetPolicy(t *testing.T) { + RegisterTestingT(t) + + mockCtrl := gomock.NewController(t) + httpc := mockutils.NewMockHTTPClient(mockCtrl) + sut := gslb.New(httpc) + + body := io.NopCloser(strings.NewReader("{}")) + + resp := &utils.Response{ + Response: &http.Response{ + StatusCode: http.StatusOK, + Body: body, + }, + } + + httpc.EXPECT().GET("gslb/policy/mypolicy").Return(resp, nil) + + res, err := sut.Policy.Get("mypolicy") + Ω(err).ShouldNot(HaveOccurred()) + Ω(res).ShouldNot(BeNil()) +} + +func TestGetServiceIP(t *testing.T) { + RegisterTestingT(t) + + mockCtrl := gomock.NewController(t) + httpc := mockutils.NewMockHTTPClient(mockCtrl) + sut := gslb.New(httpc) + + body := io.NopCloser(strings.NewReader("{}")) + + resp := &utils.Response{ + Response: &http.Response{ + StatusCode: http.StatusOK, + Body: body, + }, + } + + httpc.EXPECT().GET("gslb/service-ip/myip").Return(resp, nil) + + res, err := sut.ServiceIP.Get("myip") + Ω(err).ShouldNot(HaveOccurred()) + Ω(res).ShouldNot(BeNil()) +} + +func TestGetSite(t *testing.T) { + RegisterTestingT(t) + + mockCtrl := gomock.NewController(t) + httpc := mockutils.NewMockHTTPClient(mockCtrl) + sut := gslb.New(httpc) + + body := io.NopCloser(strings.NewReader("{}")) + + resp := &utils.Response{ + Response: &http.Response{ + StatusCode: http.StatusOK, + Body: body, + }, + } + + httpc.EXPECT().GET("gslb/site/mysite").Return(resp, nil) + + res, err := sut.Site.Get("mysite") + Ω(err).ShouldNot(HaveOccurred()) + Ω(res).ShouldNot(BeNil()) +} + +func TestGetZone(t *testing.T) { + RegisterTestingT(t) + + mockCtrl := gomock.NewController(t) + httpc := mockutils.NewMockHTTPClient(mockCtrl) + sut := gslb.New(httpc) + + body := io.NopCloser(strings.NewReader("{}")) + + resp := &utils.Response{ + Response: &http.Response{ + StatusCode: http.StatusOK, + Body: body, + }, + } + + httpc.EXPECT().GET("gslb/zone/myzone").Return(resp, nil) + + res, err := sut.Zone.Get("myzone") + Ω(err).ShouldNot(HaveOccurred()) + Ω(res).ShouldNot(BeNil()) +} diff --git a/pkg/axapi/gslb/policy/policy.go b/pkg/axapi/gslb/policy/policy.go new file mode 100644 index 0000000..fb63b00 --- /dev/null +++ b/pkg/axapi/gslb/policy/policy.go @@ -0,0 +1,108 @@ +package policy + +import ( + "fmt" + + "github.com/ureuzy/acos-client-go/pkg/axapi/shared" + "github.com/ureuzy/acos-client-go/pkg/rest" + "github.com/ureuzy/acos-client-go/utils" +) + +// Docs: https://acos.docs.a10networks.com/axapi/521p2/axapiv3/gslb_policy.html + +func New(c utils.HTTPClient, basePath string) rest.Operator[Body, ListBody] { + const path = "policy" + return rest.Rest[Body, ListBody](c, fmt.Sprintf("%s/%s", basePath, path)) +} + +type ListBody struct { + ListObjects `json:"policy-list"` +} + +type Body struct { + Object `json:"policy"` +} + +type ListObjects []Object + +// Object Docs: https://acos.docs.a10networks.com/axapi/521p2/axapiv3/gslb_policy.html#policy-attributes + +type Object struct { + shared.AxaBase `json:",inline"` + Name string `json:"name,omitempty"` + HealthCheck bool `json:"health-check,omitempty"` + HealthCheckPreferenceEnable bool `json:"health-check-preference-enable,omitempty"` + HealthPreferenceTop int `json:"health-preference-top,omitempty"` + AmountFirst bool `json:"amount-first,omitempty"` + WeightedIPEnable bool `json:"weighted-ip-enable,omitempty"` + WeightedIPTotalHits bool `json:"weighted-ip-total-hits,omitempty"` + WeightedSiteEnable bool `json:"weighted-site-enable,omitempty"` + WeightedSiteTotalHits bool `json:"weighted-site-total-hits,omitempty"` + WeightedAlias bool `json:"weighted-alias,omitempty"` + ActiveServersEnable bool `json:"active-servers-enable,omitempty"` + ActiveServersFailBreak bool `json:"active-servers-fail-break,omitempty"` + BwCostEnable bool `json:"bw-cost-enable,omitempty"` + BwCostFailBreak bool `json:"bw-cost-fail-break,omitempty"` + Geographic bool `json:"geographic,omitempty"` + NumSessionEnable bool `json:"num-session-enable,omitempty"` + NumSessionTolerance int `json:"num-session-tolerance,omitempty"` + AdminPreference bool `json:"admin-preference,omitempty"` + AliasAdminPreference bool `json:"alias-admin-preference,omitempty"` + LeastResponse bool `json:"least-response,omitempty"` + AdminIPEnable bool `json:"admin-ip-enable,omitempty"` + AdminIPTopOnly bool `json:"admin-ip-top-only,omitempty"` + OrderedIPTopOnly bool `json:"ordered-ip-top-only,omitempty"` + RoundRobin bool `json:"round-robin,omitempty"` + MetricForceCheck bool `json:"metric-force-check,omitempty"` + IPList string `json:"ip-list,omitempty"` + MetricOrder bool `json:"metric-order,omitempty"` + MetricType bool `json:"metric-type,omitempty"` // "enum":[ "health-check", "weighted-ip", "weighted-site", "capacity", "active-servers", "active-rdt", "geographic", "connection-load", "num-session", "admin-preference", "bw-cost", "least-response", "admin-ip"] + Capacity Capacity `json:"capacity,omitempty"` + ConnectionLoad ConnectionLoad `json:"connection-load,omitempty"` + DNS DNS `json:"dns,omitempty"` + GeoLocationList []GeoLocation `json:"geo-location-list,omitempty"` + GeoLocationMatch GeoLocationMatch `json:"geo-location-match,omitempty"` + ActiveRdt ActiveRdt `json:"active-rdt,omitempty"` + AutoMap AutoMap `json:"auto-map,omitempty"` + EDNS EDNS `json:"edns,omitempty"` +} + +type Capacity struct { + shared.AxaBase `json:",inline"` + // TODO +} + +type ConnectionLoad struct { + shared.AxaBase `json:",inline"` + // TODO +} + +type DNS struct { + shared.AxaBase `json:",inline"` + // TODO +} + +type GeoLocation struct { + shared.AxaBase `json:",inline"` + // TODO +} + +type GeoLocationMatch struct { + shared.AxaBase `json:",inline"` + // TODO +} + +type ActiveRdt struct { + shared.AxaBase `json:",inline"` + // TODO +} + +type AutoMap struct { + shared.AxaBase `json:",inline"` + // TODO +} + +type EDNS struct { + shared.AxaBase `json:",inline"` + // TODO +} diff --git a/pkg/axapi/gslb/serviceip/serviceip.go b/pkg/axapi/gslb/serviceip/serviceip.go new file mode 100644 index 0000000..97208b6 --- /dev/null +++ b/pkg/axapi/gslb/serviceip/serviceip.go @@ -0,0 +1,56 @@ +package serviceip + +import ( + "fmt" + + "github.com/ureuzy/acos-client-go/pkg/axapi/shared" + "github.com/ureuzy/acos-client-go/pkg/rest" + "github.com/ureuzy/acos-client-go/utils" +) + +// Docs: https://acos.docs.a10networks.com/axapi/521p2/axapiv3/gslb_service_ip.html# + +func New(c utils.HTTPClient, basePath string) rest.Operator[Body, ListBody] { + const path = "service-ip" + return rest.Rest[Body, ListBody](c, fmt.Sprintf("%s/%s", basePath, path)) +} + +type ListBody struct { + ListObjects `json:"service-ip-list"` +} + +type Body struct { + Object `json:"service-ip"` +} + +type ListObjects []Object + +// Object Docs: https://acos.docs.a10networks.com/axapi/521p2/axapiv3/gslb_service_ip.html#service-ip-attributes + +type Object struct { + shared.AxaBase `json:",inline"` + NodeName string `json:"node-name,omitempty"` + IPv6Address string `json:"ipv6-address,omitempty"` + IPAddress string `json:"ip-address,omitempty"` + Action string `json:"action,omitempty"` //"enum":["enable", "disable"] + ExternalIP string `json:"external-ip,omitempty"` + IPv6 string `json:"ipv6,omitempty"` + HealthCheck string `json:"health-check,omitempty"` + HealthCheckProtocolDisable bool `json:"health-check-protocol-disable,omitempty"` + HealthCheckDisable bool `json:"health-check-disable,omitempty"` + SamplingEnable []shared.SamplingEnable `json:"sampling-enable,omitempty"` //"enum":["all","hits","recent"] + PortList []Port `json:"port-list,omitempty"` +} + +type Port struct { + shared.AxaBase `json:",inline"` + PortNum int `json:"port-num,omitempty"` + PortProto string `json:"port-proto,omitempty"` + Action string `json:"action,omitempty"` //"enum":["enable", "disable"] + HealthCheck string `json:"health-check,omitempty"` + HealthCheckFollowPort int `json:"health-check-follow-port,omitempty"` + FollowPortProtocol string `json:"follow-port-protocol,omitempty"` + HealthCheckProtocolDisable bool `json:"health-check-protocol-disable,omitempty"` + HealthCheckDisable bool `json:"health-check-disable,omitempty"` + SamplingEnable []shared.SamplingEnable `json:"sampling-enable,omitempty"` //"enum":["all","active","current"] +} diff --git a/pkg/axapi/gslb/site/site.go b/pkg/axapi/gslb/site/site.go new file mode 100644 index 0000000..0629227 --- /dev/null +++ b/pkg/axapi/gslb/site/site.go @@ -0,0 +1,67 @@ +package site + +import ( + "fmt" + + "github.com/ureuzy/acos-client-go/pkg/axapi/shared" + "github.com/ureuzy/acos-client-go/pkg/rest" + "github.com/ureuzy/acos-client-go/utils" +) + +// Docs: https://acos.docs.a10networks.com/axapi/521p2/axapiv3/gslb_site.html + +func New(c utils.HTTPClient, basePath string) rest.Operator[Body, ListBody] { + const path = "site" + return rest.Rest[Body, ListBody](c, fmt.Sprintf("%s/%s", basePath, path)) +} + +type ListBody struct { + ListObjects `json:"site-list"` +} + +type Body struct { + Object `json:"site"` +} + +type ListObjects []Object + +// Object Docs: https://acos.docs.a10networks.com/axapi/521p2/axapiv3/gslb_site.html#site-attributes +type Object struct { + shared.AxaBase `json:",inline"` + SiteName string `json:"site-name,omitempty"` + AutoMap bool `json:"auto-map,omitempty"` + Disable bool `json:"disable,omitempty"` + Weight int `json:"weight,omitempty"` + MultipleGeoLocations []string `json:"multiple-geo-locations,omitempty"` + Template string `json:"template,omitempty"` + BwCost int `json:"bw-cost,omitempty"` + Limit int `json:"limit,omitempty"` + Threshold int `json:"threshold,omitempty"` + ProtoAgingTime int `json:"proto-aging-time,omitempty"` + ProtoAgingFast bool `json:"proto-aging-fast,omitempty"` + Controller string `json:"controller,omitempty"` + IPServerList []IPServer `json:"ip-server-list,omitempty"` + ActiveRdt ActiveRdt `json:"active-rdt,omitempty"` + EasyRdt EasyRdt `json:"easy-rdt,omitempty"` + SlbDevList []SlbDevList `json:"slb-dev-list,omitempty"` +} + +type IPServer struct { + shared.AxaBase `json:",inline"` + IPServerName string `json:"ip-server-name,omitempty"` +} + +type ActiveRdt struct { + shared.AxaBase `json:",inline"` + // TODO +} + +type EasyRdt struct { + shared.AxaBase `json:",inline"` + // TODO +} + +type SlbDevList struct { + shared.AxaBase `json:",inline"` + // TODO +} diff --git a/pkg/axapi/gslb/zone/zone.go b/pkg/axapi/gslb/zone/zone.go new file mode 100644 index 0000000..7e5def5 --- /dev/null +++ b/pkg/axapi/gslb/zone/zone.go @@ -0,0 +1,155 @@ +package zone + +import ( + "fmt" + + "github.com/ureuzy/acos-client-go/pkg/axapi/shared" + "github.com/ureuzy/acos-client-go/pkg/rest" + "github.com/ureuzy/acos-client-go/utils" +) + +// Docs: https://acos.docs.a10networks.com/axapi/521p2/axapiv3/gslb_zone.html + +func New(c utils.HTTPClient, basePath string) rest.Operator[Body, ListBody] { + const path = "zone" + return rest.Rest[Body, ListBody](c, fmt.Sprintf("%s/%s", basePath, path)) +} + +type ListBody struct { + ListObjects `json:"zone-list"` +} + +type Body struct { + Object `json:"zone"` +} + +type ListObjects []Object + +// Object Docs: https://acos.docs.a10networks.com/axapi/521p2/axapiv3/gslb_zone.html#zone-attributes +type Object struct { + shared.AxaBase `json:",inline"` + Name string `json:"name,omitempty"` + Disable bool `json:"disable,omitempty"` + Policy bool `json:"policy,omitempty"` + Template Template `json:"template,omitempty"` + TTL int `json:"ttl,omitempty"` + UseServerTTL bool `json:"use-server-ttl,omitempty"` + DNSSOARecord DNSSOARecord `json:"dns-soa-record,omitempty"` +} + +type Template struct { + DNSSec string `json:"dnssec,omitempty"` +} + +type DNSSOARecord struct { + SOAName string `json:"soa-name,omitempty"` + Mail string `json:"mail,omitempty"` + Expire int `json:"expire,omitempty"` + Refresh int `json:"refresh,omitempty"` + Retry int `json:"retry,omitempty"` + Serial int `json:"serial,omitempty"` + SOATTL int `json:"soa-ttl,omitempty"` + External string `json:"external,omitempty"` + ExMail string `json:"ex-mail,omitempty"` + ExEpire int `json:"ex-expire,omitempty"` + ExRefresh int `json:"ex-refresh,omitempty"` + ExRetry int `json:"ex-retry,omitempty"` + ExSerial int `json:"ex-serial,omitempty"` + ExSoaTTL int `json:"ex-soa-ttl,omitempty"` + SamplingEnable []shared.SamplingEnable `json:"sampling-enable,omitempty"` //"enum":[ "all", "received-query", "sent-response", "proxy-mode-response", "cache-mode-response", "server-mode-response", "sticky-mode-response", "backup-mode-response"] + DNSMXRecordList []DNSMXRecord `json:"dns-mx-record-list,omitempty"` + DNSNSRecordList []DNSNSRecord `json:"dns-ns-record-list,omitempty"` + ServiceList []Service `json:"service-list,omitempty"` +} + +type Service struct { + shared.AxaBase `json:",inline"` + ServicePort int `json:"service-port,omitempty"` + ServiceName string `json:"service-name,omitempty"` + Action string `json:"action,omitempty"` // "enum":[ "drop", "forward", "ignore", "reject"] + ForwardType string `json:"forward-type,omitempty"` // "enum":[ "both", "query", "response"] + Disable bool `json:"disable,omitempty"` + HealthCheckGateway string `json:"health-check-gateway,omitempty"` //"enum":[ "enable", "disable"] + HealthCheckPort []HealthCheckPort `json:"health-check-port,omitempty"` + Policy string `json:"policy,omitempty"` + SamplingEnable []shared.SamplingEnable `json:"sampling-enable,omitempty"` // "enum":[ "all", "received-query", "sent-response", "proxy-mode-response", "cache-mode-response", "server-mode-response", "sticky-mode-response", "backup-mode-response"] + DNSARecord DNSARecord `json:"dns-a-record,omitempty"` + DNSCNAMERecordList []DNSCnameRecord `json:"dns-cname-record-list,omitempty"` + DNSMXRecordList []DNSMXRecord `json:"dns-mx-record-list,omitempty"` + DNSNSRecordList []DNSMXRecord `json:"dns-ns-record-list,omitempty"` + DNSPtrRecordList []TodoRecord `json:"dns-ptr-record-list,omitempty"` + DNSSrvRecordList []TodoRecord `json:"dns-srv-record-list,omitempty"` + DNSNaptrRecordList []TodoRecord `json:"dns-naptr-record-list,omitempty"` + DNSTxtRecordList []TodoRecord `json:"dns-txt-record-list,omitempty"` + DNSRecordList []TodoRecord `json:"dns-record-list,omitempty"` + GeoLocationList []TodoRecord `json:"geo-location-list,omitempty"` +} + +type DNSMXRecord struct { + shared.AxaBase `json:",inline"` +} + +type DNSNSRecord struct { + shared.AxaBase `json:",inline"` +} + +type TodoRecord struct { + // TODO +} + +type HealthCheckPort struct { + HealthCheckPort int `json:"health-check-port,omitempty"` +} + +type DNSARecord struct { + DNSARecordSrvList []DNSARecordSrv `json:"dns-a-record-srv-list,omitempty"` + DNSARecordIPv4List []DNSARecordIPv4 `json:"dns-a-record-ipv4-list,omitempty"` + DNSARecordIPv6List []DNSARecordIPv6 `json:"dns-a-record-ipv6-list,omitempty"` +} + +type DNSCnameRecord struct { + AliasName string `json:"alias-name,omitempty"` + AdminPreference bool `json:"admin-preference,omitempty"` + Weight int `json:"weight,omitempty"` + AsBackup bool `json:"as-backup,omitempty"` + SamplingEnable []shared.SamplingEnable `json:"sampling-enable,omitempty"` // "enum":[ "all", "cname-hits"] +} + +type DNSARecordSrv struct { + shared.AxaBase + SvrName string `json:"svrname,omitempty"` + NoResp bool `json:"no-resp,omitempty"` + AsBackup bool `json:"as-backup,omitempty"` + Weight int `json:"weight,omitempty"` + TTL int `json:"ttl,omitempty"` + AsReplace bool `json:"as-replace,omitempty"` + Disable bool `json:"disable,omitempty"` + Static bool `json:"static,omitempty"` + AdminIP int `json:"admin-ip,omitempty"` +} + +type DNSARecordIPv4 struct { + shared.AxaBase + DNSARecordIP string `json:"dns-a-record-ip,omitempty"` + NoResp bool `json:"no-resp,omitempty"` + AsBackup bool `json:"as-backup,omitempty"` + Weight int `json:"weight,omitempty"` + TTL int `json:"ttl,omitempty"` + AsReplace bool `json:"as-replace,omitempty"` + Disable bool `json:"disable,omitempty"` + Static bool `json:"static,omitempty"` + AdminIP int `json:"admin-ip,omitempty"` +} + +type DNSARecordIPv6 struct { + shared.AxaBase + DNSARecordIP string `json:"dns-a-record-ipv6,omitempty"` + NoResp bool `json:"no-resp,omitempty"` + AsBackup bool `json:"as-backup,omitempty"` + Weight int `json:"weight,omitempty"` + TTL int `json:"ttl,omitempty"` + AsReplace bool `json:"as-replace,omitempty"` + Disable bool `json:"disable,omitempty"` + Static bool `json:"static,omitempty"` + AdminIP int `json:"admin-ip,omitempty"` +} diff --git a/pkg/axapi/health/health.go b/pkg/axapi/health/health.go new file mode 100644 index 0000000..ee9be02 --- /dev/null +++ b/pkg/axapi/health/health.go @@ -0,0 +1,19 @@ +package health + +import ( + "github.com/ureuzy/acos-client-go/pkg/axapi/health/monitor" + "github.com/ureuzy/acos-client-go/pkg/rest" + "github.com/ureuzy/acos-client-go/utils" +) + +const path = "health" + +type Operator struct { + Montitor rest.Operator[monitor.Body, monitor.ListBody] +} + +func New(c utils.HTTPClient) *Operator { + return &Operator{ + Montitor: monitor.New(c, path), + } +} diff --git a/pkg/axapi/health/health_test.go b/pkg/axapi/health/health_test.go new file mode 100644 index 0000000..f6fbff8 --- /dev/null +++ b/pkg/axapi/health/health_test.go @@ -0,0 +1,38 @@ +package health_test + +import ( + "io" + "net/http" + "strings" + "testing" + + "github.com/golang/mock/gomock" + . "github.com/onsi/gomega" + "github.com/ureuzy/acos-client-go/pkg/axapi/health" + mockutils "github.com/ureuzy/acos-client-go/pkg/mocks/utils" + "github.com/ureuzy/acos-client-go/utils" +) + +func TestGetMonitor(t *testing.T) { + RegisterTestingT(t) + + mockCtrl := gomock.NewController(t) + httpc := mockutils.NewMockHTTPClient(mockCtrl) + sut := health.New(httpc) + + body := io.NopCloser(strings.NewReader("{}")) + + resp := &utils.Response{ + Response: &http.Response{ + StatusCode: http.StatusOK, + Body: body, + }, + } + + httpc.EXPECT().GET("health/monitor/resource1").Return(resp, nil) + + res, err := sut.Montitor.Get("resource1") + Ω(err).ShouldNot(HaveOccurred()) + Ω(res).ShouldNot(BeNil()) + +} diff --git a/pkg/axapi/health/monitor/monitor.go b/pkg/axapi/health/monitor/monitor.go new file mode 100644 index 0000000..f41c677 --- /dev/null +++ b/pkg/axapi/health/monitor/monitor.go @@ -0,0 +1,143 @@ +package monitor + +import ( + "fmt" + + "github.com/ureuzy/acos-client-go/pkg/axapi/shared" + "github.com/ureuzy/acos-client-go/pkg/rest" + "github.com/ureuzy/acos-client-go/utils" +) + +// Docs: https://acos.docs.a10networks.com/axapi/521p2/axapiv3/health_monitor.html + +func New(c utils.HTTPClient, basePath string) rest.Operator[Body, ListBody] { + const path = "monitor" + return rest.Rest[Body, ListBody](c, fmt.Sprintf("%s/%s", basePath, path)) +} + +type ListBody struct { + ListObjects `json:"monitor-list,omitempty"` +} + +type Body struct { + Object `json:"monitor,omitempty"` +} + +type ListObjects []Object + +type Object struct { + shared.AxaBase `json:",inline"` + Name string `json:"name,omitempty"` + DsrL2Strict bool `json:"dsr-l2-strict,omitempty"` + Retry int `json:"retry,omitempty"` + UpRetry int `json:"up-retry,omitempty"` + OverrideIPv4 string `json:"override-ipv4,omitempty"` + OverrideIPv6 string `json:"override-ipv6,omitempty"` + OverridePort int `json:"override-port,omitempty"` + Passive bool `json:"passive,omitempty"` + StatusCode string `json:"status-code,omitempty"` //"enum":["status-code-2xx","status-code-non-5xx"] + PassiveInterval int `json:"passive-interval,omitempty"` + SampleThreshold int `json:"sample-threshold,omitempty"` + Threshold int `json:"threshold,omitempty"` + StrictRetryOnServerErrResp bool `json:"strict-retry-on-server-err-resp,omitempty"` + DisableAfterDown bool `json:"disable-after-down,omitempty"` + Interval int `json:"interval,omitempty"` + Timeout int `json:"timeout,omitempty"` + SslCiphers int `json:"ssl-ciphers,omitempty"` + SslTicket bool `json:"ssl-ticket,omitempty"` + SslTicketLifetime int `json:"ssl-ticket-lifetime,omitempty"` + SslVersion int `json:"ssl-version,omitempty"` + SslDgVersion int `json:"ssl-dgversion,omitempty"` + Method struct { + TCP TCP `json:"tcp,omitempty"` + HTTP HTTP `json:"http,omitempty"` + HTTPS HTTPS `json:"https,omitempty"` + } `json:"method,omitempty"` + A10URL string `json:"a10-url,omitempty"` +} + +type HTTPMethod string + +type HTTP struct { + shared.AxaBase `json:",inline"` + HTTP bool `json:"http,omitempty"` + HTTPPort int `json:"http-port,omitempty"` + HTTPExpect bool `json:"http-expect,omitempty"` + HTTPResponseCode string `json:"http-response-code,omitempty"` + HTTPResponseCodeRegex string `json:"response-code-regex,omitempty"` + HTTPText string `json:"http-text,omitempty"` + TextRegex string `json:"text-regex,omitempty"` + HTTPHost string `json:"http-host,omitempty"` + HTTPMaintenanceCode string `json:"http-maintenance-code,omitempty"` + HTTPURL string `json:"http-url,omitempty"` + URLType HTTPMethod `json:"url-type,omitempty"` + Maintenance bool `json:"maintenance,omitempty"` + MaintenanceText string `json:"maintenance-text,omitempty"` + MaintenanceTextRegex string `json:"maintenance-text-regex,omitempty"` + URLPath string `json:"url-path,omitempty"` + PostPath string `json:"post-path,omitempty"` + PostType string `json:"post-type,omitempty"` + HTTPPostData string `json:"http-postdata,omitempty"` + HTTPPostfile string `json:"http-postfile,omitempty"` + HTTPUsername string `json:"http-username,omitempty"` + HTTPPassword string `json:"http-password,omitempty"` + HTTPPasswordString string `json:"http-password-string,omitempty"` + HTTPKerberosAuth bool `json:"http-kerberos-auth,omitempty"` + HTTPKerberosRealm string `json:"http-kerberos-realm,omitempty"` + HTTPKerberosKdc KerberosKdc `json:"http-kerberos-kdc,omitempty"` +} + +type HTTPS struct { + shared.AxaBase `json:",inline"` + HTTP bool `json:"https,omitempty"` + WebPort int `json:"web-port,omitempty"` + DisableSslV2Hello bool `json:"disable-sslv2hello,omitempty"` + HTTPSHost string `json:"https-host,omitempty"` + Sni bool `json:"sni,omitempty"` + HTTPSExpect bool `json:"https-expect,omitempty"` + HTTPSResponseCode string `json:"https-response-code,omitempty"` + HTTPSResponseCodeRegex string `json:"response-code-regex,omitempty"` + HTTPSText string `json:"https-text,omitempty"` + TextRegex string `json:"text-regex,omitempty"` + HTTPSURL string `json:"https-url,omitempty"` + URLType HTTPMethod `json:"url-type,omitempty"` + URLPath string `json:"url-path,omitempty"` + PostPath string `json:"post-path,omitempty"` + PostType string `json:"post-type,omitempty"` + HTTPSPostData string `json:"https-postdata,omitempty"` + HTTPSPostfile string `json:"https-postfile,omitempty"` + HTTPSMaintenanceCode string `json:"https-maintenance-code,omitempty"` + Maintenance bool `json:"maintenance,omitempty"` + MaintenanceText string `json:"maintenance-text,omitempty"` + MaintenanceTextRegex string `json:"maintenance-text-regex,omitempty"` + HTTPSUsername string `json:"https-username,omitempty"` + HTTPSServerCertName string `json:"https-server-cert-name,omitempty"` + HTTPSPassword string `json:"https-password,omitempty"` + HTTPSPasswordString string `json:"https-password-string,omitempty"` + HTTPSKerberosAuth bool `json:"https-kerberos-auth,omitempty"` + HTTPSKerberosRealm string `json:"https-kerberos-realm,omitempty"` + HTTPSKerberosKdc KerberosKdc `json:"https-kerberos-kdc,omitempty"` + CertKeyShared bool `json:"cert-key-shared,omitempty"` + Cert string `json:"cert,omitempty"` + Key string `json:"key,omitempty"` + KeyPassPhrase string `json:"key-pass-phrase,omitempty"` + KeyPhrase string `json:"key-phrase,omitempty"` +} + +type TCP struct { + shared.AxaBase `json:",inline"` + MethodTCP bool `json:"method-tcp,omitempty"` + TCPPort int `json:"tcp-port,omitempty"` + PortHalfopen bool `json:"port-halfopen,omitempty"` + PortSend string `json:"port-send,omitempty"` + PortResp string `json:"port-resp,omitempty"` + Maintenance bool `json:"maintenance,omitempty"` + MaintenanceText string `json:"maintenance-text,omitempty"` +} + +type KerberosKdc struct { + HTTPKerberosHostIP string `json:"http-kerberos-hostip,omitempty"` + HTTPKerberosHostIPV6 string `json:"http-kerberos-hostipv6,omitempty"` + HTTPKerberosPort int `json:"http-kerberos-port,omitempty"` + HTTPKerberosPortV6 int `json:"http-kerberos-portv6,omitempty"` +} diff --git a/pkg/axapi/shared/types.go b/pkg/axapi/shared/types.go new file mode 100644 index 0000000..bcec7d2 --- /dev/null +++ b/pkg/axapi/shared/types.go @@ -0,0 +1,10 @@ +package shared + +type AxaBase struct { + UUID string `json:"uuid,omitempty"` + UserTag string `json:"user-tag,omitempty"` +} + +type SamplingEnable struct { + Counters1 string `json:"counters1,omitempty"` +} diff --git a/pkg/axapi/slb/server/server.go b/pkg/axapi/slb/server/server.go index 5cfcaa4..106825d 100644 --- a/pkg/axapi/slb/server/server.go +++ b/pkg/axapi/slb/server/server.go @@ -3,129 +3,89 @@ package server import ( "fmt" - "github.com/ureuzy/acos-client-go/pkg/axapi/errors" + "github.com/ureuzy/acos-client-go/pkg/axapi/shared" + "github.com/ureuzy/acos-client-go/pkg/rest" "github.com/ureuzy/acos-client-go/utils" ) // Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_server.html#server-specification -type operator struct { - utils.HttpClient +func New(c utils.HTTPClient, basePath string) rest.Operator[Body, ListBody] { + const path = "server" + return rest.Rest[Body, ListBody](c, fmt.Sprintf("%s/%s", basePath, path)) } -type Operator interface { - List() (*ListObjects, error) - Get(name string) (*Object, error) - Create(object *Body) (*Object, error) - Modify(name string, object *Body) (*Object, error) - Delete(name string) error +type ListBody struct { + ListObjects `json:"server-list"` } -func New(c utils.HttpClient) Operator { - return &operator{c} +type Body struct { + Object `json:"server"` } -func (o *operator) List() (*ListObjects, error) { - res, err := o.GET("slb/server") - if err != nil { - return nil, err - } - - if res.HasError() { - return nil, errors.Handle(res) - } - - var response ListBody - if err = res.UnmarshalJson(&response); err != nil { - return nil, err - } - - return &response.ListObjects, nil +// Object Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_server.html#server-attributes +type Object struct { + shared.AxaBase `json:",inline"` + Action string `json:"action,omitempty"` + AlternateServer *AlternateServer `json:"alternate-server,omitempty"` + ConnLimit int `json:"conn-limit,omitempty"` + ConnResume int `json:"conn-resume,omitempty"` + ExtendedStats int `json:"extended-stats,omitempty"` + ExternalIP string `json:"external-ip,omitempty"` + FqdnName string `json:"fqdn-name,omitempty"` + HealthCheck string `json:"health-check,omitempty"` + HealthCheckDisable int `json:"health-check-disable,omitempty"` + Host string `json:"host,omitempty"` + IPv6 string `json:"ipv6,omitempty"` + Name string `json:"name,omitempty"` + NoLogging int `json:"no-logging,omitempty"` + PortList *PortList `json:"port-list,omitempty"` + SamplingEnable *shared.SamplingEnable `json:"sampling-enable,omitempty"` + ServerIPv6Addr string `json:"server-ipv6-addr,omitempty"` + SlowStart int `json:"slow-start,omitempty"` + SpoofingCache int `json:"spoofing-cache,omitempty"` + StatsDataAction string `json:"stats-data-action,omitempty"` + TemplateServer string `json:"template-server,omitempty"` + Weight int `json:"weight,omitempty"` } +type ListObjects []Object -func (o *operator) Get(name string) (*Object, error) { - err := errors.EmptyStringError(name) - if err != nil { - return nil, err - } - - res, err := o.GET(fmt.Sprintf("slb/server/%s", name)) - if err != nil { - return nil, err - } - - if res.HasError() { - return nil, errors.Handle(res) - } - - var response Body - if err = res.UnmarshalJson(&response); err != nil { - return nil, err - } - - return &response.Object, nil +// AlternateServer Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_server.html#alternate-server +type AlternateServer struct { + Alternate int `json:"alternate,omitempty"` + AlternateName string `json:"alternate-name,omitempty"` } - -func (o *operator) Create(object *Body) (*Object, error) { - err := errors.EmptyStringError(object.Name) - if err != nil { - return nil, err - } - - res, err := o.POST("slb/server", object) - if err != nil { - return nil, err - } - - if res.HasError() { - return nil, errors.Handle(res) - } - - var response Body - if err = res.UnmarshalJson(&response); err != nil { - return nil, err - } - - return &response.Object, nil -} - -func (o *operator) Modify(name string, object *Body) (*Object, error) { - err := errors.EmptyStringError(name) - if err != nil { - return nil, err - } - - res, err := o.POST(fmt.Sprintf("slb/server/%s", name), object) - if err != nil { - return nil, err - } - - if res.HasError() { - return nil, errors.Handle(res) - } - - var response Body - if err = res.UnmarshalJson(&response); err != nil { - return nil, err - } - - return &response.Object, nil +type AlternateServerList []AlternateServer + +// Port Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_server.html#port-list +type Port struct { + shared.AxaBase `json:",inline"` + Action string `json:"action,omitempty"` + AlternatePort []string `json:"alternate-port,omitempty"` + AuthCfg *AuthCfg `json:"auth-cfg,omitempty"` + ConnLimit int `json:"conn-limit,omitempty"` + ConnResume int `json:"conn-resume,omitempty"` + ExtendedStats int `json:"extended-stats,omitempty"` + FollowPortProtocol string `json:"follow-port-protocol,omitempty"` + HealthCheck string `json:"health-check,omitempty"` + HealthCheckDisable int `json:"health-check-disable,omitempty"` + HealthCheckFollowPort int `json:"health-check-follow-port,omitempty"` + NoLogging int `json:"no-logging,omitempty"` + NoSSL int `json:"no-ssl,omitempty"` + PortNumber int `json:"port-number,omitempty"` + Protocol string `json:"protocol,omitempty"` + Range int `json:"range,omitempty"` + SamplingEnable *shared.SamplingEnable `json:"sampling-enable,omitempty"` + ServerIPv6Addr string `json:"server-ipv6-addr,omitempty"` + SlowStart int `json:"slow-start,omitempty"` + SpoofingCache int `json:"spoofing-cache,omitempty"` + StatsDataAction string `json:"stats-data-action,omitempty"` + TemplateServer string `json:"template-server,omitempty"` + Weight int `json:"weight,omitempty"` } +type PortList []Port -func (o *operator) Delete(name string) error { - err := errors.EmptyStringError(name) - if err != nil { - return err - } - - res, err := o.DELETE(fmt.Sprintf("slb/server/%s", name)) - if err != nil { - return err - } - - if res.HasError() { - return errors.Handle(res) - } - - return nil +// AuthCfg Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_server.html#port-list-auth-cfg +type AuthCfg struct { + ServicePrincipalName string `json:"service-principal-name,omitempty"` } diff --git a/pkg/axapi/slb/server/types.go b/pkg/axapi/slb/server/types.go deleted file mode 100644 index c6a9751..0000000 --- a/pkg/axapi/slb/server/types.go +++ /dev/null @@ -1,83 +0,0 @@ -package server - -type ListBody struct { - ListObjects `json:"server-list"` -} - -type Body struct { - Object `json:"server"` -} - -// Object Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_server.html#server-attributes -type Object struct { - Action string `json:"action,omitempty"` - AlternateServer *AlternateServer `json:"alternate-server,omitempty"` - ConnLimit int `json:"conn-limit,omitempty"` - ConnResume int `json:"conn-resume,omitempty"` - ExtendedStats int `json:"extended-stats,omitempty"` - ExternalIP string `json:"external-ip,omitempty"` - FqdnName string `json:"fqdn-name,omitempty"` - HealthCheck string `json:"health-check,omitempty"` - HealthCheckDisable int `json:"health-check-disable,omitempty"` - Host string `json:"host,omitempty"` - IPv6 string `json:"ipv6,omitempty"` - Name string `json:"name,omitempty"` - NoLogging int `json:"no-logging,omitempty"` - PortList *PortList `json:"port-list,omitempty"` - SamplingEnable *SamplingEnable `json:"sampling-enable,omitempty"` - ServerIPv6Addr string `json:"server-ipv6-addr,omitempty"` - SlowStart int `json:"slow-start,omitempty"` - SpoofingCache int `json:"spoofing-cache,omitempty"` - StatsDataAction string `json:"stats-data-action,omitempty"` - TemplateServer string `json:"template-server,omitempty"` - UserTag string `json:"user-tag,omitempty"` - UUID string `json:"uuid,omitempty"` - Weight int `json:"weight,omitempty"` -} -type ListObjects []Object - -// AlternateServer Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_server.html#alternate-server -type AlternateServer struct { - Alternate int `json:"alternate,omitempty"` - AlternateName string `json:"alternate-name,omitempty"` -} -type AlternateServerList []AlternateServer - -// Port Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_server.html#port-list -type Port struct { - Action string `json:"action,omitempty"` - AlternatePort []string `json:"alternate-port,omitempty"` - AuthCfg *AuthCfg `json:"auth-cfg,omitempty"` - ConnLimit int `json:"conn-limit,omitempty"` - ConnResume int `json:"conn-resume,omitempty"` - ExtendedStats int `json:"extended-stats,omitempty"` - FollowPortProtocol string `json:"follow-port-protocol,omitempty"` - HealthCheck string `json:"health-check,omitempty"` - HealthCheckDisable int `json:"health-check-disable,omitempty"` - HealthCheckFollowPort int `json:"health-check-follow-port,omitempty"` - NoLogging int `json:"no-logging,omitempty"` - NoSSL int `json:"no-ssl,omitempty"` - PortNumber int `json:"port-number,omitempty"` - Protocol string `json:"protocol,omitempty"` - Range int `json:"range,omitempty"` - SamplingEnable *SamplingEnable `json:"sampling-enable,omitempty"` - ServerIPv6Addr string `json:"server-ipv6-addr,omitempty"` - SlowStart int `json:"slow-start,omitempty"` - SpoofingCache int `json:"spoofing-cache,omitempty"` - StatsDataAction string `json:"stats-data-action,omitempty"` - TemplateServer string `json:"template-server,omitempty"` - UserTag string `json:"user-tag,omitempty"` - UUID string `json:"uuid,omitempty"` - Weight int `json:"weight,omitempty"` -} -type PortList []Port - -// AuthCfg Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_server.html#port-list-auth-cfg -type AuthCfg struct { - ServicePrincipalName string `json:"service-principal-name,omitempty"` -} - -// SamplingEnable Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_server.html#sampling-enable -type SamplingEnable []struct { - Counters1 string `json:"counters1,omitempty"` -} diff --git a/pkg/axapi/slb/slb.go b/pkg/axapi/slb/slb.go index ab801f6..f949f52 100644 --- a/pkg/axapi/slb/slb.go +++ b/pkg/axapi/slb/slb.go @@ -4,19 +4,22 @@ import ( "github.com/ureuzy/acos-client-go/pkg/axapi/slb/server" "github.com/ureuzy/acos-client-go/pkg/axapi/slb/virtualserver" "github.com/ureuzy/acos-client-go/pkg/axapi/slb/virtualserverport" + "github.com/ureuzy/acos-client-go/pkg/rest" "github.com/ureuzy/acos-client-go/utils" ) +const path = "slb" + type Operator struct { - Server server.Operator - VirtualServer virtualserver.Operator - VirtualServerPort virtualserverport.Operator + Server rest.Operator[server.Body, server.ListBody] + VirtualServer rest.Operator[virtualserver.Body, virtualserver.ListBody] + VirtualServerPort rest.Operator[virtualserverport.Body, virtualserverport.ListBody] } -func New(c utils.HttpClient) *Operator { +func New(c utils.HTTPClient) *Operator { return &Operator{ - server.New(c), - virtualserver.New(c), - virtualserverport.New(c), + Server: server.New(c, path), + VirtualServer: virtualserver.New(c, path), + VirtualServerPort: virtualserverport.New(c, path), } } diff --git a/pkg/axapi/slb/slb_test.go b/pkg/axapi/slb/slb_test.go new file mode 100644 index 0000000..eb1dc81 --- /dev/null +++ b/pkg/axapi/slb/slb_test.go @@ -0,0 +1,83 @@ +package slb_test + +import ( + "github.com/ureuzy/acos-client-go/pkg/axapi/slb" + "io" + "net/http" + "strings" + "testing" + + "github.com/golang/mock/gomock" + . "github.com/onsi/gomega" + mockutils "github.com/ureuzy/acos-client-go/pkg/mocks/utils" + "github.com/ureuzy/acos-client-go/utils" +) + +func TestGetServer(t *testing.T) { + RegisterTestingT(t) + + mockCtrl := gomock.NewController(t) + httpc := mockutils.NewMockHTTPClient(mockCtrl) + sut := slb.New(httpc) + + body := io.NopCloser(strings.NewReader("{}")) + + resp := &utils.Response{ + Response: &http.Response{ + StatusCode: http.StatusOK, + Body: body, + }, + } + + httpc.EXPECT().GET("slb/server/myserver").Return(resp, nil) + + res, err := sut.Server.Get("myserver") + Ω(err).ShouldNot(HaveOccurred()) + Ω(res).ShouldNot(BeNil()) +} + +func TestGetVirtualServer(t *testing.T) { + RegisterTestingT(t) + + mockCtrl := gomock.NewController(t) + httpc := mockutils.NewMockHTTPClient(mockCtrl) + sut := slb.New(httpc) + + body := io.NopCloser(strings.NewReader("{}")) + + resp := &utils.Response{ + Response: &http.Response{ + StatusCode: http.StatusOK, + Body: body, + }, + } + + httpc.EXPECT().GET("slb/virtual-server/myvirtualserver").Return(resp, nil) + + res, err := sut.VirtualServer.Get("myvirtualserver") + Ω(err).ShouldNot(HaveOccurred()) + Ω(res).ShouldNot(BeNil()) +} + +func TestGetVirtualServerPort(t *testing.T) { + RegisterTestingT(t) + + mockCtrl := gomock.NewController(t) + httpc := mockutils.NewMockHTTPClient(mockCtrl) + sut := slb.New(httpc) + + body := io.NopCloser(strings.NewReader("{}")) + + resp := &utils.Response{ + Response: &http.Response{ + StatusCode: http.StatusOK, + Body: body, + }, + } + + httpc.EXPECT().GET("slb/virtual-server/myvirtualserver/port/myport").Return(resp, nil) + + res, err := sut.VirtualServerPort.Get("myport", "myvirtualserver") + Ω(err).ShouldNot(HaveOccurred()) + Ω(res).ShouldNot(BeNil()) +} diff --git a/pkg/axapi/slb/types.go b/pkg/axapi/slb/types.go deleted file mode 100644 index a1530b3..0000000 --- a/pkg/axapi/slb/types.go +++ /dev/null @@ -1,5 +0,0 @@ -package slb - -type Slb struct { - // TODO Implementation -} diff --git a/pkg/axapi/slb/virtualserver/types.go b/pkg/axapi/slb/virtualserver/types.go deleted file mode 100644 index 2c0775b..0000000 --- a/pkg/axapi/slb/virtualserver/types.go +++ /dev/null @@ -1,53 +0,0 @@ -package virtualserver - -import "github.com/ureuzy/acos-client-go/pkg/axapi/slb/virtualserverport" - -type ListBody struct { - ListObjects `json:"virtual-server-list"` -} - -type Body struct { - Object `json:"virtual-server"` -} - -// Object Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_virtual_server.html#virtual-server-attributes -type Object struct { - AclID int `json:"acl-id,omitempty"` - AclName string `json:"acl-name,omitempty"` - ArpDisable int `json:"arp-disable,omitempty"` - Description string `json:"description,omitempty"` - DisableVipAdv int `json:"disable-vip-adv,omitempty"` - EnableDisableAction string `json:"enable-disable-action,omitempty"` - Ethernet int `json:"ethernet,omitempty"` - ExtendedStats int `json:"extended-stats,omitempty"` - HADynamic int `json:"ha-dynamic,omitempty"` - IPAddress string `json:"ip-address"` - IPv6Acl string `json:"ipv6-acl,omitempty"` - IPv6Address string `json:"ipv6-address,omitempty"` - MigrateVIP *MigrateVip `json:"migrate-vip,omitempty"` - Name string `json:"name"` - Netmask string `json:"netmask,omitempty"` - PortList *virtualserverport.ListObjects `json:"port-list,omitempty"` - RedistributeRouteMap string `json:"redistribute-route-map,omitempty"` - RedistributionFlagged int `json:"redistribution-flagged,omitempty"` - StatsDataAction string `json:"stats-data-action,omitempty"` - TemplateLogging string `json:"template-logging,omitempty"` - TemplatePolicy string `json:"template-policy,omitempty"` - TemplateScaleout string `json:"template-scaleout,omitempty"` - TemplateVirtualServer string `json:"template-virtual-server,omitempty"` - UseIfIP int `json:"use-if-ip,omitempty"` - UserTag string `json:"user-tag,omitempty"` - UUID string `json:"uuid,omitempty"` - VRID int `json:"vrid,omitempty"` -} -type ListObjects []Object - -// MigrateVip Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_virtual_server.html#migrate-vip -type MigrateVip struct { - CancelMigration bool `json:"cancel-migration,omitempty"` - FinishMigration bool `json:"finish-migration,omitempty"` - TargetDataCpu int `json:"target-data-cpu,omitempty"` - TargetFloatingIPv4 string `json:"target-floating-ipv4,omitempty"` - TargetFloatingIPv6 string `json:"target-floating-ipv6,omitempty"` - UUID string `json:"uuid,omitempty"` -} diff --git a/pkg/axapi/slb/virtualserver/virtualserver.go b/pkg/axapi/slb/virtualserver/virtualserver.go index 03aa324..884598f 100644 --- a/pkg/axapi/slb/virtualserver/virtualserver.go +++ b/pkg/axapi/slb/virtualserver/virtualserver.go @@ -3,129 +3,64 @@ package virtualserver import ( "fmt" - "github.com/ureuzy/acos-client-go/pkg/axapi/errors" + "github.com/ureuzy/acos-client-go/pkg/axapi/shared" + "github.com/ureuzy/acos-client-go/pkg/axapi/slb/virtualserverport" + "github.com/ureuzy/acos-client-go/pkg/rest" "github.com/ureuzy/acos-client-go/utils" ) // Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_virtual_server.html#virtual-server-specification -type operator struct { - utils.HttpClient +func New(c utils.HTTPClient, basePath string) rest.Operator[Body, ListBody] { + const path = "virtual-server" + return rest.Rest[Body, ListBody](c, fmt.Sprintf("%s/%s", basePath, path)) } -type Operator interface { - List() (*ListObjects, error) - Get(name string) (*Object, error) - Create(object *Body) (*Object, error) - Modify(name string, object *Body) (*Object, error) - Delete(name string) error +type ListBody struct { + ListObjects `json:"virtual-server-list"` } -func New(c utils.HttpClient) Operator { - return &operator{c} +type Body struct { + Object `json:"virtual-server"` } -func (o *operator) List() (*ListObjects, error) { - res, err := o.GET("slb/virtual-server") - if err != nil { - return nil, err - } - - if res.HasError() { - return nil, errors.Handle(res) - } - - var response ListBody - if err = res.UnmarshalJson(&response); err != nil { - return nil, err - } - - return &response.ListObjects, nil +// Object Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_virtual_server.html#virtual-server-attributes +type Object struct { + shared.AxaBase `json:",inline"` + AclID int `json:"acl-id,omitempty"` + AclName string `json:"acl-name,omitempty"` + ArpDisable int `json:"arp-disable,omitempty"` + Description string `json:"description,omitempty"` + DisableVipAdv int `json:"disable-vip-adv,omitempty"` + EnableDisableAction string `json:"enable-disable-action,omitempty"` + Ethernet int `json:"ethernet,omitempty"` + ExtendedStats int `json:"extended-stats,omitempty"` + HADynamic int `json:"ha-dynamic,omitempty"` + IPAddress string `json:"ip-address"` + IPv6Acl string `json:"ipv6-acl,omitempty"` + IPv6Address string `json:"ipv6-address,omitempty"` + MigrateVIP *MigrateVip `json:"migrate-vip,omitempty"` + Name string `json:"name"` + Netmask string `json:"netmask,omitempty"` + PortList *virtualserverport.ListObjects `json:"port-list,omitempty"` + RedistributeRouteMap string `json:"redistribute-route-map,omitempty"` + RedistributionFlagged int `json:"redistribution-flagged,omitempty"` + StatsDataAction string `json:"stats-data-action,omitempty"` + TemplateLogging string `json:"template-logging,omitempty"` + TemplatePolicy string `json:"template-policy,omitempty"` + TemplateScaleout string `json:"template-scaleout,omitempty"` + TemplateVirtualServer string `json:"template-virtual-server,omitempty"` + UseIfIP int `json:"use-if-ip,omitempty"` + VRID int `json:"vrid,omitempty"` } - -func (o *operator) Get(name string) (*Object, error) { - err := errors.EmptyStringError(name) - if err != nil { - return nil, err - } - - res, err := o.GET(fmt.Sprintf("slb/virtual-server/%s", name)) - if err != nil { - return nil, err - } - - if res.HasError() { - return nil, errors.Handle(res) - } - - var response Body - if err = res.UnmarshalJson(&response); err != nil { - return nil, err - } - - return &response.Object, nil -} - -func (o *operator) Create(object *Body) (*Object, error) { - err := errors.EmptyStringError(object.Name) - if err != nil { - return nil, err - } - - res, err := o.POST("slb/virtual-server", object) - if err != nil { - return nil, err - } - - if res.HasError() { - return nil, errors.Handle(res) - } - - var response Body - if err = res.UnmarshalJson(&response); err != nil { - return nil, err - } - - return &response.Object, nil -} - -func (o *operator) Modify(name string, object *Body) (*Object, error) { - err := errors.EmptyStringError(name) - if err != nil { - return nil, err - } - - res, err := o.POST(fmt.Sprintf("slb/virtual-server/%s", name), object) - if err != nil { - return nil, err - } - - if res.HasError() { - return nil, errors.Handle(res) - } - - var response Body - if err = res.UnmarshalJson(&response); err != nil { - return nil, err - } - - return &response.Object, nil -} - -func (o *operator) Delete(name string) error { - err := errors.EmptyStringError(name) - if err != nil { - return err - } - - res, err := o.DELETE(fmt.Sprintf("slb/virtual-server/%s", name)) - if err != nil { - return err - } - - if res.HasError() { - return errors.Handle(res) - } - - return nil +type ListObjects []Object + +// MigrateVip Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_virtual_server.html#migrate-vip +type MigrateVip struct { + shared.AxaBase `json:",inline"` + CancelMigration bool `json:"cancel-migration,omitempty"` + FinishMigration bool `json:"finish-migration,omitempty"` + TargetDataCpu int `json:"target-data-cpu,omitempty"` + TargetFloatingIPv4 string `json:"target-floating-ipv4,omitempty"` + TargetFloatingIPv6 string `json:"target-floating-ipv6,omitempty"` } diff --git a/pkg/axapi/slb/virtualserverport/types.go b/pkg/axapi/slb/virtualserverport/types.go deleted file mode 100644 index 8585296..0000000 --- a/pkg/axapi/slb/virtualserverport/types.go +++ /dev/null @@ -1,151 +0,0 @@ -package virtualserverport - -type ListBody struct { - ListObjects `json:"port-list"` -} - -type Body struct { - Object `json:"port"` -} - -// Object Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_virtual_server_port.html#port-attributes -type Object struct { - AclIDList *AclIDList `json:"acl-id-list,omitempty"` - AclNameList *AclNameList `json:"acl-name-list,omitempty"` - Action string `json:"action,omitempty"` - AflexScripts *AflexScripts `json:"aflex-scripts,omitempty"` - AltProtocol1 string `json:"alt-protocol1,omitempty"` - AltProtocol2 string `json:"alt-protocol2,omitempty"` - AlternatePort int `json:"alternate-port,omitempty"` - AlternatePortNumber int `json:"alternate-port-number,omitempty"` - AuthCfg *AuthCfg `json:"auth-cfg,omitempty"` - Auto int `json:"auto,omitempty"` - ClientIPStickyNat int `json:"clientip-sticky-nat,omitempty"` - ConnLimit int `json:"conn-limit,omitempty"` - DefSelectionIfPrefFailed string `json:"def-selection-if-pref-failed,omitempty"` - EnablePlayerIDCheck int `json:"enable-playerid-check,omitempty"` - EthFwd int `json:"eth-fwd,omitempty"` - EthRev int `json:"eth-rev,omitempty"` - Expand int `json:"expand,omitempty"` - ExtendedStats int `json:"extended-stats,omitempty"` - ForceRoutingMode int `json:"force-routing-mode,omitempty"` - GslbEnable int `json:"gslb-enable,omitempty"` - HAConnMirror int `json:"ha-conn-mirror,omitempty"` - IPInIP int `json:"ipinip,omitempty"` - L7HardwareAssist int `json:"l7-hardware-assist,omitempty"` - MessageSwitching int `json:"message-switching,omitempty"` - Name string `json:"name,omitempty"` - NoAutoUpOnAflex int `json:"no-auto-up-on-aflex,omitempty"` - NoDestNat int `json:"no-dest-nat,omitempty"` - NoLogging int `json:"no-logging,omitempty"` - OnSyn int `json:"on-syn,omitempty"` - PersistType string `json:"persist-type,omitempty"` - Pool string `json:"pool,omitempty"` - PortNumber int `json:"port-number,omitempty"` - PortTranslation int `json:"port-translation,omitempty"` - Precedence int `json:"precedence,omitempty"` - Protocol string `json:"protocol,omitempty"` - Range int `json:"range,omitempty"` - Rate int `json:"rate,omitempty"` - RedirectToHttps int `json:"redirect-to-https,omitempty"` - ReqFail int `json:"req-fail,omitempty"` - Reset int `json:"reset,omitempty"` - ResetOnServerSelectionFail int `json:"reset-on-server-selection-fail,omitempty"` - RtpSipCallIDMatch int `json:"rtp-sip-call-id-match,omitempty"` - SamplingEnable *SamplingEnable `json:"sampling-enable,omitempty"` - ScaleOutBucketCount int `json:"scaleout-bucket-count,omitempty"` - ScaleOutDeviceGroup int `json:"scaleout-device-group,omitempty"` - Secs int `json:"secs,omitempty"` - ServSelFail int `json:"serv-sel-fail,omitempty"` - ServiceGroup string `json:"service-group,omitempty"` - SharedPartitionClientSSLTemplate int `json:"shared-partition-client-ssl-template,omitempty"` - SharedPartitionHTTPTemplate int `json:"shared-partition-http-template,omitempty"` - SharedPartitionServerSSLTemplate int `json:"shared-partition-server-ssl-template,omitempty"` - SharedPartitionTCP int `json:"shared-partition-tcp,omitempty"` - SharedPartitionUDP int `json:"shared-partition-udp,omitempty"` - SkipRevHash int `json:"skip-rev-hash,omitempty"` - SNatOnVip int `json:"snat-on-vip,omitempty"` - StatsDataAction string `json:"stats-data-action,omitempty"` - SupportHttp2 int `json:"support-http2,omitempty"` - SynCookie int `json:"syn-cookie,omitempty"` - TemplateCache string `json:"template-cache,omitempty"` - TemplateClientSSL string `json:"template-client-ssl,omitempty"` - TemplateClientSSLShared string `json:"template-client-ssl-shared,omitempty"` - TemplateConnectionReuse string `json:"template-connection-reuse,omitempty"` - TemplateDBLB string `json:"template-dblb,omitempty"` - TemplateDiameter string `json:"template-diameter,omitempty"` - TemplateDNS string `json:"template-dns,omitempty"` - TemplateDynamicService string `json:"template-dynamic-service,omitempty"` - TemplateExternalService string `json:"template-external-service,omitempty"` - TemplateFileInspection string `json:"template-file-inspection,omitempty"` - TemplateFix string `json:"template-fix,omitempty"` - TemplateFTP string `json:"template-ftp,omitempty"` - TemplateHTTP string `json:"template-http,omitempty"` - TemplateHTTPPolicy string `json:"template-http-policy,omitempty"` - TemplateHTTPShared string `json:"template-http-shared,omitempty"` - TemplateImapPop3 string `json:"template-imap-pop3,omitempty"` - TemplatePersistCookie string `json:"template-persist-cookie,omitempty"` - TemplatePersistDestinationIP string `json:"template-persist-destination-ip,omitempty"` - TemplatePersistSourceIP string `json:"template-persist-source-ip,omitempty"` - TemplatePersistSSLSid string `json:"template-persist-ssl-sid,omitempty"` - TemplatePolicy string `json:"template-policy,omitempty"` - TemplateReqmodIcap string `json:"template-reqmod-icap,omitempty"` - TemplateRespmodIcap string `json:"template-respmod-icap,omitempty"` - TemplateScaleout string `json:"template-scaleout,omitempty"` - TemplateServerSSL string `json:"template-server-ssl,omitempty"` - TemplateServerSSLShared string `json:"template-server-ssl-shared,omitempty"` - TemplateSip string `json:"template-sip,omitempty"` - TemplateSmpp string `json:"template-smpp,omitempty"` - TemplateSmtp string `json:"template-smtp,omitempty"` - TemplateSsli string `json:"template-ssli,omitempty"` - TemplateTCP string `json:"template-tcp,omitempty"` - TemplateTCPProxy string `json:"template-tcp-proxy,omitempty"` - TemplateTCPProxyClient string `json:"template-tcp-proxy-client,omitempty"` - TemplateTCPProxyServer string `json:"template-tcp-proxy-server,omitempty"` - TemplateTCPShared string `json:"template-tcp-shared,omitempty"` - TemplateUDP string `json:"template-udp,omitempty"` - TemplateUDPShared string `json:"template-udp-shared,omitempty"` - TemplateVirtualPort string `json:"template-virtual-port,omitempty"` - TrunkFwd int `json:"trunk-fwd,omitempty"` - TrunkRev int `json:"trunk-rev,omitempty"` - UseAlternatePort int `json:"use-alternate-port,omitempty"` - UseCgnv6 int `json:"use-cgnv6,omitempty"` - UseDefaultIfNoServer int `json:"use-default-if-no-server,omitempty"` - UseRcvHopForResp int `json:"use-rcv-hop-for-resp,omitempty"` - UserTag string `json:"user-tag,omitempty"` - UUID string `json:"uuid,omitempty"` - View int `json:"view,omitempty"` - WafTemplate string `json:"waf-template,omitempty"` - WhenDown int `json:"when-down,omitempty"` - WhenDownProtocol2 int `json:"when-down-protocol2,omitempty"` -} -type ListObjects []Object - -// AclNameList Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_virtual_server_port.html#acl-name-list -type AclNameList []struct { - AclName string `json:"acl-name,omitempty"` - AclNameSeqNum int `json:"acl-name-seq-num,omitempty"` - AclNameSrcNatPool string `json:"acl-name-src-nat-pool,omitempty"` -} - -// SamplingEnable Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_virtual_server_port.html#sampling-enable -type SamplingEnable []struct { - Counters1 string `json:"counters1,omitempty"` -} - -// AclIDList Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_virtual_server_port.html#acl-id-list -type AclIDList []struct { - AclID int `json:"acl-id,omitempty"` - AclIDSeqNum int `json:"acl-id-seq-num,omitempty"` - AclIDSrcNatPool string `json:"acl-id-src-nat-pool,omitempty"` -} - -// AflexScripts Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_virtual_server_port.html#aflex-scripts -type AflexScripts []struct { - Aflex string `json:"aflex,omitempty"` -} - -// AuthCfg Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_virtual_server_port.html#auth-cfg -type AuthCfg struct { - AAAPolicy string `json:"aaa-policy,omitempty"` -} diff --git a/pkg/axapi/slb/virtualserverport/virtualserverport.go b/pkg/axapi/slb/virtualserverport/virtualserverport.go index 195ae74..4948637 100644 --- a/pkg/axapi/slb/virtualserverport/virtualserverport.go +++ b/pkg/axapi/slb/virtualserverport/virtualserverport.go @@ -3,165 +3,158 @@ package virtualserverport import ( "fmt" - "github.com/ureuzy/acos-client-go/pkg/axapi/errors" + "github.com/ureuzy/acos-client-go/pkg/axapi/shared" + "github.com/ureuzy/acos-client-go/pkg/rest" "github.com/ureuzy/acos-client-go/utils" ) // Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_virtual_server_port.html#port-specification -type operator struct { - utils.HttpClient +func New(c utils.HTTPClient, basePath string) rest.Operator[Body, ListBody] { + const path = "virtual-server/%s/port" + return rest.Rest[Body, ListBody](c, fmt.Sprintf("%s/%s", basePath, path)) } -type Operator interface { - List(virtualServerName string) (*ListObjects, error) - Get(virtualServerName string, protocol string, portNumber int) (*Object, error) - Create(virtualServerName string, object *Body) (*Object, error) - CreateList(virtualServerName string, object *ListBody) (*ListObjects, error) - Modify(virtualServerName string, protocol string, portNumber int, object *Body) (*Object, error) - Delete(virtualServerName string, protocol string, portNumber int) error +type ListBody struct { + ListObjects `json:"port-list"` } -func New(c utils.HttpClient) Operator { - return &operator{c} +type Body struct { + Object `json:"port"` } -func (o *operator) List(virtualServerName string) (*ListObjects, error) { - res, err := o.GET(fmt.Sprintf("slb/virtual-server/%s/port", virtualServerName)) - if err != nil { - return nil, err - } - - if res.HasError() { - return nil, errors.Handle(res) - } - - var response ListBody - if err = res.UnmarshalJson(&response); err != nil { - return nil, err - } - - return &response.ListObjects, nil -} - -func (o *operator) Get(virtualServerName string, protocol string, portNumber int) (*Object, error) { - err := errors.EmptyStringError(virtualServerName) - if err != nil { - return nil, err - } - - res, err := o.GET(fmt.Sprintf("slb/virtual-server/%s/port/%d+%s", - virtualServerName, - portNumber, - protocol, - )) - if err != nil { - return nil, err - } - - if res.HasError() { - return nil, errors.Handle(res) - } - - var response Body - if err = res.UnmarshalJson(&response); err != nil { - return nil, err - } - - return &response.Object, nil +// Object Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_virtual_server_port.html#port-attributes +type Object struct { + shared.AxaBase `json:",inline"` + AclIDList *AclIDList `json:"acl-id-list,omitempty"` + AclNameList *AclNameList `json:"acl-name-list,omitempty"` + Action string `json:"action,omitempty"` + AflexScripts *AflexScripts `json:"aflex-scripts,omitempty"` + AltProtocol1 string `json:"alt-protocol1,omitempty"` + AltProtocol2 string `json:"alt-protocol2,omitempty"` + AlternatePort int `json:"alternate-port,omitempty"` + AlternatePortNumber int `json:"alternate-port-number,omitempty"` + AuthCfg *AuthCfg `json:"auth-cfg,omitempty"` + Auto int `json:"auto,omitempty"` + ClientIPStickyNat int `json:"clientip-sticky-nat,omitempty"` + ConnLimit int `json:"conn-limit,omitempty"` + DefSelectionIfPrefFailed string `json:"def-selection-if-pref-failed,omitempty"` + EnablePlayerIDCheck int `json:"enable-playerid-check,omitempty"` + EthFwd int `json:"eth-fwd,omitempty"` + EthRev int `json:"eth-rev,omitempty"` + Expand int `json:"expand,omitempty"` + ExtendedStats int `json:"extended-stats,omitempty"` + ForceRoutingMode int `json:"force-routing-mode,omitempty"` + GslbEnable int `json:"gslb-enable,omitempty"` + HAConnMirror int `json:"ha-conn-mirror,omitempty"` + IPInIP int `json:"ipinip,omitempty"` + L7HardwareAssist int `json:"l7-hardware-assist,omitempty"` + MessageSwitching int `json:"message-switching,omitempty"` + Name string `json:"name,omitempty"` + NoAutoUpOnAflex int `json:"no-auto-up-on-aflex,omitempty"` + NoDestNat int `json:"no-dest-nat,omitempty"` + NoLogging int `json:"no-logging,omitempty"` + OnSyn int `json:"on-syn,omitempty"` + PersistType string `json:"persist-type,omitempty"` + Pool string `json:"pool,omitempty"` + PortNumber int `json:"port-number,omitempty"` + PortTranslation int `json:"port-translation,omitempty"` + Precedence int `json:"precedence,omitempty"` + Protocol string `json:"protocol,omitempty"` + Range int `json:"range,omitempty"` + Rate int `json:"rate,omitempty"` + RedirectToHttps int `json:"redirect-to-https,omitempty"` + ReqFail int `json:"req-fail,omitempty"` + Reset int `json:"reset,omitempty"` + ResetOnServerSelectionFail int `json:"reset-on-server-selection-fail,omitempty"` + RtpSipCallIDMatch int `json:"rtp-sip-call-id-match,omitempty"` + SamplingEnable *shared.SamplingEnable `json:"sampling-enable,omitempty"` + ScaleOutBucketCount int `json:"scaleout-bucket-count,omitempty"` + ScaleOutDeviceGroup int `json:"scaleout-device-group,omitempty"` + Secs int `json:"secs,omitempty"` + ServSelFail int `json:"serv-sel-fail,omitempty"` + ServiceGroup string `json:"service-group,omitempty"` + SharedPartitionClientSSLTemplate int `json:"shared-partition-client-ssl-template,omitempty"` + SharedPartitionHTTPTemplate int `json:"shared-partition-http-template,omitempty"` + SharedPartitionServerSSLTemplate int `json:"shared-partition-server-ssl-template,omitempty"` + SharedPartitionTCP int `json:"shared-partition-tcp,omitempty"` + SharedPartitionUDP int `json:"shared-partition-udp,omitempty"` + SkipRevHash int `json:"skip-rev-hash,omitempty"` + SNatOnVip int `json:"snat-on-vip,omitempty"` + StatsDataAction string `json:"stats-data-action,omitempty"` + SupportHttp2 int `json:"support-http2,omitempty"` + SynCookie int `json:"syn-cookie,omitempty"` + TemplateCache string `json:"template-cache,omitempty"` + TemplateClientSSL string `json:"template-client-ssl,omitempty"` + TemplateClientSSLShared string `json:"template-client-ssl-shared,omitempty"` + TemplateConnectionReuse string `json:"template-connection-reuse,omitempty"` + TemplateDBLB string `json:"template-dblb,omitempty"` + TemplateDiameter string `json:"template-diameter,omitempty"` + TemplateDNS string `json:"template-dns,omitempty"` + TemplateDynamicService string `json:"template-dynamic-service,omitempty"` + TemplateExternalService string `json:"template-external-service,omitempty"` + TemplateFileInspection string `json:"template-file-inspection,omitempty"` + TemplateFix string `json:"template-fix,omitempty"` + TemplateFTP string `json:"template-ftp,omitempty"` + TemplateHTTP string `json:"template-http,omitempty"` + TemplateHTTPPolicy string `json:"template-http-policy,omitempty"` + TemplateHTTPShared string `json:"template-http-shared,omitempty"` + TemplateImapPop3 string `json:"template-imap-pop3,omitempty"` + TemplatePersistCookie string `json:"template-persist-cookie,omitempty"` + TemplatePersistDestinationIP string `json:"template-persist-destination-ip,omitempty"` + TemplatePersistSourceIP string `json:"template-persist-source-ip,omitempty"` + TemplatePersistSSLSid string `json:"template-persist-ssl-sid,omitempty"` + TemplatePolicy string `json:"template-policy,omitempty"` + TemplateReqmodIcap string `json:"template-reqmod-icap,omitempty"` + TemplateRespmodIcap string `json:"template-respmod-icap,omitempty"` + TemplateScaleout string `json:"template-scaleout,omitempty"` + TemplateServerSSL string `json:"template-server-ssl,omitempty"` + TemplateServerSSLShared string `json:"template-server-ssl-shared,omitempty"` + TemplateSip string `json:"template-sip,omitempty"` + TemplateSmpp string `json:"template-smpp,omitempty"` + TemplateSmtp string `json:"template-smtp,omitempty"` + TemplateSsli string `json:"template-ssli,omitempty"` + TemplateTCP string `json:"template-tcp,omitempty"` + TemplateTCPProxy string `json:"template-tcp-proxy,omitempty"` + TemplateTCPProxyClient string `json:"template-tcp-proxy-client,omitempty"` + TemplateTCPProxyServer string `json:"template-tcp-proxy-server,omitempty"` + TemplateTCPShared string `json:"template-tcp-shared,omitempty"` + TemplateUDP string `json:"template-udp,omitempty"` + TemplateUDPShared string `json:"template-udp-shared,omitempty"` + TemplateVirtualPort string `json:"template-virtual-port,omitempty"` + TrunkFwd int `json:"trunk-fwd,omitempty"` + TrunkRev int `json:"trunk-rev,omitempty"` + UseAlternatePort int `json:"use-alternate-port,omitempty"` + UseCgnv6 int `json:"use-cgnv6,omitempty"` + UseDefaultIfNoServer int `json:"use-default-if-no-server,omitempty"` + UseRcvHopForResp int `json:"use-rcv-hop-for-resp,omitempty"` + View int `json:"view,omitempty"` + WafTemplate string `json:"waf-template,omitempty"` + WhenDown int `json:"when-down,omitempty"` + WhenDownProtocol2 int `json:"when-down-protocol2,omitempty"` } +type ListObjects []Object -func (o *operator) Create(virtualServerName string, object *Body) (*Object, error) { - err := errors.EmptyStringError(virtualServerName) - if err != nil { - return nil, err - } - - res, err := o.POST(fmt.Sprintf("slb/virtual-server/%s/port", virtualServerName), object) - if err != nil { - return nil, err - } - - if res.HasError() { - return nil, errors.Handle(res) - } - - var response Body - if err = res.UnmarshalJson(&response); err != nil { - return nil, err - } - - return &response.Object, nil +// AclNameList Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_virtual_server_port.html#acl-name-list +type AclNameList []struct { + AclName string `json:"acl-name,omitempty"` + AclNameSeqNum int `json:"acl-name-seq-num,omitempty"` + AclNameSrcNatPool string `json:"acl-name-src-nat-pool,omitempty"` } -func (o *operator) CreateList(virtualServerName string, object *ListBody) (*ListObjects, error) { - err := errors.EmptyStringError(virtualServerName) - if err != nil { - return nil, err - } - - res, err := o.POST(fmt.Sprintf("slb/virtual-server/%s/port", virtualServerName), object) - if err != nil { - return nil, err - } - - if res.HasError() { - return nil, errors.Handle(res) - } - - var response ListBody - if err = res.UnmarshalJson(&response); err != nil { - return nil, err - } - - return &response.ListObjects, nil +// AclIDList Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_virtual_server_port.html#acl-id-list +type AclIDList []struct { + AclID int `json:"acl-id,omitempty"` + AclIDSeqNum int `json:"acl-id-seq-num,omitempty"` + AclIDSrcNatPool string `json:"acl-id-src-nat-pool,omitempty"` } -func (o *operator) Modify(virtualServerName string, protocol string, portNumber int, object *Body) (*Object, error) { - err := errors.EmptyStringError(virtualServerName) - if err != nil { - return nil, err - } - - res, err := o.POST(fmt.Sprintf("slb/virtual-server/%s/port/%d+%s", - virtualServerName, - portNumber, - protocol, - ), object) - if err != nil { - return nil, err - } - - if res.HasError() { - return nil, errors.Handle(res) - } - - var response Body - if err = res.UnmarshalJson(&response); err != nil { - return nil, err - } - - return &response.Object, nil +// AflexScripts Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_virtual_server_port.html#aflex-scripts +type AflexScripts []struct { + Aflex string `json:"aflex,omitempty"` } -func (o *operator) Delete(virtualServerName string, protocol string, portNumber int) error { - err := errors.EmptyStringError(virtualServerName) - if err != nil { - return err - } - - res, err := o.DELETE(fmt.Sprintf("slb/virtual-server/%s/port/%d+%s", - virtualServerName, - portNumber, - protocol, - )) - if err != nil { - return err - } - - if res.HasError() { - return errors.Handle(res) - } - - return nil +// AuthCfg Docs: https://documentation.a10networks.com/ACOS/414x/ACOS_4_1_4-P1/html/axapiv3/slb_virtual_server_port.html#auth-cfg +type AuthCfg struct { + AAAPolicy string `json:"aaa-policy,omitempty"` } diff --git a/pkg/client/client.go b/pkg/client/client.go index 87f64a6..126e39f 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -5,16 +5,22 @@ import ( "fmt" "net/http" + ap "github.com/ureuzy/acos-client-go/pkg/axapi/activepartition" "github.com/ureuzy/acos-client-go/pkg/axapi/auth" + "github.com/ureuzy/acos-client-go/pkg/axapi/gslb" + "github.com/ureuzy/acos-client-go/pkg/axapi/health" "github.com/ureuzy/acos-client-go/pkg/axapi/slb" "github.com/ureuzy/acos-client-go/utils" ) type Client struct { - conf Config - http utils.HttpClient - Auth auth.Operator - Slb *slb.Operator + conf Config + http utils.HTTPClient + Auth auth.Operator + ActivePartition ap.Operator + Health *health.Operator + Slb *slb.Operator + Gslb *gslb.Operator } type Config struct { @@ -40,28 +46,37 @@ func New(conf Config, options ...Option) (*Client, error) { opt(httpClient) } - baseUrl := fmt.Sprintf("https://%s/axapi/v3", conf.Host) - client := generateClient(utils.NewHttpClient(baseUrl, httpClient, &http.Header{}, conf.Debug), conf) + baseURL := fmt.Sprintf("https://%s/axapi/v3", conf.Host) + client := generateClient(utils.NewHTTPClient(baseURL, httpClient, &http.Header{}, conf.Debug), conf) client.http.AddHeader("Content-Type", "application/json") if err := client.Authenticate(); err != nil { return nil, err } + return client, nil } func (c *Client) Authenticate() error { - if res, err := c.Auth.Request(&auth.Request{Credentials: auth.Credentials{ + res, err := c.Auth.Request(&auth.Request{Credentials: auth.Credentials{ Username: c.conf.User, Password: c.conf.Pass, - }}); err != nil { + }}) + if err != nil { return err - } else { - c.http.AddHeader("Authorization", fmt.Sprintf("A10 %s", res.Signature)) } + c.http.AddHeader("Authorization", fmt.Sprintf("A10 %s", res.Signature)) return nil } -func generateClient(client utils.HttpClient, conf Config) *Client { - return &Client{conf, client, auth.New(client), slb.New(client)} +func generateClient(client utils.HTTPClient, conf Config) *Client { + return &Client{ + conf: conf, + http: client, + Auth: auth.New(client), + ActivePartition: ap.New(client), + Health: health.New(client), + Slb: slb.New(client), + Gslb: gslb.New(client), + } } diff --git a/pkg/mocks/utils/mock.go b/pkg/mocks/utils/mock.go new file mode 100644 index 0000000..998df35 --- /dev/null +++ b/pkg/mocks/utils/mock.go @@ -0,0 +1,107 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: utils/http.go + +// Package mock_utils is a generated GoMock package. +package mock_utils + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + utils "github.com/ureuzy/acos-client-go/utils" +) + +// MockHTTPClient is a mock of HTTPClient interface. +type MockHTTPClient struct { + ctrl *gomock.Controller + recorder *MockHTTPClientMockRecorder +} + +// MockHTTPClientMockRecorder is the mock recorder for MockHTTPClient. +type MockHTTPClientMockRecorder struct { + mock *MockHTTPClient +} + +// NewMockHTTPClient creates a new mock instance. +func NewMockHTTPClient(ctrl *gomock.Controller) *MockHTTPClient { + mock := &MockHTTPClient{ctrl: ctrl} + mock.recorder = &MockHTTPClientMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockHTTPClient) EXPECT() *MockHTTPClientMockRecorder { + return m.recorder +} + +// AddHeader mocks base method. +func (m *MockHTTPClient) AddHeader(key, value string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "AddHeader", key, value) +} + +// AddHeader indicates an expected call of AddHeader. +func (mr *MockHTTPClientMockRecorder) AddHeader(key, value interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddHeader", reflect.TypeOf((*MockHTTPClient)(nil).AddHeader), key, value) +} + +// DELETE mocks base method. +func (m *MockHTTPClient) DELETE(path string) (*utils.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DELETE", path) + ret0, _ := ret[0].(*utils.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DELETE indicates an expected call of DELETE. +func (mr *MockHTTPClientMockRecorder) DELETE(path interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DELETE", reflect.TypeOf((*MockHTTPClient)(nil).DELETE), path) +} + +// GET mocks base method. +func (m *MockHTTPClient) GET(path string) (*utils.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GET", path) + ret0, _ := ret[0].(*utils.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GET indicates an expected call of GET. +func (mr *MockHTTPClientMockRecorder) GET(path interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GET", reflect.TypeOf((*MockHTTPClient)(nil).GET), path) +} + +// POST mocks base method. +func (m *MockHTTPClient) POST(path string, body interface{}) (*utils.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "POST", path, body) + ret0, _ := ret[0].(*utils.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// POST indicates an expected call of POST. +func (mr *MockHTTPClientMockRecorder) POST(path, body interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "POST", reflect.TypeOf((*MockHTTPClient)(nil).POST), path, body) +} + +// PUT mocks base method. +func (m *MockHTTPClient) PUT(path string, body interface{}) (*utils.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PUT", path, body) + ret0, _ := ret[0].(*utils.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// PUT indicates an expected call of PUT. +func (mr *MockHTTPClientMockRecorder) PUT(path, body interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PUT", reflect.TypeOf((*MockHTTPClient)(nil).PUT), path, body) +} diff --git a/pkg/rest/rest.go b/pkg/rest/rest.go new file mode 100644 index 0000000..cc3b623 --- /dev/null +++ b/pkg/rest/rest.go @@ -0,0 +1,158 @@ +package rest + +import ( + "fmt" + + "github.com/ureuzy/acos-client-go/pkg/axapi/errors" + "github.com/ureuzy/acos-client-go/utils" +) + +type Operator[object any, objectList any] interface { + Get(name string, parentnames ...string) (*object, error) + List(parentnames ...string) (*objectList, error) + Create(object *object, parentnames ...string) (*object, error) + CreateList(object *objectList, parentnames ...string) (*objectList, error) + Modify(name string, object *object, parentnames ...string) (*object, error) + Delete(name string, parentnames ...string) error +} + +type operator[object any, objectList any] struct { + utils.HTTPClient + basePath string +} + +func Rest[object any, objectList any](c utils.HTTPClient, path string) Operator[object, objectList] { + return &operator[object, objectList]{HTTPClient: c, basePath: path} +} + +func (o *operator[object, objectList]) Get(name string, parentnames ...string) (*object, error) { + err := errors.EmptyStringError(name) + if err != nil { + return nil, err + } + + parentnames = append(parentnames, name) + + res, err := o.GET(o.getFormattedURL(o.basePath+"/%s", parentnames)) + if err != nil { + return nil, err + } + + if res.HasError() { + return nil, errors.Handle(res) + } + + var response object + if err = res.UnmarshalJSON(&response); err != nil { + return nil, err + } + + return &response, nil +} + +func (o *operator[object, objectList]) List(parentnames ...string) (*objectList, error) { + res, err := o.GET(o.getFormattedURL(o.basePath, parentnames)) + if err != nil { + return nil, err + } + + if res.HasError() { + return nil, errors.Handle(res) + } + + var response objectList + if err = res.UnmarshalJSON(&response); err != nil { + return nil, err + } + + return &response, nil +} + +func (o *operator[object, objectList]) Create(instance *object, parentnames ...string) (*object, error) { + res, err := o.POST(o.getFormattedURL(o.basePath, parentnames), instance) + if err != nil { + return nil, err + } + + if res.HasError() { + return nil, errors.Handle(res) + } + + var response object + if err = res.UnmarshalJSON(&response); err != nil { + return nil, err + } + + return &response, nil +} + +func (o *operator[object, objectList]) CreateList(instance *objectList, parentnames ...string) (*objectList, error) { + res, err := o.POST(o.getFormattedURL(o.basePath, parentnames), instance) + if err != nil { + return nil, err + } + + if res.HasError() { + return nil, errors.Handle(res) + } + + var response objectList + if err = res.UnmarshalJSON(&response); err != nil { + return nil, err + } + + return &response, nil +} + +func (o *operator[object, objectList]) Modify(name string, instance *object, parentnames ...string) (*object, error) { + err := errors.EmptyStringError(name) + if err != nil { + return nil, err + } + + parentnames = append(parentnames, name) + + res, err := o.POST(o.getFormattedURL(o.basePath+"/%s", parentnames), instance) + if err != nil { + return nil, err + } + + if res.HasError() { + return nil, errors.Handle(res) + } + + var response object + if err = res.UnmarshalJSON(&response); err != nil { + return nil, err + } + + return &response, nil +} + +func (o *operator[object, objectList]) Delete(name string, parentnames ...string) error { + err := errors.EmptyStringError(name) + if err != nil { + return err + } + + parentnames = append(parentnames, name) + + res, err := o.DELETE(o.getFormattedURL(o.basePath+"/%s", parentnames)) + if err != nil { + return err + } + + if res.HasError() { + return errors.Handle(res) + } + + return nil +} + +func (o *operator[object, objectList]) getFormattedURL(urlFormat string, args []string) string { + is := make([]interface{}, len(args)) + for i := range args { + is[i] = args[i] + } + return fmt.Sprintf(urlFormat, is...) +} diff --git a/utils/http.go b/utils/http.go index 8e91804..31c3ac3 100644 --- a/utils/http.go +++ b/utils/http.go @@ -10,13 +10,13 @@ import ( ) type httpClient struct { - baseUrl string + baseURL string debug bool *http.Client *http.Header } -type HttpClient interface { +type HTTPClient interface { GET(path string) (*Response, error) POST(path string, body interface{}) (*Response, error) PUT(path string, body interface{}) (*Response, error) @@ -24,14 +24,14 @@ type HttpClient interface { AddHeader(key string, value string) } -func NewHttpClient(baseUrl string, client *http.Client, header *http.Header, debug bool) HttpClient { - return &httpClient{baseUrl: baseUrl, Client: client, Header: header, debug: debug} +func NewHTTPClient(baseURL string, client *http.Client, header *http.Header, debug bool) HTTPClient { + return &httpClient{baseURL: baseURL, Client: client, Header: header, debug: debug} } func (c *httpClient) GET(path string) (*Response, error) { req, err := http.NewRequest( http.MethodGet, - fmt.Sprintf("%s/%s", c.baseUrl, path), + fmt.Sprintf("%s/%s", c.baseURL, path), nil, ) if err != nil { @@ -54,7 +54,7 @@ func (c *httpClient) POST(path string, body interface{}) (*Response, error) { req, err := http.NewRequest( http.MethodPost, - fmt.Sprintf("%s/%s", c.baseUrl, path), + fmt.Sprintf("%s/%s", c.baseURL, path), bytes.NewReader(data), ) if err != nil { @@ -77,7 +77,7 @@ func (c *httpClient) PUT(path string, body interface{}) (*Response, error) { req, err := http.NewRequest( http.MethodPut, - fmt.Sprintf("%s/%s", c.baseUrl, path), + fmt.Sprintf("%s/%s", c.baseURL, path), bytes.NewReader(data), ) if err != nil { @@ -95,7 +95,7 @@ func (c *httpClient) PUT(path string, body interface{}) (*Response, error) { func (c *httpClient) DELETE(path string) (*Response, error) { req, err := http.NewRequest( http.MethodDelete, - fmt.Sprintf("%s/%s", c.baseUrl, path), + fmt.Sprintf("%s/%s", c.baseURL, path), nil, ) if err != nil { @@ -141,7 +141,7 @@ func (r *Response) HasError() bool { return r.StatusCode >= http.StatusBadRequest } -func (r *Response) UnmarshalJson(v interface{}) error { +func (r *Response) UnmarshalJSON(v interface{}) error { buf := new(bytes.Buffer) if _, err := io.Copy(buf, r.Body); err != nil { return err