forked from TrueCloudLab/lego
sakuracloud: supports concurrent update (#850)
This commit is contained in:
parent
5d557fdc6d
commit
f400ec5163
40 changed files with 2594 additions and 179 deletions
|
@ -78,3 +78,6 @@
|
||||||
[[issues.exclude-rules]]
|
[[issues.exclude-rules]]
|
||||||
path = "providers/http/memcached/memcached_test.go"
|
path = "providers/http/memcached/memcached_test.go"
|
||||||
text = "`memcachedHosts` is a global variable"
|
text = "`memcachedHosts` is a global variable"
|
||||||
|
[[issues.exclude-rules]]
|
||||||
|
path = "providers/dns/sakuracloud/client_test.go"
|
||||||
|
text = "cyclomatic complexity 13 of func `(TestDNSProvider_cleanupTXTRecord_concurrent|TestDNSProvider_addTXTRecord_concurrent)` is high"
|
||||||
|
|
7
Gopkg.lock
generated
7
Gopkg.lock
generated
|
@ -431,17 +431,18 @@
|
||||||
revision = "1031fa0ce2f20c1c0e1e1b51951d8ea02c84fa05"
|
revision = "1031fa0ce2f20c1c0e1e1b51951d8ea02c84fa05"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
digest = "1:5a632dc3d841d803524bd442976a52e390e4294826ece65722cb77020879d156"
|
||||||
digest = "1:180e8ec2d3734b269a8a30b51dbca47fede2ce274fa76da2f00e664481cfb39e"
|
|
||||||
name = "github.com/sacloud/libsacloud"
|
name = "github.com/sacloud/libsacloud"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
"api",
|
"api",
|
||||||
"sacloud",
|
"sacloud",
|
||||||
"sacloud/ostype",
|
"sacloud/ostype",
|
||||||
|
"utils/mutexkv",
|
||||||
]
|
]
|
||||||
pruneopts = "NUT"
|
pruneopts = "NUT"
|
||||||
revision = "108b1efe4b4d106fee6760bdf1847c4f92e1a92e"
|
revision = "a949b57af53e809207587f8c41571d81f140276e"
|
||||||
|
version = "v1.19.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:6bc0652ea6e39e22ccd522458b8bdd8665bf23bdc5a20eec90056e4dc7e273ca"
|
digest = "1:6bc0652ea6e39e22ccd522458b8bdd8665bf23bdc5a20eec90056e4dc7e273ca"
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
name = "gopkg.in/ns1/ns1-go.v2"
|
name = "gopkg.in/ns1/ns1-go.v2"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
branch = "master"
|
version = "1.19.0"
|
||||||
name = "github.com/sacloud/libsacloud"
|
name = "github.com/sacloud/libsacloud"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
|
|
|
@ -1014,6 +1014,7 @@ func displayDNSHelp(name string) {
|
||||||
fmt.Fprintln(w)
|
fmt.Fprintln(w)
|
||||||
|
|
||||||
fmt.Fprintln(w, `Additional Configuration:`)
|
fmt.Fprintln(w, `Additional Configuration:`)
|
||||||
|
fmt.Fprintln(w, ` - "SAKURACLOUD_HTTP_TIMEOUT": API request timeout`)
|
||||||
fmt.Fprintln(w, ` - "SAKURACLOUD_POLLING_INTERVAL": Time between DNS propagation check`)
|
fmt.Fprintln(w, ` - "SAKURACLOUD_POLLING_INTERVAL": Time between DNS propagation check`)
|
||||||
fmt.Fprintln(w, ` - "SAKURACLOUD_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`)
|
fmt.Fprintln(w, ` - "SAKURACLOUD_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`)
|
||||||
fmt.Fprintln(w, ` - "SAKURACLOUD_TTL": The TTL of the TXT record used for the DNS challenge`)
|
fmt.Fprintln(w, ` - "SAKURACLOUD_TTL": The TTL of the TXT record used for the DNS challenge`)
|
||||||
|
|
|
@ -39,6 +39,7 @@ More information [here](/lego/dns/#configuration-and-credentials).
|
||||||
|
|
||||||
| Environment Variable Name | Description |
|
| Environment Variable Name | Description |
|
||||||
|--------------------------------|-------------|
|
|--------------------------------|-------------|
|
||||||
|
| `SAKURACLOUD_HTTP_TIMEOUT` | API request timeout |
|
||||||
| `SAKURACLOUD_POLLING_INTERVAL` | Time between DNS propagation check |
|
| `SAKURACLOUD_POLLING_INTERVAL` | Time between DNS propagation check |
|
||||||
| `SAKURACLOUD_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation |
|
| `SAKURACLOUD_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation |
|
||||||
| `SAKURACLOUD_TTL` | The TTL of the TXT record used for the DNS challenge |
|
| `SAKURACLOUD_TTL` | The TTL of the TXT record used for the DNS challenge |
|
||||||
|
|
106
providers/dns/sakuracloud/client.go
Normal file
106
providers/dns/sakuracloud/client.go
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
package sakuracloud
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-acme/lego/challenge/dns01"
|
||||||
|
"github.com/sacloud/libsacloud/api"
|
||||||
|
"github.com/sacloud/libsacloud/sacloud"
|
||||||
|
)
|
||||||
|
|
||||||
|
const sacloudAPILockKey = "lego/dns/sacloud"
|
||||||
|
|
||||||
|
func (d *DNSProvider) addTXTRecord(fqdn, domain, value string, ttl int) error {
|
||||||
|
sacloud.LockByKey(sacloudAPILockKey)
|
||||||
|
defer sacloud.UnlockByKey(sacloudAPILockKey)
|
||||||
|
|
||||||
|
zone, err := d.getHostedZone(domain)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("sakuracloud: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
name := d.extractRecordName(fqdn, zone.Name)
|
||||||
|
|
||||||
|
zone.AddRecord(zone.CreateNewRecord(name, "TXT", value, ttl))
|
||||||
|
_, err = d.client.Update(zone.ID, zone)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("sakuracloud: API call failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DNSProvider) cleanupTXTRecord(fqdn, domain string) error {
|
||||||
|
sacloud.LockByKey(sacloudAPILockKey)
|
||||||
|
defer sacloud.UnlockByKey(sacloudAPILockKey)
|
||||||
|
|
||||||
|
zone, err := d.getHostedZone(domain)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("sakuracloud: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
records := d.findTxtRecords(fqdn, zone)
|
||||||
|
|
||||||
|
for _, record := range records {
|
||||||
|
var updRecords []sacloud.DNSRecordSet
|
||||||
|
for _, r := range zone.Settings.DNS.ResourceRecordSets {
|
||||||
|
if !(r.Name == record.Name && r.Type == record.Type && r.RData == record.RData) {
|
||||||
|
updRecords = append(updRecords, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zone.Settings.DNS.ResourceRecordSets = updRecords
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = d.client.Update(zone.ID, zone)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("sakuracloud: API call failed: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DNSProvider) getHostedZone(domain string) (*sacloud.DNS, error) {
|
||||||
|
authZone, err := dns01.FindZoneByFqdn(dns01.ToFqdn(domain))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
zoneName := dns01.UnFqdn(authZone)
|
||||||
|
|
||||||
|
res, err := d.client.Reset().WithNameLike(zoneName).Find()
|
||||||
|
if err != nil {
|
||||||
|
if notFound, ok := err.(api.Error); ok && notFound.ResponseCode() == http.StatusNotFound {
|
||||||
|
return nil, fmt.Errorf("zone %s not found on SakuraCloud DNS: %v", zoneName, err)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("API call failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, zone := range res.CommonServiceDNSItems {
|
||||||
|
if zone.Name == zoneName {
|
||||||
|
return &zone, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("zone %s not found", zoneName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DNSProvider) findTxtRecords(fqdn string, zone *sacloud.DNS) []sacloud.DNSRecordSet {
|
||||||
|
recordName := d.extractRecordName(fqdn, zone.Name)
|
||||||
|
|
||||||
|
var res []sacloud.DNSRecordSet
|
||||||
|
for _, record := range zone.Settings.DNS.ResourceRecordSets {
|
||||||
|
if record.Name == recordName && record.Type == "TXT" {
|
||||||
|
res = append(res, record)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DNSProvider) extractRecordName(fqdn, domain string) string {
|
||||||
|
name := dns01.UnFqdn(fqdn)
|
||||||
|
if idx := strings.Index(name, "."+domain); idx != -1 {
|
||||||
|
return name[:idx]
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
320
providers/dns/sakuracloud/client_test.go
Normal file
320
providers/dns/sakuracloud/client_test.go
Normal file
|
@ -0,0 +1,320 @@
|
||||||
|
package sakuracloud
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/sacloud/libsacloud/api"
|
||||||
|
"github.com/sacloud/libsacloud/sacloud"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
type simpleResponse struct {
|
||||||
|
*sacloud.DNS `json:"CommonServiceItem,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type apiQuery struct {
|
||||||
|
Filter struct {
|
||||||
|
Name string `json:"Name"`
|
||||||
|
ProviderClass string `json:"Provider.Class"`
|
||||||
|
} `json:"Filter"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func fakeAPIServer(handler func(rw http.ResponseWriter, req *http.Request)) func() {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
|
||||||
|
mux.HandleFunc("/is1a/api/cloud/1.1/commonserviceitem/", handler)
|
||||||
|
|
||||||
|
backup := api.SakuraCloudAPIRoot
|
||||||
|
api.SakuraCloudAPIRoot = server.URL
|
||||||
|
return func() {
|
||||||
|
api.SakuraCloudAPIRoot = backup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDNSProvider_addTXTRecord(t *testing.T) {
|
||||||
|
searchResp := &api.SearchDNSResponse{}
|
||||||
|
tearDown := fakeAPIServer(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
switch req.Method {
|
||||||
|
case http.MethodGet:
|
||||||
|
if len(searchResp.CommonServiceDNSItems) == 0 {
|
||||||
|
q := &apiQuery{}
|
||||||
|
if err := json.Unmarshal([]byte(req.URL.RawQuery), q); err != nil {
|
||||||
|
http.Error(rw, err.Error(), http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
|
||||||
|
fakeZone := sacloud.CreateNewDNS(q.Filter.Name)
|
||||||
|
fakeZone.ID = 123456789012
|
||||||
|
searchResp = &api.SearchDNSResponse{CommonServiceDNSItems: []sacloud.DNS{*fakeZone}}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.NewEncoder(rw).Encode(searchResp); err != nil {
|
||||||
|
http.Error(rw, err.Error(), http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
case http.MethodPut: // Update
|
||||||
|
resp := &simpleResponse{}
|
||||||
|
if err := json.NewDecoder(req.Body).Decode(resp); err != nil {
|
||||||
|
http.Error(rw, err.Error(), http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
|
||||||
|
var items []sacloud.DNS
|
||||||
|
for _, v := range searchResp.CommonServiceDNSItems {
|
||||||
|
if resp.Name == v.Name {
|
||||||
|
items = append(items, *resp.DNS)
|
||||||
|
} else {
|
||||||
|
items = append(items, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
searchResp.CommonServiceDNSItems = items
|
||||||
|
|
||||||
|
if err := json.NewEncoder(rw).Encode(searchResp); err != nil {
|
||||||
|
http.Error(rw, err.Error(), http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
http.Error(rw, "OOPS", http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
defer tearDown()
|
||||||
|
|
||||||
|
config := NewDefaultConfig()
|
||||||
|
config.Token = "token1"
|
||||||
|
config.Secret = "secret1"
|
||||||
|
|
||||||
|
p, err := NewDNSProviderConfig(config)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = p.addTXTRecord("test.example.com", "example.com", "dummyValue", 10)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
updZone, err := p.getHostedZone("example.com")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, updZone)
|
||||||
|
|
||||||
|
require.Len(t, updZone.Settings.DNS.ResourceRecordSets, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDNSProvider_cleanupTXTRecord(t *testing.T) {
|
||||||
|
searchResp := &api.SearchDNSResponse{}
|
||||||
|
|
||||||
|
tearDown := fakeAPIServer(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
switch req.Method {
|
||||||
|
case http.MethodGet:
|
||||||
|
if len(searchResp.CommonServiceDNSItems) == 0 {
|
||||||
|
q := &apiQuery{}
|
||||||
|
if err := json.Unmarshal([]byte(req.URL.RawQuery), q); err != nil {
|
||||||
|
http.Error(rw, err.Error(), http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
|
||||||
|
fakeZone := sacloud.CreateNewDNS(q.Filter.Name)
|
||||||
|
fakeZone.ID = 123456789012
|
||||||
|
fakeZone.CreateNewRecord("test", "TXT", "dummyValue", 10)
|
||||||
|
searchResp = &api.SearchDNSResponse{CommonServiceDNSItems: []sacloud.DNS{*fakeZone}}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.NewEncoder(rw).Encode(searchResp); err != nil {
|
||||||
|
http.Error(rw, err.Error(), http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
case http.MethodPut: // Update
|
||||||
|
resp := &simpleResponse{}
|
||||||
|
if err := json.NewDecoder(req.Body).Decode(resp); err != nil {
|
||||||
|
http.Error(rw, err.Error(), http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
|
||||||
|
var items []sacloud.DNS
|
||||||
|
for _, v := range searchResp.CommonServiceDNSItems {
|
||||||
|
if resp.Name == v.Name {
|
||||||
|
items = append(items, *resp.DNS)
|
||||||
|
} else {
|
||||||
|
items = append(items, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
searchResp.CommonServiceDNSItems = items
|
||||||
|
|
||||||
|
if err := json.NewEncoder(rw).Encode(searchResp); err != nil {
|
||||||
|
http.Error(rw, err.Error(), http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
http.Error(rw, "OOPS", http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
defer tearDown()
|
||||||
|
|
||||||
|
config := NewDefaultConfig()
|
||||||
|
config.Token = "token2"
|
||||||
|
config.Secret = "secret2"
|
||||||
|
|
||||||
|
p, err := NewDNSProviderConfig(config)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = p.cleanupTXTRecord("test.example.com", "example.com")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
updZone, err := p.getHostedZone("example.com")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, updZone)
|
||||||
|
|
||||||
|
require.Len(t, updZone.Settings.DNS.ResourceRecordSets, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDNSProvider_addTXTRecord_concurrent(t *testing.T) {
|
||||||
|
searchResp := &api.SearchDNSResponse{}
|
||||||
|
|
||||||
|
tearDown := fakeAPIServer(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
switch req.Method {
|
||||||
|
case http.MethodGet:
|
||||||
|
if len(searchResp.CommonServiceDNSItems) == 0 {
|
||||||
|
q := &apiQuery{}
|
||||||
|
if err := json.Unmarshal([]byte(req.URL.RawQuery), q); err != nil {
|
||||||
|
http.Error(rw, err.Error(), http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
|
||||||
|
fakeZone := sacloud.CreateNewDNS(q.Filter.Name)
|
||||||
|
fakeZone.ID = 123456789012
|
||||||
|
searchResp = &api.SearchDNSResponse{CommonServiceDNSItems: []sacloud.DNS{*fakeZone}}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.NewEncoder(rw).Encode(searchResp); err != nil {
|
||||||
|
http.Error(rw, err.Error(), http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
case http.MethodPut: // Update
|
||||||
|
resp := &simpleResponse{}
|
||||||
|
if err := json.NewDecoder(req.Body).Decode(resp); err != nil {
|
||||||
|
http.Error(rw, err.Error(), http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
|
||||||
|
var items []sacloud.DNS
|
||||||
|
for _, v := range searchResp.CommonServiceDNSItems {
|
||||||
|
if resp.Name == v.Name {
|
||||||
|
items = append(items, *resp.DNS)
|
||||||
|
} else {
|
||||||
|
items = append(items, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
searchResp.CommonServiceDNSItems = items
|
||||||
|
|
||||||
|
if err := json.NewEncoder(rw).Encode(searchResp); err != nil {
|
||||||
|
http.Error(rw, err.Error(), http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
http.Error(rw, "OOPS", http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
defer tearDown()
|
||||||
|
|
||||||
|
dummyRecordCount := 10
|
||||||
|
|
||||||
|
var providers []*DNSProvider
|
||||||
|
for i := 0; i < dummyRecordCount; i++ {
|
||||||
|
config := NewDefaultConfig()
|
||||||
|
config.Token = "token3"
|
||||||
|
config.Secret = "secret3"
|
||||||
|
|
||||||
|
p, err := NewDNSProviderConfig(config)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
providers = append(providers, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(len(providers))
|
||||||
|
|
||||||
|
for i, p := range providers {
|
||||||
|
go func(fqdn string, client *DNSProvider) {
|
||||||
|
err := client.addTXTRecord(fqdn, "example.com", "dummyValue", 10)
|
||||||
|
require.NoError(t, err)
|
||||||
|
wg.Done()
|
||||||
|
}(fmt.Sprintf("test%d.example.com", i), p)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
updZone, err := providers[0].getHostedZone("example.com")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, updZone)
|
||||||
|
|
||||||
|
require.Len(t, updZone.Settings.DNS.ResourceRecordSets, dummyRecordCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDNSProvider_cleanupTXTRecord_concurrent(t *testing.T) {
|
||||||
|
dummyRecordCount := 10
|
||||||
|
|
||||||
|
baseFakeZone := sacloud.CreateNewDNS("example.com")
|
||||||
|
baseFakeZone.ID = 123456789012
|
||||||
|
for i := 0; i < dummyRecordCount; i++ {
|
||||||
|
baseFakeZone.AddRecord(baseFakeZone.CreateNewRecord(fmt.Sprintf("test%d", i), "TXT", "dummyValue", 10))
|
||||||
|
}
|
||||||
|
|
||||||
|
searchResp := &api.SearchDNSResponse{CommonServiceDNSItems: []sacloud.DNS{*baseFakeZone}}
|
||||||
|
|
||||||
|
tearDown := fakeAPIServer(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
switch req.Method {
|
||||||
|
case http.MethodGet:
|
||||||
|
if err := json.NewEncoder(rw).Encode(searchResp); err != nil {
|
||||||
|
http.Error(rw, err.Error(), http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
case http.MethodPut: // Update
|
||||||
|
resp := &simpleResponse{}
|
||||||
|
if err := json.NewDecoder(req.Body).Decode(resp); err != nil {
|
||||||
|
http.Error(rw, err.Error(), http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
|
||||||
|
var items []sacloud.DNS
|
||||||
|
for _, v := range searchResp.CommonServiceDNSItems {
|
||||||
|
if resp.Name == v.Name {
|
||||||
|
items = append(items, *resp.DNS)
|
||||||
|
} else {
|
||||||
|
items = append(items, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
searchResp.CommonServiceDNSItems = items
|
||||||
|
|
||||||
|
if err := json.NewEncoder(rw).Encode(searchResp); err != nil {
|
||||||
|
http.Error(rw, err.Error(), http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
http.Error(rw, "OOPS", http.StatusServiceUnavailable)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
defer tearDown()
|
||||||
|
|
||||||
|
fakeZone := sacloud.CreateNewDNS("example.com")
|
||||||
|
fakeZone.ID = 123456789012
|
||||||
|
for i := 0; i < dummyRecordCount; i++ {
|
||||||
|
fakeZone.AddRecord(fakeZone.CreateNewRecord(fmt.Sprintf("test%d", i), "TXT", "dummyValue", 10))
|
||||||
|
}
|
||||||
|
|
||||||
|
var providers []*DNSProvider
|
||||||
|
for i := 0; i < dummyRecordCount; i++ {
|
||||||
|
config := NewDefaultConfig()
|
||||||
|
config.Token = "token4"
|
||||||
|
config.Secret = "secret4"
|
||||||
|
|
||||||
|
p, err := NewDNSProviderConfig(config)
|
||||||
|
require.NoError(t, err)
|
||||||
|
providers = append(providers, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(len(providers))
|
||||||
|
|
||||||
|
for i, p := range providers {
|
||||||
|
go func(fqdn string, client *DNSProvider) {
|
||||||
|
err := client.cleanupTXTRecord(fqdn, "example.com")
|
||||||
|
require.NoError(t, err)
|
||||||
|
wg.Done()
|
||||||
|
}(fmt.Sprintf("test%d.example.com", i), p)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
updZone, err := providers[0].getHostedZone("example.com")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, updZone)
|
||||||
|
|
||||||
|
require.Len(t, updZone.Settings.DNS.ResourceRecordSets, 0)
|
||||||
|
}
|
|
@ -5,13 +5,11 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-acme/lego/challenge/dns01"
|
"github.com/go-acme/lego/challenge/dns01"
|
||||||
"github.com/go-acme/lego/platform/config/env"
|
"github.com/go-acme/lego/platform/config/env"
|
||||||
"github.com/sacloud/libsacloud/api"
|
"github.com/sacloud/libsacloud/api"
|
||||||
"github.com/sacloud/libsacloud/sacloud"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config is used to configure the creation of the DNSProvider
|
// Config is used to configure the creation of the DNSProvider
|
||||||
|
@ -21,6 +19,7 @@ type Config struct {
|
||||||
PropagationTimeout time.Duration
|
PropagationTimeout time.Duration
|
||||||
PollingInterval time.Duration
|
PollingInterval time.Duration
|
||||||
TTL int
|
TTL int
|
||||||
|
HTTPClient *http.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDefaultConfig returns a default configuration for the DNSProvider
|
// NewDefaultConfig returns a default configuration for the DNSProvider
|
||||||
|
@ -29,13 +28,16 @@ func NewDefaultConfig() *Config {
|
||||||
TTL: env.GetOrDefaultInt("SAKURACLOUD_TTL", dns01.DefaultTTL),
|
TTL: env.GetOrDefaultInt("SAKURACLOUD_TTL", dns01.DefaultTTL),
|
||||||
PropagationTimeout: env.GetOrDefaultSecond("SAKURACLOUD_PROPAGATION_TIMEOUT", dns01.DefaultPropagationTimeout),
|
PropagationTimeout: env.GetOrDefaultSecond("SAKURACLOUD_PROPAGATION_TIMEOUT", dns01.DefaultPropagationTimeout),
|
||||||
PollingInterval: env.GetOrDefaultSecond("SAKURACLOUD_POLLING_INTERVAL", dns01.DefaultPollingInterval),
|
PollingInterval: env.GetOrDefaultSecond("SAKURACLOUD_POLLING_INTERVAL", dns01.DefaultPollingInterval),
|
||||||
|
HTTPClient: &http.Client{
|
||||||
|
Timeout: env.GetOrDefaultSecond("SAKURACLOUD_HTTP_TIMEOUT", 10*time.Second),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
|
// DNSProvider is an implementation of the acme.ChallengeProvider interface.
|
||||||
type DNSProvider struct {
|
type DNSProvider struct {
|
||||||
config *Config
|
config *Config
|
||||||
client *api.Client
|
client *api.DNSAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDNSProvider returns a DNSProvider instance configured for SakuraCloud.
|
// NewDNSProvider returns a DNSProvider instance configured for SakuraCloud.
|
||||||
|
@ -67,58 +69,29 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
|
||||||
return nil, errors.New("sakuracloud: AccessSecret is missing")
|
return nil, errors.New("sakuracloud: AccessSecret is missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
client := api.NewClient(config.Token, config.Secret, "tk1a")
|
apiClient := api.NewClient(config.Token, config.Secret, "is1a")
|
||||||
|
if config.HTTPClient == nil {
|
||||||
|
apiClient.HTTPClient = http.DefaultClient
|
||||||
|
} else {
|
||||||
|
apiClient.HTTPClient = config.HTTPClient
|
||||||
|
}
|
||||||
|
|
||||||
return &DNSProvider{client: client, config: config}, nil
|
return &DNSProvider{
|
||||||
|
client: apiClient.GetDNSAPI(),
|
||||||
|
config: config,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present creates a TXT record to fulfill the dns-01 challenge.
|
// Present creates a TXT record to fulfill the dns-01 challenge.
|
||||||
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
|
||||||
fqdn, value := dns01.GetRecord(domain, keyAuth)
|
fqdn, value := dns01.GetRecord(domain, keyAuth)
|
||||||
|
return d.addTXTRecord(fqdn, domain, value, d.config.TTL)
|
||||||
zone, err := d.getHostedZone(domain)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("sakuracloud: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
name := d.extractRecordName(fqdn, zone.Name)
|
|
||||||
|
|
||||||
zone.AddRecord(zone.CreateNewRecord(name, "TXT", value, d.config.TTL))
|
|
||||||
_, err = d.client.GetDNSAPI().Update(zone.ID, zone)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("sakuracloud: API call failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CleanUp removes the TXT record matching the specified parameters.
|
// CleanUp removes the TXT record matching the specified parameters.
|
||||||
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||||
fqdn, _ := dns01.GetRecord(domain, keyAuth)
|
fqdn, _ := dns01.GetRecord(domain, keyAuth)
|
||||||
|
return d.cleanupTXTRecord(fqdn, domain)
|
||||||
zone, err := d.getHostedZone(domain)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("sakuracloud: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
records := d.findTxtRecords(fqdn, zone)
|
|
||||||
|
|
||||||
for _, record := range records {
|
|
||||||
var updRecords []sacloud.DNSRecordSet
|
|
||||||
for _, r := range zone.Settings.DNS.ResourceRecordSets {
|
|
||||||
if !(r.Name == record.Name && r.Type == record.Type && r.RData == record.RData) {
|
|
||||||
updRecords = append(updRecords, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
zone.Settings.DNS.ResourceRecordSets = updRecords
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = d.client.GetDNSAPI().Update(zone.ID, zone)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("sakuracloud: API call failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timeout returns the timeout and interval to use when checking for DNS propagation.
|
// Timeout returns the timeout and interval to use when checking for DNS propagation.
|
||||||
|
@ -126,48 +99,3 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
|
||||||
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
|
||||||
return d.config.PropagationTimeout, d.config.PollingInterval
|
return d.config.PropagationTimeout, d.config.PollingInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DNSProvider) getHostedZone(domain string) (*sacloud.DNS, error) {
|
|
||||||
authZone, err := dns01.FindZoneByFqdn(dns01.ToFqdn(domain))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
zoneName := dns01.UnFqdn(authZone)
|
|
||||||
|
|
||||||
res, err := d.client.GetDNSAPI().WithNameLike(zoneName).Find()
|
|
||||||
if err != nil {
|
|
||||||
if notFound, ok := err.(api.Error); ok && notFound.ResponseCode() == http.StatusNotFound {
|
|
||||||
return nil, fmt.Errorf("zone %s not found on SakuraCloud DNS: %v", zoneName, err)
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("API call failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, zone := range res.CommonServiceDNSItems {
|
|
||||||
if zone.Name == zoneName {
|
|
||||||
return &zone, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("zone %s not found", zoneName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DNSProvider) findTxtRecords(fqdn string, zone *sacloud.DNS) []sacloud.DNSRecordSet {
|
|
||||||
recordName := d.extractRecordName(fqdn, zone.Name)
|
|
||||||
|
|
||||||
var res []sacloud.DNSRecordSet
|
|
||||||
for _, record := range zone.Settings.DNS.ResourceRecordSets {
|
|
||||||
if record.Name == recordName && record.Type == "TXT" {
|
|
||||||
res = append(res, record)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DNSProvider) extractRecordName(fqdn, domain string) string {
|
|
||||||
name := dns01.UnFqdn(fqdn)
|
|
||||||
if idx := strings.Index(name, "."+domain); idx != -1 {
|
|
||||||
return name[:idx]
|
|
||||||
}
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ Example = ''''''
|
||||||
SAKURACLOUD_POLLING_INTERVAL = "Time between DNS propagation check"
|
SAKURACLOUD_POLLING_INTERVAL = "Time between DNS propagation check"
|
||||||
SAKURACLOUD_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation"
|
SAKURACLOUD_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation"
|
||||||
SAKURACLOUD_TTL = "The TTL of the TXT record used for the DNS challenge"
|
SAKURACLOUD_TTL = "The TTL of the TXT record used for the DNS challenge"
|
||||||
|
SAKURACLOUD_HTTP_TIMEOUT = "API request timeout"
|
||||||
|
|
||||||
[Links]
|
[Links]
|
||||||
API = "https://developer.sakura.ad.jp/cloud/api/1.1/"
|
API = "https://developer.sakura.ad.jp/cloud/api/1.1/"
|
||||||
|
|
8
vendor/github.com/sacloud/libsacloud/api/archive.go
generated
vendored
8
vendor/github.com/sacloud/libsacloud/api/archive.go
generated
vendored
|
@ -39,6 +39,7 @@ var (
|
||||||
archiveLatestStableWindows2016SQLServer2017Standard = []string{"os-windows", "distro-ver-2016", "windows-sqlserver", "sqlserver-2017", "edition-standard"}
|
archiveLatestStableWindows2016SQLServer2017Standard = []string{"os-windows", "distro-ver-2016", "windows-sqlserver", "sqlserver-2017", "edition-standard"}
|
||||||
archiveLatestStableWindows2016SQLServerStandardAll = []string{"os-windows", "distro-ver-2016", "windows-sqlserver", "sqlserver-2016", "edition-standard", "windows-rds", "with-office"}
|
archiveLatestStableWindows2016SQLServerStandardAll = []string{"os-windows", "distro-ver-2016", "windows-sqlserver", "sqlserver-2016", "edition-standard", "windows-rds", "with-office"}
|
||||||
archiveLatestStableWindows2016SQLServer2017StandardAll = []string{"os-windows", "distro-ver-2016", "windows-sqlserver", "sqlserver-2017", "edition-standard", "windows-rds", "with-office"}
|
archiveLatestStableWindows2016SQLServer2017StandardAll = []string{"os-windows", "distro-ver-2016", "windows-sqlserver", "sqlserver-2017", "edition-standard", "windows-rds", "with-office"}
|
||||||
|
archiveLatestStableWindows2019Tags = []string{"os-windows", "distro-ver-2019"}
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewArchiveAPI アーカイブAPI作成
|
// NewArchiveAPI アーカイブAPI作成
|
||||||
|
@ -361,6 +362,13 @@ func (api *ArchiveAPI) FindLatestStableWindows2016SQLServer2017StandardAll() (*s
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindLatestStableWindows2019 安定版最新のWindows2019パブリックアーカイブを取得
|
||||||
|
func (api *ArchiveAPI) FindLatestStableWindows2019() (*sacloud.Archive, error) {
|
||||||
|
return api.findByOSTags(archiveLatestStableWindows2019Tags, map[string]interface{}{
|
||||||
|
"Name": "Windows Server 2019 Datacenter Edition",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// FindByOSType 指定のOS種別の安定版最新のパブリックアーカイブを取得
|
// FindByOSType 指定のOS種別の安定版最新のパブリックアーカイブを取得
|
||||||
func (api *ArchiveAPI) FindByOSType(os ostype.ArchiveOSTypes) (*sacloud.Archive, error) {
|
func (api *ArchiveAPI) FindByOSType(os ostype.ArchiveOSTypes) (*sacloud.Archive, error) {
|
||||||
if f, ok := api.findFuncMapPerOSType[os]; ok {
|
if f, ok := api.findFuncMapPerOSType[os]; ok {
|
||||||
|
|
2
vendor/github.com/sacloud/libsacloud/api/base_api.go
generated
vendored
2
vendor/github.com/sacloud/libsacloud/api/base_api.go
generated
vendored
|
@ -138,7 +138,7 @@ func (api *baseAPI) filterBy(key string, value interface{}, multiple bool) *base
|
||||||
if f, ok := state.Filter[key]; ok {
|
if f, ok := state.Filter[key]; ok {
|
||||||
if s, ok := f.(string); ok && s != "" {
|
if s, ok := f.(string); ok && s != "" {
|
||||||
if v, ok := value.(string); ok {
|
if v, ok := value.(string); ok {
|
||||||
state.Filter[key] = fmt.Sprintf("%s %s", s, v)
|
state.Filter[key] = fmt.Sprintf("%s%%20%s", s, v)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
22
vendor/github.com/sacloud/libsacloud/api/client.go
generated
vendored
22
vendor/github.com/sacloud/libsacloud/api/client.go
generated
vendored
|
@ -45,6 +45,8 @@ type Client struct {
|
||||||
RetryMax int
|
RetryMax int
|
||||||
// 503エラー時のリトライ待ち時間
|
// 503エラー時のリトライ待ち時間
|
||||||
RetryInterval time.Duration
|
RetryInterval time.Duration
|
||||||
|
// APIコール時に利用される*http.Client 未指定の場合http.DefaultClientが利用される
|
||||||
|
HTTPClient *http.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient APIクライアント作成
|
// NewClient APIクライアント作成
|
||||||
|
@ -112,6 +114,7 @@ func (c *Client) isOkStatus(code int) bool {
|
||||||
func (c *Client) newRequest(method, uri string, body interface{}) ([]byte, error) {
|
func (c *Client) newRequest(method, uri string, body interface{}) ([]byte, error) {
|
||||||
var (
|
var (
|
||||||
client = &retryableHTTPClient{
|
client = &retryableHTTPClient{
|
||||||
|
Client: c.HTTPClient,
|
||||||
retryMax: c.RetryMax,
|
retryMax: c.RetryMax,
|
||||||
retryInterval: c.RetryInterval,
|
retryInterval: c.RetryInterval,
|
||||||
}
|
}
|
||||||
|
@ -233,12 +236,15 @@ func newRequest(method, url string, body io.ReadSeeker) (*request, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type retryableHTTPClient struct {
|
type retryableHTTPClient struct {
|
||||||
http.Client
|
*http.Client
|
||||||
retryInterval time.Duration
|
retryInterval time.Duration
|
||||||
retryMax int
|
retryMax int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *retryableHTTPClient) Do(req *request) (*http.Response, error) {
|
func (c *retryableHTTPClient) Do(req *request) (*http.Response, error) {
|
||||||
|
if c.Client == nil {
|
||||||
|
c.Client = http.DefaultClient
|
||||||
|
}
|
||||||
for i := 0; ; i++ {
|
for i := 0; ; i++ {
|
||||||
|
|
||||||
if req.body != nil {
|
if req.body != nil {
|
||||||
|
@ -278,6 +284,7 @@ type API struct {
|
||||||
Bill *BillAPI // 請求情報API
|
Bill *BillAPI // 請求情報API
|
||||||
Bridge *BridgeAPI // ブリッジAPi
|
Bridge *BridgeAPI // ブリッジAPi
|
||||||
CDROM *CDROMAPI // ISOイメージAPI
|
CDROM *CDROMAPI // ISOイメージAPI
|
||||||
|
Coupon *CouponAPI // クーポンAPI
|
||||||
Database *DatabaseAPI // データベースAPI
|
Database *DatabaseAPI // データベースAPI
|
||||||
Disk *DiskAPI // ディスクAPI
|
Disk *DiskAPI // ディスクAPI
|
||||||
DNS *DNSAPI // DNS API
|
DNS *DNSAPI // DNS API
|
||||||
|
@ -296,6 +303,7 @@ type API struct {
|
||||||
NFS *NFSAPI // NFS API
|
NFS *NFSAPI // NFS API
|
||||||
Note *NoteAPI // スタートアップスクリプトAPI
|
Note *NoteAPI // スタートアップスクリプトAPI
|
||||||
PacketFilter *PacketFilterAPI // パケットフィルタAPI
|
PacketFilter *PacketFilterAPI // パケットフィルタAPI
|
||||||
|
ProxyLB *ProxyLBAPI // プロキシLBAPI
|
||||||
PrivateHost *PrivateHostAPI // 専有ホストAPI
|
PrivateHost *PrivateHostAPI // 専有ホストAPI
|
||||||
Product *ProductAPI // 製品情報API
|
Product *ProductAPI // 製品情報API
|
||||||
Server *ServerAPI // サーバーAPI
|
Server *ServerAPI // サーバーAPI
|
||||||
|
@ -338,6 +346,11 @@ func (api *API) GetCDROMAPI() *CDROMAPI {
|
||||||
return api.CDROM
|
return api.CDROM
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCouponAPI クーポン情報API取得
|
||||||
|
func (api *API) GetCouponAPI() *CouponAPI {
|
||||||
|
return api.Coupon
|
||||||
|
}
|
||||||
|
|
||||||
// GetDatabaseAPI データベースAPI取得
|
// GetDatabaseAPI データベースAPI取得
|
||||||
func (api *API) GetDatabaseAPI() *DatabaseAPI {
|
func (api *API) GetDatabaseAPI() *DatabaseAPI {
|
||||||
return api.Database
|
return api.Database
|
||||||
|
@ -433,6 +446,11 @@ func (api *API) GetPacketFilterAPI() *PacketFilterAPI {
|
||||||
return api.PacketFilter
|
return api.PacketFilter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetProxyLBAPI プロキシLBAPI取得
|
||||||
|
func (api *API) GetProxyLBAPI() *ProxyLBAPI {
|
||||||
|
return api.ProxyLB
|
||||||
|
}
|
||||||
|
|
||||||
// GetPrivateHostAPI 専有ホストAPI取得
|
// GetPrivateHostAPI 専有ホストAPI取得
|
||||||
func (api *API) GetPrivateHostAPI() *PrivateHostAPI {
|
func (api *API) GetPrivateHostAPI() *PrivateHostAPI {
|
||||||
return api.PrivateHost
|
return api.PrivateHost
|
||||||
|
@ -567,6 +585,7 @@ func newAPI(client *Client) *API {
|
||||||
Bill: NewBillAPI(client),
|
Bill: NewBillAPI(client),
|
||||||
Bridge: NewBridgeAPI(client),
|
Bridge: NewBridgeAPI(client),
|
||||||
CDROM: NewCDROMAPI(client),
|
CDROM: NewCDROMAPI(client),
|
||||||
|
Coupon: NewCouponAPI(client),
|
||||||
Database: NewDatabaseAPI(client),
|
Database: NewDatabaseAPI(client),
|
||||||
Disk: NewDiskAPI(client),
|
Disk: NewDiskAPI(client),
|
||||||
DNS: NewDNSAPI(client),
|
DNS: NewDNSAPI(client),
|
||||||
|
@ -588,6 +607,7 @@ func newAPI(client *Client) *API {
|
||||||
NFS: NewNFSAPI(client),
|
NFS: NewNFSAPI(client),
|
||||||
Note: NewNoteAPI(client),
|
Note: NewNoteAPI(client),
|
||||||
PacketFilter: NewPacketFilterAPI(client),
|
PacketFilter: NewPacketFilterAPI(client),
|
||||||
|
ProxyLB: NewProxyLBAPI(client),
|
||||||
PrivateHost: NewPrivateHostAPI(client),
|
PrivateHost: NewPrivateHostAPI(client),
|
||||||
Product: &ProductAPI{
|
Product: &ProductAPI{
|
||||||
Server: NewProductServerAPI(client),
|
Server: NewProductServerAPI(client),
|
||||||
|
|
59
vendor/github.com/sacloud/libsacloud/api/coupon.go
generated
vendored
Normal file
59
vendor/github.com/sacloud/libsacloud/api/coupon.go
generated
vendored
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/sacloud/libsacloud/sacloud"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CouponAPI クーポン情報API
|
||||||
|
type CouponAPI struct {
|
||||||
|
*baseAPI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCouponAPI クーポン情報API作成
|
||||||
|
func NewCouponAPI(client *Client) *CouponAPI {
|
||||||
|
return &CouponAPI{
|
||||||
|
&baseAPI{
|
||||||
|
client: client,
|
||||||
|
apiRootSuffix: sakuraBillingAPIRootSuffix,
|
||||||
|
FuncGetResourceURL: func() string {
|
||||||
|
return "coupon"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CouponResponse クーポン情報レスポンス
|
||||||
|
type CouponResponse struct {
|
||||||
|
*sacloud.ResultFlagValue
|
||||||
|
// AllCount 件数
|
||||||
|
AllCount int `json:",omitempty"`
|
||||||
|
// CountPerPage ページあたり件数
|
||||||
|
CountPerPage int `json:",omitempty"`
|
||||||
|
// Page 現在のページ番号
|
||||||
|
Page int `json:",omitempty"`
|
||||||
|
// Coupons クーポン情報 リスト
|
||||||
|
Coupons []*sacloud.Coupon
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find クーポン情報 全件取得
|
||||||
|
func (api *CouponAPI) Find() ([]*sacloud.Coupon, error) {
|
||||||
|
authStatus, err := api.client.AuthStatus.Read()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
accountID := authStatus.Account.GetStrID()
|
||||||
|
|
||||||
|
uri := fmt.Sprintf("%s/%s", api.getResourceURL(), accountID)
|
||||||
|
data, err := api.client.newRequest("GET", uri, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var res CouponResponse
|
||||||
|
if err := json.Unmarshal(data, &res); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res.Coupons, nil
|
||||||
|
}
|
23
vendor/github.com/sacloud/libsacloud/api/load_balancer.go
generated
vendored
23
vendor/github.com/sacloud/libsacloud/api/load_balancer.go
generated
vendored
|
@ -39,6 +39,12 @@ type loadBalancerResponse struct {
|
||||||
Success interface{} `json:",omitempty"` //HACK: さくらのAPI側仕様: 戻り値:Successがbool値へ変換できないためinterface{}
|
Success interface{} `json:",omitempty"` //HACK: さくらのAPI側仕様: 戻り値:Successがbool値へ変換できないためinterface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type loadBalancerStatusResponse struct {
|
||||||
|
*sacloud.ResultFlagValue
|
||||||
|
Success interface{} `json:",omitempty"` //HACK: さくらのAPI側仕様: 戻り値:Successがbool値へ変換できないためinterface{}
|
||||||
|
LoadBalancer *sacloud.LoadBalancerStatusResult `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// LoadBalancerAPI ロードバランサーAPI
|
// LoadBalancerAPI ロードバランサーAPI
|
||||||
type LoadBalancerAPI struct {
|
type LoadBalancerAPI struct {
|
||||||
*baseAPI
|
*baseAPI
|
||||||
|
@ -231,3 +237,20 @@ func (api *LoadBalancerAPI) AsyncSleepWhileCopying(id int64, timeout time.Durati
|
||||||
func (api *LoadBalancerAPI) Monitor(id int64, body *sacloud.ResourceMonitorRequest) (*sacloud.MonitorValues, error) {
|
func (api *LoadBalancerAPI) Monitor(id int64, body *sacloud.ResourceMonitorRequest) (*sacloud.MonitorValues, error) {
|
||||||
return api.baseAPI.applianceMonitorBy(id, "interface", 0, body)
|
return api.baseAPI.applianceMonitorBy(id, "interface", 0, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Status ステータス取得
|
||||||
|
func (api *LoadBalancerAPI) Status(id int64) (*sacloud.LoadBalancerStatusResult, error) {
|
||||||
|
var (
|
||||||
|
method = "GET"
|
||||||
|
uri = fmt.Sprintf("%s/%d/status", api.getResourceURL(), id)
|
||||||
|
res = &loadBalancerStatusResponse{}
|
||||||
|
)
|
||||||
|
err := api.baseAPI.request(method, uri, nil, res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if res.LoadBalancer == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return res.LoadBalancer, nil
|
||||||
|
}
|
||||||
|
|
5
vendor/github.com/sacloud/libsacloud/api/mobile_gateway.go
generated
vendored
5
vendor/github.com/sacloud/libsacloud/api/mobile_gateway.go
generated
vendored
|
@ -473,3 +473,8 @@ func (api *MobileGatewayAPI) GetTrafficStatus(id int64) (*sacloud.TrafficStatus,
|
||||||
}
|
}
|
||||||
return res.TrafficStatus, nil
|
return res.TrafficStatus, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MonitorBy 指定位置のインターフェースのアクティビティーモニター取得
|
||||||
|
func (api *MobileGatewayAPI) MonitorBy(id int64, nicIndex int, body *sacloud.ResourceMonitorRequest) (*sacloud.MonitorValues, error) {
|
||||||
|
return api.baseAPI.applianceMonitorBy(id, "interface", nicIndex, body)
|
||||||
|
}
|
||||||
|
|
59
vendor/github.com/sacloud/libsacloud/api/nfs.go
generated
vendored
59
vendor/github.com/sacloud/libsacloud/api/nfs.go
generated
vendored
|
@ -2,6 +2,7 @@ package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -95,6 +96,58 @@ func (api *NFSAPI) Create(value *sacloud.NFS) (*sacloud.NFS, error) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateWithPlan プラン/サイズを指定してNFSを作成
|
||||||
|
func (api *NFSAPI) CreateWithPlan(value *sacloud.CreateNFSValue, plan sacloud.NFSPlan, size sacloud.NFSSize) (*sacloud.NFS, error) {
|
||||||
|
|
||||||
|
nfs := sacloud.NewNFS(value)
|
||||||
|
// get plan
|
||||||
|
plans, err := api.GetNFSPlans()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if plans == nil {
|
||||||
|
return nil, errors.New("NFS plans not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
planID := plans.FindPlanID(plan, size)
|
||||||
|
if planID < 0 {
|
||||||
|
return nil, errors.New("NFS plans not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
nfs.Plan = sacloud.NewResource(planID)
|
||||||
|
nfs.Remark.SetRemarkPlanID(planID)
|
||||||
|
|
||||||
|
return api.request(func(res *nfsResponse) error {
|
||||||
|
return api.create(api.createRequest(nfs), res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNFSPlans プラン一覧取得
|
||||||
|
func (api *NFSAPI) GetNFSPlans() (*sacloud.NFSPlans, error) {
|
||||||
|
notes, err := api.client.Note.Reset().Find()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, note := range notes.Notes {
|
||||||
|
if note.Class == sacloud.ENoteClass("json") && note.Name == "sys-nfs" {
|
||||||
|
rawPlans := note.Content
|
||||||
|
|
||||||
|
var plans struct {
|
||||||
|
Plans *sacloud.NFSPlans `json:"plans"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json.Unmarshal([]byte(rawPlans), &plans)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return plans.Plans, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Read 読み取り
|
// Read 読み取り
|
||||||
func (api *NFSAPI) Read(id int64) (*sacloud.NFS, error) {
|
func (api *NFSAPI) Read(id int64) (*sacloud.NFS, error) {
|
||||||
return api.request(func(res *nfsResponse) error {
|
return api.request(func(res *nfsResponse) error {
|
||||||
|
@ -224,9 +277,9 @@ func (api *NFSAPI) AsyncSleepWhileCopying(id int64, timeout time.Duration, maxRe
|
||||||
return poll(handler, timeout)
|
return poll(handler, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MonitorNFS NFS固有項目アクティビティモニター取得
|
// MonitorFreeDiskSize NFSディスク残量アクティビティモニター取得
|
||||||
func (api *NFSAPI) MonitorNFS(id int64, body *sacloud.ResourceMonitorRequest) (*sacloud.MonitorValues, error) {
|
func (api *NFSAPI) MonitorFreeDiskSize(id int64, body *sacloud.ResourceMonitorRequest) (*sacloud.MonitorValues, error) {
|
||||||
return api.baseAPI.applianceMonitorBy(id, "nfs", 0, body)
|
return api.baseAPI.applianceMonitorBy(id, "database", 0, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MonitorInterface NICアクティビティーモニター取得
|
// MonitorInterface NICアクティビティーモニター取得
|
||||||
|
|
224
vendor/github.com/sacloud/libsacloud/api/proxylb.go
generated
vendored
Normal file
224
vendor/github.com/sacloud/libsacloud/api/proxylb.go
generated
vendored
Normal file
|
@ -0,0 +1,224 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json" // "strings"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/sacloud/libsacloud/sacloud"
|
||||||
|
)
|
||||||
|
|
||||||
|
//HACK: さくらのAPI側仕様: CommonServiceItemsの内容によってJSONフォーマットが異なるため
|
||||||
|
// DNS/ProxyLB/シンプル監視それぞれでリクエスト/レスポンスデータ型を定義する。
|
||||||
|
|
||||||
|
// SearchProxyLBResponse ProxyLB検索レスポンス
|
||||||
|
type SearchProxyLBResponse struct {
|
||||||
|
// Total 総件数
|
||||||
|
Total int `json:",omitempty"`
|
||||||
|
// From ページング開始位置
|
||||||
|
From int `json:",omitempty"`
|
||||||
|
// Count 件数
|
||||||
|
Count int `json:",omitempty"`
|
||||||
|
// CommonServiceProxyLBItems ProxyLBリスト
|
||||||
|
CommonServiceProxyLBItems []sacloud.ProxyLB `json:"CommonServiceItems,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type proxyLBRequest struct {
|
||||||
|
CommonServiceProxyLBItem *sacloud.ProxyLB `json:"CommonServiceItem,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 proxyLBResponse struct {
|
||||||
|
*sacloud.ResultFlagValue
|
||||||
|
*sacloud.ProxyLB `json:"CommonServiceItem,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProxyLBAPI ProxyLB API
|
||||||
|
type ProxyLBAPI struct {
|
||||||
|
*baseAPI
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewProxyLBAPI ProxyLB API作成
|
||||||
|
func NewProxyLBAPI(client *Client) *ProxyLBAPI {
|
||||||
|
return &ProxyLBAPI{
|
||||||
|
&baseAPI{
|
||||||
|
client: client,
|
||||||
|
FuncGetResourceURL: func() string {
|
||||||
|
return "commonserviceitem"
|
||||||
|
},
|
||||||
|
FuncBaseSearchCondition: func() *sacloud.Request {
|
||||||
|
res := &sacloud.Request{}
|
||||||
|
res.AddFilter("Provider.Class", "proxylb")
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find 検索
|
||||||
|
func (api *ProxyLBAPI) Find() (*SearchProxyLBResponse, error) {
|
||||||
|
|
||||||
|
data, err := api.client.newRequest("GET", api.getResourceURL(), api.getSearchState())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var res SearchProxyLBResponse
|
||||||
|
if err := json.Unmarshal(data, &res); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *ProxyLBAPI) request(f func(*proxyLBResponse) error) (*sacloud.ProxyLB, error) {
|
||||||
|
res := &proxyLBResponse{}
|
||||||
|
err := f(res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res.ProxyLB, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *ProxyLBAPI) createRequest(value *sacloud.ProxyLB) *proxyLBResponse {
|
||||||
|
return &proxyLBResponse{ProxyLB: value}
|
||||||
|
}
|
||||||
|
|
||||||
|
// New 新規作成用パラメーター作成
|
||||||
|
func (api *ProxyLBAPI) New(name string) *sacloud.ProxyLB {
|
||||||
|
return sacloud.CreateNewProxyLB(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create 新規作成
|
||||||
|
func (api *ProxyLBAPI) Create(value *sacloud.ProxyLB) (*sacloud.ProxyLB, error) {
|
||||||
|
return api.request(func(res *proxyLBResponse) error {
|
||||||
|
return api.create(api.createRequest(value), res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read 読み取り
|
||||||
|
func (api *ProxyLBAPI) Read(id int64) (*sacloud.ProxyLB, error) {
|
||||||
|
return api.request(func(res *proxyLBResponse) error {
|
||||||
|
return api.read(id, nil, res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update 更新
|
||||||
|
func (api *ProxyLBAPI) Update(id int64, value *sacloud.ProxyLB) (*sacloud.ProxyLB, error) {
|
||||||
|
return api.request(func(res *proxyLBResponse) error {
|
||||||
|
return api.update(id, api.createRequest(value), res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateSetting 設定更新
|
||||||
|
func (api *ProxyLBAPI) UpdateSetting(id int64, value *sacloud.ProxyLB) (*sacloud.ProxyLB, error) {
|
||||||
|
req := &sacloud.ProxyLB{
|
||||||
|
// Settings
|
||||||
|
Settings: value.Settings,
|
||||||
|
}
|
||||||
|
return api.request(func(res *proxyLBResponse) error {
|
||||||
|
return api.update(id, api.createRequest(req), res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete 削除
|
||||||
|
func (api *ProxyLBAPI) Delete(id int64) (*sacloud.ProxyLB, error) {
|
||||||
|
return api.request(func(res *proxyLBResponse) error {
|
||||||
|
return api.delete(id, nil, res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChangePlan プラン変更
|
||||||
|
func (api *ProxyLBAPI) ChangePlan(id int64, newPlan sacloud.ProxyLBPlan) (*sacloud.ProxyLB, error) {
|
||||||
|
var (
|
||||||
|
method = "PUT"
|
||||||
|
uri = fmt.Sprintf("%s/%d/plan", api.getResourceURL(), id)
|
||||||
|
)
|
||||||
|
body := &sacloud.ProxyLB{}
|
||||||
|
body.SetPlan(newPlan)
|
||||||
|
realBody := map[string]interface{}{
|
||||||
|
"CommonServiceItem": map[string]interface{}{
|
||||||
|
"ServiceClass": body.ServiceClass,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return api.request(func(res *proxyLBResponse) error {
|
||||||
|
return api.baseAPI.request(method, uri, realBody, res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type proxyLBCertificateResponse struct {
|
||||||
|
*sacloud.ResultFlagValue
|
||||||
|
ProxyLB *sacloud.ProxyLBCertificates `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCertificates 証明書取得
|
||||||
|
func (api *ProxyLBAPI) GetCertificates(id int64) (*sacloud.ProxyLBCertificates, error) {
|
||||||
|
var (
|
||||||
|
method = "GET"
|
||||||
|
uri = fmt.Sprintf("%s/%d/proxylb/sslcertificate", api.getResourceURL(), id)
|
||||||
|
res = &proxyLBCertificateResponse{}
|
||||||
|
)
|
||||||
|
err := api.baseAPI.request(method, uri, nil, res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if res.ProxyLB == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return res.ProxyLB, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetCertificates 証明書設定
|
||||||
|
func (api *ProxyLBAPI) SetCertificates(id int64, certs *sacloud.ProxyLBCertificates) (bool, error) {
|
||||||
|
var (
|
||||||
|
method = "PUT"
|
||||||
|
uri = fmt.Sprintf("%s/%d/proxylb/sslcertificate", api.getResourceURL(), id)
|
||||||
|
res = &proxyLBCertificateResponse{}
|
||||||
|
)
|
||||||
|
err := api.baseAPI.request(method, uri, map[string]interface{}{
|
||||||
|
"ProxyLB": certs,
|
||||||
|
}, res)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteCertificates 証明書削除
|
||||||
|
func (api *ProxyLBAPI) DeleteCertificates(id int64) (bool, error) {
|
||||||
|
var (
|
||||||
|
method = "DELETE"
|
||||||
|
uri = fmt.Sprintf("%s/%d/proxylb/sslcertificate", api.getResourceURL(), id)
|
||||||
|
)
|
||||||
|
return api.baseAPI.modify(method, uri, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
type proxyLBHealthResponse struct {
|
||||||
|
*sacloud.ResultFlagValue
|
||||||
|
ProxyLB *sacloud.ProxyLBStatus `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Health ヘルスチェックステータス取得
|
||||||
|
func (api *ProxyLBAPI) Health(id int64) (*sacloud.ProxyLBStatus, error) {
|
||||||
|
var (
|
||||||
|
method = "GET"
|
||||||
|
uri = fmt.Sprintf("%s/%d/health", api.getResourceURL(), id)
|
||||||
|
res = &proxyLBHealthResponse{}
|
||||||
|
)
|
||||||
|
err := api.baseAPI.request(method, uri, nil, res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if res.ProxyLB == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return res.ProxyLB, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monitor アクティビティーモニター取得
|
||||||
|
func (api *ProxyLBAPI) Monitor(id int64, body *sacloud.ResourceMonitorRequest) (*sacloud.MonitorValues, error) {
|
||||||
|
return api.baseAPI.applianceMonitorBy(id, "activity/proxylb", 0, body)
|
||||||
|
}
|
238
vendor/github.com/sacloud/libsacloud/api/proxylb_gen.go
generated
vendored
Normal file
238
vendor/github.com/sacloud/libsacloud/api/proxylb_gen.go
generated
vendored
Normal file
|
@ -0,0 +1,238 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
/************************************************
|
||||||
|
generated by IDE. for [ProxyLBAPI]
|
||||||
|
************************************************/
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/sacloud/libsacloud/sacloud"
|
||||||
|
)
|
||||||
|
|
||||||
|
/************************************************
|
||||||
|
To support fluent interface for Find()
|
||||||
|
************************************************/
|
||||||
|
|
||||||
|
// Reset 検索条件のリセット
|
||||||
|
func (api *ProxyLBAPI) Reset() *ProxyLBAPI {
|
||||||
|
api.reset()
|
||||||
|
return api
|
||||||
|
}
|
||||||
|
|
||||||
|
// Offset オフセット
|
||||||
|
func (api *ProxyLBAPI) Offset(offset int) *ProxyLBAPI {
|
||||||
|
api.offset(offset)
|
||||||
|
return api
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limit リミット
|
||||||
|
func (api *ProxyLBAPI) Limit(limit int) *ProxyLBAPI {
|
||||||
|
api.limit(limit)
|
||||||
|
return api
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include 取得する項目
|
||||||
|
func (api *ProxyLBAPI) Include(key string) *ProxyLBAPI {
|
||||||
|
api.include(key)
|
||||||
|
return api
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exclude 除外する項目
|
||||||
|
func (api *ProxyLBAPI) Exclude(key string) *ProxyLBAPI {
|
||||||
|
api.exclude(key)
|
||||||
|
return api
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterBy 指定キーでのフィルター
|
||||||
|
func (api *ProxyLBAPI) FilterBy(key string, value interface{}) *ProxyLBAPI {
|
||||||
|
api.filterBy(key, value, false)
|
||||||
|
return api
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterMultiBy 任意項目でのフィルタ(完全一致 OR条件)
|
||||||
|
func (api *ProxyLBAPI) FilterMultiBy(key string, value interface{}) *ProxyLBAPI {
|
||||||
|
api.filterBy(key, value, true)
|
||||||
|
return api
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithNameLike 名称条件
|
||||||
|
func (api *ProxyLBAPI) WithNameLike(name string) *ProxyLBAPI {
|
||||||
|
return api.FilterBy("Name", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTag タグ条件
|
||||||
|
func (api *ProxyLBAPI) WithTag(tag string) *ProxyLBAPI {
|
||||||
|
return api.FilterBy("Tags.Name", tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTags タグ(複数)条件
|
||||||
|
func (api *ProxyLBAPI) WithTags(tags []string) *ProxyLBAPI {
|
||||||
|
return api.FilterBy("Tags.Name", []interface{}{tags})
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (api *ProxyLBAPI) WithSizeGib(size int) *ProxyLBAPI {
|
||||||
|
// api.FilterBy("SizeMB", size*1024)
|
||||||
|
// return api
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (api *ProxyLBAPI) WithSharedScope() *ProxyLBAPI {
|
||||||
|
// api.FilterBy("Scope", "shared")
|
||||||
|
// return api
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (api *ProxyLBAPI) WithUserScope() *ProxyLBAPI {
|
||||||
|
// api.FilterBy("Scope", "user")
|
||||||
|
// return api
|
||||||
|
// }
|
||||||
|
|
||||||
|
// SortBy 指定キーでのソート
|
||||||
|
func (api *ProxyLBAPI) SortBy(key string, reverse bool) *ProxyLBAPI {
|
||||||
|
api.sortBy(key, reverse)
|
||||||
|
return api
|
||||||
|
}
|
||||||
|
|
||||||
|
// SortByName 名称でのソート
|
||||||
|
func (api *ProxyLBAPI) SortByName(reverse bool) *ProxyLBAPI {
|
||||||
|
api.sortByName(reverse)
|
||||||
|
return api
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (api *ProxyLBAPI) SortBySize(reverse bool) *ProxyLBAPI {
|
||||||
|
// api.sortBy("SizeMB", reverse)
|
||||||
|
// return api
|
||||||
|
// }
|
||||||
|
|
||||||
|
/************************************************
|
||||||
|
To support Setxxx interface for Find()
|
||||||
|
************************************************/
|
||||||
|
|
||||||
|
// SetEmpty 検索条件のリセット
|
||||||
|
func (api *ProxyLBAPI) SetEmpty() {
|
||||||
|
api.reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOffset オフセット
|
||||||
|
func (api *ProxyLBAPI) SetOffset(offset int) {
|
||||||
|
api.offset(offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLimit リミット
|
||||||
|
func (api *ProxyLBAPI) SetLimit(limit int) {
|
||||||
|
api.limit(limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetInclude 取得する項目
|
||||||
|
func (api *ProxyLBAPI) SetInclude(key string) {
|
||||||
|
api.include(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetExclude 除外する項目
|
||||||
|
func (api *ProxyLBAPI) SetExclude(key string) {
|
||||||
|
api.exclude(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetFilterBy 指定キーでのフィルター
|
||||||
|
func (api *ProxyLBAPI) SetFilterBy(key string, value interface{}) {
|
||||||
|
api.filterBy(key, value, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetFilterMultiBy 任意項目でのフィルタ(完全一致 OR条件)
|
||||||
|
func (api *ProxyLBAPI) SetFilterMultiBy(key string, value interface{}) {
|
||||||
|
api.filterBy(key, value, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNameLike 名称条件
|
||||||
|
func (api *ProxyLBAPI) SetNameLike(name string) {
|
||||||
|
api.FilterBy("Name", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTag タグ条件
|
||||||
|
func (api *ProxyLBAPI) SetTag(tag string) {
|
||||||
|
api.FilterBy("Tags.Name", tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTags タグ(複数)条件
|
||||||
|
func (api *ProxyLBAPI) SetTags(tags []string) {
|
||||||
|
api.FilterBy("Tags.Name", []interface{}{tags})
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (api *ProxyLBAPI) SetSizeGib(size int) {
|
||||||
|
// api.FilterBy("SizeMB", size*1024)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (api *ProxyLBAPI) SetSharedScope() {
|
||||||
|
// api.FilterBy("Scope", "shared")
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (api *ProxyLBAPI) SetUserScope() {
|
||||||
|
// api.FilterBy("Scope", "user")
|
||||||
|
// }
|
||||||
|
|
||||||
|
// SetSortBy 指定キーでのソート
|
||||||
|
func (api *ProxyLBAPI) SetSortBy(key string, reverse bool) {
|
||||||
|
api.sortBy(key, reverse)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSortByName 名称でのソート
|
||||||
|
func (api *ProxyLBAPI) SetSortByName(reverse bool) {
|
||||||
|
api.sortByName(reverse)
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (api *ProxyLBAPI) SetSortBySize(reverse bool) {
|
||||||
|
// api.sortBy("SizeMB", reverse)
|
||||||
|
// }
|
||||||
|
|
||||||
|
/************************************************
|
||||||
|
To support CRUD(Create/Read/Update/Delete)
|
||||||
|
************************************************/
|
||||||
|
|
||||||
|
// func (api *ProxyLBAPI) New() *sacloud.ProxyLB {
|
||||||
|
// return &sacloud.ProxyLB{}
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (api *ProxyLBAPI) Create(value *sacloud.ProxyLB) (*sacloud.ProxyLB, error) {
|
||||||
|
// return api.request(func(res *sacloud.Response) error {
|
||||||
|
// return api.create(api.createRequest(value), res)
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (api *ProxyLBAPI) Read(id string) (*sacloud.ProxyLB, error) {
|
||||||
|
// return api.request(func(res *sacloud.Response) error {
|
||||||
|
// return api.read(id, nil, res)
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (api *ProxyLBAPI) Update(id string, value *sacloud.ProxyLB) (*sacloud.ProxyLB, error) {
|
||||||
|
// return api.request(func(res *sacloud.Response) error {
|
||||||
|
// return api.update(id, api.createRequest(value), res)
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (api *ProxyLBAPI) Delete(id string) (*sacloud.ProxyLB, error) {
|
||||||
|
// return api.request(func(res *sacloud.Response) error {
|
||||||
|
// return api.delete(id, nil, res)
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
/************************************************
|
||||||
|
Inner functions
|
||||||
|
************************************************/
|
||||||
|
|
||||||
|
func (api *ProxyLBAPI) setStateValue(setFunc func(*sacloud.Request)) *ProxyLBAPI {
|
||||||
|
api.baseAPI.setStateValue(setFunc)
|
||||||
|
return api
|
||||||
|
}
|
||||||
|
|
||||||
|
//func (api *ProxyLBAPI) request(f func(*sacloud.Response) error) (*sacloud.ProxyLB, error) {
|
||||||
|
// res := &sacloud.Response{}
|
||||||
|
// err := f(res)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
// return res.ProxyLB, nil
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func (api *ProxyLBAPI) createRequest(value *sacloud.ProxyLB) *sacloud.Request {
|
||||||
|
// req := &sacloud.Request{}
|
||||||
|
// req.ProxyLB = value
|
||||||
|
// return req
|
||||||
|
//}
|
31
vendor/github.com/sacloud/libsacloud/api/sim.go
generated
vendored
31
vendor/github.com/sacloud/libsacloud/api/sim.go
generated
vendored
|
@ -204,6 +204,37 @@ func (api *SIMAPI) Logs(id int64, body interface{}) ([]sacloud.SIMLog, error) {
|
||||||
return res.Logs, nil
|
return res.Logs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetNetworkOperator 通信キャリア 取得
|
||||||
|
func (api *SIMAPI) GetNetworkOperator(id int64) (*sacloud.SIMNetworkOperatorConfigs, error) {
|
||||||
|
|
||||||
|
var (
|
||||||
|
method = "GET"
|
||||||
|
uri = fmt.Sprintf("%s/%d/sim/network_operator_config", api.getResourceURL(), id)
|
||||||
|
)
|
||||||
|
|
||||||
|
res := &sacloud.SIMNetworkOperatorConfigs{}
|
||||||
|
err := api.baseAPI.request(method, uri, nil, res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNetworkOperator 通信キャリア 設定
|
||||||
|
func (api *SIMAPI) SetNetworkOperator(id int64, opConfig ...*sacloud.SIMNetworkOperatorConfig) (bool, error) {
|
||||||
|
|
||||||
|
var (
|
||||||
|
method = "PUT"
|
||||||
|
uri = fmt.Sprintf("%s/%d/sim/network_operator_config", api.getResourceURL(), id)
|
||||||
|
)
|
||||||
|
|
||||||
|
err := api.baseAPI.request(method, uri, &sacloud.SIMNetworkOperatorConfigs{NetworkOperatorConfigs: opConfig}, nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Monitor アクティビティーモニター(Up/Down link BPS)取得
|
// Monitor アクティビティーモニター(Up/Down link BPS)取得
|
||||||
func (api *SIMAPI) Monitor(id int64, body *sacloud.ResourceMonitorRequest) (*sacloud.MonitorValues, error) {
|
func (api *SIMAPI) Monitor(id int64, body *sacloud.ResourceMonitorRequest) (*sacloud.MonitorValues, error) {
|
||||||
var (
|
var (
|
||||||
|
|
19
vendor/github.com/sacloud/libsacloud/api/simple_monitor.go
generated
vendored
19
vendor/github.com/sacloud/libsacloud/api/simple_monitor.go
generated
vendored
|
@ -118,6 +118,25 @@ func (api *SimpleMonitorAPI) Delete(id int64) (*sacloud.SimpleMonitor, error) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Health ヘルスチェック
|
||||||
|
//
|
||||||
|
// まだチェックが行われていない場合nilを返す
|
||||||
|
func (api *SimpleMonitorAPI) Health(id int64) (*sacloud.SimpleMonitorHealthCheckStatus, error) {
|
||||||
|
var (
|
||||||
|
method = "GET"
|
||||||
|
uri = fmt.Sprintf("%s/%d/health", api.getResourceURL(), id)
|
||||||
|
)
|
||||||
|
res := struct {
|
||||||
|
SimpleMonitor *sacloud.SimpleMonitorHealthCheckStatus `json:",omitempty"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
err := api.baseAPI.request(method, uri, nil, &res)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return res.SimpleMonitor, nil
|
||||||
|
}
|
||||||
|
|
||||||
// MonitorResponseTimeSec アクティビティーモニター(レスポンスタイム)取得
|
// MonitorResponseTimeSec アクティビティーモニター(レスポンスタイム)取得
|
||||||
func (api *SimpleMonitorAPI) MonitorResponseTimeSec(id int64, body *sacloud.ResourceMonitorRequest) (*sacloud.MonitorValues, error) {
|
func (api *SimpleMonitorAPI) MonitorResponseTimeSec(id int64, body *sacloud.ResourceMonitorRequest) (*sacloud.MonitorValues, error) {
|
||||||
var (
|
var (
|
||||||
|
|
2
vendor/github.com/sacloud/libsacloud/libsacloud.go
generated
vendored
2
vendor/github.com/sacloud/libsacloud/libsacloud.go
generated
vendored
|
@ -2,4 +2,4 @@
|
||||||
package libsacloud
|
package libsacloud
|
||||||
|
|
||||||
// Version バージョン
|
// Version バージョン
|
||||||
const Version = "1.0.0"
|
const Version = "1.19.0"
|
||||||
|
|
30
vendor/github.com/sacloud/libsacloud/sacloud/common_types.go
generated
vendored
30
vendor/github.com/sacloud/libsacloud/sacloud/common_types.go
generated
vendored
|
@ -138,6 +138,36 @@ var (
|
||||||
// EDiskConnection ディスク接続方法
|
// EDiskConnection ディスク接続方法
|
||||||
type EDiskConnection string
|
type EDiskConnection string
|
||||||
|
|
||||||
|
// EUpstreamNetworkType 上流ネットワーク種別
|
||||||
|
type EUpstreamNetworkType string
|
||||||
|
|
||||||
|
// String EUpstreamNetworkTypeの文字列表現
|
||||||
|
func (t EUpstreamNetworkType) String() string {
|
||||||
|
return string(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// EUpstreamNetworkUnknown 不明
|
||||||
|
EUpstreamNetworkUnknown = EUpstreamNetworkType("unknown")
|
||||||
|
// EUpstreamNetworkShared 共有セグメント
|
||||||
|
EUpstreamNetworkShared = EUpstreamNetworkType("shared")
|
||||||
|
// EUpstreamNetworkSwitch スイッチ(非スイッチ+ルータ)
|
||||||
|
EUpstreamNetworkSwitch = EUpstreamNetworkType("switch")
|
||||||
|
// EUpstreamNetworkRouter ルータ(スイッチ+ルータのスイッチ)
|
||||||
|
EUpstreamNetworkRouter = EUpstreamNetworkType("router")
|
||||||
|
// EUpstreamNetworkNone 接続なし
|
||||||
|
EUpstreamNetworkNone = EUpstreamNetworkType("none")
|
||||||
|
|
||||||
|
// UpstreamNetworks 文字列とEUpstreamNetworkTypeのマッピング
|
||||||
|
UpstreamNetworks = map[string]EUpstreamNetworkType{
|
||||||
|
"unknown": EUpstreamNetworkUnknown,
|
||||||
|
"shared": EUpstreamNetworkShared,
|
||||||
|
"switch": EUpstreamNetworkSwitch,
|
||||||
|
"router": EUpstreamNetworkRouter,
|
||||||
|
"none": EUpstreamNetworkNone,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// SakuraCloudResources さくらのクラウド上のリソース種別一覧
|
// SakuraCloudResources さくらのクラウド上のリソース種別一覧
|
||||||
type SakuraCloudResources struct {
|
type SakuraCloudResources struct {
|
||||||
Server *Server `json:",omitempty"` // サーバー
|
Server *Server `json:",omitempty"` // サーバー
|
||||||
|
|
14
vendor/github.com/sacloud/libsacloud/sacloud/coupon.go
generated
vendored
Normal file
14
vendor/github.com/sacloud/libsacloud/sacloud/coupon.go
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package sacloud
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// Coupon クーポン情報
|
||||||
|
type Coupon struct {
|
||||||
|
CouponID string `json:",omitempty"` // クーポンID
|
||||||
|
MemberID string `json:",omitempty"` // メンバーID
|
||||||
|
ContractID int64 `json:",omitempty"` // 契約ID
|
||||||
|
ServiceClassID int64 `json:",omitempty"` // サービスクラスID
|
||||||
|
Discount int64 `json:",omitempty"` // クーポン残高
|
||||||
|
AppliedAt time.Time `json:",omitempty"` // 適用開始日
|
||||||
|
UntilAt time.Time `json:",omitempty"` // 有効期限
|
||||||
|
}
|
71
vendor/github.com/sacloud/libsacloud/sacloud/database.go
generated
vendored
71
vendor/github.com/sacloud/libsacloud/sacloud/database.go
generated
vendored
|
@ -181,7 +181,9 @@ type DatabaseReplicationSetting struct {
|
||||||
// Model レプリケーションモデル
|
// Model レプリケーションモデル
|
||||||
Model DatabaseReplicationModels `json:",omitempty"`
|
Model DatabaseReplicationModels `json:",omitempty"`
|
||||||
// Appliance マスター側アプライアンス
|
// Appliance マスター側アプライアンス
|
||||||
Appliance *Resource `json:",omitempty"`
|
Appliance *struct {
|
||||||
|
ID string
|
||||||
|
} `json:",omitempty"`
|
||||||
// IPAddress IPアドレス
|
// IPAddress IPアドレス
|
||||||
IPAddress string `json:",omitempty"`
|
IPAddress string `json:",omitempty"`
|
||||||
// Port ポート
|
// Port ポート
|
||||||
|
@ -456,7 +458,7 @@ func NewSlaveDatabaseValue(values *SlaveDatabaseValue) *Database {
|
||||||
// Replication
|
// Replication
|
||||||
Replication: &DatabaseReplicationSetting{
|
Replication: &DatabaseReplicationSetting{
|
||||||
Model: DatabaseReplicationModelAsyncReplica,
|
Model: DatabaseReplicationModelAsyncReplica,
|
||||||
Appliance: NewResource(values.MasterApplianceID),
|
Appliance: &struct{ ID string }{ID: fmt.Sprintf("%d", values.MasterApplianceID)},
|
||||||
IPAddress: values.MasterIPAddress,
|
IPAddress: values.MasterIPAddress,
|
||||||
Port: values.MasterPort,
|
Port: values.MasterPort,
|
||||||
User: "replica",
|
User: "replica",
|
||||||
|
@ -504,5 +506,68 @@ func (s *Database) DeleteSourceNetwork(nw string) {
|
||||||
|
|
||||||
// IsReplicationMaster レプリケーションが有効かつマスターとして構成されているか
|
// IsReplicationMaster レプリケーションが有効かつマスターとして構成されているか
|
||||||
func (s *Database) IsReplicationMaster() bool {
|
func (s *Database) IsReplicationMaster() bool {
|
||||||
return s.Settings.DBConf.Replication != nil && s.Settings.DBConf.Replication.Model == DatabaseReplicationModelMasterSlave
|
return s.IsReplicationEnabled() && s.Settings.DBConf.Replication.Model == DatabaseReplicationModelMasterSlave
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsReplicationEnabled レプリケーションが有効な場合はTrueを返す
|
||||||
|
func (s *Database) IsReplicationEnabled() bool {
|
||||||
|
return s.Settings.DBConf.Replication != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DatabaseName MariaDB or PostgreSQLの何れかを返す
|
||||||
|
func (s *Database) DatabaseName() string {
|
||||||
|
return s.Remark.DBConf.Common.DatabaseName
|
||||||
|
}
|
||||||
|
|
||||||
|
// DatabaseRevision データベースのリビジョンを返す
|
||||||
|
//
|
||||||
|
// 例: MariaDBの場合 => 10.2.15 / PostgreSQLの場合 => 10.3
|
||||||
|
func (s *Database) DatabaseRevision() string {
|
||||||
|
return s.Remark.DBConf.Common.DatabaseRevision
|
||||||
|
}
|
||||||
|
|
||||||
|
// DatabaseVersion データベースのバージョンを返す
|
||||||
|
//
|
||||||
|
// 例: MariaDBの場合 => 10.2 / PostgreSQLの場合 => 10
|
||||||
|
func (s *Database) DatabaseVersion() string {
|
||||||
|
return s.Remark.DBConf.Common.DatabaseVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebUIAddress WebUIが有効な場合、IPアドレス or FQDNを返す、無効な場合は空文字を返す
|
||||||
|
func (s *Database) WebUIAddress() string {
|
||||||
|
webUI := s.Settings.DBConf.Common.WebUI
|
||||||
|
if webUI != nil {
|
||||||
|
if v, ok := webUI.(string); ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPAddress IPアドレスを取得
|
||||||
|
func (s *Database) IPAddress() string {
|
||||||
|
if len(s.Remark.Servers) < 1 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
v, ok := s.Remark.Servers[0].(map[string]string)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return v["IPAddress"]
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkMaskLen ネットワークマスク長を取得
|
||||||
|
func (s *Database) NetworkMaskLen() int {
|
||||||
|
if s.Remark.Network == nil {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return s.Remark.Network.NetworkMaskLen
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultRoute デフォルトゲートウェイアドレスを取得
|
||||||
|
func (s *Database) DefaultRoute() string {
|
||||||
|
if s.Remark.Network == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return s.Remark.Network.DefaultRoute
|
||||||
}
|
}
|
||||||
|
|
18
vendor/github.com/sacloud/libsacloud/sacloud/interface.go
generated
vendored
18
vendor/github.com/sacloud/libsacloud/sacloud/interface.go
generated
vendored
|
@ -41,3 +41,21 @@ func (i *Interface) GetHostName() string {
|
||||||
func (i *Interface) GetPacketFilter() *PacketFilter {
|
func (i *Interface) GetPacketFilter() *PacketFilter {
|
||||||
return i.PacketFilter
|
return i.PacketFilter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpstreamType 上流ネットワーク種別
|
||||||
|
func (i *Interface) UpstreamType() EUpstreamNetworkType {
|
||||||
|
sw := i.Switch
|
||||||
|
if sw == nil {
|
||||||
|
return EUpstreamNetworkNone
|
||||||
|
}
|
||||||
|
|
||||||
|
if sw.Subnet == nil {
|
||||||
|
return EUpstreamNetworkSwitch
|
||||||
|
}
|
||||||
|
|
||||||
|
if sw.Scope == ESCopeShared {
|
||||||
|
return EUpstreamNetworkShared
|
||||||
|
}
|
||||||
|
|
||||||
|
return EUpstreamNetworkRouter
|
||||||
|
}
|
||||||
|
|
111
vendor/github.com/sacloud/libsacloud/sacloud/loadbalancer.go
generated
vendored
111
vendor/github.com/sacloud/libsacloud/sacloud/loadbalancer.go
generated
vendored
|
@ -1,5 +1,7 @@
|
||||||
package sacloud
|
package sacloud
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
// LoadBalancer ロードバランサー
|
// LoadBalancer ロードバランサー
|
||||||
type LoadBalancer struct {
|
type LoadBalancer struct {
|
||||||
*Appliance // アプライアンス共通属性
|
*Appliance // アプライアンス共通属性
|
||||||
|
@ -8,6 +10,43 @@ type LoadBalancer struct {
|
||||||
Settings *LoadBalancerSettings `json:",omitempty"` // ロードバランサー設定
|
Settings *LoadBalancerSettings `json:",omitempty"` // ロードバランサー設定
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsHA 冗長化されている場合にtrueを返す
|
||||||
|
func (l *LoadBalancer) IsHA() bool {
|
||||||
|
isHA := false
|
||||||
|
if len(l.Remark.Servers) > 1 {
|
||||||
|
if v, ok := l.Remark.Servers[1].(map[string]string); ok {
|
||||||
|
if _, ok := v["IPAddress"]; ok {
|
||||||
|
isHA = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isHA
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPAddress1 ロードバランサ本体のIPアドレス(1番目)を返す
|
||||||
|
func (l *LoadBalancer) IPAddress1() string {
|
||||||
|
if len(l.Remark.Servers) > 0 {
|
||||||
|
if v, ok := l.Remark.Servers[0].(map[string]string); ok {
|
||||||
|
if v, ok := v["IPAddress"]; ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPAddress2 ロードバランサ本体のIPアドレス(2番目)を返す
|
||||||
|
func (l *LoadBalancer) IPAddress2() string {
|
||||||
|
if len(l.Remark.Servers) > 1 {
|
||||||
|
if v, ok := l.Remark.Servers[1].(map[string]string); ok {
|
||||||
|
if v, ok := v["IPAddress"]; ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// LoadBalancerRemark リマーク
|
// LoadBalancerRemark リマーク
|
||||||
type LoadBalancerRemark struct {
|
type LoadBalancerRemark struct {
|
||||||
*ApplianceRemarkBase
|
*ApplianceRemarkBase
|
||||||
|
@ -17,7 +56,7 @@ type LoadBalancerRemark struct {
|
||||||
|
|
||||||
// LoadBalancerSettings ロードバランサー設定リスト
|
// LoadBalancerSettings ロードバランサー設定リスト
|
||||||
type LoadBalancerSettings struct {
|
type LoadBalancerSettings struct {
|
||||||
LoadBalancer []*LoadBalancerSetting `json:",omitempty"` // ロードバランサー設定リスト
|
LoadBalancer []*LoadBalancerSetting // ロードバランサー設定リスト
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadBalancerSetting ロードバランサー仮想IP設定
|
// LoadBalancerSetting ロードバランサー仮想IP設定
|
||||||
|
@ -180,3 +219,73 @@ func (s *LoadBalancerSetting) DeleteServer(ip string, port string) {
|
||||||
s.Servers = res
|
s.Servers = res
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadBalancerStatusResult ロードバランサーのステータスAPI戻り値
|
||||||
|
type LoadBalancerStatusResult []*LoadBalancerStatus
|
||||||
|
|
||||||
|
// Get VIPに対応するステータスを取得
|
||||||
|
func (l *LoadBalancerStatusResult) Get(vip string) *LoadBalancerStatus {
|
||||||
|
for _, v := range *l {
|
||||||
|
if v.VirtualIPAddress == vip {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadBalancerStatus ロードバランサーのステータス
|
||||||
|
type LoadBalancerStatus struct {
|
||||||
|
VirtualIPAddress string
|
||||||
|
Port string
|
||||||
|
Servers []*LoadBalancerServerStatus `json:",omitempty"`
|
||||||
|
CPS string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get IPアドレスに対応する実サーバのステータスを取得
|
||||||
|
func (l *LoadBalancerStatus) Get(ip string) *LoadBalancerServerStatus {
|
||||||
|
for _, v := range l.Servers {
|
||||||
|
if v.IPAddress == ip {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NumCPS CPSを数値にして返す
|
||||||
|
func (l *LoadBalancerStatus) NumCPS() int {
|
||||||
|
v, _ := strconv.Atoi(l.CPS) // nolint - ignore error
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// NumPort Portを数値にして返す
|
||||||
|
func (l *LoadBalancerStatus) NumPort() int {
|
||||||
|
v, _ := strconv.Atoi(l.Port) // nolint - ignore error
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadBalancerServerStatus ロードバランサーのVIP配下の実サーバのステータス
|
||||||
|
type LoadBalancerServerStatus struct {
|
||||||
|
ActiveConn string
|
||||||
|
IPAddress string
|
||||||
|
Status string
|
||||||
|
Port string
|
||||||
|
CPS string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NumActiveConn ActiveConnを数値にして返す
|
||||||
|
func (l *LoadBalancerServerStatus) NumActiveConn() int {
|
||||||
|
v, _ := strconv.Atoi(l.ActiveConn) // nolint - ignore error
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// NumCPS CPSを数値にして返す
|
||||||
|
func (l *LoadBalancerServerStatus) NumCPS() int {
|
||||||
|
v, _ := strconv.Atoi(l.CPS) // nolint - ignore error
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// NumPort Portを数値にして返す
|
||||||
|
func (l *LoadBalancerServerStatus) NumPort() int {
|
||||||
|
v, _ := strconv.Atoi(l.Port) // nolint - ignore error
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
29
vendor/github.com/sacloud/libsacloud/sacloud/lock.go
generated
vendored
Normal file
29
vendor/github.com/sacloud/libsacloud/sacloud/lock.go
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
package sacloud
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/sacloud/libsacloud/utils/mutexkv"
|
||||||
|
)
|
||||||
|
|
||||||
|
var resourceMu = mutexkv.NewMutexKV()
|
||||||
|
|
||||||
|
// LockByKey 任意のキーでのMutexロック
|
||||||
|
func LockByKey(key string) {
|
||||||
|
resourceMu.Lock(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnlockByKey 任意のキーでのMutexアンロック
|
||||||
|
func UnlockByKey(key string) {
|
||||||
|
resourceMu.Unlock(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LockByResourceID リソース単位でのMutexロック
|
||||||
|
func LockByResourceID(resourceID int64) {
|
||||||
|
resourceMu.Lock(fmt.Sprintf("%d", resourceID))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnlockByResourceID リソース単位でのMutexアンロック
|
||||||
|
func UnlockByResourceID(resourceID int64) {
|
||||||
|
resourceMu.Unlock(fmt.Sprintf("%d", resourceID))
|
||||||
|
}
|
64
vendor/github.com/sacloud/libsacloud/sacloud/mobile_gateway.go
generated
vendored
64
vendor/github.com/sacloud/libsacloud/sacloud/mobile_gateway.go
generated
vendored
|
@ -29,9 +29,10 @@ type MobileGatewaySettings struct {
|
||||||
|
|
||||||
// MobileGatewaySetting モバイルゲートウェイ設定
|
// MobileGatewaySetting モバイルゲートウェイ設定
|
||||||
type MobileGatewaySetting struct {
|
type MobileGatewaySetting struct {
|
||||||
InternetConnection *MGWInternetConnection `json:",omitempty"` // インターネット接続
|
InternetConnection *MGWInternetConnection `json:",omitempty"` // インターネット接続
|
||||||
Interfaces []*MGWInterface `json:",omitempty"` // インターフェース
|
InterDeviceCommunication *MGWInterDeviceCommunication `json:",omitempty"` // デバイス間通信
|
||||||
StaticRoutes []*MGWStaticRoute `json:",omitempty"` // スタティックルート
|
Interfaces []*MGWInterface `json:",omitempty"` // インターフェース
|
||||||
|
StaticRoutes []*MGWStaticRoute `json:",omitempty"` // スタティックルート
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasStaticRoutes スタティックルートを保持しているか
|
// HasStaticRoutes スタティックルートを保持しているか
|
||||||
|
@ -90,6 +91,11 @@ func (m *MobileGatewaySetting) FindStaticRoute(prefix string, nextHop string) (i
|
||||||
return -1, nil
|
return -1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MGWInterDeviceCommunication デバイス間通信
|
||||||
|
type MGWInterDeviceCommunication struct {
|
||||||
|
Enabled string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// MGWInternetConnection インターネット接続
|
// MGWInternetConnection インターネット接続
|
||||||
type MGWInternetConnection struct {
|
type MGWInternetConnection struct {
|
||||||
Enabled string `json:",omitempty"`
|
Enabled string `json:",omitempty"`
|
||||||
|
@ -188,6 +194,58 @@ func (m *MobileGateway) HasStaticRoutes() bool {
|
||||||
return m.HasSetting() && m.Settings.MobileGateway.HasStaticRoutes()
|
return m.HasSetting() && m.Settings.MobileGateway.HasStaticRoutes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InternetConnection インターネット接続が有効な場合にTrueを返す
|
||||||
|
func (m *MobileGateway) InternetConnection() bool {
|
||||||
|
return m.HasSetting() &&
|
||||||
|
m.Settings.MobileGateway.InternetConnection != nil &&
|
||||||
|
m.Settings.MobileGateway.InternetConnection.Enabled == "True"
|
||||||
|
}
|
||||||
|
|
||||||
|
// InterDeviceCommunication デバイス間通信が有効な場合にTrueを返す
|
||||||
|
func (m *MobileGateway) InterDeviceCommunication() bool {
|
||||||
|
return m.HasSetting() &&
|
||||||
|
m.Settings.MobileGateway.InterDeviceCommunication != nil &&
|
||||||
|
m.Settings.MobileGateway.InterDeviceCommunication.Enabled == "True"
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPAddress 0番目のNICのIPアドレスを取得
|
||||||
|
func (m *MobileGateway) IPAddress() string {
|
||||||
|
return m.IPAddressAt(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPAddressAt IPアドレスを取得
|
||||||
|
func (m *MobileGateway) IPAddressAt(index int) string {
|
||||||
|
if len(m.Interfaces) <= index {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if index == 0 {
|
||||||
|
return m.Interfaces[0].IPAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
ipaddresses := m.Settings.MobileGateway.Interfaces[index].IPAddress
|
||||||
|
if len(ipaddresses) < 1 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return ipaddresses[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkMaskLen 0番目のNICのネットワークマスク長を取得
|
||||||
|
func (m *MobileGateway) NetworkMaskLen() int {
|
||||||
|
return m.NetworkMaskLenAt(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkMaskLenAt ネットワークマスク長を取得
|
||||||
|
func (m *MobileGateway) NetworkMaskLenAt(index int) int {
|
||||||
|
if len(m.Interfaces) <= index {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if index == 0 {
|
||||||
|
return m.Interfaces[0].Switch.UserSubnet.NetworkMaskLen
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.Settings.MobileGateway.Interfaces[0].NetworkMaskLen
|
||||||
|
}
|
||||||
|
|
||||||
// NewMobileGatewayResolver DNS登録用パラメータ作成
|
// NewMobileGatewayResolver DNS登録用パラメータ作成
|
||||||
func NewMobileGatewayResolver(dns1, dns2 string) *MobileGatewayResolver {
|
func NewMobileGatewayResolver(dns1, dns2 string) *MobileGatewayResolver {
|
||||||
return &MobileGatewayResolver{
|
return &MobileGatewayResolver{
|
||||||
|
|
119
vendor/github.com/sacloud/libsacloud/sacloud/monitor.go
generated
vendored
119
vendor/github.com/sacloud/libsacloud/sacloud/monitor.go
generated
vendored
|
@ -9,23 +9,27 @@ import (
|
||||||
|
|
||||||
// MonitorValue アクティビティモニター
|
// MonitorValue アクティビティモニター
|
||||||
type MonitorValue struct {
|
type MonitorValue struct {
|
||||||
CPUTime *float64 `json:"CPU-TIME,omitempty"` // CPU時間
|
CPUTime *float64 `json:"CPU-TIME,omitempty"` // CPU時間
|
||||||
Write *float64 `json:",omitempty"` // ディスク書き込み
|
Write *float64 `json:",omitempty"` // ディスク書き込み
|
||||||
Read *float64 `json:",omitempty"` // ディスク読み取り
|
Read *float64 `json:",omitempty"` // ディスク読み取り
|
||||||
Receive *float64 `json:",omitempty"` // パケット受信
|
Receive *float64 `json:",omitempty"` // パケット受信
|
||||||
Send *float64 `json:",omitempty"` // パケット送信
|
Send *float64 `json:",omitempty"` // パケット送信
|
||||||
In *float64 `json:",omitempty"` // パケット受信
|
In *float64 `json:",omitempty"` // パケット受信
|
||||||
Out *float64 `json:",omitempty"` // パケット送信
|
Out *float64 `json:",omitempty"` // パケット送信
|
||||||
TotalMemorySize *float64 `json:"Total-Memory-Size,omitempty"` // 総メモリサイズ
|
TotalMemorySize *float64 `json:"Total-Memory-Size,omitempty"` // 総メモリサイズ
|
||||||
UsedMemorySize *float64 `json:"Used-Memory-Size,omitempty"` // 使用済みメモリサイズ
|
UsedMemorySize *float64 `json:"Used-Memory-Size,omitempty"` // 使用済みメモリサイズ
|
||||||
TotalDisk1Size *float64 `json:"Total-Disk1-Size,omitempty"` // 総ディスクサイズ
|
TotalDisk1Size *float64 `json:"Total-Disk1-Size,omitempty"` // 総ディスクサイズ
|
||||||
UsedDisk1Size *float64 `json:"Used-Disk1-Size,omitempty"` // 使用済みディスクサイズ
|
UsedDisk1Size *float64 `json:"Used-Disk1-Size,omitempty"` // 使用済みディスクサイズ
|
||||||
TotalDisk2Size *float64 `json:"Total-Disk2-Size,omitempty"` // 総ディスクサイズ
|
TotalDisk2Size *float64 `json:"Total-Disk2-Size,omitempty"` // 総ディスクサイズ
|
||||||
UsedDisk2Size *float64 `json:"Used-Disk2-Size,omitempty"` // 使用済みディスクサイズ
|
UsedDisk2Size *float64 `json:"Used-Disk2-Size,omitempty"` // 使用済みディスクサイズ
|
||||||
FreeDiskSize *float64 `json:"Free-Disk-Size,omitempty"` // 空きディスクサイズ(NFS)
|
BinlogUsedSizeKiB *float64 `json:"binlogUsedSizeKiB,omitempty"` // バイナリログのサイズ(レプリケーション有効時のみ、master/slave両方で利用可能)
|
||||||
ResponseTimeSec *float64 `json:"responsetimesec,omitempty"` // レスポンスタイム(シンプル監視)
|
DelayTimeSec *float64 `json:"delayTimeSec,omitempty"` // レプリケーション遅延時間(レプリケーション有効時のみ、slave側のみ)
|
||||||
UplinkBPS *float64 `json:"UplinkBps,omitempty"` // 上り方向トラフィック
|
FreeDiskSize *float64 `json:"Free-Disk-Size,omitempty"` // 空きディスクサイズ(NFS)
|
||||||
DownlinkBPS *float64 `json:"DownlinkBps"` // 下り方向トラフィック
|
ResponseTimeSec *float64 `json:"responsetimesec,omitempty"` // レスポンスタイム(シンプル監視)
|
||||||
|
UplinkBPS *float64 `json:"UplinkBps,omitempty"` // 上り方向トラフィック
|
||||||
|
DownlinkBPS *float64 `json:"DownlinkBps,omitempty"` // 下り方向トラフィック
|
||||||
|
ActiveConnections *float64 `json:"activeConnections,omitempty"` // アクティブコネクション(プロキシLB)
|
||||||
|
ConnectionsPerSec *float64 `json:"connectionsPerSec,omitempty"` // 秒間コネクション数
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON JSONアンマーシャル(配列、オブジェクトが混在するためここで対応)
|
// UnmarshalJSON JSONアンマーシャル(配列、オブジェクトが混在するためここで対応)
|
||||||
|
@ -36,23 +40,27 @@ func (m *MonitorValue) UnmarshalJSON(data []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp := &struct {
|
tmp := &struct {
|
||||||
CPUTime *float64 `json:"CPU-TIME,omitempty"`
|
CPUTime *float64 `json:"CPU-TIME,omitempty"`
|
||||||
Write *float64 `json:",omitempty"`
|
Write *float64 `json:",omitempty"`
|
||||||
Read *float64 `json:",omitempty"`
|
Read *float64 `json:",omitempty"`
|
||||||
Receive *float64 `json:",omitempty"`
|
Receive *float64 `json:",omitempty"`
|
||||||
Send *float64 `json:",omitempty"`
|
Send *float64 `json:",omitempty"`
|
||||||
In *float64 `json:",omitempty"`
|
In *float64 `json:",omitempty"`
|
||||||
Out *float64 `json:",omitempty"`
|
Out *float64 `json:",omitempty"`
|
||||||
TotalMemorySize *float64 `json:"Total-Memory-Size,omitempty"`
|
TotalMemorySize *float64 `json:"Total-Memory-Size,omitempty"`
|
||||||
UsedMemorySize *float64 `json:"Used-Memory-Size,omitempty"`
|
UsedMemorySize *float64 `json:"Used-Memory-Size,omitempty"`
|
||||||
TotalDisk1Size *float64 `json:"Total-Disk1-Size,omitempty"`
|
TotalDisk1Size *float64 `json:"Total-Disk1-Size,omitempty"`
|
||||||
UsedDisk1Size *float64 `json:"Used-Disk1-Size,omitempty"`
|
UsedDisk1Size *float64 `json:"Used-Disk1-Size,omitempty"`
|
||||||
TotalDisk2Size *float64 `json:"Total-Disk2-Size,omitempty"`
|
TotalDisk2Size *float64 `json:"Total-Disk2-Size,omitempty"`
|
||||||
UsedDisk2Size *float64 `json:"Used-Disk2-Size,omitempty"`
|
UsedDisk2Size *float64 `json:"Used-Disk2-Size,omitempty"`
|
||||||
FreeDiskSize *float64 `json:"Free-Disk-Size,omitempty"`
|
BinlogUsedSizeKiB *float64 `json:"binlogUsedSizeKiB,omitempty"`
|
||||||
ResponseTimeSec *float64 `json:"responsetimesec,omitempty"`
|
DelayTimeSec *float64 `json:"delayTimeSec,omitempty"`
|
||||||
UplinkBPS *float64 `json:"UplinkBps,omitempty"`
|
FreeDiskSize *float64 `json:"Free-Disk-Size,omitempty"`
|
||||||
DownlinkBPS *float64 `json:"DownlinkBps"`
|
ResponseTimeSec *float64 `json:"responsetimesec,omitempty"`
|
||||||
|
UplinkBPS *float64 `json:"UplinkBps,omitempty"`
|
||||||
|
DownlinkBPS *float64 `json:"DownlinkBps,omitempty"`
|
||||||
|
ActiveConnections *float64 `json:"activeConnections,omitempty"`
|
||||||
|
ConnectionsPerSec *float64 `json:"connectionsPerSec,omitempty"`
|
||||||
}{}
|
}{}
|
||||||
if err := json.Unmarshal(data, &tmp); err != nil {
|
if err := json.Unmarshal(data, &tmp); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -71,10 +79,14 @@ func (m *MonitorValue) UnmarshalJSON(data []byte) error {
|
||||||
m.UsedDisk1Size = tmp.UsedDisk1Size
|
m.UsedDisk1Size = tmp.UsedDisk1Size
|
||||||
m.TotalDisk2Size = tmp.TotalDisk2Size
|
m.TotalDisk2Size = tmp.TotalDisk2Size
|
||||||
m.UsedDisk2Size = tmp.UsedDisk2Size
|
m.UsedDisk2Size = tmp.UsedDisk2Size
|
||||||
|
m.BinlogUsedSizeKiB = tmp.BinlogUsedSizeKiB
|
||||||
|
m.DelayTimeSec = tmp.DelayTimeSec
|
||||||
m.FreeDiskSize = tmp.FreeDiskSize
|
m.FreeDiskSize = tmp.FreeDiskSize
|
||||||
m.ResponseTimeSec = tmp.ResponseTimeSec
|
m.ResponseTimeSec = tmp.ResponseTimeSec
|
||||||
m.UplinkBPS = tmp.UplinkBPS
|
m.UplinkBPS = tmp.UplinkBPS
|
||||||
m.DownlinkBPS = tmp.DownlinkBPS
|
m.DownlinkBPS = tmp.DownlinkBPS
|
||||||
|
m.ActiveConnections = tmp.ActiveConnections
|
||||||
|
m.ConnectionsPerSec = tmp.ConnectionsPerSec
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -104,6 +116,23 @@ type ResourceMonitorResponse struct {
|
||||||
Data *MonitorValues `json:",omitempty"` // メトリクス
|
Data *MonitorValues `json:",omitempty"` // メトリクス
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON JSONアンマーシャル(配列、オブジェクトが混在するためここで対応)
|
||||||
|
func (m *MonitorValues) UnmarshalJSON(data []byte) error {
|
||||||
|
targetData := strings.Replace(strings.Replace(string(data), " ", "", -1), "\n", "", -1)
|
||||||
|
if targetData == `[]` {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp := map[string]*MonitorValue{}
|
||||||
|
if err := json.Unmarshal(data, &tmp); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
value := MonitorValues(tmp)
|
||||||
|
*m = value
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// MonitorSummaryData メトリクスサマリー
|
// MonitorSummaryData メトリクスサマリー
|
||||||
type MonitorSummaryData struct {
|
type MonitorSummaryData struct {
|
||||||
Max float64 // 最大値
|
Max float64 // 最大値
|
||||||
|
@ -242,6 +271,16 @@ func (m *MonitorValues) FlattenUsedDisk2SizeValue() ([]FlatMonitorValue, error)
|
||||||
return m.flattenValue(func(v *MonitorValue) *float64 { return v.UsedDisk2Size })
|
return m.flattenValue(func(v *MonitorValue) *float64 { return v.UsedDisk2Size })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FlattenBinlogUsedSizeKiBValue フラット化 バイナリログサイズ
|
||||||
|
func (m *MonitorValues) FlattenBinlogUsedSizeKiBValue() ([]FlatMonitorValue, error) {
|
||||||
|
return m.flattenValue(func(v *MonitorValue) *float64 { return v.BinlogUsedSizeKiB })
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlattenDelayTimeSecValue フラット化 レプリケーション遅延時間
|
||||||
|
func (m *MonitorValues) FlattenDelayTimeSecValue() ([]FlatMonitorValue, error) {
|
||||||
|
return m.flattenValue(func(v *MonitorValue) *float64 { return v.DelayTimeSec })
|
||||||
|
}
|
||||||
|
|
||||||
// FlattenFreeDiskSizeValue フラット化 空きディスクサイズ(NFS)
|
// FlattenFreeDiskSizeValue フラット化 空きディスクサイズ(NFS)
|
||||||
func (m *MonitorValues) FlattenFreeDiskSizeValue() ([]FlatMonitorValue, error) {
|
func (m *MonitorValues) FlattenFreeDiskSizeValue() ([]FlatMonitorValue, error) {
|
||||||
return m.flattenValue(func(v *MonitorValue) *float64 { return v.FreeDiskSize })
|
return m.flattenValue(func(v *MonitorValue) *float64 { return v.FreeDiskSize })
|
||||||
|
@ -262,6 +301,16 @@ func (m *MonitorValues) FlattenDownlinkBPSValue() ([]FlatMonitorValue, error) {
|
||||||
return m.flattenValue(func(v *MonitorValue) *float64 { return v.DownlinkBPS })
|
return m.flattenValue(func(v *MonitorValue) *float64 { return v.DownlinkBPS })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FlattenActiveConnections フラット化 アクティブコネクション
|
||||||
|
func (m *MonitorValues) FlattenActiveConnections() ([]FlatMonitorValue, error) {
|
||||||
|
return m.flattenValue(func(v *MonitorValue) *float64 { return v.ActiveConnections })
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlattenConnectionsPerSec フラット化 秒間接続数
|
||||||
|
func (m *MonitorValues) FlattenConnectionsPerSec() ([]FlatMonitorValue, error) {
|
||||||
|
return m.flattenValue(func(v *MonitorValue) *float64 { return v.ConnectionsPerSec })
|
||||||
|
}
|
||||||
|
|
||||||
func (m *MonitorValues) flattenValue(f func(*MonitorValue) *float64) ([]FlatMonitorValue, error) {
|
func (m *MonitorValues) flattenValue(f func(*MonitorValue) *float64) ([]FlatMonitorValue, error) {
|
||||||
var res []FlatMonitorValue
|
var res []FlatMonitorValue
|
||||||
|
|
||||||
|
@ -293,8 +342,10 @@ func (m *MonitorValue) HasValue() bool {
|
||||||
m.TotalMemorySize, m.UsedMemorySize,
|
m.TotalMemorySize, m.UsedMemorySize,
|
||||||
m.TotalDisk1Size, m.UsedDisk1Size,
|
m.TotalDisk1Size, m.UsedDisk1Size,
|
||||||
m.TotalDisk2Size, m.UsedDisk2Size,
|
m.TotalDisk2Size, m.UsedDisk2Size,
|
||||||
|
m.BinlogUsedSizeKiB, m.DelayTimeSec,
|
||||||
m.FreeDiskSize, m.ResponseTimeSec,
|
m.FreeDiskSize, m.ResponseTimeSec,
|
||||||
m.UplinkBPS, m.DownlinkBPS,
|
m.UplinkBPS, m.DownlinkBPS,
|
||||||
|
m.ActiveConnections, m.ConnectionsPerSec,
|
||||||
}
|
}
|
||||||
for _, v := range values {
|
for _, v := range values {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
|
|
206
vendor/github.com/sacloud/libsacloud/sacloud/nfs.go
generated
vendored
206
vendor/github.com/sacloud/libsacloud/sacloud/nfs.go
generated
vendored
|
@ -1,5 +1,9 @@
|
||||||
package sacloud
|
package sacloud
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
// NFS NFS
|
// NFS NFS
|
||||||
type NFS struct {
|
type NFS struct {
|
||||||
*Appliance // アプライアンス共通属性
|
*Appliance // アプライアンス共通属性
|
||||||
|
@ -11,47 +15,97 @@ type NFS struct {
|
||||||
// NFSRemark リマーク
|
// NFSRemark リマーク
|
||||||
type NFSRemark struct {
|
type NFSRemark struct {
|
||||||
*ApplianceRemarkBase
|
*ApplianceRemarkBase
|
||||||
propPlanID
|
Plan *struct {
|
||||||
|
ID json.Number `json:",omitempty"`
|
||||||
|
} `json:",omitempty"` // プラン
|
||||||
// TODO Zone
|
// TODO Zone
|
||||||
//Zone *Resource
|
//Zone *Resource
|
||||||
//SourceAppliance *Resource // クローン元DB
|
//SourceAppliance *Resource // クローン元DB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetRemarkPlanID プランID設定
|
||||||
|
func (n NFSRemark) SetRemarkPlanID(planID int64) {
|
||||||
|
if n.Plan == nil {
|
||||||
|
n.Plan = &struct {
|
||||||
|
ID json.Number `json:",omitempty"`
|
||||||
|
}{}
|
||||||
|
}
|
||||||
|
n.Plan.ID = json.Number(planID)
|
||||||
|
}
|
||||||
|
|
||||||
// NFSSettings NFS設定リスト
|
// NFSSettings NFS設定リスト
|
||||||
type NFSSettings struct {
|
type NFSSettings struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NFSPlan NFSプラン
|
// NFSPlan プラン(HDD/SSD)
|
||||||
type NFSPlan int
|
type NFSPlan int
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// NFSPlan100G 100Gプラン
|
// NFSPlanHDD 標準プラン(HDD)
|
||||||
NFSPlan100G = NFSPlan(100)
|
NFSPlanHDD = NFSPlan(1)
|
||||||
// NFSPlan500G 500Gプラン
|
// NFSPlanSSD SSHプラン
|
||||||
NFSPlan500G = NFSPlan(500)
|
NFSPlanSSD = NFSPlan(2)
|
||||||
// NFSPlan1T 1T(1024GB)プラン
|
|
||||||
NFSPlan1T = NFSPlan(1024 * 1)
|
|
||||||
// NFSPlan2T 2T(2048GB)プラン
|
|
||||||
NFSPlan2T = NFSPlan(1024 * 2)
|
|
||||||
// NFSPlan4T 4T(4096GB)プラン
|
|
||||||
NFSPlan4T = NFSPlan(1024 * 4)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// AllowNFSPlans 指定可能なNFSプラン
|
// String NFSプランの文字列表現
|
||||||
func AllowNFSPlans() []int {
|
func (p NFSPlan) String() string {
|
||||||
|
switch p {
|
||||||
|
case NFSPlanHDD:
|
||||||
|
return "HDD"
|
||||||
|
case NFSPlanSSD:
|
||||||
|
return "SSD"
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NFSSize NFSサイズ
|
||||||
|
type NFSSize int
|
||||||
|
|
||||||
|
var (
|
||||||
|
// NFSSize100G 100Gプラン
|
||||||
|
NFSSize100G = NFSSize(100)
|
||||||
|
// NFSSize500G 500Gプラン
|
||||||
|
NFSSize500G = NFSSize(500)
|
||||||
|
// NFSSize1T 1T(1024GB)プラン
|
||||||
|
NFSSize1T = NFSSize(1024 * 1)
|
||||||
|
// NFSSize2T 2T(2048GB)プラン
|
||||||
|
NFSSize2T = NFSSize(1024 * 2)
|
||||||
|
// NFSSize4T 4T(4096GB)プラン
|
||||||
|
NFSSize4T = NFSSize(1024 * 4)
|
||||||
|
// NFSSize8T 8TBプラン
|
||||||
|
NFSSize8T = NFSSize(1024 * 8)
|
||||||
|
// NFSSize12T 12TBプラン
|
||||||
|
NFSSize12T = NFSSize(1024 * 12)
|
||||||
|
)
|
||||||
|
|
||||||
|
// AllowNFSNormalPlanSizes 指定可能なNFSサイズ(標準プラン)
|
||||||
|
func AllowNFSNormalPlanSizes() []int {
|
||||||
return []int{
|
return []int{
|
||||||
int(NFSPlan100G),
|
int(NFSSize100G),
|
||||||
int(NFSPlan500G),
|
int(NFSSize500G),
|
||||||
int(NFSPlan1T),
|
int(NFSSize1T),
|
||||||
int(NFSPlan2T),
|
int(NFSSize2T),
|
||||||
int(NFSPlan4T),
|
int(NFSSize4T),
|
||||||
|
int(NFSSize8T),
|
||||||
|
int(NFSSize12T),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowNFSSSDPlanSizes 指定可能なNFSサイズ(SSDプラン)
|
||||||
|
func AllowNFSSSDPlanSizes() []int {
|
||||||
|
return []int{
|
||||||
|
int(NFSSize100G),
|
||||||
|
int(NFSSize500G),
|
||||||
|
int(NFSSize1T),
|
||||||
|
int(NFSSize2T),
|
||||||
|
int(NFSSize4T),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateNFSValue NFS作成用パラメーター
|
// CreateNFSValue NFS作成用パラメーター
|
||||||
type CreateNFSValue struct {
|
type CreateNFSValue struct {
|
||||||
SwitchID string // 接続先スイッチID
|
SwitchID string // 接続先スイッチID
|
||||||
Plan NFSPlan // プラン
|
|
||||||
IPAddress string // IPアドレス
|
IPAddress string // IPアドレス
|
||||||
MaskLen int // ネットワークマスク長
|
MaskLen int // ネットワークマスク長
|
||||||
DefaultRoute string // デフォルトルート
|
DefaultRoute string // デフォルトルート
|
||||||
|
@ -62,27 +116,16 @@ type CreateNFSValue struct {
|
||||||
SourceAppliance *Resource // クローン元NFS
|
SourceAppliance *Resource // クローン元NFS
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCreateNFSValue NFS作成用パラメーター
|
|
||||||
func NewCreateNFSValue() *CreateNFSValue {
|
|
||||||
return &CreateNFSValue{
|
|
||||||
Plan: NFSPlan100G,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNFS NFS作成(冗長化なし)
|
// NewNFS NFS作成(冗長化なし)
|
||||||
func NewNFS(values *CreateNFSValue) *NFS {
|
func NewNFS(values *CreateNFSValue) *NFS {
|
||||||
|
|
||||||
if int(values.Plan) == 0 {
|
|
||||||
values.Plan = NFSPlan100G
|
|
||||||
}
|
|
||||||
|
|
||||||
return &NFS{
|
return &NFS{
|
||||||
Appliance: &Appliance{
|
Appliance: &Appliance{
|
||||||
Class: "nfs",
|
Class: "nfs",
|
||||||
propName: propName{Name: values.Name},
|
propName: propName{Name: values.Name},
|
||||||
propDescription: propDescription{Description: values.Description},
|
propDescription: propDescription{Description: values.Description},
|
||||||
propTags: propTags{Tags: values.Tags},
|
propTags: propTags{Tags: values.Tags},
|
||||||
propPlanID: propPlanID{Plan: &Resource{ID: int64(values.Plan)}},
|
//propPlanID: propPlanID{Plan: &Resource{ID: int64(values.Plan)}},
|
||||||
propIcon: propIcon{
|
propIcon: propIcon{
|
||||||
&Icon{
|
&Icon{
|
||||||
Resource: values.Icon,
|
Resource: values.Icon,
|
||||||
|
@ -102,9 +145,104 @@ func NewNFS(values *CreateNFSValue) *NFS {
|
||||||
map[string]interface{}{"IPAddress": values.IPAddress},
|
map[string]interface{}{"IPAddress": values.IPAddress},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
propPlanID: propPlanID{Plan: &Resource{ID: int64(values.Plan)}},
|
//propPlanID: propPlanID{Plan: &Resource{ID: int64(values.Plan)}},
|
||||||
//SourceAppliance: values.SourceAppliance,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IPAddress IPアドレスを取得
|
||||||
|
func (n *NFS) IPAddress() string {
|
||||||
|
if len(n.Remark.Servers) < 1 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
v, ok := n.Remark.Servers[0].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip, ok := v["IPAddress"]; ok {
|
||||||
|
return ip.(string)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkMaskLen ネットワークマスク長を取得
|
||||||
|
func (n *NFS) NetworkMaskLen() int {
|
||||||
|
if n.Remark.Network == nil {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return n.Remark.Network.NetworkMaskLen
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultRoute デフォルトゲートウェイを取得
|
||||||
|
func (n *NFS) DefaultRoute() string {
|
||||||
|
if n.Remark.Network == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return n.Remark.Network.DefaultRoute
|
||||||
|
}
|
||||||
|
|
||||||
|
// NFSPlans NFSプラン
|
||||||
|
type NFSPlans struct {
|
||||||
|
HDD []NFSPlanValue
|
||||||
|
SSD []NFSPlanValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindPlanID プランとサイズからプランIDを取得
|
||||||
|
func (p NFSPlans) FindPlanID(plan NFSPlan, size NFSSize) int64 {
|
||||||
|
var plans []NFSPlanValue
|
||||||
|
switch plan {
|
||||||
|
case NFSPlanHDD:
|
||||||
|
plans = p.HDD
|
||||||
|
case NFSPlanSSD:
|
||||||
|
plans = p.SSD
|
||||||
|
default:
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, plan := range plans {
|
||||||
|
if plan.Availability == "available" && plan.Size == int(size) {
|
||||||
|
res, err := plan.PlanID.Int64()
|
||||||
|
if err != nil {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindByPlanID プランIDから該当プランを取得
|
||||||
|
func (p NFSPlans) FindByPlanID(planID int64) (NFSPlan, *NFSPlanValue) {
|
||||||
|
|
||||||
|
for _, plan := range p.SSD {
|
||||||
|
id, err := plan.PlanID.Int64()
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if id == planID {
|
||||||
|
return NFSPlanSSD, &plan
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, plan := range p.HDD {
|
||||||
|
id, err := plan.PlanID.Int64()
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if id == planID {
|
||||||
|
return NFSPlanHDD, &plan
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NFSPlan(-1), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NFSPlanValue NFSプラン
|
||||||
|
type NFSPlanValue struct {
|
||||||
|
Size int `json:"size"`
|
||||||
|
Availability string `json:"availability"`
|
||||||
|
PlanID json.Number `json:"planId"`
|
||||||
|
}
|
||||||
|
|
8
vendor/github.com/sacloud/libsacloud/sacloud/ostype/archive_ostype.go
generated
vendored
8
vendor/github.com/sacloud/libsacloud/sacloud/ostype/archive_ostype.go
generated
vendored
|
@ -53,6 +53,8 @@ const (
|
||||||
Windows2016SQLServerStandardAll
|
Windows2016SQLServerStandardAll
|
||||||
// Windows2016SQLServer2017StandardAll OS種別:Windows Server 2016 SQLServer 2017(Standard) + RDS + Office
|
// Windows2016SQLServer2017StandardAll OS種別:Windows Server 2016 SQLServer 2017(Standard) + RDS + Office
|
||||||
Windows2016SQLServer2017StandardAll
|
Windows2016SQLServer2017StandardAll
|
||||||
|
// Windows2019 OS種別:Windows Server 2019 Datacenter Edition
|
||||||
|
Windows2019
|
||||||
// Custom OS種別:カスタム
|
// Custom OS種別:カスタム
|
||||||
Custom
|
Custom
|
||||||
)
|
)
|
||||||
|
@ -66,6 +68,7 @@ var OSTypeShortNames = []string{
|
||||||
"windows2016", "windows2016-rds", "windows2016-rds-office",
|
"windows2016", "windows2016-rds", "windows2016-rds-office",
|
||||||
"windows2016-sql-web", "windows2016-sql-standard", "windows2016-sql-standard-all",
|
"windows2016-sql-web", "windows2016-sql-standard", "windows2016-sql-standard-all",
|
||||||
"windows2016-sql2017-standard", "windows2016-sql2017-standard-all",
|
"windows2016-sql2017-standard", "windows2016-sql2017-standard-all",
|
||||||
|
"windows2019",
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsWindows Windowsか
|
// IsWindows Windowsか
|
||||||
|
@ -74,7 +77,8 @@ func (o ArchiveOSTypes) IsWindows() bool {
|
||||||
case Windows2012, Windows2012RDS, Windows2012RDSOffice,
|
case Windows2012, Windows2012RDS, Windows2012RDSOffice,
|
||||||
Windows2016, Windows2016RDS, Windows2016RDSOffice,
|
Windows2016, Windows2016RDS, Windows2016RDSOffice,
|
||||||
Windows2016SQLServerWeb, Windows2016SQLServerStandard, Windows2016SQLServerStandardAll,
|
Windows2016SQLServerWeb, Windows2016SQLServerStandard, Windows2016SQLServerStandardAll,
|
||||||
Windows2016SQLServer2017Standard, Windows2016SQLServer2017StandardAll:
|
Windows2016SQLServer2017Standard, Windows2016SQLServer2017StandardAll,
|
||||||
|
Windows2019:
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
|
@ -140,6 +144,8 @@ func StrToOSType(osType string) ArchiveOSTypes {
|
||||||
return Windows2016SQLServerStandardAll
|
return Windows2016SQLServerStandardAll
|
||||||
case "windows2016-sql2017-standard-all":
|
case "windows2016-sql2017-standard-all":
|
||||||
return Windows2016SQLServer2017StandardAll
|
return Windows2016SQLServer2017StandardAll
|
||||||
|
case "windows2019":
|
||||||
|
return Windows2019
|
||||||
default:
|
default:
|
||||||
return Custom
|
return Custom
|
||||||
}
|
}
|
||||||
|
|
4
vendor/github.com/sacloud/libsacloud/sacloud/ostype/archiveostypes_string.go
generated
vendored
4
vendor/github.com/sacloud/libsacloud/sacloud/ostype/archiveostypes_string.go
generated
vendored
|
@ -4,9 +4,9 @@ package ostype
|
||||||
|
|
||||||
import "strconv"
|
import "strconv"
|
||||||
|
|
||||||
const _ArchiveOSTypes_name = "CentOSCentOS6UbuntuDebianVyOSCoreOSRancherOSKusanagiSophosUTMFreeBSDNetwiserOPNsenseWindows2012Windows2012RDSWindows2012RDSOfficeWindows2016Windows2016RDSWindows2016RDSOfficeWindows2016SQLServerWebWindows2016SQLServerStandardWindows2016SQLServer2017StandardWindows2016SQLServerStandardAllWindows2016SQLServer2017StandardAllCustom"
|
const _ArchiveOSTypes_name = "CentOSCentOS6UbuntuDebianVyOSCoreOSRancherOSKusanagiSophosUTMFreeBSDNetwiserOPNsenseWindows2012Windows2012RDSWindows2012RDSOfficeWindows2016Windows2016RDSWindows2016RDSOfficeWindows2016SQLServerWebWindows2016SQLServerStandardWindows2016SQLServer2017StandardWindows2016SQLServerStandardAllWindows2016SQLServer2017StandardAllWindows2019Custom"
|
||||||
|
|
||||||
var _ArchiveOSTypes_index = [...]uint16{0, 6, 13, 19, 25, 29, 35, 44, 52, 61, 68, 76, 84, 95, 109, 129, 140, 154, 174, 197, 225, 257, 288, 323, 329}
|
var _ArchiveOSTypes_index = [...]uint16{0, 6, 13, 19, 25, 29, 35, 44, 52, 61, 68, 76, 84, 95, 109, 129, 140, 154, 174, 197, 225, 257, 288, 323, 334, 340}
|
||||||
|
|
||||||
func (i ArchiveOSTypes) String() string {
|
func (i ArchiveOSTypes) String() string {
|
||||||
if i < 0 || i >= ArchiveOSTypes(len(_ArchiveOSTypes_index)-1) {
|
if i < 0 || i >= ArchiveOSTypes(len(_ArchiveOSTypes_index)-1) {
|
||||||
|
|
517
vendor/github.com/sacloud/libsacloud/sacloud/proxylb.go
generated
vendored
Normal file
517
vendor/github.com/sacloud/libsacloud/sacloud/proxylb.go
generated
vendored
Normal file
|
@ -0,0 +1,517 @@
|
||||||
|
package sacloud
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/json"
|
||||||
|
"encoding/pem"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ProxyLB ProxyLB(CommonServiceItem)
|
||||||
|
type ProxyLB struct {
|
||||||
|
*Resource // ID
|
||||||
|
propName // 名称
|
||||||
|
propDescription // 説明
|
||||||
|
propServiceClass // サービスクラス
|
||||||
|
propIcon // アイコン
|
||||||
|
propTags // タグ
|
||||||
|
propCreatedAt // 作成日時
|
||||||
|
propModifiedAt // 変更日時
|
||||||
|
propAvailability // 有効状態
|
||||||
|
|
||||||
|
Status *ProxyLBStatus `json:",omitempty"` // ステータス
|
||||||
|
Provider ProxyLBProvider `json:",omitempty"` // プロバイダ
|
||||||
|
Settings ProxyLBSettings `json:",omitempty"` // ProxyLB設定
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProxyLBSettings ProxyLB設定
|
||||||
|
type ProxyLBSettings struct {
|
||||||
|
ProxyLB ProxyLBSetting `json:",omitempty"` // ProxyLB ProxyLBエントリー
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProxyLBStatus ProxyLBステータス
|
||||||
|
type ProxyLBStatus struct {
|
||||||
|
FQDN string `json:",omitempty"` // 割り当てられたFQDN(site-*******.proxylb?.sakura.ne.jp) UseVIPFailoverがtrueの場合のみ有効
|
||||||
|
VirtualIPAddress string `json:",omitempty"` // 割り当てられたVIP UseVIPFailoverがfalseの場合のみ有効
|
||||||
|
ProxyNetworks []string `json:",omitempty"` // プロキシ元ネットワークアドレス(CIDR)
|
||||||
|
UseVIPFailover bool // VIPフェイルオーバ
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProxyLBProvider プロバイダ
|
||||||
|
type ProxyLBProvider struct {
|
||||||
|
Class string `json:",omitempty"` // クラス
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateNewProxyLB ProxyLB作成
|
||||||
|
func CreateNewProxyLB(name string) *ProxyLB {
|
||||||
|
return &ProxyLB{
|
||||||
|
Resource: &Resource{},
|
||||||
|
propName: propName{Name: name},
|
||||||
|
Provider: ProxyLBProvider{
|
||||||
|
Class: "proxylb",
|
||||||
|
},
|
||||||
|
Settings: ProxyLBSettings{
|
||||||
|
ProxyLB: ProxyLBSetting{
|
||||||
|
HealthCheck: defaultProxyLBHealthCheck,
|
||||||
|
SorryServer: ProxyLBSorryServer{},
|
||||||
|
Servers: []ProxyLBServer{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProxyLBPlan ProxyLBプラン
|
||||||
|
type ProxyLBPlan int
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ProxyLBPlan1000 1,000cpsプラン
|
||||||
|
ProxyLBPlan1000 = ProxyLBPlan(1000)
|
||||||
|
// ProxyLBPlan5000 5,000cpsプラン
|
||||||
|
ProxyLBPlan5000 = ProxyLBPlan(5000)
|
||||||
|
// ProxyLBPlan10000 10,000cpsプラン
|
||||||
|
ProxyLBPlan10000 = ProxyLBPlan(10000)
|
||||||
|
// ProxyLBPlan50000 50,000cpsプラン
|
||||||
|
ProxyLBPlan50000 = ProxyLBPlan(50000)
|
||||||
|
// ProxyLBPlan100000 100,000cpsプラン
|
||||||
|
ProxyLBPlan100000 = ProxyLBPlan(100000)
|
||||||
|
)
|
||||||
|
|
||||||
|
// AllowProxyLBPlans 有効なプランIDリスト
|
||||||
|
var AllowProxyLBPlans = []int{
|
||||||
|
int(ProxyLBPlan1000),
|
||||||
|
int(ProxyLBPlan5000),
|
||||||
|
int(ProxyLBPlan10000),
|
||||||
|
int(ProxyLBPlan50000),
|
||||||
|
int(ProxyLBPlan100000),
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPlan プラン取得(デフォルト: 1000cps)
|
||||||
|
func (p *ProxyLB) GetPlan() ProxyLBPlan {
|
||||||
|
classes := strings.Split(p.ServiceClass, "/")
|
||||||
|
class, err := strconv.Atoi(classes[len(classes)-1])
|
||||||
|
if err != nil {
|
||||||
|
return ProxyLBPlan1000
|
||||||
|
}
|
||||||
|
return ProxyLBPlan(class)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPlan プラン指定
|
||||||
|
func (p *ProxyLB) SetPlan(plan ProxyLBPlan) {
|
||||||
|
p.ServiceClass = fmt.Sprintf("cloud/proxylb/plain/%d", plan)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHTTPHealthCheck HTTPヘルスチェック 設定
|
||||||
|
func (p *ProxyLB) SetHTTPHealthCheck(hostHeader, path string, delayLoop int) {
|
||||||
|
if delayLoop <= 0 {
|
||||||
|
delayLoop = 10
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Settings.ProxyLB.HealthCheck.Protocol = "http"
|
||||||
|
p.Settings.ProxyLB.HealthCheck.Host = hostHeader
|
||||||
|
p.Settings.ProxyLB.HealthCheck.Path = path
|
||||||
|
p.Settings.ProxyLB.HealthCheck.DelayLoop = delayLoop
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTCPHealthCheck TCPヘルスチェック 設定
|
||||||
|
func (p *ProxyLB) SetTCPHealthCheck(delayLoop int) {
|
||||||
|
if delayLoop <= 0 {
|
||||||
|
delayLoop = 10
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Settings.ProxyLB.HealthCheck.Protocol = "tcp"
|
||||||
|
p.Settings.ProxyLB.HealthCheck.Host = ""
|
||||||
|
p.Settings.ProxyLB.HealthCheck.Path = ""
|
||||||
|
p.Settings.ProxyLB.HealthCheck.DelayLoop = delayLoop
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSorryServer ソーリーサーバ 設定
|
||||||
|
func (p *ProxyLB) SetSorryServer(ipaddress string, port int) {
|
||||||
|
var pt *int
|
||||||
|
if port > 0 {
|
||||||
|
pt = &port
|
||||||
|
}
|
||||||
|
p.Settings.ProxyLB.SorryServer = ProxyLBSorryServer{
|
||||||
|
IPAddress: ipaddress,
|
||||||
|
Port: pt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearSorryServer ソーリーサーバ クリア
|
||||||
|
func (p *ProxyLB) ClearSorryServer() {
|
||||||
|
p.SetSorryServer("", 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasProxyLBServer ProxyLB配下にサーバーを保持しているか判定
|
||||||
|
func (p *ProxyLB) HasProxyLBServer() bool {
|
||||||
|
return len(p.Settings.ProxyLB.Servers) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearProxyLBServer ProxyLB配下のサーバーをクリア
|
||||||
|
func (p *ProxyLB) ClearProxyLBServer() {
|
||||||
|
p.Settings.ProxyLB.Servers = []ProxyLBServer{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddBindPort バインドポート追加
|
||||||
|
func (p *ProxyLB) AddBindPort(mode string, port int) {
|
||||||
|
p.Settings.ProxyLB.AddBindPort(mode, port)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteBindPort バインドポート削除
|
||||||
|
func (p *ProxyLB) DeleteBindPort(mode string, port int) {
|
||||||
|
p.Settings.ProxyLB.DeleteBindPort(mode, port)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearBindPorts バインドポート クリア
|
||||||
|
func (p *ProxyLB) ClearBindPorts() {
|
||||||
|
p.Settings.ProxyLB.BindPorts = []*ProxyLBBindPorts{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddServer ProxyLB配下のサーバーを追加
|
||||||
|
func (p *ProxyLB) AddServer(ip string, port int, enabled bool) {
|
||||||
|
p.Settings.ProxyLB.AddServer(ip, port, enabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteServer ProxyLB配下のサーバーを削除
|
||||||
|
func (p *ProxyLB) DeleteServer(ip string, port int) {
|
||||||
|
p.Settings.ProxyLB.DeleteServer(ip, port)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProxyLBSetting ProxyLBセッティング
|
||||||
|
type ProxyLBSetting struct {
|
||||||
|
HealthCheck ProxyLBHealthCheck `json:",omitempty"` // ヘルスチェック
|
||||||
|
SorryServer ProxyLBSorryServer `json:",omitempty"` // ソーリーサーバー
|
||||||
|
BindPorts []*ProxyLBBindPorts `json:",omitempty"` // プロキシ方式(プロトコル&ポート)
|
||||||
|
Servers []ProxyLBServer `json:",omitempty"` // サーバー
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProxyLBSorryServer ソーリーサーバ
|
||||||
|
type ProxyLBSorryServer struct {
|
||||||
|
IPAddress string // IPアドレス
|
||||||
|
Port *int // ポート
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddBindPort バインドポート追加
|
||||||
|
func (s *ProxyLBSetting) AddBindPort(mode string, port int) {
|
||||||
|
var isExist bool
|
||||||
|
for i := range s.BindPorts {
|
||||||
|
if s.BindPorts[i].ProxyMode == mode && s.BindPorts[i].Port == port {
|
||||||
|
isExist = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isExist {
|
||||||
|
s.BindPorts = append(s.BindPorts, &ProxyLBBindPorts{
|
||||||
|
ProxyMode: mode,
|
||||||
|
Port: port,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteBindPort バインドポート削除
|
||||||
|
func (s *ProxyLBSetting) DeleteBindPort(mode string, port int) {
|
||||||
|
var res []*ProxyLBBindPorts
|
||||||
|
for i := range s.BindPorts {
|
||||||
|
if s.BindPorts[i].ProxyMode != mode || s.BindPorts[i].Port != port {
|
||||||
|
res = append(res, s.BindPorts[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.BindPorts = res
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddServer ProxyLB配下のサーバーを追加
|
||||||
|
func (s *ProxyLBSetting) AddServer(ip string, port int, enabled bool) {
|
||||||
|
var record ProxyLBServer
|
||||||
|
var isExist = false
|
||||||
|
for i := range s.Servers {
|
||||||
|
if s.Servers[i].IPAddress == ip && s.Servers[i].Port == port {
|
||||||
|
isExist = true
|
||||||
|
s.Servers[i].Enabled = enabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isExist {
|
||||||
|
record = ProxyLBServer{
|
||||||
|
IPAddress: ip,
|
||||||
|
Port: port,
|
||||||
|
Enabled: enabled,
|
||||||
|
}
|
||||||
|
s.Servers = append(s.Servers, record)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteServer ProxyLB配下のサーバーを削除
|
||||||
|
func (s *ProxyLBSetting) DeleteServer(ip string, port int) {
|
||||||
|
var res []ProxyLBServer
|
||||||
|
for i := range s.Servers {
|
||||||
|
if s.Servers[i].IPAddress != ip || s.Servers[i].Port != port {
|
||||||
|
res = append(res, s.Servers[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Servers = res
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowProxyLBBindModes プロキシ方式
|
||||||
|
var AllowProxyLBBindModes = []string{"http", "https"}
|
||||||
|
|
||||||
|
// ProxyLBBindPorts プロキシ方式
|
||||||
|
type ProxyLBBindPorts struct {
|
||||||
|
ProxyMode string `json:",omitempty"` // モード(プロトコル)
|
||||||
|
Port int `json:",omitempty"` // ポート
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProxyLBServer ProxyLB配下のサーバー
|
||||||
|
type ProxyLBServer struct {
|
||||||
|
IPAddress string `json:",omitempty"` // IPアドレス
|
||||||
|
Port int `json:",omitempty"` // ポート
|
||||||
|
Enabled bool `json:",omitempty"` // 有効/無効
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewProxyLBServer ProxyLB配下のサーバ作成
|
||||||
|
func NewProxyLBServer(ipaddress string, port int) *ProxyLBServer {
|
||||||
|
return &ProxyLBServer{
|
||||||
|
IPAddress: ipaddress,
|
||||||
|
Port: port,
|
||||||
|
Enabled: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowProxyLBHealthCheckProtocols プロキシLBで利用できるヘルスチェックプロトコル
|
||||||
|
var AllowProxyLBHealthCheckProtocols = []string{"http", "tcp"}
|
||||||
|
|
||||||
|
// ProxyLBHealthCheck ヘルスチェック
|
||||||
|
type ProxyLBHealthCheck struct {
|
||||||
|
Protocol string `json:",omitempty"` // プロトコル
|
||||||
|
Host string `json:",omitempty"` // 対象ホスト
|
||||||
|
Path string `json:",omitempty"` // HTTPの場合のリクエストパス
|
||||||
|
DelayLoop int `json:",omitempty"` // 監視間隔
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultProxyLBHealthCheck = ProxyLBHealthCheck{
|
||||||
|
Protocol: "http",
|
||||||
|
Host: "",
|
||||||
|
Path: "/",
|
||||||
|
DelayLoop: 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProxyLBAdditionalCerts additional certificates
|
||||||
|
type ProxyLBAdditionalCerts []*ProxyLBCertificate
|
||||||
|
|
||||||
|
// ProxyLBCertificates ProxyLBのSSL証明書
|
||||||
|
type ProxyLBCertificates struct {
|
||||||
|
ServerCertificate string // サーバ証明書
|
||||||
|
IntermediateCertificate string // 中間証明書
|
||||||
|
PrivateKey string // 秘密鍵
|
||||||
|
CertificateEndDate time.Time `json:",omitempty"` // 有効期限
|
||||||
|
CertificateCommonName string `json:",omitempty"` // CommonName
|
||||||
|
AdditionalCerts ProxyLBAdditionalCerts
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON UnmarshalJSON(AdditionalCertsが空の場合に空文字を返す問題への対応)
|
||||||
|
func (p *ProxyLBAdditionalCerts) UnmarshalJSON(data []byte) error {
|
||||||
|
targetData := strings.Replace(strings.Replace(string(data), " ", "", -1), "\n", "", -1)
|
||||||
|
if targetData == `` {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var certs []*ProxyLBCertificate
|
||||||
|
if err := json.Unmarshal(data, &certs); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*p = certs
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPrimaryCert PrimaryCertを設定
|
||||||
|
func (p *ProxyLBCertificates) SetPrimaryCert(cert *ProxyLBCertificate) {
|
||||||
|
p.ServerCertificate = cert.ServerCertificate
|
||||||
|
p.IntermediateCertificate = cert.IntermediateCertificate
|
||||||
|
p.PrivateKey = cert.PrivateKey
|
||||||
|
p.CertificateEndDate = cert.CertificateEndDate
|
||||||
|
p.CertificateCommonName = cert.CertificateCommonName
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPrimaryCertValue PrimaryCertを設定
|
||||||
|
func (p *ProxyLBCertificates) SetPrimaryCertValue(serverCert, intermediateCert, privateKey string) {
|
||||||
|
p.ServerCertificate = serverCert
|
||||||
|
p.IntermediateCertificate = intermediateCert
|
||||||
|
p.PrivateKey = privateKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddAdditionalCert AdditionalCertを追加
|
||||||
|
func (p *ProxyLBCertificates) AddAdditionalCert(serverCert, intermediateCert, privateKey string) {
|
||||||
|
p.AdditionalCerts = append(p.AdditionalCerts, &ProxyLBCertificate{
|
||||||
|
ServerCertificate: serverCert,
|
||||||
|
IntermediateCertificate: intermediateCert,
|
||||||
|
PrivateKey: privateKey,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveAdditionalCertAt 指定のインデックスを持つAdditionalCertを削除
|
||||||
|
func (p *ProxyLBCertificates) RemoveAdditionalCertAt(index int) {
|
||||||
|
var certs []*ProxyLBCertificate
|
||||||
|
for i, cert := range p.AdditionalCerts {
|
||||||
|
if i != index {
|
||||||
|
certs = append(certs, cert)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.AdditionalCerts = certs
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveAdditionalCert 指定の内容を持つAdditionalCertを削除
|
||||||
|
func (p *ProxyLBCertificates) RemoveAdditionalCert(serverCert, intermediateCert, privateKey string) {
|
||||||
|
var certs []*ProxyLBCertificate
|
||||||
|
for _, cert := range p.AdditionalCerts {
|
||||||
|
if !(cert.ServerCertificate == serverCert && cert.IntermediateCertificate == intermediateCert && cert.PrivateKey == privateKey) {
|
||||||
|
certs = append(certs, cert)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.AdditionalCerts = certs
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveAdditionalCerts AdditionalCertsを全て削除
|
||||||
|
func (p *ProxyLBCertificates) RemoveAdditionalCerts() {
|
||||||
|
p.AdditionalCerts = []*ProxyLBCertificate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON UnmarshalJSON(CertificateEndDateのtime.TimeへのUnmarshal対応)
|
||||||
|
func (p *ProxyLBCertificates) UnmarshalJSON(data []byte) error {
|
||||||
|
var tmp map[string]interface{}
|
||||||
|
if err := json.Unmarshal(data, &tmp); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.ServerCertificate = tmp["ServerCertificate"].(string)
|
||||||
|
p.IntermediateCertificate = tmp["IntermediateCertificate"].(string)
|
||||||
|
p.PrivateKey = tmp["PrivateKey"].(string)
|
||||||
|
p.CertificateCommonName = tmp["CertificateCommonName"].(string)
|
||||||
|
endDate := tmp["CertificateEndDate"].(string)
|
||||||
|
if endDate != "" {
|
||||||
|
date, err := time.Parse("Jan _2 15:04:05 2006 MST", endDate)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.CertificateEndDate = date
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := tmp["AdditionalCerts"].(string); !ok {
|
||||||
|
rawCerts, err := json.Marshal(tmp["AdditionalCerts"])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var additionalCerts ProxyLBAdditionalCerts
|
||||||
|
if err := json.Unmarshal(rawCerts, &additionalCerts); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.AdditionalCerts = additionalCerts
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseServerCertificate サーバ証明書のパース
|
||||||
|
func (p *ProxyLBCertificates) ParseServerCertificate() (*x509.Certificate, error) {
|
||||||
|
cert, e := p.parseCertificate(p.ServerCertificate)
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
return cert, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseIntermediateCertificate 中間証明書のパース
|
||||||
|
func (p *ProxyLBCertificates) ParseIntermediateCertificate() (*x509.Certificate, error) {
|
||||||
|
cert, e := p.parseCertificate(p.IntermediateCertificate)
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
return cert, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ProxyLBCertificates) parseCertificate(certPEM string) (*x509.Certificate, error) {
|
||||||
|
block, _ := pem.Decode([]byte(certPEM))
|
||||||
|
if block != nil {
|
||||||
|
return x509.ParseCertificate(block.Bytes)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("can't decode certificate")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProxyLBCertificate ProxyLBのSSL証明書詳細
|
||||||
|
type ProxyLBCertificate struct {
|
||||||
|
ServerCertificate string // サーバ証明書
|
||||||
|
IntermediateCertificate string // 中間証明書
|
||||||
|
PrivateKey string // 秘密鍵
|
||||||
|
CertificateEndDate time.Time `json:",omitempty"` // 有効期限
|
||||||
|
CertificateCommonName string `json:",omitempty"` // CommonName
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON UnmarshalJSON(CertificateEndDateのtime.TimeへのUnmarshal対応)
|
||||||
|
func (p *ProxyLBCertificate) UnmarshalJSON(data []byte) error {
|
||||||
|
var tmp map[string]interface{}
|
||||||
|
if err := json.Unmarshal(data, &tmp); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.ServerCertificate = tmp["ServerCertificate"].(string)
|
||||||
|
p.IntermediateCertificate = tmp["IntermediateCertificate"].(string)
|
||||||
|
p.PrivateKey = tmp["PrivateKey"].(string)
|
||||||
|
p.CertificateCommonName = tmp["CertificateCommonName"].(string)
|
||||||
|
endDate := tmp["CertificateEndDate"].(string)
|
||||||
|
if endDate != "" {
|
||||||
|
date, err := time.Parse("Jan _2 15:04:05 2006 MST", endDate)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.CertificateEndDate = date
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseServerCertificate サーバ証明書のパース
|
||||||
|
func (p *ProxyLBCertificate) ParseServerCertificate() (*x509.Certificate, error) {
|
||||||
|
cert, e := p.parseCertificate(p.ServerCertificate)
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
return cert, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseIntermediateCertificate 中間証明書のパース
|
||||||
|
func (p *ProxyLBCertificate) ParseIntermediateCertificate() (*x509.Certificate, error) {
|
||||||
|
cert, e := p.parseCertificate(p.IntermediateCertificate)
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
return cert, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ProxyLBCertificate) parseCertificate(certPEM string) (*x509.Certificate, error) {
|
||||||
|
block, _ := pem.Decode([]byte(certPEM))
|
||||||
|
if block != nil {
|
||||||
|
return x509.ParseCertificate(block.Bytes)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("can't decode certificate")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProxyLBHealth ProxyLBのヘルスチェック戻り値
|
||||||
|
type ProxyLBHealth struct {
|
||||||
|
ActiveConn int // アクティブなコネクション数
|
||||||
|
CPS int // 秒あたりコネクション数
|
||||||
|
Servers []*ProxyLBHealthServer // 実サーバのステータス
|
||||||
|
CurrentVIP string // 現在のVIP
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProxyLBHealthServer ProxyLBの実サーバのステータス
|
||||||
|
type ProxyLBHealthServer struct {
|
||||||
|
ActiveConn int // アクティブなコネクション数
|
||||||
|
Status string // ステータス(UP or DOWN)
|
||||||
|
IPAddress string // IPアドレス
|
||||||
|
Port string // ポート
|
||||||
|
CPS int // 秒あたりコネクション数
|
||||||
|
}
|
113
vendor/github.com/sacloud/libsacloud/sacloud/server.go
generated
vendored
113
vendor/github.com/sacloud/libsacloud/sacloud/server.go
generated
vendored
|
@ -86,6 +86,119 @@ func (s *Server) CIDRIPAddress() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpstreamType 1番目(0番目)のNICの上流ネットワーク種別
|
||||||
|
func (s *Server) UpstreamType() EUpstreamNetworkType {
|
||||||
|
return s.UpstreamTypeAt(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpstreamTypeAt 指定インデックスのNICの上流ネットワーク種別
|
||||||
|
func (s *Server) UpstreamTypeAt(index int) EUpstreamNetworkType {
|
||||||
|
if len(s.Interfaces) <= index {
|
||||||
|
return EUpstreamNetworkUnknown
|
||||||
|
}
|
||||||
|
return s.Interfaces[index].UpstreamType()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwitchID 上流のスイッチのID
|
||||||
|
//
|
||||||
|
// NICがない、上流スイッチが見つからない、上流が共有セグメントの場合は-1を返す
|
||||||
|
func (s *Server) SwitchID() int64 {
|
||||||
|
return s.SwitchIDAt(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwitchIDAt 上流ネットワークのスイッチのID
|
||||||
|
//
|
||||||
|
// NICがない、上流スイッチが見つからない、上流が共有セグメントの場合は-1を返す
|
||||||
|
func (s *Server) SwitchIDAt(index int) int64 {
|
||||||
|
if len(s.Interfaces) <= index {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
nic := s.Interfaces[index]
|
||||||
|
if nic.Switch == nil || nic.Switch.Scope == ESCopeShared {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return nic.Switch.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwitchName 上流のスイッチのID
|
||||||
|
//
|
||||||
|
// NICがない、上流スイッチが見つからない、上流が共有セグメントの場合は空文字を返す
|
||||||
|
func (s *Server) SwitchName() string {
|
||||||
|
return s.SwitchNameAt(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwitchNameAt 上流ネットワークのスイッチのID
|
||||||
|
//
|
||||||
|
// NICがない、上流スイッチが見つからない、上流が共有セグメントの場合は空文字を返す
|
||||||
|
func (s *Server) SwitchNameAt(index int) string {
|
||||||
|
if len(s.Interfaces) <= index {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
nic := s.Interfaces[index]
|
||||||
|
if nic.Switch == nil || nic.Switch.Scope == ESCopeShared {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return nic.Switch.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bandwidth 上流ネットワークの帯域幅(単位:Mbps)
|
||||||
|
//
|
||||||
|
// -1: 1番目(0番目)のNICが存在しない場合 or 切断されている場合
|
||||||
|
// 0 : 制限なしの場合
|
||||||
|
// 以外: 帯域幅(Mbps)
|
||||||
|
func (s *Server) Bandwidth() int {
|
||||||
|
return s.BandwidthAt(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BandwidthAt 上流ネットワークの帯域幅(単位:Mbps)
|
||||||
|
//
|
||||||
|
// -1: 存在しないインデックスを取得した場合 or 切断されている場合
|
||||||
|
// 0 : 制限なしの場合
|
||||||
|
// 以外: 帯域幅(Mbps)
|
||||||
|
func (s *Server) BandwidthAt(index int) int {
|
||||||
|
if len(s.Interfaces) <= index {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
nic := s.Interfaces[index]
|
||||||
|
|
||||||
|
switch nic.UpstreamType() {
|
||||||
|
case EUpstreamNetworkNone:
|
||||||
|
return -1
|
||||||
|
case EUpstreamNetworkShared:
|
||||||
|
return 100
|
||||||
|
case EUpstreamNetworkSwitch, EUpstreamNetworkRouter:
|
||||||
|
//
|
||||||
|
// 上流ネットワークがスイッチだった場合の帯域制限
|
||||||
|
// https://manual.sakura.ad.jp/cloud/support/technical/network.html#support-network-03
|
||||||
|
//
|
||||||
|
|
||||||
|
// 専有ホストの場合は制限なし
|
||||||
|
if s.PrivateHost != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// メモリに応じた制限
|
||||||
|
memory := s.GetMemoryGB()
|
||||||
|
switch {
|
||||||
|
case memory < 32:
|
||||||
|
return 1000
|
||||||
|
case 32 <= memory && memory < 128:
|
||||||
|
return 2000
|
||||||
|
case 128 <= memory && memory < 224:
|
||||||
|
return 5000
|
||||||
|
case 224 <= memory:
|
||||||
|
return 10000
|
||||||
|
default:
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// ServerMaxInterfaceLen サーバーに接続できるNICの最大数
|
// ServerMaxInterfaceLen サーバーに接続できるNICの最大数
|
||||||
ServerMaxInterfaceLen = 10
|
ServerMaxInterfaceLen = 10
|
||||||
|
|
21
vendor/github.com/sacloud/libsacloud/sacloud/sim.go
generated
vendored
21
vendor/github.com/sacloud/libsacloud/sacloud/sim.go
generated
vendored
|
@ -7,6 +7,15 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// SIMOperatorsKDDI KDDI
|
||||||
|
SIMOperatorsKDDI = "KDDI"
|
||||||
|
// SIMOperatorsDOCOMO Docomo
|
||||||
|
SIMOperatorsDOCOMO = "NTT DOCOMO"
|
||||||
|
// SIMOperatorsSoftBank SoftBank
|
||||||
|
SIMOperatorsSoftBank = "SoftBank"
|
||||||
|
)
|
||||||
|
|
||||||
// SIM SIM(CommonServiceItem)
|
// SIM SIM(CommonServiceItem)
|
||||||
type SIM struct {
|
type SIM struct {
|
||||||
*Resource // ID
|
*Resource // ID
|
||||||
|
@ -101,6 +110,18 @@ type SIMLog struct {
|
||||||
IMSI string `json:"imsi,omitempty"`
|
IMSI string `json:"imsi,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SIMNetworkOperatorConfig SIM通信キャリア設定
|
||||||
|
type SIMNetworkOperatorConfig struct {
|
||||||
|
Allow bool `json:"allow,omitempty"`
|
||||||
|
CountryCode string `json:"country_code,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SIMNetworkOperatorConfigs SIM通信キャリア設定 リクエストパラメータ
|
||||||
|
type SIMNetworkOperatorConfigs struct {
|
||||||
|
NetworkOperatorConfigs []*SIMNetworkOperatorConfig `json:"network_operator_config,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// CreateNewSIM SIM作成
|
// CreateNewSIM SIM作成
|
||||||
func CreateNewSIM(name string, iccID string, passcode string) *SIM {
|
func CreateNewSIM(name string, iccID string, passcode string) *SIM {
|
||||||
return &SIM{
|
return &SIM{
|
||||||
|
|
29
vendor/github.com/sacloud/libsacloud/sacloud/simple_monitor.go
generated
vendored
29
vendor/github.com/sacloud/libsacloud/sacloud/simple_monitor.go
generated
vendored
|
@ -1,5 +1,7 @@
|
||||||
package sacloud
|
package sacloud
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
// SimpleMonitor シンプル監視
|
// SimpleMonitor シンプル監視
|
||||||
type SimpleMonitor struct {
|
type SimpleMonitor struct {
|
||||||
*Resource // ID
|
*Resource // ID
|
||||||
|
@ -70,6 +72,33 @@ type SimpleMonitorNotify struct {
|
||||||
IncomingWebhooksURL string `json:",omitempty"` // Slack通知の場合のWebhook URL
|
IncomingWebhooksURL string `json:",omitempty"` // Slack通知の場合のWebhook URL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ESimpleMonitorHealth シンプル監視ステータス
|
||||||
|
type ESimpleMonitorHealth string
|
||||||
|
|
||||||
|
var (
|
||||||
|
// EHealthUp Up
|
||||||
|
EHealthUp = ESimpleMonitorHealth("UP")
|
||||||
|
// EHealthDown Down
|
||||||
|
EHealthDown = ESimpleMonitorHealth("DOWN")
|
||||||
|
)
|
||||||
|
|
||||||
|
// IsUp アップ
|
||||||
|
func (e ESimpleMonitorHealth) IsUp() bool {
|
||||||
|
return e == EHealthUp
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsDown ダウン
|
||||||
|
func (e ESimpleMonitorHealth) IsDown() bool {
|
||||||
|
return e == EHealthDown
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimpleMonitorHealthCheckStatus シンプル監視ステータス
|
||||||
|
type SimpleMonitorHealthCheckStatus struct {
|
||||||
|
LastCheckedAt time.Time
|
||||||
|
LastHealthChangedAt time.Time
|
||||||
|
Health ESimpleMonitorHealth
|
||||||
|
}
|
||||||
|
|
||||||
// CreateNewSimpleMonitor シンプル監視作成
|
// CreateNewSimpleMonitor シンプル監視作成
|
||||||
func CreateNewSimpleMonitor(target string) *SimpleMonitor {
|
func CreateNewSimpleMonitor(target string) *SimpleMonitor {
|
||||||
return &SimpleMonitor{
|
return &SimpleMonitor{
|
||||||
|
|
1
vendor/github.com/sacloud/libsacloud/sacloud/switch.go
generated
vendored
1
vendor/github.com/sacloud/libsacloud/sacloud/switch.go
generated
vendored
|
@ -15,6 +15,7 @@ type Switch struct {
|
||||||
propIcon // アイコン
|
propIcon // アイコン
|
||||||
propTags // タグ
|
propTags // タグ
|
||||||
propCreatedAt // 作成日時
|
propCreatedAt // 作成日時
|
||||||
|
propZone // ゾーン
|
||||||
|
|
||||||
ServerCount int `json:",omitempty"` // 接続サーバー数
|
ServerCount int `json:",omitempty"` // 接続サーバー数
|
||||||
ApplianceCount int `json:",omitempty"` // 接続アプライアンス数
|
ApplianceCount int `json:",omitempty"` // 接続アプライアンス数
|
||||||
|
|
131
vendor/github.com/sacloud/libsacloud/sacloud/vpc_router.go
generated
vendored
131
vendor/github.com/sacloud/libsacloud/sacloud/vpc_router.go
generated
vendored
|
@ -236,3 +236,134 @@ func (v *VPCRouter) FindBelongsInterface(ip net.IP) (int, *VPCRouterInterface) {
|
||||||
}
|
}
|
||||||
return -1, nil
|
return -1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IPAddress1 1番目(0番目)のNICのIPアドレス1
|
||||||
|
func (v *VPCRouter) IPAddress1() string {
|
||||||
|
return v.IPAddress1At(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPAddress1At 指定インデックスのNICのIPアドレス1
|
||||||
|
func (v *VPCRouter) IPAddress1At(index int) string {
|
||||||
|
if len(v.Interfaces) <= index {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if index == 0 {
|
||||||
|
if v.IsStandardPlan() {
|
||||||
|
return v.Interfaces[0].IPAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
if !v.HasInterfaces() {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if len(v.Settings.Router.Interfaces[0].IPAddress) < 1 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return v.Settings.Router.Interfaces[0].IPAddress[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
nic := v.Settings.Router.Interfaces[index]
|
||||||
|
if len(nic.IPAddress) < 1 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return nic.IPAddress[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPAddress2 1番目(0番目)のNICのIPアドレス2
|
||||||
|
func (v *VPCRouter) IPAddress2() string {
|
||||||
|
return v.IPAddress2At(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPAddress2At 指定インデックスのNICのIPアドレス2
|
||||||
|
func (v *VPCRouter) IPAddress2At(index int) string {
|
||||||
|
if v.IsStandardPlan() {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if len(v.Interfaces) <= index {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if index == 0 {
|
||||||
|
if !v.HasInterfaces() {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if len(v.Settings.Router.Interfaces[0].IPAddress) < 2 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return v.Settings.Router.Interfaces[0].IPAddress[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
nic := v.Settings.Router.Interfaces[index]
|
||||||
|
if len(nic.IPAddress) < 2 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return nic.IPAddress[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// VirtualIPAddress 1番目(0番目)のNICのVIP
|
||||||
|
func (v *VPCRouter) VirtualIPAddress() string {
|
||||||
|
return v.VirtualIPAddressAt(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// VirtualIPAddressAt 指定インデックスのNICのVIP
|
||||||
|
func (v *VPCRouter) VirtualIPAddressAt(index int) string {
|
||||||
|
if v.IsStandardPlan() {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if len(v.Interfaces) <= index {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.Settings.Router.Interfaces[0].VirtualIPAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkMaskLen 1番目(0番目)のNICのネットワークマスク長
|
||||||
|
func (v *VPCRouter) NetworkMaskLen() int {
|
||||||
|
return v.NetworkMaskLenAt(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkMaskLenAt 指定インデックスのNICのネットワークマスク長
|
||||||
|
func (v *VPCRouter) NetworkMaskLenAt(index int) int {
|
||||||
|
if !v.HasInterfaces() {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
if len(v.Interfaces) <= index {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if index == 0 {
|
||||||
|
return v.Interfaces[0].Switch.Subnet.NetworkMaskLen
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.Settings.Router.Interfaces[index].NetworkMaskLen
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zone スイッチから現在のゾーン名を取得
|
||||||
|
//
|
||||||
|
// Note: 共有セグメント接続時は取得不能
|
||||||
|
func (v *VPCRouter) Zone() string {
|
||||||
|
if v.Switch != nil {
|
||||||
|
return v.Switch.GetZoneName()
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(v.Interfaces) > 0 && v.Interfaces[0].Switch != nil {
|
||||||
|
return v.Interfaces[0].Switch.GetZoneName()
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// VRID VRIDを取得
|
||||||
|
//
|
||||||
|
// スタンダードプラン、またはVRIDの参照に失敗した場合は-1を返す
|
||||||
|
func (v *VPCRouter) VRID() int {
|
||||||
|
if v.IsStandardPlan() {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if !v.HasSetting() || v.Settings.Router.VRID == nil {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
return *v.Settings.Router.VRID
|
||||||
|
}
|
||||||
|
|
5
vendor/github.com/sacloud/libsacloud/sacloud/vpc_router_status.go
generated
vendored
5
vendor/github.com/sacloud/libsacloud/sacloud/vpc_router_status.go
generated
vendored
|
@ -5,6 +5,7 @@ type VPCRouterStatus struct {
|
||||||
FirewallReceiveLogs []string
|
FirewallReceiveLogs []string
|
||||||
FirewallSendLogs []string
|
FirewallSendLogs []string
|
||||||
VPNLogs []string
|
VPNLogs []string
|
||||||
|
SessionCount int
|
||||||
DHCPServerLeases []struct {
|
DHCPServerLeases []struct {
|
||||||
IPAddress string
|
IPAddress string
|
||||||
MACAddress string
|
MACAddress string
|
||||||
|
@ -12,12 +13,12 @@ type VPCRouterStatus struct {
|
||||||
L2TPIPsecServerSessions []struct {
|
L2TPIPsecServerSessions []struct {
|
||||||
User string
|
User string
|
||||||
IPAddress string
|
IPAddress string
|
||||||
TimeSec string
|
TimeSec int
|
||||||
}
|
}
|
||||||
PPTPServerSessions []struct {
|
PPTPServerSessions []struct {
|
||||||
User string
|
User string
|
||||||
IPAddress string
|
IPAddress string
|
||||||
TimeSec string
|
TimeSec int
|
||||||
}
|
}
|
||||||
SiteToSiteIPsecVPNPeers []struct {
|
SiteToSiteIPsecVPNPeers []struct {
|
||||||
Status string
|
Status string
|
||||||
|
|
43
vendor/github.com/sacloud/libsacloud/utils/mutexkv/mutexkv.go
generated
vendored
Normal file
43
vendor/github.com/sacloud/libsacloud/utils/mutexkv/mutexkv.go
generated
vendored
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
package mutexkv
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MutexKV is a simple key/value store for arbitrary mutexes. It can be used to
|
||||||
|
// serialize changes across arbitrary collaborators that share knowledge of the
|
||||||
|
// keys they must serialize on.
|
||||||
|
type MutexKV struct {
|
||||||
|
lock sync.Mutex
|
||||||
|
store map[string]*sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock the mutex for the given key. Caller is responsible for calling Unlock
|
||||||
|
// for the same key
|
||||||
|
func (m *MutexKV) Lock(key string) {
|
||||||
|
m.get(key).Lock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unlock the mutex for the given key. Caller must have called Lock for the same key first
|
||||||
|
func (m *MutexKV) Unlock(key string) {
|
||||||
|
m.get(key).Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a mutex for the given key, no guarantee of its lock status
|
||||||
|
func (m *MutexKV) get(key string) *sync.Mutex {
|
||||||
|
m.lock.Lock()
|
||||||
|
defer m.lock.Unlock()
|
||||||
|
mutex, ok := m.store[key]
|
||||||
|
if !ok {
|
||||||
|
mutex = &sync.Mutex{}
|
||||||
|
m.store[key] = mutex
|
||||||
|
}
|
||||||
|
return mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMutexKV Returns a properly initalized MutexKV
|
||||||
|
func NewMutexKV() *MutexKV {
|
||||||
|
return &MutexKV{
|
||||||
|
store: make(map[string]*sync.Mutex),
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue