traefik/vendor/github.com/sacloud/libsacloud/api/vpc_router.go
2019-04-26 11:26:04 +02:00

438 lines
13 KiB
Go

package api
import (
"encoding/json"
"fmt"
"time"
"github.com/sacloud/libsacloud/sacloud"
)
//HACK: さくらのAPI側仕様: Applianceの内容によってJSONフォーマットが異なるため
// ロードバランサ/VPCルータそれぞれでリクエスト/レスポンスデータ型を定義する。
// SearchVPCRouterResponse VPCルーター検索レスポンス
type SearchVPCRouterResponse struct {
// Total 総件数
Total int `json:",omitempty"`
// From ページング開始位置
From int `json:",omitempty"`
// Count 件数
Count int `json:",omitempty"`
// VPCRouters VPCルーター リスト
VPCRouters []sacloud.VPCRouter `json:"Appliances,omitempty"`
}
type vpcRouterRequest struct {
VPCRouter *sacloud.VPCRouter `json:"Appliance,omitempty"`
From int `json:",omitempty"`
Count int `json:",omitempty"`
Sort []string `json:",omitempty"`
Filter map[string]interface{} `json:",omitempty"`
Exclude []string `json:",omitempty"`
Include []string `json:",omitempty"`
}
type vpcRouterResponse struct {
*sacloud.ResultFlagValue
*sacloud.VPCRouter `json:"Appliance,omitempty"`
Success interface{} `json:",omitempty"` //HACK: さくらのAPI側仕様: 戻り値:Successがbool値へ変換できないためinterface{}
}
type vpcRouterStatusResponse struct {
*sacloud.ResultFlagValue
*sacloud.VPCRouterStatus `json:"Router"`
Success interface{} `json:",omitempty"` //HACK: さくらのAPI側仕様: 戻り値:Successがbool値へ変換できないためinterface{}
}
type vpcRouterS2sConnInfoResponse struct {
*sacloud.ResultFlagValue
*sacloud.SiteToSiteConnectionInfo
Name string
}
// VPCRouterAPI VPCルーターAPI
type VPCRouterAPI struct {
*baseAPI
}
// NewVPCRouterAPI VPCルーターAPI作成
func NewVPCRouterAPI(client *Client) *VPCRouterAPI {
return &VPCRouterAPI{
&baseAPI{
client: client,
FuncGetResourceURL: func() string {
return "appliance"
},
FuncBaseSearchCondition: func() *sacloud.Request {
res := &sacloud.Request{}
res.AddFilter("Class", "vpcrouter")
return res
},
},
}
}
// Find 検索
func (api *VPCRouterAPI) Find() (*SearchVPCRouterResponse, error) {
data, err := api.client.newRequest("GET", api.getResourceURL(), api.getSearchState())
if err != nil {
return nil, err
}
var res SearchVPCRouterResponse
if err := json.Unmarshal(data, &res); err != nil {
return nil, err
}
return &res, nil
}
func (api *VPCRouterAPI) request(f func(*vpcRouterResponse) error) (*sacloud.VPCRouter, error) {
res := &vpcRouterResponse{}
err := f(res)
if err != nil {
return nil, err
}
return res.VPCRouter, nil
}
func (api *VPCRouterAPI) createRequest(value *sacloud.VPCRouter) *vpcRouterResponse {
return &vpcRouterResponse{VPCRouter: value}
}
// New 新規作成用パラメーター作成
func (api *VPCRouterAPI) New() *sacloud.VPCRouter {
return sacloud.CreateNewVPCRouter()
}
// Create 新規作成
func (api *VPCRouterAPI) Create(value *sacloud.VPCRouter) (*sacloud.VPCRouter, error) {
return api.request(func(res *vpcRouterResponse) error {
return api.create(api.createRequest(value), res)
})
}
// Read 読み取り
func (api *VPCRouterAPI) Read(id int64) (*sacloud.VPCRouter, error) {
return api.request(func(res *vpcRouterResponse) error {
return api.read(id, nil, res)
})
}
// Update 更新
func (api *VPCRouterAPI) Update(id int64, value *sacloud.VPCRouter) (*sacloud.VPCRouter, error) {
return api.request(func(res *vpcRouterResponse) error {
return api.update(id, api.createRequest(value), res)
})
}
// UpdateSetting 設定更新
func (api *VPCRouterAPI) UpdateSetting(id int64, value *sacloud.VPCRouter) (*sacloud.VPCRouter, error) {
req := &sacloud.VPCRouter{
// Settings
Settings: value.Settings,
}
return api.request(func(res *vpcRouterResponse) error {
return api.update(id, api.createRequest(req), res)
})
}
// Delete 削除
func (api *VPCRouterAPI) Delete(id int64) (*sacloud.VPCRouter, error) {
return api.request(func(res *vpcRouterResponse) error {
return api.delete(id, nil, res)
})
}
// Config 設定変更の反映
func (api *VPCRouterAPI) Config(id int64) (bool, error) {
var (
method = "PUT"
uri = fmt.Sprintf("%s/%d/config", api.getResourceURL(), id)
)
return api.modify(method, uri, nil)
}
// ConnectToSwitch 指定のインデックス位置のNICをスイッチへ接続
func (api *VPCRouterAPI) ConnectToSwitch(id int64, switchID int64, nicIndex int) (bool, error) {
var (
method = "PUT"
uri = fmt.Sprintf("%s/%d/interface/%d/to/switch/%d", api.getResourceURL(), id, nicIndex, switchID)
)
return api.modify(method, uri, nil)
}
// DisconnectFromSwitch 指定のインデックス位置のNICをスイッチから切断
func (api *VPCRouterAPI) DisconnectFromSwitch(id int64, nicIndex int) (bool, error) {
var (
method = "DELETE"
uri = fmt.Sprintf("%s/%d/interface/%d/to/switch", api.getResourceURL(), id, nicIndex)
)
return api.modify(method, uri, nil)
}
// IsUp 起動しているか判定
func (api *VPCRouterAPI) IsUp(id int64) (bool, error) {
router, err := api.Read(id)
if err != nil {
return false, err
}
return router.Instance.IsUp(), nil
}
// IsDown ダウンしているか判定
func (api *VPCRouterAPI) IsDown(id int64) (bool, error) {
router, err := api.Read(id)
if err != nil {
return false, err
}
return router.Instance.IsDown(), nil
}
// Boot 起動
func (api *VPCRouterAPI) Boot(id int64) (bool, error) {
var (
method = "PUT"
uri = fmt.Sprintf("%s/%d/power", api.getResourceURL(), id)
)
return api.modify(method, uri, nil)
}
// Shutdown シャットダウン(graceful)
func (api *VPCRouterAPI) Shutdown(id int64) (bool, error) {
var (
method = "DELETE"
uri = fmt.Sprintf("%s/%d/power", api.getResourceURL(), id)
)
return api.modify(method, uri, nil)
}
// Stop シャットダウン(force)
func (api *VPCRouterAPI) Stop(id int64) (bool, error) {
var (
method = "DELETE"
uri = fmt.Sprintf("%s/%d/power", api.getResourceURL(), id)
)
return api.modify(method, uri, map[string]bool{"Force": true})
}
// RebootForce 再起動
func (api *VPCRouterAPI) RebootForce(id int64) (bool, error) {
var (
method = "PUT"
uri = fmt.Sprintf("%s/%d/reset", api.getResourceURL(), id)
)
return api.modify(method, uri, nil)
}
// SleepUntilUp 起動するまで待機
func (api *VPCRouterAPI) SleepUntilUp(id int64, timeout time.Duration) error {
handler := waitingForUpFunc(func() (hasUpDown, error) {
return api.Read(id)
}, 0)
return blockingPoll(handler, timeout)
}
// SleepUntilDown ダウンするまで待機
func (api *VPCRouterAPI) SleepUntilDown(id int64, timeout time.Duration) error {
handler := waitingForDownFunc(func() (hasUpDown, error) {
return api.Read(id)
}, 0)
return blockingPoll(handler, timeout)
}
// SleepWhileCopying コピー終了まで待機
//
// maxRetry: リクエストタイミングによって、コピー完了までの間に404エラーとなる場合がある。
// 通常そのまま待てばコピー完了するため、404エラーが発生してもmaxRetryで指定した回数分は待機する。
func (api *VPCRouterAPI) SleepWhileCopying(id int64, timeout time.Duration, maxRetry int) error {
handler := waitingForAvailableFunc(func() (hasAvailable, error) {
return api.Read(id)
}, maxRetry)
return blockingPoll(handler, timeout)
}
// AsyncSleepWhileCopying コピー終了まで待機(非同期)
func (api *VPCRouterAPI) AsyncSleepWhileCopying(id int64, timeout time.Duration, maxRetry int) (chan (interface{}), chan (interface{}), chan (error)) {
handler := waitingForAvailableFunc(func() (hasAvailable, error) {
return api.Read(id)
}, maxRetry)
return poll(handler, timeout)
}
// AddStandardInterface スタンダードプランでのインターフェース追加
func (api *VPCRouterAPI) AddStandardInterface(routerID int64, switchID int64, ipaddress string, maskLen int) (*sacloud.VPCRouter, error) {
return api.addInterface(routerID, switchID, &sacloud.VPCRouterInterface{
IPAddress: []string{ipaddress},
NetworkMaskLen: maskLen,
VirtualIPAddress: "",
})
}
// AddPremiumInterface プレミアムプランでのインターフェース追加
func (api *VPCRouterAPI) AddPremiumInterface(routerID int64, switchID int64, ipaddresses []string, maskLen int, virtualIP string) (*sacloud.VPCRouter, error) {
return api.addInterface(routerID, switchID, &sacloud.VPCRouterInterface{
IPAddress: ipaddresses,
NetworkMaskLen: maskLen,
VirtualIPAddress: virtualIP,
})
}
func (api *VPCRouterAPI) addInterface(routerID int64, switchID int64, routerNIC *sacloud.VPCRouterInterface) (*sacloud.VPCRouter, error) {
router, err := api.Read(routerID)
if err != nil {
return nil, err
}
req := &sacloud.VPCRouter{Settings: &sacloud.VPCRouterSettings{}}
if router.Settings == nil {
req.Settings = &sacloud.VPCRouterSettings{
Router: &sacloud.VPCRouterSetting{
Interfaces: []*sacloud.VPCRouterInterface{nil},
},
}
} else {
req.Settings.Router = router.Settings.Router
}
index := len(req.Settings.Router.Interfaces) // add to last
return api.addInterfaceAt(routerID, switchID, routerNIC, index)
}
// AddStandardInterfaceAt スタンダードプランでの指定位置へのインターフェース追加
func (api *VPCRouterAPI) AddStandardInterfaceAt(routerID int64, switchID int64, ipaddress string, maskLen int, index int) (*sacloud.VPCRouter, error) {
return api.addInterfaceAt(routerID, switchID, &sacloud.VPCRouterInterface{
IPAddress: []string{ipaddress},
NetworkMaskLen: maskLen,
VirtualIPAddress: "",
}, index)
}
// AddPremiumInterfaceAt プレミアムプランでの指定位置へのインターフェース追加
func (api *VPCRouterAPI) AddPremiumInterfaceAt(routerID int64, switchID int64, ipaddresses []string, maskLen int, virtualIP string, index int) (*sacloud.VPCRouter, error) {
return api.addInterfaceAt(routerID, switchID, &sacloud.VPCRouterInterface{
IPAddress: ipaddresses,
NetworkMaskLen: maskLen,
VirtualIPAddress: virtualIP,
}, index)
}
func (api *VPCRouterAPI) addInterfaceAt(routerID int64, switchID int64, routerNIC *sacloud.VPCRouterInterface, index int) (*sacloud.VPCRouter, error) {
router, err := api.Read(routerID)
if err != nil {
return nil, err
}
req := &sacloud.VPCRouter{Settings: &sacloud.VPCRouterSettings{}}
if router.Settings == nil {
req.Settings = &sacloud.VPCRouterSettings{
Router: &sacloud.VPCRouterSetting{
Interfaces: []*sacloud.VPCRouterInterface{nil},
},
}
} else {
req.Settings.Router = router.Settings.Router
}
//connect to switch
_, err = api.ConnectToSwitch(routerID, switchID, index)
if err != nil {
return nil, err
}
for i := 0; i < index; i++ {
if len(req.Settings.Router.Interfaces) < index {
req.Settings.Router.Interfaces = append(req.Settings.Router.Interfaces, nil)
}
}
if len(req.Settings.Router.Interfaces) < index+1 {
req.Settings.Router.Interfaces = append(req.Settings.Router.Interfaces, routerNIC)
} else {
req.Settings.Router.Interfaces[index] = routerNIC
}
res, err := api.UpdateSetting(routerID, req)
if err != nil {
return nil, err
}
return res, nil
}
// DeleteInterfaceAt 指定位置のインターフェース削除
func (api *VPCRouterAPI) DeleteInterfaceAt(routerID int64, index int) (*sacloud.VPCRouter, error) {
router, err := api.Read(routerID)
if err != nil {
return nil, err
}
req := &sacloud.VPCRouter{Settings: &sacloud.VPCRouterSettings{}}
if router.Settings == nil {
req.Settings = &sacloud.VPCRouterSettings{
// Router
Router: &sacloud.VPCRouterSetting{
// Interfaces
Interfaces: []*sacloud.VPCRouterInterface{nil},
},
}
} else {
req.Settings.Router = router.Settings.Router
}
//disconnect to switch
_, err = api.DisconnectFromSwitch(routerID, index)
if err != nil {
return nil, err
}
if index < len(req.Settings.Router.Interfaces) {
req.Settings.Router.Interfaces[index] = nil
}
res, err := api.UpdateSetting(routerID, req)
if err != nil {
return nil, err
}
return res, nil
}
// MonitorBy 指定位置のインターフェースのアクティビティーモニター取得
func (api *VPCRouterAPI) MonitorBy(id int64, nicIndex int, body *sacloud.ResourceMonitorRequest) (*sacloud.MonitorValues, error) {
return api.baseAPI.applianceMonitorBy(id, "interface", nicIndex, body)
}
// Status ログなどのステータス情報 取得
func (api *VPCRouterAPI) Status(id int64) (*sacloud.VPCRouterStatus, error) {
var (
method = "GET"
uri = fmt.Sprintf("%s/%d/status", api.getResourceURL(), id)
res = &vpcRouterStatusResponse{}
)
err := api.baseAPI.request(method, uri, nil, res)
if err != nil {
return nil, err
}
return res.VPCRouterStatus, nil
}
// SiteToSiteConnectionDetails サイト間VPN接続情報を取得
func (api *VPCRouterAPI) SiteToSiteConnectionDetails(id int64) (*sacloud.SiteToSiteConnectionInfo, error) {
var (
method = "GET"
uri = fmt.Sprintf("%s/%d/vpcrouter/sitetosite/connectiondetails", api.getResourceURL(), id)
res = &vpcRouterS2sConnInfoResponse{}
)
err := api.baseAPI.request(method, uri, nil, res)
if err != nil {
return nil, err
}
return res.SiteToSiteConnectionInfo, nil
}